Commit 5fa5e6de authored by Dan Sneddon's avatar Dan Sneddon Committed by Mark Brown

spi: atmel: Switch to transfer_one transfer method

Switch from using our own transfer_one_message routine to using the one
provided by the SPI core.
Signed-off-by: default avatarDan Sneddon <dan.sneddon@microchip.com>
Link: https://lore.kernel.org/r/20210602160816.4890-1-dan.sneddon@microchip.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent ec679bda
...@@ -863,7 +863,6 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, ...@@ -863,7 +863,6 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
* lock is held, spi irq is blocked * lock is held, spi irq is blocked
*/ */
static void atmel_spi_pdc_next_xfer(struct spi_master *master, static void atmel_spi_pdc_next_xfer(struct spi_master *master,
struct spi_message *msg,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
struct atmel_spi *as = spi_master_get_devdata(master); struct atmel_spi *as = spi_master_get_devdata(master);
...@@ -879,12 +878,12 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master, ...@@ -879,12 +878,12 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
spi_writel(as, RPR, rx_dma); spi_writel(as, RPR, rx_dma);
spi_writel(as, TPR, tx_dma); spi_writel(as, TPR, tx_dma);
if (msg->spi->bits_per_word > 8) if (xfer->bits_per_word > 8)
len >>= 1; len >>= 1;
spi_writel(as, RCR, len); spi_writel(as, RCR, len);
spi_writel(as, TCR, len); spi_writel(as, TCR, len);
dev_dbg(&msg->spi->dev, dev_dbg(&master->dev,
" start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n", " start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
xfer, xfer->len, xfer->tx_buf, xfer, xfer->len, xfer->tx_buf,
(unsigned long long)xfer->tx_dma, xfer->rx_buf, (unsigned long long)xfer->tx_dma, xfer->rx_buf,
...@@ -898,12 +897,12 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master, ...@@ -898,12 +897,12 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
spi_writel(as, RNPR, rx_dma); spi_writel(as, RNPR, rx_dma);
spi_writel(as, TNPR, tx_dma); spi_writel(as, TNPR, tx_dma);
if (msg->spi->bits_per_word > 8) if (xfer->bits_per_word > 8)
len >>= 1; len >>= 1;
spi_writel(as, RNCR, len); spi_writel(as, RNCR, len);
spi_writel(as, TNCR, len); spi_writel(as, TNCR, len);
dev_dbg(&msg->spi->dev, dev_dbg(&master->dev,
" next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n", " next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
xfer, xfer->len, xfer->tx_buf, xfer, xfer->len, xfer->tx_buf,
(unsigned long long)xfer->tx_dma, xfer->rx_buf, (unsigned long long)xfer->tx_dma, xfer->rx_buf,
...@@ -1273,12 +1272,28 @@ static int atmel_spi_setup(struct spi_device *spi) ...@@ -1273,12 +1272,28 @@ static int atmel_spi_setup(struct spi_device *spi)
return 0; return 0;
} }
static void atmel_spi_set_cs(struct spi_device *spi, bool enable)
{
struct atmel_spi *as = spi_master_get_devdata(spi->master);
/* the core doesn't really pass us enable/disable, but CS HIGH vs CS LOW
* since we already have routines for activate/deactivate translate
* high/low to active/inactive
*/
enable = (!!(spi->mode & SPI_CS_HIGH) == enable);
if (enable) {
cs_activate(as, spi);
} else {
cs_deactivate(as, spi);
}
}
static int atmel_spi_one_transfer(struct spi_master *master, static int atmel_spi_one_transfer(struct spi_master *master,
struct spi_message *msg, struct spi_device *spi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
struct atmel_spi *as; struct atmel_spi *as;
struct spi_device *spi = msg->spi;
u8 bits; u8 bits;
u32 len; u32 len;
struct atmel_spi_device *asd; struct atmel_spi_device *asd;
...@@ -1287,11 +1302,8 @@ static int atmel_spi_one_transfer(struct spi_master *master, ...@@ -1287,11 +1302,8 @@ static int atmel_spi_one_transfer(struct spi_master *master,
unsigned long dma_timeout; unsigned long dma_timeout;
as = spi_master_get_devdata(master); as = spi_master_get_devdata(master);
/* This lock was orignally taken in atmel_spi_trasfer_one_message */
if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) { atmel_spi_lock(as);
dev_dbg(&spi->dev, "missing rx or tx buf\n");
return -EINVAL;
}
asd = spi->controller_state; asd = spi->controller_state;
bits = (asd->csr >> 4) & 0xf; bits = (asd->csr >> 4) & 0xf;
...@@ -1305,13 +1317,13 @@ static int atmel_spi_one_transfer(struct spi_master *master, ...@@ -1305,13 +1317,13 @@ static int atmel_spi_one_transfer(struct spi_master *master,
* DMA map early, for performance (empties dcache ASAP) and * DMA map early, for performance (empties dcache ASAP) and
* better fault reporting. * better fault reporting.
*/ */
if ((!msg->is_dma_mapped) if ((!master->cur_msg_mapped)
&& as->use_pdc) { && as->use_pdc) {
if (atmel_spi_dma_map_xfer(as, xfer) < 0) if (atmel_spi_dma_map_xfer(as, xfer) < 0)
return -ENOMEM; return -ENOMEM;
} }
atmel_spi_set_xfer_speed(as, msg->spi, xfer); atmel_spi_set_xfer_speed(as, spi, xfer);
as->done_status = 0; as->done_status = 0;
as->current_transfer = xfer; as->current_transfer = xfer;
...@@ -1320,7 +1332,7 @@ static int atmel_spi_one_transfer(struct spi_master *master, ...@@ -1320,7 +1332,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
reinit_completion(&as->xfer_completion); reinit_completion(&as->xfer_completion);
if (as->use_pdc) { if (as->use_pdc) {
atmel_spi_pdc_next_xfer(master, msg, xfer); atmel_spi_pdc_next_xfer(master, xfer);
} else if (atmel_spi_use_dma(as, xfer)) { } else if (atmel_spi_use_dma(as, xfer)) {
len = as->current_remaining_bytes; len = as->current_remaining_bytes;
ret = atmel_spi_next_xfer_dma_submit(master, ret = atmel_spi_next_xfer_dma_submit(master,
...@@ -1328,7 +1340,8 @@ static int atmel_spi_one_transfer(struct spi_master *master, ...@@ -1328,7 +1340,8 @@ static int atmel_spi_one_transfer(struct spi_master *master,
if (ret) { if (ret) {
dev_err(&spi->dev, dev_err(&spi->dev,
"unable to use DMA, fallback to PIO\n"); "unable to use DMA, fallback to PIO\n");
atmel_spi_next_xfer_pio(master, xfer); as->done_status = ret;
break;
} else { } else {
as->current_remaining_bytes -= len; as->current_remaining_bytes -= len;
if (as->current_remaining_bytes < 0) if (as->current_remaining_bytes < 0)
...@@ -1381,90 +1394,18 @@ static int atmel_spi_one_transfer(struct spi_master *master, ...@@ -1381,90 +1394,18 @@ static int atmel_spi_one_transfer(struct spi_master *master,
} else if (atmel_spi_use_dma(as, xfer)) { } else if (atmel_spi_use_dma(as, xfer)) {
atmel_spi_stop_dma(master); atmel_spi_stop_dma(master);
} }
if (!msg->is_dma_mapped
&& as->use_pdc)
atmel_spi_dma_unmap_xfer(master, xfer);
return 0;
} else {
/* only update length if no error */
msg->actual_length += xfer->len;
} }
if (!msg->is_dma_mapped if (!master->cur_msg_mapped
&& as->use_pdc) && as->use_pdc)
atmel_spi_dma_unmap_xfer(master, xfer); atmel_spi_dma_unmap_xfer(master, xfer);
spi_transfer_delay_exec(xfer);
if (xfer->cs_change) {
if (list_is_last(&xfer->transfer_list,
&msg->transfers)) {
as->keep_cs = true;
} else {
cs_deactivate(as, msg->spi);
udelay(10);
cs_activate(as, msg->spi);
}
}
return 0;
}
static int atmel_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
{
struct atmel_spi *as;
struct spi_transfer *xfer;
struct spi_device *spi = msg->spi;
int ret = 0;
as = spi_master_get_devdata(master);
dev_dbg(&spi->dev, "new message %p submitted for %s\n",
msg, dev_name(&spi->dev));
atmel_spi_lock(as);
cs_activate(as, spi);
as->keep_cs = false;
msg->status = 0;
msg->actual_length = 0;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
trace_spi_transfer_start(msg, xfer);
ret = atmel_spi_one_transfer(master, msg, xfer);
if (ret)
goto msg_done;
trace_spi_transfer_stop(msg, xfer);
}
if (as->use_pdc) if (as->use_pdc)
atmel_spi_disable_pdc_transfer(as); atmel_spi_disable_pdc_transfer(as);
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
dev_dbg(&spi->dev,
" xfer %p: len %u tx %p/%pad rx %p/%pad\n",
xfer, xfer->len,
xfer->tx_buf, &xfer->tx_dma,
xfer->rx_buf, &xfer->rx_dma);
}
msg_done:
if (!as->keep_cs)
cs_deactivate(as, msg->spi);
atmel_spi_unlock(as); atmel_spi_unlock(as);
msg->status = as->done_status; return as->done_status;
spi_finalize_current_message(spi->master);
return ret;
} }
static void atmel_spi_cleanup(struct spi_device *spi) static void atmel_spi_cleanup(struct spi_device *spi)
...@@ -1554,7 +1495,8 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1554,7 +1495,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
master->num_chipselect = 4; master->num_chipselect = 4;
master->setup = atmel_spi_setup; master->setup = atmel_spi_setup;
master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX); master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX);
master->transfer_one_message = atmel_spi_transfer_one_message; master->transfer_one = atmel_spi_one_transfer;
master->set_cs = atmel_spi_set_cs;
master->cleanup = atmel_spi_cleanup; master->cleanup = atmel_spi_cleanup;
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
master->max_dma_len = SPI_MAX_DMA_XFER; master->max_dma_len = SPI_MAX_DMA_XFER;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment