diff options
author | Hannu Heikkinen <ext-hannu.m.heikkinen@nokia.com> | 2011-02-24 14:31:33 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-02-24 14:44:37 -0500 |
commit | 57d9c10dd91f942f836592f407d6351e2969548a (patch) | |
tree | 38ffc12947c93bf96de66b88d4c719913e0477f0 /drivers/spi | |
parent | 1648237dc2053bfd6ade3ce3dca3716d53cf9dcf (diff) |
spi/omap_mcspi: Off-by-one error in finding the right divisor
Off-by-one error, gave erroneous divisor value 16 if speed_hz is over zero but
less than OMAP2_MCSPI_MAX_FREQ / (1 << 15), that is, [1..1463].
Also few overly complex bit shifts in divisor fixed.
Also one dev_dgb line fixed, which indicated max speed exceeding transfer speed.
Introducing a new function omap2_mcspi_calc_divisor() for getting the right
divisor in omap2_mcspi_setup_transfer().
Signed-off-by: Phil Carmody <ext-phil.2.carmody@nokia.com>
Signed-off-by: Hannu Heikkinen <ext-hannu.m.heikkinen@nokia.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/omap2_mcspi.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index abb1ffbf3d20..1a2d0b8bdd6a 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
@@ -651,6 +651,17 @@ out: | |||
651 | return count - c; | 651 | return count - c; |
652 | } | 652 | } |
653 | 653 | ||
654 | static u32 omap2_mcspi_calc_divisor(u32 speed_hz) | ||
655 | { | ||
656 | u32 div; | ||
657 | |||
658 | for (div = 0; div < 15; div++) | ||
659 | if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div)) | ||
660 | return div; | ||
661 | |||
662 | return 15; | ||
663 | } | ||
664 | |||
654 | /* called only when no transfer is active to this device */ | 665 | /* called only when no transfer is active to this device */ |
655 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, | 666 | static int omap2_mcspi_setup_transfer(struct spi_device *spi, |
656 | struct spi_transfer *t) | 667 | struct spi_transfer *t) |
@@ -673,12 +684,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
673 | if (t && t->speed_hz) | 684 | if (t && t->speed_hz) |
674 | speed_hz = t->speed_hz; | 685 | speed_hz = t->speed_hz; |
675 | 686 | ||
676 | if (speed_hz) { | 687 | speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ); |
677 | while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div)) | 688 | div = omap2_mcspi_calc_divisor(speed_hz); |
678 | > speed_hz) | ||
679 | div++; | ||
680 | } else | ||
681 | div = 15; | ||
682 | 689 | ||
683 | l = mcspi_cached_chconf0(spi); | 690 | l = mcspi_cached_chconf0(spi); |
684 | 691 | ||
@@ -715,7 +722,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, | |||
715 | mcspi_write_chconf0(spi, l); | 722 | mcspi_write_chconf0(spi, l); |
716 | 723 | ||
717 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", | 724 | dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", |
718 | OMAP2_MCSPI_MAX_FREQ / (1 << div), | 725 | OMAP2_MCSPI_MAX_FREQ >> div, |
719 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", | 726 | (spi->mode & SPI_CPHA) ? "trailing" : "leading", |
720 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); | 727 | (spi->mode & SPI_CPOL) ? "inverted" : "normal"); |
721 | 728 | ||
@@ -1015,10 +1022,10 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m) | |||
1015 | t->bits_per_word); | 1022 | t->bits_per_word); |
1016 | return -EINVAL; | 1023 | return -EINVAL; |
1017 | } | 1024 | } |
1018 | if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) { | 1025 | if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { |
1019 | dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", | 1026 | dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n", |
1020 | t->speed_hz, | 1027 | t->speed_hz, |
1021 | OMAP2_MCSPI_MAX_FREQ/(1<<16)); | 1028 | OMAP2_MCSPI_MAX_FREQ >> 15); |
1022 | return -EINVAL; | 1029 | return -EINVAL; |
1023 | } | 1030 | } |
1024 | 1031 | ||