summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorVignesh R <vigneshr@ti.com>2017-04-11 07:52:25 -0400
committerMark Brown <broonie@kernel.org>2017-04-21 13:03:53 -0400
commitc687c46e9e4527c4b4d82bc3cca58c1b08bcfb83 (patch)
tree1e7db7fdf3adb9e07d1e528c277c84fe54f41c51 /drivers/spi
parent2bca34455b257d75080d87e800ae14afe49001bf (diff)
spi: spi-ti-qspi: Use bounce buffer if read buffer is not DMA'ble
Flash filesystems like JFFS2, UBIFS and MTD block layer can provide vmalloc'd or kmap'd buffers that cannot be mapped using dma_map_sg() and can potentially be in memory region above 32bit addressable region(ie buffers belonging to memory region backed by LPAE) of DMA, implement spi_flash_can_dma() interface to inform SPI core not to map such buffers. When buffers are not mapped for DMA, then use a pre allocated bounce buffer(64K = typical flash erase sector size) to read from flash and then do a copy to actual destination buffer. This is approach is much faster than using memcpy using CPU and also reduces CPU load. With this patch, UBIFS read speed is ~18MB/s and CPU utilization <20% on DRA74 Rev H EVM. Performance degradation is negligible when compared with non bounce buffer case while using UBIFS. Signed-off-by: Vignesh R <vigneshr@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-ti-qspi.c66
1 files changed, 59 insertions, 7 deletions
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 804914ebfd9d..23a06148b8ae 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -33,6 +33,7 @@
33#include <linux/pinctrl/consumer.h> 33#include <linux/pinctrl/consumer.h>
34#include <linux/mfd/syscon.h> 34#include <linux/mfd/syscon.h>
35#include <linux/regmap.h> 35#include <linux/regmap.h>
36#include <linux/sizes.h>
36 37
37#include <linux/spi/spi.h> 38#include <linux/spi/spi.h>
38 39
@@ -57,6 +58,8 @@ struct ti_qspi {
57 struct ti_qspi_regs ctx_reg; 58 struct ti_qspi_regs ctx_reg;
58 59
59 dma_addr_t mmap_phys_base; 60 dma_addr_t mmap_phys_base;
61 dma_addr_t rx_bb_dma_addr;
62 void *rx_bb_addr;
60 struct dma_chan *rx_chan; 63 struct dma_chan *rx_chan;
61 64
62 u32 spi_max_frequency; 65 u32 spi_max_frequency;
@@ -126,6 +129,8 @@ struct ti_qspi {
126#define QSPI_SETUP_ADDR_SHIFT 8 129#define QSPI_SETUP_ADDR_SHIFT 8
127#define QSPI_SETUP_DUMMY_SHIFT 10 130#define QSPI_SETUP_DUMMY_SHIFT 10
128 131
132#define QSPI_DMA_BUFFER_SIZE SZ_64K
133
129static inline unsigned long ti_qspi_read(struct ti_qspi *qspi, 134static inline unsigned long ti_qspi_read(struct ti_qspi *qspi,
130 unsigned long reg) 135 unsigned long reg)
131{ 136{
@@ -429,6 +434,35 @@ static int ti_qspi_dma_xfer(struct ti_qspi *qspi, dma_addr_t dma_dst,
429 return 0; 434 return 0;
430} 435}
431 436
437static int ti_qspi_dma_bounce_buffer(struct ti_qspi *qspi,
438 struct spi_flash_read_message *msg)
439{
440 size_t readsize = msg->len;
441 void *to = msg->buf;
442 dma_addr_t dma_src = qspi->mmap_phys_base + msg->from;
443 int ret = 0;
444
445 /*
446 * Use bounce buffer as FS like jffs2, ubifs may pass
447 * buffers that does not belong to kernel lowmem region.
448 */
449 while (readsize != 0) {
450 size_t xfer_len = min_t(size_t, QSPI_DMA_BUFFER_SIZE,
451 readsize);
452
453 ret = ti_qspi_dma_xfer(qspi, qspi->rx_bb_dma_addr,
454 dma_src, xfer_len);
455 if (ret != 0)
456 return ret;
457 memcpy(to, qspi->rx_bb_addr, xfer_len);
458 readsize -= xfer_len;
459 dma_src += xfer_len;
460 to += xfer_len;
461 }
462
463 return ret;
464}
465
432static int ti_qspi_dma_xfer_sg(struct ti_qspi *qspi, struct sg_table rx_sg, 466static int ti_qspi_dma_xfer_sg(struct ti_qspi *qspi, struct sg_table rx_sg,
433 loff_t from) 467 loff_t from)
434{ 468{
@@ -496,6 +530,12 @@ static void ti_qspi_setup_mmap_read(struct spi_device *spi,
496 QSPI_SPI_SETUP_REG(spi->chip_select)); 530 QSPI_SPI_SETUP_REG(spi->chip_select));
497} 531}
498 532
533static bool ti_qspi_spi_flash_can_dma(struct spi_device *spi,
534 struct spi_flash_read_message *msg)
535{
536 return virt_addr_valid(msg->buf);
537}
538
499static int ti_qspi_spi_flash_read(struct spi_device *spi, 539static int ti_qspi_spi_flash_read(struct spi_device *spi,
500 struct spi_flash_read_message *msg) 540 struct spi_flash_read_message *msg)
501{ 541{
@@ -509,15 +549,12 @@ static int ti_qspi_spi_flash_read(struct spi_device *spi,
509 ti_qspi_setup_mmap_read(spi, msg); 549 ti_qspi_setup_mmap_read(spi, msg);
510 550
511 if (qspi->rx_chan) { 551 if (qspi->rx_chan) {
512 if (msg->cur_msg_mapped) { 552 if (msg->cur_msg_mapped)
513 ret = ti_qspi_dma_xfer_sg(qspi, msg->rx_sg, msg->from); 553 ret = ti_qspi_dma_xfer_sg(qspi, msg->rx_sg, msg->from);
514 if (ret) 554 else
515 goto err_unlock; 555 ret = ti_qspi_dma_bounce_buffer(qspi, msg);
516 } else { 556 if (ret)
517 dev_err(qspi->dev, "Invalid address for DMA\n");
518 ret = -EIO;
519 goto err_unlock; 557 goto err_unlock;
520 }
521 } else { 558 } else {
522 memcpy_fromio(msg->buf, qspi->mmap_base + msg->from, msg->len); 559 memcpy_fromio(msg->buf, qspi->mmap_base + msg->from, msg->len);
523 } 560 }
@@ -718,6 +755,17 @@ static int ti_qspi_probe(struct platform_device *pdev)
718 ret = 0; 755 ret = 0;
719 goto no_dma; 756 goto no_dma;
720 } 757 }
758 qspi->rx_bb_addr = dma_alloc_coherent(qspi->dev,
759 QSPI_DMA_BUFFER_SIZE,
760 &qspi->rx_bb_dma_addr,
761 GFP_KERNEL | GFP_DMA);
762 if (!qspi->rx_bb_addr) {
763 dev_err(qspi->dev,
764 "dma_alloc_coherent failed, using PIO mode\n");
765 dma_release_channel(qspi->rx_chan);
766 goto no_dma;
767 }
768 master->spi_flash_can_dma = ti_qspi_spi_flash_can_dma;
721 master->dma_rx = qspi->rx_chan; 769 master->dma_rx = qspi->rx_chan;
722 init_completion(&qspi->transfer_complete); 770 init_completion(&qspi->transfer_complete);
723 if (res_mmap) 771 if (res_mmap)
@@ -757,6 +805,10 @@ static int ti_qspi_remove(struct platform_device *pdev)
757 pm_runtime_put_sync(&pdev->dev); 805 pm_runtime_put_sync(&pdev->dev);
758 pm_runtime_disable(&pdev->dev); 806 pm_runtime_disable(&pdev->dev);
759 807
808 if (qspi->rx_bb_addr)
809 dma_free_coherent(qspi->dev, QSPI_DMA_BUFFER_SIZE,
810 qspi->rx_bb_addr,
811 qspi->rx_bb_dma_addr);
760 if (qspi->rx_chan) 812 if (qspi->rx_chan)
761 dma_release_channel(qspi->rx_chan); 813 dma_release_channel(qspi->rx_chan);
762 814