Commit 730bbfaf authored by Stefan Wahren's avatar Stefan Wahren Committed by Mark Brown

spi: spi-fsl-lpspi: Fix scldiv calculation

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: 5314987d ("spi: imx: add lpspi bus driver")
Signed-off-by: default avatarStefan Wahren <wahrenst@gmx.net>
Link: https://patch.msgid.link/20240804113611.83613-1-wahrenst@gmx.netSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent e4c4638b
...@@ -296,7 +296,7 @@ static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi) ...@@ -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) static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
{ {
struct lpspi_config config = fsl_lpspi->config; struct lpspi_config config = fsl_lpspi->config;
unsigned int perclk_rate, scldiv; unsigned int perclk_rate, scldiv, div;
u8 prescale; u8 prescale;
perclk_rate = clk_get_rate(fsl_lpspi->clk_per); 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) ...@@ -313,8 +313,10 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
return -EINVAL; return -EINVAL;
} }
div = DIV_ROUND_UP(perclk_rate, config.speed_hz);
for (prescale = 0; prescale < 8; prescale++) { for (prescale = 0; prescale < 8; prescale++) {
scldiv = perclk_rate / config.speed_hz / (1 << prescale) - 2; scldiv = div / (1 << prescale) - 2;
if (scldiv < 256) { if (scldiv < 256) {
fsl_lpspi->config.prescale = prescale; fsl_lpspi->config.prescale = prescale;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment