diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 17:37:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 17:37:00 -0400 |
commit | 70ada77920723fbc2b35e9b301022fb1e166b41b (patch) | |
tree | f30f24135eff89020d8ae21d6c7a83cf5c812585 /drivers/spi/omap2_mcspi.c | |
parent | b22793f7fdc38d73c4bb4299a313deef56dcfe66 (diff) | |
parent | 2764c500be0c1f057349ee6c81557239de060f87 (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.c | 81 |
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 | ||
299 | static 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 | |||
299 | static unsigned | 312 | static unsigned |
300 | omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | 313 | omap2_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 | ||
438 | static 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 | |||
451 | static unsigned | 464 | static unsigned |
452 | omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | 465 | omap2_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 | } |
648 | out: | 649 | out: |
649 | omap2_mcspi_set_enable(spi, 1); | 650 | omap2_mcspi_set_enable(spi, 1); |