Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a44648b057f5331fe6c0e863dc693ed335490e7a
Commit:     a44648b057f5331fe6c0e863dc693ed335490e7a
Parent:     e24a4d1ee337e3a67a502f3f19cdec3ffc45ad05
Author:     Anton Vorontsov <[EMAIL PROTECTED]>
AuthorDate: Fri Aug 10 13:01:02 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Sat Aug 11 15:47:41 2007 -0700

    spi_mpc83xx: fix prescale modulus calculation
    
    Long ago I've noticed (but didn't pay much attention) that
    spi_mpc83xx using PM calculations that differs from what
    specs describe. I.e.
    
    u8 pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 4);
    
    While specs says: "The SPI baud rate generator clock source (either
    system clock or system clock divided by 16, depending on DIV16 bit) is
    divided by 4 * ([PM] + 1), a range from 4 to 64.".
    
    Thus " - 1" is missing in the spi_mpc83xx's formula.
    
    Why nobody noticed that bug? Probably because sysclk usually less then
    user expects, e.g. you expect 200 MHz, but real clock is 198 MHz,
    and integer rounding helps when this formula is used.
    
    Suppose it's SPI in QE, SYSCLK at 198 MHz, thus SPIBRG at 99MHz, 25 MHz
    requested.
    
    PM = (99MHz / ( 25 MHz * 4 )), PM == 0, output SPICLK will be 24.75 MHz
    
    At lower frequencies this bug is more noticeable, though.
    
    And this bug shows itself in all its beauty if SYSCLK is equal or a bit
    more than you expect (200 MHz SYSCLK, 100 MHz SPIBRG):
    PM = (100MHz / ( 25 MHz * 4 )), PM == 1, output SPICLK will be 12.625 MHz!
    
    Signed-off-by: Anton Vorontsov <[EMAIL PROTECTED]>
    Signed-off-by: David Brownell <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 drivers/spi/spi_mpc83xx.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index fe69e94..2adf856 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -148,6 +148,8 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, 
int value)
        if (value == BITBANG_CS_ACTIVE) {
                u32 regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
                u32 len = spi->bits_per_word;
+               u8 pm;
+
                if (len == 32)
                        len = 0;
                else
@@ -170,7 +172,7 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, 
int value)
                regval |= SPMODE_LEN(len);
 
                if ((mpc83xx_spi->spibrg / spi->max_speed_hz) >= 64) {
-                       u8 pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 64);
+                       pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 64) - 1;
                        if (pm > 0x0f) {
                                dev_err(&spi->dev, "Requested speed is too "
                                        "low: %d Hz. Will use %d Hz instead.\n",
@@ -180,7 +182,9 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, 
int value)
                        }
                        regval |= SPMODE_PM(pm) | SPMODE_DIV16;
                } else {
-                       u8 pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 4);
+                       pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 4);
+                       if (pm)
+                               pm--;
                        regval |= SPMODE_PM(pm);
                }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to