Message ID | 20210718211143.143557-1-marex@denx.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | spi: imx: mx51-ecspi: Fix low-speed CONFIGREG delay calculation | expand |
On Sun, Jul 18, 2021 at 11:11:43PM +0200, Marek Vasut wrote: > 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> > --- > Sigh ... > --- > drivers/spi/spi-imx.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) > > diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c > index 4aee3db6d6df..e18338fc3108 100644 > --- a/drivers/spi/spi-imx.c > +++ b/drivers/spi/spi-imx.c > @@ -505,7 +505,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); > > @@ -578,7 +580,13 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, > * the SPI communication as the device on the other end would consider > * the change of SCLK polarity as a clock tick already. > */ > - 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); > + } Can it happen that all transfer's spped_hz are zero? > + > + delay = (2 * 1000000) / min_speed_hz; Orthogonal to your change: I wonder if we need to round up the division here. > if (likely(delay < 10)) /* SCLK is faster than 100 kHz */ > udelay(delay); > else /* SCLK is _very_ slow */ Also the comments are wrong here. Is SCLK is 150 kHz we have min_speed_hz = 150000, right? Then delay becomes 13 and the slow freq path is entered. The right comment (when keeping delay = (2 * 1000000) / min_speed_hz) would be if (likely(delay < 10)) /* SCLK is faster than 181.818 kHz */ Best regards Uwe
On 7/19/21 10:20 AM, Uwe Kleine-König wrote: [...] >> @@ -505,7 +505,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); >> >> @@ -578,7 +580,13 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, >> * the SPI communication as the device on the other end would consider >> * the change of SCLK polarity as a clock tick already. >> */ >> - 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); >> + } > > Can it happen that all transfer's spped_hz are zero? I don't think so, what kind of spi_message would that be ? And even if it was zero, the delay would be 2000000/~0U , so zero as well, which I suppose is the best we can do in such a case. >> + >> + delay = (2 * 1000000) / min_speed_hz; > > Orthogonal to your change: I wonder if we need to round up the division > here. That is not necessary, since the delay here is twice what it needs to be (because we really do not know what happens in the hardware internally). >> if (likely(delay < 10)) /* SCLK is faster than 100 kHz */ >> udelay(delay); >> else /* SCLK is _very_ slow */ > > Also the comments are wrong here. Is SCLK is 150 kHz we have > min_speed_hz = 150000, right? Then delay becomes 13 and the slow freq > path is entered. The right comment (when keeping delay = (2 * 1000000) / > min_speed_hz) would be > > if (likely(delay < 10)) /* SCLK is faster than 181.818 kHz */ This whole if/else is in fact based on Documentation/timers/timers-howto.rst , which says use usleep_range() for delays above 10uS or so. The comment should be updated, but that's a separate patch.
On Mon, Jul 19, 2021 at 03:38:55PM +0200, Marek Vasut wrote: > On 7/19/21 10:20 AM, Uwe Kleine-König wrote: > > Can it happen that all transfer's spped_hz are zero? > I don't think so, what kind of spi_message would that be ? > And even if it was zero, the delay would be 2000000/~0U , so zero as well, > which I suppose is the best we can do in such a case. I can see that happening for a controller that didn't set any speed information with a driver that also didn't set any speed information, everything is just hoping that the default is fine but only the hardware is actually setting something. I've not gone and checked if anything ever insists there absolutely must be something specified in software.
On 7/19/21 11:12 PM, Mark Brown wrote: > On Mon, Jul 19, 2021 at 03:38:55PM +0200, Marek Vasut wrote: >> On 7/19/21 10:20 AM, Uwe Kleine-König wrote: > >>> Can it happen that all transfer's spped_hz are zero? > >> I don't think so, what kind of spi_message would that be ? > >> And even if it was zero, the delay would be 2000000/~0U , so zero as well, >> which I suppose is the best we can do in such a case. > > I can see that happening for a controller that didn't set any speed > information with a driver that also didn't set any speed information, > everything is just hoping that the default is fine but only the hardware > is actually setting something. I've not gone and checked if anything > ever insists there absolutely must be something specified in software. So, should I send a V2 here with any changes or is this one OK as-is ?
On Wed, Jul 21, 2021 at 10:18:35PM +0200, Marek Vasut wrote:
> So, should I send a V2 here with any changes or is this one OK as-is ?
It wasn't clear that Uwe was OK with the current version, I don't mind.
On Mon, Jul 26, 2021 at 02:46:06AM +0100, Mark Brown wrote: > On Wed, Jul 21, 2021 at 10:18:35PM +0200, Marek Vasut wrote: > > > So, should I send a V2 here with any changes or is this one OK as-is ? > > It wasn't clear that Uwe was OK with the current version, I don't mind. My concerns were mostly orthogonal to Marek's patch. The only (little critical) thing is: Can it happen that all transfer's speed_hz are zero? What happens with the code change is ok, when reading the code this looks this is by chance howver. So I would have added a comment describing that. But all in all I'm convinced that the change is an improvement, so no further concerns from my side. Best regards Uwe
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 4aee3db6d6df..e18338fc3108 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -505,7 +505,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); @@ -578,7 +580,13 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, * the SPI communication as the device on the other end would consider * the change of SCLK polarity as a clock tick already. */ - 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 */
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> --- Sigh ... --- drivers/spi/spi-imx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)