aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/omap2_mcspi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-21 17:37:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-21 17:37:00 -0400
commit70ada77920723fbc2b35e9b301022fb1e166b41b (patch)
treef30f24135eff89020d8ae21d6c7a83cf5c812585 /drivers/spi/omap2_mcspi.c
parentb22793f7fdc38d73c4bb4299a313deef56dcfe66 (diff)
parent2764c500be0c1f057349ee6c81557239de060f87 (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: (53 commits) spi/omap2_mcspi: Verify TX reg is empty after TX only xfer with DMA spi/omap2_mcspi: disable channel after TX_ONLY transfer in PIO mode spi/bfin_spi: namespace local structs spi/bfin_spi: init early spi/bfin_spi: check per-transfer bits_per_word spi/bfin_spi: warn when CS is driven by hardware (CPHA=0) spi/bfin_spi: cs should be always low when a new transfer begins spi/bfin_spi: fix typo in comment spi/bfin_spi: reject unsupported SPI modes spi/bfin_spi: use dma_disable_irq_nosync() in irq handler spi/bfin_spi: combine duplicate SPI_CTL read/write logic spi/bfin_spi: reset ctl_reg bits when setup is run again on a device spi/bfin_spi: push all size checks into the transfer function spi/bfin_spi: use nosync when disabling the IRQ from the IRQ handler spi/bfin_spi: sync hardware state before reprogramming everything spi/bfin_spi: save/restore state when suspending/resuming spi/bfin_spi: redo GPIO CS handling Blackfin: SPI: expand SPI bitmasks spi/bfin_spi: use the SPI namespaced bit names spi/bfin_spi: drop extra memory we don't need ...
Diffstat (limited to 'drivers/spi/omap2_mcspi.c')
-rw-r--r--drivers/spi/omap2_mcspi.c81
1 files changed, 41 insertions, 40 deletions
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index b3a94ca0a75a..2a651e61bfbf 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
296 return 0; 296 return 0;
297} 297}
298 298
299static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
300{
301 unsigned long timeout;
302
303 timeout = jiffies + msecs_to_jiffies(1000);
304 while (!(__raw_readl(reg) & bit)) {
305 if (time_after(jiffies, timeout))
306 return -1;
307 cpu_relax();
308 }
309 return 0;
310}
311
299static unsigned 312static unsigned
300omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) 313omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
301{ 314{
@@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
309 u32 l; 322 u32 l;
310 u8 * rx; 323 u8 * rx;
311 const u8 * tx; 324 const u8 * tx;
325 void __iomem *chstat_reg;
312 326
313 mcspi = spi_master_get_devdata(spi->master); 327 mcspi = spi_master_get_devdata(spi->master);
314 mcspi_dma = &mcspi->dma_channels[spi->chip_select]; 328 mcspi_dma = &mcspi->dma_channels[spi->chip_select];
315 l = mcspi_cached_chconf0(spi); 329 l = mcspi_cached_chconf0(spi);
316 330
331 chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
332
317 count = xfer->len; 333 count = xfer->len;
318 c = count; 334 c = count;
319 word_len = cs->word_len; 335 word_len = cs->word_len;
@@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
382 if (tx != NULL) { 398 if (tx != NULL) {
383 wait_for_completion(&mcspi_dma->dma_tx_completion); 399 wait_for_completion(&mcspi_dma->dma_tx_completion);
384 dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE); 400 dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
401
402 /* for TX_ONLY mode, be sure all words have shifted out */
403 if (rx == NULL) {
404 if (mcspi_wait_for_reg_bit(chstat_reg,
405 OMAP2_MCSPI_CHSTAT_TXS) < 0)
406 dev_err(&spi->dev, "TXS timed out\n");
407 else if (mcspi_wait_for_reg_bit(chstat_reg,
408 OMAP2_MCSPI_CHSTAT_EOT) < 0)
409 dev_err(&spi->dev, "EOT timed out\n");
410 }
385 } 411 }
386 412
387 if (rx != NULL) { 413 if (rx != NULL) {
@@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
435 return count; 461 return count;
436} 462}
437 463
438static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
439{
440 unsigned long timeout;
441
442 timeout = jiffies + msecs_to_jiffies(1000);
443 while (!(__raw_readl(reg) & bit)) {
444 if (time_after(jiffies, timeout))
445 return -1;
446 cpu_relax();
447 }
448 return 0;
449}
450
451static unsigned 464static unsigned
452omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) 465omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
453{ 466{
@@ -489,10 +502,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
489 dev_err(&spi->dev, "TXS timed out\n"); 502 dev_err(&spi->dev, "TXS timed out\n");
490 goto out; 503 goto out;
491 } 504 }
492#ifdef VERBOSE 505 dev_vdbg(&spi->dev, "write-%d %02x\n",
493 dev_dbg(&spi->dev, "write-%d %02x\n",
494 word_len, *tx); 506 word_len, *tx);
495#endif
496 __raw_writel(*tx++, tx_reg); 507 __raw_writel(*tx++, tx_reg);
497 } 508 }
498 if (rx != NULL) { 509 if (rx != NULL) {
@@ -506,10 +517,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
506 (l & OMAP2_MCSPI_CHCONF_TURBO)) { 517 (l & OMAP2_MCSPI_CHCONF_TURBO)) {
507 omap2_mcspi_set_enable(spi, 0); 518 omap2_mcspi_set_enable(spi, 0);
508 *rx++ = __raw_readl(rx_reg); 519 *rx++ = __raw_readl(rx_reg);
509#ifdef VERBOSE 520 dev_vdbg(&spi->dev, "read-%d %02x\n",
510 dev_dbg(&spi->dev, "read-%d %02x\n",
511 word_len, *(rx - 1)); 521 word_len, *(rx - 1));
512#endif
513 if (mcspi_wait_for_reg_bit(chstat_reg, 522 if (mcspi_wait_for_reg_bit(chstat_reg,
514 OMAP2_MCSPI_CHSTAT_RXS) < 0) { 523 OMAP2_MCSPI_CHSTAT_RXS) < 0) {
515 dev_err(&spi->dev, 524 dev_err(&spi->dev,
@@ -522,10 +531,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
522 } 531 }
523 532
524 *rx++ = __raw_readl(rx_reg); 533 *rx++ = __raw_readl(rx_reg);
525#ifdef VERBOSE 534 dev_vdbg(&spi->dev, "read-%d %02x\n",
526 dev_dbg(&spi->dev, "read-%d %02x\n",
527 word_len, *(rx - 1)); 535 word_len, *(rx - 1));
528#endif
529 } 536 }
530 } while (c); 537 } while (c);
531 } else if (word_len <= 16) { 538 } else if (word_len <= 16) {
@@ -542,10 +549,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
542 dev_err(&spi->dev, "TXS timed out\n"); 549 dev_err(&spi->dev, "TXS timed out\n");
543 goto out; 550 goto out;
544 } 551 }
545#ifdef VERBOSE 552 dev_vdbg(&spi->dev, "write-%d %04x\n",
546 dev_dbg(&spi->dev, "write-%d %04x\n",
547 word_len, *tx); 553 word_len, *tx);
548#endif
549 __raw_writel(*tx++, tx_reg); 554 __raw_writel(*tx++, tx_reg);
550 } 555 }
551 if (rx != NULL) { 556 if (rx != NULL) {
@@ -559,10 +564,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
559 (l & OMAP2_MCSPI_CHCONF_TURBO)) { 564 (l & OMAP2_MCSPI_CHCONF_TURBO)) {
560 omap2_mcspi_set_enable(spi, 0); 565 omap2_mcspi_set_enable(spi, 0);
561 *rx++ = __raw_readl(rx_reg); 566 *rx++ = __raw_readl(rx_reg);
562#ifdef VERBOSE 567 dev_vdbg(&spi->dev, "read-%d %04x\n",
563 dev_dbg(&spi->dev, "read-%d %04x\n",
564 word_len, *(rx - 1)); 568 word_len, *(rx - 1));
565#endif
566 if (mcspi_wait_for_reg_bit(chstat_reg, 569 if (mcspi_wait_for_reg_bit(chstat_reg,
567 OMAP2_MCSPI_CHSTAT_RXS) < 0) { 570 OMAP2_MCSPI_CHSTAT_RXS) < 0) {
568 dev_err(&spi->dev, 571 dev_err(&spi->dev,
@@ -575,10 +578,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
575 } 578 }
576 579
577 *rx++ = __raw_readl(rx_reg); 580 *rx++ = __raw_readl(rx_reg);
578#ifdef VERBOSE 581 dev_vdbg(&spi->dev, "read-%d %04x\n",
579 dev_dbg(&spi->dev, "read-%d %04x\n",
580 word_len, *(rx - 1)); 582 word_len, *(rx - 1));
581#endif
582 } 583 }
583 } while (c); 584 } while (c);
584 } else if (word_len <= 32) { 585 } else if (word_len <= 32) {
@@ -595,10 +596,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
595 dev_err(&spi->dev, "TXS timed out\n"); 596 dev_err(&spi->dev, "TXS timed out\n");
596 goto out; 597 goto out;
597 } 598 }
598#ifdef VERBOSE 599 dev_vdbg(&spi->dev, "write-%d %08x\n",
599 dev_dbg(&spi->dev, "write-%d %08x\n",
600 word_len, *tx); 600 word_len, *tx);
601#endif
602 __raw_writel(*tx++, tx_reg); 601 __raw_writel(*tx++, tx_reg);
603 } 602 }
604 if (rx != NULL) { 603 if (rx != NULL) {
@@ -612,10 +611,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
612 (l & OMAP2_MCSPI_CHCONF_TURBO)) { 611 (l & OMAP2_MCSPI_CHCONF_TURBO)) {
613 omap2_mcspi_set_enable(spi, 0); 612 omap2_mcspi_set_enable(spi, 0);
614 *rx++ = __raw_readl(rx_reg); 613 *rx++ = __raw_readl(rx_reg);
615#ifdef VERBOSE 614 dev_vdbg(&spi->dev, "read-%d %08x\n",
616 dev_dbg(&spi->dev, "read-%d %08x\n",
617 word_len, *(rx - 1)); 615 word_len, *(rx - 1));
618#endif
619 if (mcspi_wait_for_reg_bit(chstat_reg, 616 if (mcspi_wait_for_reg_bit(chstat_reg,
620 OMAP2_MCSPI_CHSTAT_RXS) < 0) { 617 OMAP2_MCSPI_CHSTAT_RXS) < 0) {
621 dev_err(&spi->dev, 618 dev_err(&spi->dev,
@@ -628,10 +625,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
628 } 625 }
629 626
630 *rx++ = __raw_readl(rx_reg); 627 *rx++ = __raw_readl(rx_reg);
631#ifdef VERBOSE 628 dev_vdbg(&spi->dev, "read-%d %08x\n",
632 dev_dbg(&spi->dev, "read-%d %08x\n",
633 word_len, *(rx - 1)); 629 word_len, *(rx - 1));
634#endif
635 } 630 }
636 } while (c); 631 } while (c);
637 } 632 }
@@ -644,6 +639,12 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
644 } else if (mcspi_wait_for_reg_bit(chstat_reg, 639 } else if (mcspi_wait_for_reg_bit(chstat_reg,
645 OMAP2_MCSPI_CHSTAT_EOT) < 0) 640 OMAP2_MCSPI_CHSTAT_EOT) < 0)
646 dev_err(&spi->dev, "EOT timed out\n"); 641 dev_err(&spi->dev, "EOT timed out\n");
642
643 /* disable chan to purge rx datas received in TX_ONLY transfer,
644 * otherwise these rx datas will affect the direct following
645 * RX_ONLY transfer.
646 */
647 omap2_mcspi_set_enable(spi, 0);
647 } 648 }
648out: 649out:
649 omap2_mcspi_set_enable(spi, 1); 650 omap2_mcspi_set_enable(spi, 1);