Merge remote-tracking branches 'spi/fix/au1550', 'spi/fix/davinci', 'spi/fix/doc', 'spi/fix/dw', 'spi/fix/omap-mcspi', 'spi/fix/pxa2xx', 'spi/fix/rockchip' and 'spi/fix/rspi' into spi-linus
This commit is contained in:
parent
e0a7ab4b50
61a2381c7b
3f2dad99f6
2c67568903
08a707b878
3d0763c006
aca2636468
5d1d150d7d
3819bc8752
commit
360b2eaeb5
@ -945,7 +945,7 @@ static int au1550_spi_remove(struct platform_device *pdev)
|
|||||||
spi_bitbang_stop(&hw->bitbang);
|
spi_bitbang_stop(&hw->bitbang);
|
||||||
free_irq(hw->irq, hw);
|
free_irq(hw->irq, hw);
|
||||||
iounmap((void __iomem *)hw->regs);
|
iounmap((void __iomem *)hw->regs);
|
||||||
release_mem_region(r->start, sizeof(psc_spi_t));
|
release_mem_region(hw->ioarea->start, sizeof(psc_spi_t));
|
||||||
|
|
||||||
if (hw->usedma) {
|
if (hw->usedma) {
|
||||||
au1550_spi_dma_rxtmp_free(hw);
|
au1550_spi_dma_rxtmp_free(hw);
|
||||||
|
@ -417,16 +417,16 @@ static int davinci_spi_setup(struct spi_device *spi)
|
|||||||
flags, dev_name(&spi->dev));
|
flags, dev_name(&spi->dev));
|
||||||
internal_cs = false;
|
internal_cs = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
|
dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
|
||||||
spi->cs_gpio, retval);
|
spi->cs_gpio, retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internal_cs)
|
if (internal_cs)
|
||||||
set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
|
set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
|
||||||
|
}
|
||||||
|
|
||||||
if (spi->mode & SPI_READY)
|
if (spi->mode & SPI_READY)
|
||||||
set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
|
set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
|
||||||
|
@ -62,6 +62,8 @@ static int spi_pci_probe(struct pci_dev *pdev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
dws->regs = pcim_iomap_table(pdev)[pci_bar];
|
||||||
|
|
||||||
dws->bus_num = 0;
|
dws->bus_num = 0;
|
||||||
dws->num_cs = 4;
|
dws->num_cs = 4;
|
||||||
dws->irq = pdev->irq;
|
dws->irq = pdev->irq;
|
||||||
|
@ -271,7 +271,7 @@ static void giveback(struct dw_spi *dws)
|
|||||||
transfer_list);
|
transfer_list);
|
||||||
|
|
||||||
if (!last_transfer->cs_change)
|
if (!last_transfer->cs_change)
|
||||||
spi_chip_sel(dws, dws->cur_msg->spi, 0);
|
spi_chip_sel(dws, msg->spi, 0);
|
||||||
|
|
||||||
spi_finalize_current_message(dws->master);
|
spi_finalize_current_message(dws->master);
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,8 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
|||||||
disable_fifo:
|
disable_fifo:
|
||||||
if (t->rx_buf != NULL)
|
if (t->rx_buf != NULL)
|
||||||
chconf &= ~OMAP2_MCSPI_CHCONF_FFER;
|
chconf &= ~OMAP2_MCSPI_CHCONF_FFER;
|
||||||
else
|
|
||||||
|
if (t->tx_buf != NULL)
|
||||||
chconf &= ~OMAP2_MCSPI_CHCONF_FFET;
|
chconf &= ~OMAP2_MCSPI_CHCONF_FFET;
|
||||||
|
|
||||||
mcspi_write_chconf0(spi, chconf);
|
mcspi_write_chconf0(spi, chconf);
|
||||||
|
@ -1074,6 +1074,7 @@ static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
|
|||||||
{ "INT3430", 0 },
|
{ "INT3430", 0 },
|
||||||
{ "INT3431", 0 },
|
{ "INT3431", 0 },
|
||||||
{ "80860F0E", 0 },
|
{ "80860F0E", 0 },
|
||||||
|
{ "8086228E", 0 },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
|
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
|
||||||
|
@ -499,7 +499,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* div doesn't support odd number */
|
/* div doesn't support odd number */
|
||||||
div = rs->max_freq / rs->speed;
|
div = max_t(u32, rs->max_freq / rs->speed, 1);
|
||||||
div = (div + 1) & 0xfffe;
|
div = (div + 1) & 0xfffe;
|
||||||
|
|
||||||
spi_enable_chip(rs, 0);
|
spi_enable_chip(rs, 0);
|
||||||
@ -678,7 +678,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
|
|||||||
rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);
|
rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);
|
||||||
rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);
|
rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);
|
||||||
rs->dma_tx.direction = DMA_MEM_TO_DEV;
|
rs->dma_tx.direction = DMA_MEM_TO_DEV;
|
||||||
rs->dma_tx.direction = DMA_DEV_TO_MEM;
|
rs->dma_rx.direction = DMA_DEV_TO_MEM;
|
||||||
|
|
||||||
master->can_dma = rockchip_spi_can_dma;
|
master->can_dma = rockchip_spi_can_dma;
|
||||||
master->dma_tx = rs->dma_tx.ch;
|
master->dma_tx = rs->dma_tx.ch;
|
||||||
|
@ -472,25 +472,52 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
|
|||||||
dma_cookie_t cookie;
|
dma_cookie_t cookie;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (tx) {
|
/* First prepare and submit the DMA request(s), as this may fail */
|
||||||
desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
|
|
||||||
tx->sgl, tx->nents, DMA_TO_DEVICE,
|
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
|
||||||
if (!desc_tx)
|
|
||||||
goto no_dma;
|
|
||||||
|
|
||||||
irq_mask |= SPCR_SPTIE;
|
|
||||||
}
|
|
||||||
if (rx) {
|
if (rx) {
|
||||||
desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
|
desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
|
||||||
rx->sgl, rx->nents, DMA_FROM_DEVICE,
|
rx->sgl, rx->nents, DMA_FROM_DEVICE,
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
if (!desc_rx)
|
if (!desc_rx) {
|
||||||
goto no_dma;
|
ret = -EAGAIN;
|
||||||
|
goto no_dma_rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc_rx->callback = rspi_dma_complete;
|
||||||
|
desc_rx->callback_param = rspi;
|
||||||
|
cookie = dmaengine_submit(desc_rx);
|
||||||
|
if (dma_submit_error(cookie)) {
|
||||||
|
ret = cookie;
|
||||||
|
goto no_dma_rx;
|
||||||
|
}
|
||||||
|
|
||||||
irq_mask |= SPCR_SPRIE;
|
irq_mask |= SPCR_SPRIE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tx) {
|
||||||
|
desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
|
||||||
|
tx->sgl, tx->nents, DMA_TO_DEVICE,
|
||||||
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
|
if (!desc_tx) {
|
||||||
|
ret = -EAGAIN;
|
||||||
|
goto no_dma_tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx) {
|
||||||
|
/* No callback */
|
||||||
|
desc_tx->callback = NULL;
|
||||||
|
} else {
|
||||||
|
desc_tx->callback = rspi_dma_complete;
|
||||||
|
desc_tx->callback_param = rspi;
|
||||||
|
}
|
||||||
|
cookie = dmaengine_submit(desc_tx);
|
||||||
|
if (dma_submit_error(cookie)) {
|
||||||
|
ret = cookie;
|
||||||
|
goto no_dma_tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_mask |= SPCR_SPTIE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
|
* DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
|
||||||
* called. So, this driver disables the IRQ while DMA transfer.
|
* called. So, this driver disables the IRQ while DMA transfer.
|
||||||
@ -503,34 +530,24 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
|
|||||||
rspi_enable_irq(rspi, irq_mask);
|
rspi_enable_irq(rspi, irq_mask);
|
||||||
rspi->dma_callbacked = 0;
|
rspi->dma_callbacked = 0;
|
||||||
|
|
||||||
if (rx) {
|
/* Now start DMA */
|
||||||
desc_rx->callback = rspi_dma_complete;
|
if (rx)
|
||||||
desc_rx->callback_param = rspi;
|
|
||||||
cookie = dmaengine_submit(desc_rx);
|
|
||||||
if (dma_submit_error(cookie))
|
|
||||||
return cookie;
|
|
||||||
dma_async_issue_pending(rspi->master->dma_rx);
|
dma_async_issue_pending(rspi->master->dma_rx);
|
||||||
}
|
if (tx)
|
||||||
if (tx) {
|
|
||||||
if (rx) {
|
|
||||||
/* No callback */
|
|
||||||
desc_tx->callback = NULL;
|
|
||||||
} else {
|
|
||||||
desc_tx->callback = rspi_dma_complete;
|
|
||||||
desc_tx->callback_param = rspi;
|
|
||||||
}
|
|
||||||
cookie = dmaengine_submit(desc_tx);
|
|
||||||
if (dma_submit_error(cookie))
|
|
||||||
return cookie;
|
|
||||||
dma_async_issue_pending(rspi->master->dma_tx);
|
dma_async_issue_pending(rspi->master->dma_tx);
|
||||||
}
|
|
||||||
|
|
||||||
ret = wait_event_interruptible_timeout(rspi->wait,
|
ret = wait_event_interruptible_timeout(rspi->wait,
|
||||||
rspi->dma_callbacked, HZ);
|
rspi->dma_callbacked, HZ);
|
||||||
if (ret > 0 && rspi->dma_callbacked)
|
if (ret > 0 && rspi->dma_callbacked)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
else if (!ret)
|
else if (!ret) {
|
||||||
|
dev_err(&rspi->master->dev, "DMA timeout\n");
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
if (tx)
|
||||||
|
dmaengine_terminate_all(rspi->master->dma_tx);
|
||||||
|
if (rx)
|
||||||
|
dmaengine_terminate_all(rspi->master->dma_rx);
|
||||||
|
}
|
||||||
|
|
||||||
rspi_disable_irq(rspi, irq_mask);
|
rspi_disable_irq(rspi, irq_mask);
|
||||||
|
|
||||||
@ -541,11 +558,16 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
no_dma:
|
no_dma_tx:
|
||||||
pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
|
if (rx)
|
||||||
dev_driver_string(&rspi->master->dev),
|
dmaengine_terminate_all(rspi->master->dma_rx);
|
||||||
dev_name(&rspi->master->dev));
|
no_dma_rx:
|
||||||
return -EAGAIN;
|
if (ret == -EAGAIN) {
|
||||||
|
pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
|
||||||
|
dev_driver_string(&rspi->master->dev),
|
||||||
|
dev_name(&rspi->master->dev));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rspi_receive_init(const struct rspi_data *rspi)
|
static void rspi_receive_init(const struct rspi_data *rspi)
|
||||||
|
@ -848,6 +848,7 @@ out:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* spi_finalize_current_transfer - report completion of a transfer
|
* spi_finalize_current_transfer - report completion of a transfer
|
||||||
|
* @master: the master reporting completion
|
||||||
*
|
*
|
||||||
* Called by SPI drivers using the core transfer_one_message()
|
* Called by SPI drivers using the core transfer_one_message()
|
||||||
* implementation to notify it that the current interrupt driven
|
* implementation to notify it that the current interrupt driven
|
||||||
|
@ -253,6 +253,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
|
|||||||
* the device whose settings are being modified.
|
* the device whose settings are being modified.
|
||||||
* @transfer: adds a message to the controller's transfer queue.
|
* @transfer: adds a message to the controller's transfer queue.
|
||||||
* @cleanup: frees controller-specific state
|
* @cleanup: frees controller-specific state
|
||||||
|
* @can_dma: determine whether this master supports DMA
|
||||||
* @queued: whether this master is providing an internal message queue
|
* @queued: whether this master is providing an internal message queue
|
||||||
* @kworker: thread struct for message pump
|
* @kworker: thread struct for message pump
|
||||||
* @kworker_task: pointer to task for message pump kworker thread
|
* @kworker_task: pointer to task for message pump kworker thread
|
||||||
@ -262,6 +263,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
|
|||||||
* @cur_msg: the currently in-flight message
|
* @cur_msg: the currently in-flight message
|
||||||
* @cur_msg_prepared: spi_prepare_message was called for the currently
|
* @cur_msg_prepared: spi_prepare_message was called for the currently
|
||||||
* in-flight message
|
* in-flight message
|
||||||
|
* @cur_msg_mapped: message has been mapped for DMA
|
||||||
* @xfer_completion: used by core transfer_one_message()
|
* @xfer_completion: used by core transfer_one_message()
|
||||||
* @busy: message pump is busy
|
* @busy: message pump is busy
|
||||||
* @running: message pump is running
|
* @running: message pump is running
|
||||||
@ -299,6 +301,10 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
|
|||||||
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
|
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
|
||||||
* number. Any individual value may be -ENOENT for CS lines that
|
* number. Any individual value may be -ENOENT for CS lines that
|
||||||
* are not GPIOs (driven by the SPI controller itself).
|
* are not GPIOs (driven by the SPI controller itself).
|
||||||
|
* @dma_tx: DMA transmit channel
|
||||||
|
* @dma_rx: DMA receive channel
|
||||||
|
* @dummy_rx: dummy receive buffer for full-duplex devices
|
||||||
|
* @dummy_tx: dummy transmit buffer for full-duplex devices
|
||||||
*
|
*
|
||||||
* Each SPI master controller can communicate with one or more @spi_device
|
* Each SPI master controller can communicate with one or more @spi_device
|
||||||
* children. These make a small bus, sharing MOSI, MISO and SCK signals
|
* children. These make a small bus, sharing MOSI, MISO and SCK signals
|
||||||
@ -632,6 +638,7 @@ struct spi_transfer {
|
|||||||
* addresses for each transfer buffer
|
* addresses for each transfer buffer
|
||||||
* @complete: called to report transaction completions
|
* @complete: called to report transaction completions
|
||||||
* @context: the argument to complete() when it's called
|
* @context: the argument to complete() when it's called
|
||||||
|
* @frame_length: the total number of bytes in the message
|
||||||
* @actual_length: the total number of bytes that were transferred in all
|
* @actual_length: the total number of bytes that were transferred in all
|
||||||
* successful segments
|
* successful segments
|
||||||
* @status: zero for success, else negative errno
|
* @status: zero for success, else negative errno
|
||||||
|
Loading…
Reference in New Issue
Block a user