]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
spi: Correct SPI clock frequency setting in spi_mpc8xxx
authorErnst Schwab <eschwab@online.de>
Wed, 17 Feb 2010 04:02:57 +0000 (21:02 -0700)
committerGrant Likely <grant.likely@secretlab.ca>
Tue, 16 Feb 2010 21:26:58 +0000 (14:26 -0700)
Correct SPI clock frequency division factor rounding, preventing clock rates
higher than the maximum specified clock frequency being used.

When specifying spi-max-frequency = <10000000> in the device tree,
the resulting frequency was 11.1 MHz, with spibrg being 133333332.

According to the freescale data sheet [1], the spi clock rate is
spiclk = spibrg / (4 * (pm+1))

The existing code calculated
  pm = mpc8xxx_spi->spibrg / (hz * 4); pm--;
  resulting in pm = (int) (3.3333) - 1 = 2,
  resulting in spiclk = 133333332/(4*(2+1)) = 11111111

  With the fix,
   pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1; pm--;
   resulting in pm = (int) (4.3333) - 1 = 3,
   resulting in spiclk = 133333332/(4*(3+1)) = 8333333

   Without the fix, for every desired SPI frequency that
   is not exactly derivable from spibrg, pm will be too
   small due to rounding down, resulting in a too high SPI clock,
   so we need a pm which is one higher.

   For values that are exactly derivable, spibrg will
   be dividable by (hz*4) without remainder, and
   (int) ((spibrg-1)/(hz*4)) will be one lower than
   (int) (spibrg)/(hz*4), which is compensated by adding 1.
   For these values, the fixed version calculates the same pm
   as the unfixed version.

   For all values that are not exactly derivable,
   spibrg will be not dividable by (hz*4) without
   remainder, and (int) ((spibrg-1)/(hz*4)) will be
   the same as (int) (spibrg)/(hz*4), and the calculated pm will
   be one higher than calculated by the unfixed version.

References:
[1] http://www.freescale.com/files/32bit/doc/ref_manual/MPC8315ERM.pdf,
   page 22-10 -> 1398

Signed-off-by: Ernst Schwab <eschwab@online.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
drivers/spi/spi_mpc8xxx.c

index 08065fb15817b000c4f9c12a9e66eceedaa3d7aa..4f0cc9d457e04b6c115d08a72014e83ff4e5bd58 100644 (file)
@@ -365,7 +365,7 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 
        if ((mpc8xxx_spi->spibrg / hz) > 64) {
                cs->hw_mode |= SPMODE_DIV16;
-               pm = mpc8xxx_spi->spibrg / (hz * 64);
+               pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
 
                WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
                          "Will use %d Hz instead.\n", dev_name(&spi->dev),
@@ -373,7 +373,7 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                if (pm > 16)
                        pm = 16;
        } else
-               pm = mpc8xxx_spi->spibrg / (hz * 4);
+               pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
        if (pm)
                pm--;