summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-mt65xx.c
diff options
context:
space:
mode:
authorDaniel Kurtz <djkurtz@chromium.org>2017-01-26 11:21:54 -0500
committerMark Brown <broonie@kernel.org>2017-01-31 14:55:38 -0500
commit1ce24864bff40e11500a699789412115fdf244bf (patch)
tree3be94f991de7179870c8be5e42db3ea7c55e2905 /drivers/spi/spi-mt65xx.c
parent88b0aa544af58ce3be125a1845a227264ec9ab89 (diff)
spi: mediatek: Only do dma for 4-byte aligned buffers
Mediatek SPI DMA only works when tx and rx buffer addresses are 4-byte aligned. Unaligned DMA transactions appeared to work previously, since we the spi core was incorrectly using the spi_master device for dma, which had a 0 dma_mask, and therefore the swiotlb dma map operations were falling back to using bounce buffers. Since each DMA transaction would use its own buffer, the mapped starting address of each transaction was always aligned. When doing real DMA, the mapped address will share the alignment of the raw tx/rx buffer provided by the SPI user, which may or may not be aligned. If a buffer is not aligned, we cannot use DMA, and must use FIFO based transaction instead. So, this patch implements a scheme that allows using the FIFO for arbitrary length transactions (larger than the 32-byte FIFO size) by reloading the FIFO in the interrupt handler. Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> Cc: Leilk Liu <leilk.liu@mediatek.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-mt65xx.c')
-rw-r--r--drivers/spi/spi-mt65xx.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 899d7a8f0889..278867a31950 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -73,7 +73,7 @@
73#define MTK_SPI_IDLE 0 73#define MTK_SPI_IDLE 0
74#define MTK_SPI_PAUSED 1 74#define MTK_SPI_PAUSED 1
75 75
76#define MTK_SPI_MAX_FIFO_SIZE 32 76#define MTK_SPI_MAX_FIFO_SIZE 32U
77#define MTK_SPI_PACKET_SIZE 1024 77#define MTK_SPI_PACKET_SIZE 1024
78 78
79struct mtk_spi_compatible { 79struct mtk_spi_compatible {
@@ -333,7 +333,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
333 struct mtk_spi *mdata = spi_master_get_devdata(master); 333 struct mtk_spi *mdata = spi_master_get_devdata(master);
334 334
335 mdata->cur_transfer = xfer; 335 mdata->cur_transfer = xfer;
336 mdata->xfer_len = xfer->len; 336 mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);
337 mtk_spi_prepare_transfer(master, xfer); 337 mtk_spi_prepare_transfer(master, xfer);
338 mtk_spi_setup_packet(master); 338 mtk_spi_setup_packet(master);
339 339
@@ -410,7 +410,10 @@ static bool mtk_spi_can_dma(struct spi_master *master,
410 struct spi_device *spi, 410 struct spi_device *spi,
411 struct spi_transfer *xfer) 411 struct spi_transfer *xfer)
412{ 412{
413 return xfer->len > MTK_SPI_MAX_FIFO_SIZE; 413 /* Buffers for DMA transactions must be 4-byte aligned */
414 return (xfer->len > MTK_SPI_MAX_FIFO_SIZE &&
415 (unsigned long)xfer->tx_buf % 4 == 0 &&
416 (unsigned long)xfer->rx_buf % 4 == 0);
414} 417}
415 418
416static int mtk_spi_setup(struct spi_device *spi) 419static int mtk_spi_setup(struct spi_device *spi)
@@ -451,7 +454,33 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
451 &reg_val, remainder); 454 &reg_val, remainder);
452 } 455 }
453 } 456 }
454 spi_finalize_current_transfer(master); 457
458 trans->len -= mdata->xfer_len;
459 if (!trans->len) {
460 spi_finalize_current_transfer(master);
461 return IRQ_HANDLED;
462 }
463
464 if (trans->tx_buf)
465 trans->tx_buf += mdata->xfer_len;
466 if (trans->rx_buf)
467 trans->rx_buf += mdata->xfer_len;
468
469 mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, trans->len);
470 mtk_spi_setup_packet(master);
471
472 cnt = trans->len / 4;
473 iowrite32_rep(mdata->base + SPI_TX_DATA_REG, trans->tx_buf, cnt);
474
475 remainder = trans->len % 4;
476 if (remainder > 0) {
477 reg_val = 0;
478 memcpy(&reg_val, trans->tx_buf + (cnt * 4), remainder);
479 writel(reg_val, mdata->base + SPI_TX_DATA_REG);
480 }
481
482 mtk_spi_enable_transfer(master);
483
455 return IRQ_HANDLED; 484 return IRQ_HANDLED;
456 } 485 }
457 486