]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
spi: spi-fsl-lpspi: Fix scldiv calculation
authorStefan Wahren <wahrenst@gmx.net>
Sun, 4 Aug 2024 11:36:11 +0000 (13:36 +0200)
committerMark Brown <broonie@kernel.org>
Wed, 7 Aug 2024 22:45:12 +0000 (23:45 +0100)
The effective SPI clock frequency should never exceed speed_hz
otherwise this might result in undefined behavior of the SPI device.

Currently the scldiv calculation could violate this constraint.
For the example parameters perclk_rate = 24 MHz and speed_hz = 7 MHz,
the function fsl_lpspi_set_bitrate will determine perscale = 0 and
scldiv = 1, which is a effective SPI clock of 8 MHz.

So fix this by rounding up the quotient of perclk_rate and speed_hz.
While this never change within the loop, we can pull this out.

Fixes: 5314987de5e5 ("spi: imx: add lpspi bus driver")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Link: https://patch.msgid.link/20240804113611.83613-1-wahrenst@gmx.net
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-fsl-lpspi.c

index 32baa14dfd83e5f93f81637ac5a4ce9fcbbc5456..be261ac09df823ae10cde7f141b6fe98355f6733 100644 (file)
@@ -296,7 +296,7 @@ static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi)
 static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
 {
        struct lpspi_config config = fsl_lpspi->config;
-       unsigned int perclk_rate, scldiv;
+       unsigned int perclk_rate, scldiv, div;
        u8 prescale;
 
        perclk_rate = clk_get_rate(fsl_lpspi->clk_per);
@@ -313,8 +313,10 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
                return -EINVAL;
        }
 
+       div = DIV_ROUND_UP(perclk_rate, config.speed_hz);
+
        for (prescale = 0; prescale < 8; prescale++) {
-               scldiv = perclk_rate / config.speed_hz / (1 << prescale) - 2;
+               scldiv = div / (1 << prescale) - 2;
                if (scldiv < 256) {
                        fsl_lpspi->config.prescale = prescale;
                        break;