diff options
Diffstat (limited to 'drivers/spi/omap2_mcspi.c')
-rw-r--r-- | drivers/spi/omap2_mcspi.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 36501adc125d..3a5ed06d3d2f 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
@@ -467,6 +467,9 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
467 | rx_reg = base + OMAP2_MCSPI_RX0; | 467 | rx_reg = base + OMAP2_MCSPI_RX0; |
468 | chstat_reg = base + OMAP2_MCSPI_CHSTAT0; | 468 | chstat_reg = base + OMAP2_MCSPI_CHSTAT0; |
469 | 469 | ||
470 | if (c < (word_len>>3)) | ||
471 | return 0; | ||
472 | |||
470 | if (word_len <= 8) { | 473 | if (word_len <= 8) { |
471 | u8 *rx; | 474 | u8 *rx; |
472 | const u8 *tx; | 475 | const u8 *tx; |
@@ -514,7 +517,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
514 | dev_vdbg(&spi->dev, "read-%d %02x\n", | 517 | dev_vdbg(&spi->dev, "read-%d %02x\n", |
515 | word_len, *(rx - 1)); | 518 | word_len, *(rx - 1)); |
516 | } | 519 | } |
517 | } while (c); | 520 | } while (c > (word_len>>3)); |
518 | } else if (word_len <= 16) { | 521 | } else if (word_len <= 16) { |
519 | u16 *rx; | 522 | u16 *rx; |
520 | const u16 *tx; | 523 | const u16 *tx; |
@@ -561,7 +564,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
561 | dev_vdbg(&spi->dev, "read-%d %04x\n", | 564 | dev_vdbg(&spi->dev, "read-%d %04x\n", |
562 | word_len, *(rx - 1)); | 565 | word_len, *(rx - 1)); |
563 | } | 566 | } |
564 | } while (c); | 567 | } while (c > (word_len>>3)); |
565 | } else if (word_len <= 32) { | 568 | } else if (word_len <= 32) { |
566 | u32 *rx; | 569 | u32 *rx; |
567 | const u32 *tx; | 570 | const u32 *tx; |
@@ -608,7 +611,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
608 | dev_vdbg(&spi->dev, "read-%d %08x\n", | 611 | dev_vdbg(&spi->dev, "read-%d %08x\n", |
609 | word_len, *(rx - 1)); | 612 | word_len, *(rx - 1)); |
610 | } | 613 | } |
611 | } while (c); | 614 | } while (c > (word_len>>3)); |
612 | } | 615 | } |
613 | 616 | ||
614 | /* for TX_ONLY mode, be sure all words have shifted out */ | 617 | /* for TX_ONLY mode, be sure all words have shifted out */ |
@@ -631,6 +634,17 @@ out: | |||
631 | return count - c; | 634 | return count - c; |
632 | } | 635 | } |
633 | 636 | ||
637 | static u32 omap2_mcspi_calc_divisor(u32 speed_hz) | ||
638 | { | ||
639 | u32 div; | ||
640 | |||
641 | for (div = 0; div < 15; div++) | ||
642 | if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div)) | ||
643 | return div; | ||
644 | |||
645 | return 15; | ||
646 | } | ||
647 | |||
634 | /* called only when no transfer is active to this device */ | 648 | /* called only when no transfer is active to this device */ |
635 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, | 649 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, |
636 | struct spi_transfer *t) | 650 | struct spi_transfer *t) |
@@ -653,12 +667,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
653 | if (t && t->speed_hz) | 667 | if (t && t->speed_hz) |
654 | speed_hz = t->speed_hz; | 668 | speed_hz = t->speed_hz; |
655 | 669 | ||
656 | if (speed_hz) { | 670 | speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); |
657 | while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div)) | 671 | div = omap2_mcspi_calc_divisor(speed_hz); |
658 | > speed_hz) | ||
659 | div++; | ||
660 | } else | ||
661 | div = 15; | ||
662 | 672 | ||
663 | l = mcspi_cached_chconf0(spi); | 673 | l = mcspi_cached_chconf0(spi); |
664 | 674 | ||
@@ -695,7 +705,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
695 | mcspi_write_chconf0(spi, l); | 705 | mcspi_write_chconf0(spi, l); |
696 | 706 | ||
697 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", | 707 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", |
698 | OMAP2_MCSPI_MAX_FREQ / (1 << div), | 708 | OMAP2_MCSPI_MAX_FREQ >> div, |
699 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", | 709 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", |
700 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); | 710 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); |
701 | 711 | ||
@@ -996,10 +1006,10 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
996 | t->bits_per_word); | 1006 | t->bits_per_word); |
997 | return -EINVAL; | 1007 | return -EINVAL; |
998 | } | 1008 | } |
999 | if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) { | 1009 | if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { |
1000 | dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", | 1010 | dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n", |
1001 | t->speed_hz, | 1011 | t->speed_hz, |
1002 | OMAP2_MCSPI_MAX_FREQ/(1<<16)); | 1012 | OMAP2_MCSPI_MAX_FREQ >> 15); |
1003 | return -EINVAL; | 1013 | return -EINVAL; |
1004 | } | 1014 | } |
1005 | 1015 | ||