mirror of https://gitee.com/openkylin/linux.git
spi: Correct SPI clock frequency setting in spi_mpc8xxx
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>
This commit is contained in:
parent
8a349d4b13
commit
4f4517c45f
|
@ -365,7 +365,7 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
||||||
|
|
||||||
if ((mpc8xxx_spi->spibrg / hz) > 64) {
|
if ((mpc8xxx_spi->spibrg / hz) > 64) {
|
||||||
cs->hw_mode |= SPMODE_DIV16;
|
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. "
|
WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
|
||||||
"Will use %d Hz instead.\n", dev_name(&spi->dev),
|
"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)
|
if (pm > 16)
|
||||||
pm = 16;
|
pm = 16;
|
||||||
} else
|
} else
|
||||||
pm = mpc8xxx_spi->spibrg / (hz * 4);
|
pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
|
||||||
if (pm)
|
if (pm)
|
||||||
pm--;
|
pm--;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue