aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-omap2-mcspi.c
diff options
context:
space:
mode:
authorIllia Smyrnov <illia.smyrnov@ti.com>2013-06-17 09:31:06 -0400
committerMark Brown <broonie@linaro.org>2013-06-17 12:17:23 -0400
commitd33f473dcd8e69321f001ba330d648f475b504c9 (patch)
tree00ff1bce2d3e9b005552269ef6aae3f3b03e9262 /drivers/spi/spi-omap2-mcspi.c
parent56cd5c1578135120d73a7054140855728f8cca36 (diff)
spi: omap2-mcspi: Add FIFO buffer support
The MCSPI controller has a built-in FIFO buffer to unload the DMA or interrupt handler and improve data throughput. This patch adds FIFO buffer support for SPI transfers in DMA mode. For SPI transfers in DMA mode, the largest possible FIFO buffer size will be calculated and set up. The FIFO won't be used for the SPI transfers in DMA mode if: calculated FIFO buffer size is less then 2 bytes or the FIFO buffer size isn't multiple of the SPI word length. Signed-off-by: Illia Smyrnov <illia.smyrnov@ti.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
-rw-r--r--drivers/spi/spi-omap2-mcspi.c147
1 files changed, 130 insertions, 17 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 5a93a0df551f..6802806d1f18 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -38,12 +38,15 @@
38#include <linux/pm_runtime.h> 38#include <linux/pm_runtime.h>
39#include <linux/of.h> 39#include <linux/of.h>
40#include <linux/of_device.h> 40#include <linux/of_device.h>
41#include <linux/gcd.h>
41 42
42#include <linux/spi/spi.h> 43#include <linux/spi/spi.h>
43 44
44#include <linux/platform_data/spi-omap2-mcspi.h> 45#include <linux/platform_data/spi-omap2-mcspi.h>
45 46
46#define OMAP2_MCSPI_MAX_FREQ 48000000 47#define OMAP2_MCSPI_MAX_FREQ 48000000
48#define OMAP2_MCSPI_MAX_FIFODEPTH 64
49#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF
47#define SPI_AUTOSUSPEND_TIMEOUT 2000 50#define SPI_AUTOSUSPEND_TIMEOUT 2000
48 51
49#define OMAP2_MCSPI_REVISION 0x00 52#define OMAP2_MCSPI_REVISION 0x00
@@ -53,6 +56,7 @@
53#define OMAP2_MCSPI_WAKEUPENABLE 0x20 56#define OMAP2_MCSPI_WAKEUPENABLE 0x20
54#define OMAP2_MCSPI_SYST 0x24 57#define OMAP2_MCSPI_SYST 0x24
55#define OMAP2_MCSPI_MODULCTRL 0x28 58#define OMAP2_MCSPI_MODULCTRL 0x28
59#define OMAP2_MCSPI_XFERLEVEL 0x7c
56 60
57/* per-channel banks, 0x14 bytes each, first is: */ 61/* per-channel banks, 0x14 bytes each, first is: */
58#define OMAP2_MCSPI_CHCONF0 0x2c 62#define OMAP2_MCSPI_CHCONF0 0x2c
@@ -62,6 +66,7 @@
62#define OMAP2_MCSPI_RX0 0x3c 66#define OMAP2_MCSPI_RX0 0x3c
63 67
64/* per-register bitmasks: */ 68/* per-register bitmasks: */
69#define OMAP2_MCSPI_IRQSTATUS_EOW BIT(17)
65 70
66#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0) 71#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0)
67#define OMAP2_MCSPI_MODULCTRL_MS BIT(2) 72#define OMAP2_MCSPI_MODULCTRL_MS BIT(2)
@@ -82,10 +87,13 @@
82#define OMAP2_MCSPI_CHCONF_IS BIT(18) 87#define OMAP2_MCSPI_CHCONF_IS BIT(18)
83#define OMAP2_MCSPI_CHCONF_TURBO BIT(19) 88#define OMAP2_MCSPI_CHCONF_TURBO BIT(19)
84#define OMAP2_MCSPI_CHCONF_FORCE BIT(20) 89#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
90#define OMAP2_MCSPI_CHCONF_FFET BIT(27)
91#define OMAP2_MCSPI_CHCONF_FFER BIT(28)
85 92
86#define OMAP2_MCSPI_CHSTAT_RXS BIT(0) 93#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
87#define OMAP2_MCSPI_CHSTAT_TXS BIT(1) 94#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
88#define OMAP2_MCSPI_CHSTAT_EOT BIT(2) 95#define OMAP2_MCSPI_CHSTAT_EOT BIT(2)
96#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3)
89 97
90#define OMAP2_MCSPI_CHCTRL_EN BIT(0) 98#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
91 99
@@ -128,6 +136,7 @@ struct omap2_mcspi {
128 struct omap2_mcspi_dma *dma_channels; 136 struct omap2_mcspi_dma *dma_channels;
129 struct device *dev; 137 struct device *dev;
130 struct omap2_mcspi_regs ctx; 138 struct omap2_mcspi_regs ctx;
139 int fifo_depth;
131 unsigned int pin_dir:1; 140 unsigned int pin_dir:1;
132}; 141};
133 142
@@ -257,6 +266,58 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master)
257 ctx->modulctrl = l; 266 ctx->modulctrl = l;
258} 267}
259 268
269static void omap2_mcspi_set_fifo(const struct spi_device *spi,
270 struct spi_transfer *t, int enable)
271{
272 struct spi_master *master = spi->master;
273 struct omap2_mcspi_cs *cs = spi->controller_state;
274 struct omap2_mcspi *mcspi;
275 unsigned int wcnt;
276 int fifo_depth, bytes_per_word;
277 u32 chconf, xferlevel;
278
279 mcspi = spi_master_get_devdata(master);
280
281 chconf = mcspi_cached_chconf0(spi);
282 if (enable) {
283 bytes_per_word = mcspi_bytes_per_word(cs->word_len);
284 if (t->len % bytes_per_word != 0)
285 goto disable_fifo;
286
287 fifo_depth = gcd(t->len, OMAP2_MCSPI_MAX_FIFODEPTH);
288 if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0)
289 goto disable_fifo;
290
291 wcnt = t->len / bytes_per_word;
292 if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT)
293 goto disable_fifo;
294
295 xferlevel = wcnt << 16;
296 if (t->rx_buf != NULL) {
297 chconf |= OMAP2_MCSPI_CHCONF_FFER;
298 xferlevel |= (fifo_depth - 1) << 8;
299 } else {
300 chconf |= OMAP2_MCSPI_CHCONF_FFET;
301 xferlevel |= fifo_depth - 1;
302 }
303
304 mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel);
305 mcspi_write_chconf0(spi, chconf);
306 mcspi->fifo_depth = fifo_depth;
307
308 return;
309 }
310
311disable_fifo:
312 if (t->rx_buf != NULL)
313 chconf &= ~OMAP2_MCSPI_CHCONF_FFER;
314 else
315 chconf &= ~OMAP2_MCSPI_CHCONF_FFET;
316
317 mcspi_write_chconf0(spi, chconf);
318 mcspi->fifo_depth = 0;
319}
320
260static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) 321static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
261{ 322{
262 struct spi_master *spi_cntrl = mcspi->master; 323 struct spi_master *spi_cntrl = mcspi->master;
@@ -373,7 +434,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
373{ 434{
374 struct omap2_mcspi *mcspi; 435 struct omap2_mcspi *mcspi;
375 struct omap2_mcspi_dma *mcspi_dma; 436 struct omap2_mcspi_dma *mcspi_dma;
376 unsigned int count; 437 unsigned int count, dma_count;
377 u32 l; 438 u32 l;
378 int elements = 0; 439 int elements = 0;
379 int word_len, element_count; 440 int word_len, element_count;
@@ -381,6 +442,11 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
381 mcspi = spi_master_get_devdata(spi->master); 442 mcspi = spi_master_get_devdata(spi->master);
382 mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 443 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
383 count = xfer->len; 444 count = xfer->len;
445 dma_count = xfer->len;
446
447 if (mcspi->fifo_depth == 0)
448 dma_count -= es;
449
384 word_len = cs->word_len; 450 word_len = cs->word_len;
385 l = mcspi_cached_chconf0(spi); 451 l = mcspi_cached_chconf0(spi);
386 452
@@ -394,16 +460,15 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
394 if (mcspi_dma->dma_rx) { 460 if (mcspi_dma->dma_rx) {
395 struct dma_async_tx_descriptor *tx; 461 struct dma_async_tx_descriptor *tx;
396 struct scatterlist sg; 462 struct scatterlist sg;
397 size_t len = xfer->len - es;
398 463
399 dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); 464 dmaengine_slave_config(mcspi_dma->dma_rx, &cfg);
400 465
401 if (l & OMAP2_MCSPI_CHCONF_TURBO) 466 if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0)
402 len -= es; 467 dma_count -= es;
403 468
404 sg_init_table(&sg, 1); 469 sg_init_table(&sg, 1);
405 sg_dma_address(&sg) = xfer->rx_dma; 470 sg_dma_address(&sg) = xfer->rx_dma;
406 sg_dma_len(&sg) = len; 471 sg_dma_len(&sg) = dma_count;
407 472
408 tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, 473 tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
409 DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | 474 DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |
@@ -423,6 +488,10 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
423 wait_for_completion(&mcspi_dma->dma_rx_completion); 488 wait_for_completion(&mcspi_dma->dma_rx_completion);
424 dma_unmap_single(mcspi->dev, xfer->rx_dma, count, 489 dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
425 DMA_FROM_DEVICE); 490 DMA_FROM_DEVICE);
491
492 if (mcspi->fifo_depth > 0)
493 return count;
494
426 omap2_mcspi_set_enable(spi, 0); 495 omap2_mcspi_set_enable(spi, 0);
427 496
428 elements = element_count - 1; 497 elements = element_count - 1;
@@ -481,7 +550,10 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
481 struct dma_slave_config cfg; 550 struct dma_slave_config cfg;
482 enum dma_slave_buswidth width; 551 enum dma_slave_buswidth width;
483 unsigned es; 552 unsigned es;
553 u32 burst;
484 void __iomem *chstat_reg; 554 void __iomem *chstat_reg;
555 void __iomem *irqstat_reg;
556 int wait_res;
485 557
486 mcspi = spi_master_get_devdata(spi->master); 558 mcspi = spi_master_get_devdata(spi->master);
487 mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 559 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
@@ -499,19 +571,27 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
499 es = 4; 571 es = 4;
500 } 572 }
501 573
574 count = xfer->len;
575 burst = 1;
576
577 if (mcspi->fifo_depth > 0) {
578 if (count > mcspi->fifo_depth)
579 burst = mcspi->fifo_depth / es;
580 else
581 burst = count / es;
582 }
583
502 memset(&cfg, 0, sizeof(cfg)); 584 memset(&cfg, 0, sizeof(cfg));
503 cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; 585 cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0;
504 cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; 586 cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
505 cfg.src_addr_width = width; 587 cfg.src_addr_width = width;
506 cfg.dst_addr_width = width; 588 cfg.dst_addr_width = width;
507 cfg.src_maxburst = 1; 589 cfg.src_maxburst = burst;
508 cfg.dst_maxburst = 1; 590 cfg.dst_maxburst = burst;
509 591
510 rx = xfer->rx_buf; 592 rx = xfer->rx_buf;
511 tx = xfer->tx_buf; 593 tx = xfer->tx_buf;
512 594
513 count = xfer->len;
514
515 if (tx != NULL) 595 if (tx != NULL)
516 omap2_mcspi_tx_dma(spi, xfer, cfg); 596 omap2_mcspi_tx_dma(spi, xfer, cfg);
517 597
@@ -519,18 +599,38 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
519 count = omap2_mcspi_rx_dma(spi, xfer, cfg, es); 599 count = omap2_mcspi_rx_dma(spi, xfer, cfg, es);
520 600
521 if (tx != NULL) { 601 if (tx != NULL) {
522 chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
523 wait_for_completion(&mcspi_dma->dma_tx_completion); 602 wait_for_completion(&mcspi_dma->dma_tx_completion);
524 dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len, 603 dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
525 DMA_TO_DEVICE); 604 DMA_TO_DEVICE);
526 605
606 if (mcspi->fifo_depth > 0) {
607 irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;
608
609 if (mcspi_wait_for_reg_bit(irqstat_reg,
610 OMAP2_MCSPI_IRQSTATUS_EOW) < 0)
611 dev_err(&spi->dev, "EOW timed out\n");
612
613 mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS,
614 OMAP2_MCSPI_IRQSTATUS_EOW);
615 }
616
527 /* for TX_ONLY mode, be sure all words have shifted out */ 617 /* for TX_ONLY mode, be sure all words have shifted out */
528 if (rx == NULL) { 618 if (rx == NULL) {
529 if (mcspi_wait_for_reg_bit(chstat_reg, 619 chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
530 OMAP2_MCSPI_CHSTAT_TXS) < 0) 620 if (mcspi->fifo_depth > 0) {
531 dev_err(&spi->dev, "TXS timed out\n"); 621 wait_res = mcspi_wait_for_reg_bit(chstat_reg,
532 else if (mcspi_wait_for_reg_bit(chstat_reg, 622 OMAP2_MCSPI_CHSTAT_TXFFE);
533 OMAP2_MCSPI_CHSTAT_EOT) < 0) 623 if (wait_res < 0)
624 dev_err(&spi->dev, "TXFFE timed out\n");
625 } else {
626 wait_res = mcspi_wait_for_reg_bit(chstat_reg,
627 OMAP2_MCSPI_CHSTAT_TXS);
628 if (wait_res < 0)
629 dev_err(&spi->dev, "TXS timed out\n");
630 }
631 if (wait_res >= 0 &&
632 (mcspi_wait_for_reg_bit(chstat_reg,
633 OMAP2_MCSPI_CHSTAT_EOT) < 0))
534 dev_err(&spi->dev, "EOT timed out\n"); 634 dev_err(&spi->dev, "EOT timed out\n");
535 } 635 }
536 } 636 }
@@ -957,7 +1057,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
957 cs = spi->controller_state; 1057 cs = spi->controller_state;
958 cd = spi->controller_data; 1058 cd = spi->controller_data;
959 1059
960 omap2_mcspi_set_enable(spi, 1); 1060 omap2_mcspi_set_enable(spi, 0);
961 list_for_each_entry(t, &m->transfers, transfer_list) { 1061 list_for_each_entry(t, &m->transfers, transfer_list) {
962 if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { 1062 if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
963 status = -EINVAL; 1063 status = -EINVAL;
@@ -1005,6 +1105,12 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
1005 if (t->len) { 1105 if (t->len) {
1006 unsigned count; 1106 unsigned count;
1007 1107
1108 if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
1109 (m->is_dma_mapped || t->len >= DMA_MIN_BYTES))
1110 omap2_mcspi_set_fifo(spi, t, 1);
1111
1112 omap2_mcspi_set_enable(spi, 1);
1113
1008 /* RX_ONLY mode needs dummy data in TX reg */ 1114 /* RX_ONLY mode needs dummy data in TX reg */
1009 if (t->tx_buf == NULL) 1115 if (t->tx_buf == NULL)
1010 __raw_writel(0, cs->base 1116 __raw_writel(0, cs->base
@@ -1031,6 +1137,11 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
1031 omap2_mcspi_force_cs(spi, 0); 1137 omap2_mcspi_force_cs(spi, 0);
1032 cs_active = 0; 1138 cs_active = 0;
1033 } 1139 }
1140
1141 omap2_mcspi_set_enable(spi, 0);
1142
1143 if (mcspi->fifo_depth > 0)
1144 omap2_mcspi_set_fifo(spi, t, 0);
1034 } 1145 }
1035 /* Restore defaults if they were overriden */ 1146 /* Restore defaults if they were overriden */
1036 if (par_override) { 1147 if (par_override) {
@@ -1051,8 +1162,10 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
1051 1162
1052 omap2_mcspi_set_enable(spi, 0); 1163 omap2_mcspi_set_enable(spi, 0);
1053 1164
1054 m->status = status; 1165 if (mcspi->fifo_depth > 0 && t)
1166 omap2_mcspi_set_fifo(spi, t, 0);
1055 1167
1168 m->status = status;
1056} 1169}
1057 1170
1058static int omap2_mcspi_transfer_one_message(struct spi_master *master, 1171static int omap2_mcspi_transfer_one_message(struct spi_master *master,