atmel_spi: clean up baud rate divisor calculation
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>
Wed, 30 Apr 2008 07:52:17 +0000 (00:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Apr 2008 15:29:31 +0000 (08:29 -0700)
Make the baud rate divisor calculation code a bit more readable and add a
few comments.

Also fix wrong debug information being displayed when !new_1 and
max_speed_hz == 0.

[david-b@pacbell.net: fix it]
Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Cc: "Janesh Ramakrishnan" <jramakrishnan@neuropace.com>
Acked-by David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/spi/atmel_spi.c

index 02c8e305b14fd783e3b94a71d3c8b4d9c4ed9c68..e81d59d789108041fee33e62b22b82d14e34fef3 100644 (file)
@@ -497,7 +497,7 @@ static int atmel_spi_setup(struct spi_device *spi)
        struct atmel_spi        *as;
        u32                     scbr, csr;
        unsigned int            bits = spi->bits_per_word;
-       unsigned long           bus_hz, sck_hz;
+       unsigned long           bus_hz;
        unsigned int            npcs_pin;
        int                     ret;
 
@@ -536,14 +536,25 @@ static int atmel_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       /* speed zero convention is used by some upper layers */
+       /*
+        * Pre-new_1 chips start out at half the peripheral
+        * bus speed.
+        */
        bus_hz = clk_get_rate(as->clk);
+       if (!as->new_1)
+               bus_hz /= 2;
+
        if (spi->max_speed_hz) {
-               /* assume div32/fdiv/mbz == 0 */
-               if (!as->new_1)
-                       bus_hz /= 2;
-               scbr = ((bus_hz + spi->max_speed_hz - 1)
-                       / spi->max_speed_hz);
+               /*
+                * Calculate the lowest divider that satisfies the
+                * constraint, assuming div32/fdiv/mbz == 0.
+                */
+               scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
+
+               /*
+                * If the resulting divider doesn't fit into the
+                * register bitfield, we can't satisfy the constraint.
+                */
                if (scbr >= (1 << SPI_SCBR_SIZE)) {
                        dev_dbg(&spi->dev,
                                "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
@@ -551,8 +562,8 @@ static int atmel_spi_setup(struct spi_device *spi)
                        return -EINVAL;
                }
        } else
+               /* speed zero means "as slow as possible" */
                scbr = 0xff;
-       sck_hz = bus_hz / scbr;
 
        csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
        if (spi->mode & SPI_CPOL)
@@ -589,7 +600,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 
        dev_dbg(&spi->dev,
                "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
-               sck_hz, bits, spi->mode, spi->chip_select, csr);
+               bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
 
        spi_writel(as, CSR0 + 4 * spi->chip_select, csr);