aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/omap2_mcspi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 15:04:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 15:04:17 -0400
commit702c0b04978ce316ec05f4d0a9c148fac124335b (patch)
tree3908c5821221d950a6b1a7e2e898899e63e7d437 /drivers/spi/omap2_mcspi.c
parentc19eb8f0d1bd442ed1aff0b413dd822620771c29 (diff)
parentbf6a67ee3427ab142136e03e90d0b67ecbca5ff2 (diff)
Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6
* 'next-spi' of git://git.secretlab.ca/git/linux-2.6: spi/xilinx: Fix compile error spi/davinci: Fix clock prescale factor computation spi: move bitbang txrx utility functions to private header spi/mpc5121: Add SPI master driver for MPC5121 PSC powerpc/mpc5121: move PSC FIFO memory init to platform code spi/ep93xx: implemented driver for Cirrus EP93xx SPI controller Documentation/spi/* compile warning fix spi/omap2_mcspi: Check params before dereference or use spi/omap2_mcspi: add turbo mode support spi/omap2_mcspi: change default DMA_MIN_BYTES value to 160 spi/pl022: fix stop queue procedure spi/pl022: add support for the PL023 derivate spi/pl022: fix up differences between ARM and ST versions spi/spi_mpc8xxx: Do not use map_tx_dma to unmap rx_dma spi/spi_mpc8xxx: Fix QE mode Litte Endian spi/spi_mpc8xxx: fix potential memory corruption.
Diffstat (limited to 'drivers/spi/omap2_mcspi.c')
-rw-r--r--drivers/spi/omap2_mcspi.c153
1 files changed, 123 insertions, 30 deletions
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index e0de0d0eedea..b3a94ca0a75a 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -38,7 +38,7 @@
38 38
39#include <plat/dma.h> 39#include <plat/dma.h>
40#include <plat/clock.h> 40#include <plat/clock.h>
41 41#include <plat/mcspi.h>
42 42
43#define OMAP2_MCSPI_MAX_FREQ 48000000 43#define OMAP2_MCSPI_MAX_FREQ 48000000
44 44
@@ -113,7 +113,7 @@ struct omap2_mcspi_dma {
113/* use PIO for small transfers, avoiding DMA setup/teardown overhead and 113/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
114 * cache operations; better heuristics consider wordsize and bitrate. 114 * cache operations; better heuristics consider wordsize and bitrate.
115 */ 115 */
116#define DMA_MIN_BYTES 8 116#define DMA_MIN_BYTES 160
117 117
118 118
119struct omap2_mcspi { 119struct omap2_mcspi {
@@ -229,6 +229,8 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
229 229
230 l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0; 230 l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
231 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l); 231 mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
232 /* Flash post-writes */
233 mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
232} 234}
233 235
234static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) 236static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
@@ -303,11 +305,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
303 unsigned int count, c; 305 unsigned int count, c;
304 unsigned long base, tx_reg, rx_reg; 306 unsigned long base, tx_reg, rx_reg;
305 int word_len, data_type, element_count; 307 int word_len, data_type, element_count;
308 int elements;
309 u32 l;
306 u8 * rx; 310 u8 * rx;
307 const u8 * tx; 311 const u8 * tx;
308 312
309 mcspi = spi_master_get_devdata(spi->master); 313 mcspi = spi_master_get_devdata(spi->master);
310 mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 314 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
315 l = mcspi_cached_chconf0(spi);
311 316
312 count = xfer->len; 317 count = xfer->len;
313 c = count; 318 c = count;
@@ -346,8 +351,12 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
346 } 351 }
347 352
348 if (rx != NULL) { 353 if (rx != NULL) {
354 elements = element_count - 1;
355 if (l & OMAP2_MCSPI_CHCONF_TURBO)
356 elements--;
357
349 omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel, 358 omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
350 data_type, element_count - 1, 1, 359 data_type, elements, 1,
351 OMAP_DMA_SYNC_ELEMENT, 360 OMAP_DMA_SYNC_ELEMENT,
352 mcspi_dma->dma_rx_sync_dev, 1); 361 mcspi_dma->dma_rx_sync_dev, 1);
353 362
@@ -379,17 +388,42 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
379 wait_for_completion(&mcspi_dma->dma_rx_completion); 388 wait_for_completion(&mcspi_dma->dma_rx_completion);
380 dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE); 389 dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
381 omap2_mcspi_set_enable(spi, 0); 390 omap2_mcspi_set_enable(spi, 0);
391
392 if (l & OMAP2_MCSPI_CHCONF_TURBO) {
393
394 if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
395 & OMAP2_MCSPI_CHSTAT_RXS)) {
396 u32 w;
397
398 w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
399 if (word_len <= 8)
400 ((u8 *)xfer->rx_buf)[elements++] = w;
401 else if (word_len <= 16)
402 ((u16 *)xfer->rx_buf)[elements++] = w;
403 else /* word_len <= 32 */
404 ((u32 *)xfer->rx_buf)[elements++] = w;
405 } else {
406 dev_err(&spi->dev,
407 "DMA RX penultimate word empty");
408 count -= (word_len <= 8) ? 2 :
409 (word_len <= 16) ? 4 :
410 /* word_len <= 32 */ 8;
411 omap2_mcspi_set_enable(spi, 1);
412 return count;
413 }
414 }
415
382 if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) 416 if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
383 & OMAP2_MCSPI_CHSTAT_RXS)) { 417 & OMAP2_MCSPI_CHSTAT_RXS)) {
384 u32 w; 418 u32 w;
385 419
386 w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); 420 w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
387 if (word_len <= 8) 421 if (word_len <= 8)
388 ((u8 *)xfer->rx_buf)[element_count - 1] = w; 422 ((u8 *)xfer->rx_buf)[elements] = w;
389 else if (word_len <= 16) 423 else if (word_len <= 16)
390 ((u16 *)xfer->rx_buf)[element_count - 1] = w; 424 ((u16 *)xfer->rx_buf)[elements] = w;
391 else /* word_len <= 32 */ 425 else /* word_len <= 32 */
392 ((u32 *)xfer->rx_buf)[element_count - 1] = w; 426 ((u32 *)xfer->rx_buf)[elements] = w;
393 } else { 427 } else {
394 dev_err(&spi->dev, "DMA RX last word empty"); 428 dev_err(&spi->dev, "DMA RX last word empty");
395 count -= (word_len <= 8) ? 1 : 429 count -= (word_len <= 8) ? 1 :
@@ -433,7 +467,6 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
433 word_len = cs->word_len; 467 word_len = cs->word_len;
434 468
435 l = mcspi_cached_chconf0(spi); 469 l = mcspi_cached_chconf0(spi);
436 l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
437 470
438 /* We store the pre-calculated register addresses on stack to speed 471 /* We store the pre-calculated register addresses on stack to speed
439 * up the transfer loop. */ 472 * up the transfer loop. */
@@ -468,11 +501,26 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
468 dev_err(&spi->dev, "RXS timed out\n"); 501 dev_err(&spi->dev, "RXS timed out\n");
469 goto out; 502 goto out;
470 } 503 }
471 /* prevent last RX_ONLY read from triggering 504
472 * more word i/o: switch to rx+tx 505 if (c == 1 && tx == NULL &&
473 */ 506 (l & OMAP2_MCSPI_CHCONF_TURBO)) {
474 if (c == 0 && tx == NULL) 507 omap2_mcspi_set_enable(spi, 0);
475 mcspi_write_chconf0(spi, l); 508 *rx++ = __raw_readl(rx_reg);
509#ifdef VERBOSE
510 dev_dbg(&spi->dev, "read-%d %02x\n",
511 word_len, *(rx - 1));
512#endif
513 if (mcspi_wait_for_reg_bit(chstat_reg,
514 OMAP2_MCSPI_CHSTAT_RXS) < 0) {
515 dev_err(&spi->dev,
516 "RXS timed out\n");
517 goto out;
518 }
519 c = 0;
520 } else if (c == 0 && tx == NULL) {
521 omap2_mcspi_set_enable(spi, 0);
522 }
523
476 *rx++ = __raw_readl(rx_reg); 524 *rx++ = __raw_readl(rx_reg);
477#ifdef VERBOSE 525#ifdef VERBOSE
478 dev_dbg(&spi->dev, "read-%d %02x\n", 526 dev_dbg(&spi->dev, "read-%d %02x\n",
@@ -506,11 +554,26 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
506 dev_err(&spi->dev, "RXS timed out\n"); 554 dev_err(&spi->dev, "RXS timed out\n");
507 goto out; 555 goto out;
508 } 556 }
509 /* prevent last RX_ONLY read from triggering 557
510 * more word i/o: switch to rx+tx 558 if (c == 2 && tx == NULL &&
511 */ 559 (l & OMAP2_MCSPI_CHCONF_TURBO)) {
512 if (c == 0 && tx == NULL) 560 omap2_mcspi_set_enable(spi, 0);
513 mcspi_write_chconf0(spi, l); 561 *rx++ = __raw_readl(rx_reg);
562#ifdef VERBOSE
563 dev_dbg(&spi->dev, "read-%d %04x\n",
564 word_len, *(rx - 1));
565#endif
566 if (mcspi_wait_for_reg_bit(chstat_reg,
567 OMAP2_MCSPI_CHSTAT_RXS) < 0) {
568 dev_err(&spi->dev,
569 "RXS timed out\n");
570 goto out;
571 }
572 c = 0;
573 } else if (c == 0 && tx == NULL) {
574 omap2_mcspi_set_enable(spi, 0);
575 }
576
514 *rx++ = __raw_readl(rx_reg); 577 *rx++ = __raw_readl(rx_reg);
515#ifdef VERBOSE 578#ifdef VERBOSE
516 dev_dbg(&spi->dev, "read-%d %04x\n", 579 dev_dbg(&spi->dev, "read-%d %04x\n",
@@ -544,11 +607,26 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
544 dev_err(&spi->dev, "RXS timed out\n"); 607 dev_err(&spi->dev, "RXS timed out\n");
545 goto out; 608 goto out;
546 } 609 }
547 /* prevent last RX_ONLY read from triggering 610
548 * more word i/o: switch to rx+tx 611 if (c == 4 && tx == NULL &&
549 */ 612 (l & OMAP2_MCSPI_CHCONF_TURBO)) {
550 if (c == 0 && tx == NULL) 613 omap2_mcspi_set_enable(spi, 0);
551 mcspi_write_chconf0(spi, l); 614 *rx++ = __raw_readl(rx_reg);
615#ifdef VERBOSE
616 dev_dbg(&spi->dev, "read-%d %08x\n",
617 word_len, *(rx - 1));
618#endif
619 if (mcspi_wait_for_reg_bit(chstat_reg,
620 OMAP2_MCSPI_CHSTAT_RXS) < 0) {
621 dev_err(&spi->dev,
622 "RXS timed out\n");
623 goto out;
624 }
625 c = 0;
626 } else if (c == 0 && tx == NULL) {
627 omap2_mcspi_set_enable(spi, 0);
628 }
629
552 *rx++ = __raw_readl(rx_reg); 630 *rx++ = __raw_readl(rx_reg);
553#ifdef VERBOSE 631#ifdef VERBOSE
554 dev_dbg(&spi->dev, "read-%d %08x\n", 632 dev_dbg(&spi->dev, "read-%d %08x\n",
@@ -568,6 +646,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
568 dev_err(&spi->dev, "EOT timed out\n"); 646 dev_err(&spi->dev, "EOT timed out\n");
569 } 647 }
570out: 648out:
649 omap2_mcspi_set_enable(spi, 1);
571 return count - c; 650 return count - c;
572} 651}
573 652
@@ -755,7 +834,6 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
755 struct omap2_mcspi_cs *cs; 834 struct omap2_mcspi_cs *cs;
756 835
757 mcspi = spi_master_get_devdata(spi->master); 836 mcspi = spi_master_get_devdata(spi->master);
758 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
759 837
760 if (spi->controller_state) { 838 if (spi->controller_state) {
761 /* Unlink controller state from context save list */ 839 /* Unlink controller state from context save list */
@@ -765,13 +843,17 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
765 kfree(spi->controller_state); 843 kfree(spi->controller_state);
766 } 844 }
767 845
768 if (mcspi_dma->dma_rx_channel != -1) { 846 if (spi->chip_select < spi->master->num_chipselect) {
769 omap_free_dma(mcspi_dma->dma_rx_channel); 847 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
770 mcspi_dma->dma_rx_channel = -1; 848
771 } 849 if (mcspi_dma->dma_rx_channel != -1) {
772 if (mcspi_dma->dma_tx_channel != -1) { 850 omap_free_dma(mcspi_dma->dma_rx_channel);
773 omap_free_dma(mcspi_dma->dma_tx_channel); 851 mcspi_dma->dma_rx_channel = -1;
774 mcspi_dma->dma_tx_channel = -1; 852 }
853 if (mcspi_dma->dma_tx_channel != -1) {
854 omap_free_dma(mcspi_dma->dma_tx_channel);
855 mcspi_dma->dma_tx_channel = -1;
856 }
775 } 857 }
776} 858}
777 859
@@ -797,6 +879,7 @@ static void omap2_mcspi_work(struct work_struct *work)
797 struct spi_transfer *t = NULL; 879 struct spi_transfer *t = NULL;
798 int cs_active = 0; 880 int cs_active = 0;
799 struct omap2_mcspi_cs *cs; 881 struct omap2_mcspi_cs *cs;
882 struct omap2_mcspi_device_config *cd;
800 int par_override = 0; 883 int par_override = 0;
801 int status = 0; 884 int status = 0;
802 u32 chconf; 885 u32 chconf;
@@ -809,6 +892,7 @@ static void omap2_mcspi_work(struct work_struct *work)
809 892
810 spi = m->spi; 893 spi = m->spi;
811 cs = spi->controller_state; 894 cs = spi->controller_state;
895 cd = spi->controller_data;
812 896
813 omap2_mcspi_set_enable(spi, 1); 897 omap2_mcspi_set_enable(spi, 1);
814 list_for_each_entry(t, &m->transfers, transfer_list) { 898 list_for_each_entry(t, &m->transfers, transfer_list) {
@@ -832,10 +916,19 @@ static void omap2_mcspi_work(struct work_struct *work)
832 916
833 chconf = mcspi_cached_chconf0(spi); 917 chconf = mcspi_cached_chconf0(spi);
834 chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; 918 chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
919 chconf &= ~OMAP2_MCSPI_CHCONF_TURBO;
920
835 if (t->tx_buf == NULL) 921 if (t->tx_buf == NULL)
836 chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY; 922 chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
837 else if (t->rx_buf == NULL) 923 else if (t->rx_buf == NULL)
838 chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY; 924 chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
925
926 if (cd && cd->turbo_mode && t->tx_buf == NULL) {
927 /* Turbo mode is for more than one word */
928 if (t->len > ((cs->word_len + 7) >> 3))
929 chconf |= OMAP2_MCSPI_CHCONF_TURBO;
930 }
931
839 mcspi_write_chconf0(spi, chconf); 932 mcspi_write_chconf0(spi, chconf);
840 933
841 if (t->len) { 934 if (t->len) {