| From 957f1174fc35b2df738b89bb4aa152a16a26f655 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 26 Jul 2021 12:01:02 +0200 |
| Subject: spi: imx: mx51-ecspi: Fix low-speed CONFIGREG delay calculation |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Marek Vasut <marex@denx.de> |
| |
| [ Upstream commit 53ca18acbe645656132fb5a329833db711067e54 ] |
| |
| The spi_imx->spi_bus_clk may be uninitialized and thus also zero in |
| mx51_ecspi_prepare_message(), which would lead to division by zero |
| in kernel. Since bitbang .setup_transfer callback which initializes |
| the spi_imx->spi_bus_clk is called after bitbang prepare_message |
| callback, iterate over all the transfers in spi_message, find the |
| one with lowest bus frequency, and use that bus frequency for the |
| delay calculation. |
| |
| Note that it is not possible to move this CONFIGREG delay back into |
| the .setup_transfer callback, because that is invoked too late, after |
| the GPIO chipselects were already configured. |
| |
| Fixes: 135cbd378eab ("spi: imx: mx51-ecspi: Reinstate low-speed CONFIGREG delay") |
| Signed-off-by: Marek Vasut <marex@denx.de> |
| Cc: Uwe Kleine-Kรถnig <u.kleine-koenig@pengutronix.de> |
| Cc: Mark Brown <broonie@kernel.org> |
| Link: https://lore.kernel.org/r/20210726100102.5188-1-marex@denx.de |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/spi/spi-imx.c | 16 +++++++++++++++- |
| 1 file changed, 15 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c |
| index 14cebcda0ccc..474d5a7fa95e 100644 |
| --- a/drivers/spi/spi-imx.c |
| +++ b/drivers/spi/spi-imx.c |
| @@ -497,7 +497,9 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, |
| struct spi_message *msg) |
| { |
| struct spi_device *spi = msg->spi; |
| + struct spi_transfer *xfer; |
| u32 ctrl = MX51_ECSPI_CTRL_ENABLE; |
| + u32 min_speed_hz = ~0U; |
| u32 testreg, delay; |
| u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); |
| |
| @@ -569,8 +571,20 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, |
| * be asserted before the SCLK polarity changes, which would disrupt |
| * the SPI communication as the device on the other end would consider |
| * the change of SCLK polarity as a clock tick already. |
| + * |
| + * Because spi_imx->spi_bus_clk is only set in bitbang prepare_message |
| + * callback, iterate over all the transfers in spi_message, find the |
| + * one with lowest bus frequency, and use that bus frequency for the |
| + * delay calculation. In case all transfers have speed_hz == 0, then |
| + * min_speed_hz is ~0 and the resulting delay is zero. |
| */ |
| - delay = (2 * 1000000) / spi_imx->spi_bus_clk; |
| + list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
| + if (!xfer->speed_hz) |
| + continue; |
| + min_speed_hz = min(xfer->speed_hz, min_speed_hz); |
| + } |
| + |
| + delay = (2 * 1000000) / min_speed_hz; |
| if (likely(delay < 10)) /* SCLK is faster than 100 kHz */ |
| udelay(delay); |
| else /* SCLK is _very_ slow */ |
| -- |
| 2.30.2 |
| |