spi/omap_mcspi: Off-by-one error in finding the right divisor
authorHannu Heikkinen <ext-hannu.m.heikkinen@nokia.com>
Thu, 24 Feb 2011 19:31:33 +0000 (21:31 +0200)
committerGrant Likely <grant.likely@secretlab.ca>
Thu, 24 Feb 2011 19:44:37 +0000 (12:44 -0700)
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>
drivers/spi/omap2_mcspi.c

index abb1ffb..1a2d0b8 100644 (file)
@@ -651,6 +651,17 @@ out:
        return count - c;
 }
 
+static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
+{
+       u32 div;
+
+       for (div = 0; div < 15; div++)
+               if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
+                       return div;
+
+       return 15;
+}
+
 /* called only when no transfer is active to this device */
 static int omap2_mcspi_setup_transfer(struct spi_device *spi,
                struct spi_transfer *t)
@@ -673,12 +684,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
        if (t && t->speed_hz)
                speed_hz = t->speed_hz;
 
-       if (speed_hz) {
-               while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div))
-                                       > speed_hz)
-                       div++;
-       } else
-               div = 15;
+       speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
+       div = omap2_mcspi_calc_divisor(speed_hz);
 
        l = mcspi_cached_chconf0(spi);
 
@@ -715,7 +722,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
        mcspi_write_chconf0(spi, l);
 
        dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
-                       OMAP2_MCSPI_MAX_FREQ / (1 << div),
+                       OMAP2_MCSPI_MAX_FREQ >> div,
                        (spi->mode & SPI_CPHA) ? "trailing" : "leading",
                        (spi->mode & SPI_CPOL) ? "inverted" : "normal");
 
@@ -1015,10 +1022,10 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
                                        t->bits_per_word);
                        return -EINVAL;
                }
-               if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) {
-                       dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
-                                       t->speed_hz,
-                                       OMAP2_MCSPI_MAX_FREQ/(1<<16));
+               if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
+                       dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n",
+                               t->speed_hz,
+                               OMAP2_MCSPI_MAX_FREQ >> 15);
                        return -EINVAL;
                }