- the memory optimization in fsl-spi
- the fix of the max speed setting bug in spidev
Oleksandr Suvorov (2):
spi: fsl-lpspi: remove unneeded array
spi: spidev: fix a max speed setting
drivers/spi/spi-fsl-lpspi.c | 7 ++-----
drivers/spi/spidev.c | 10 ++++++----
2 files changed, 8 insertions(+), 9 deletions(-)
--
2.24.1
SPI_IOC_WR_MAX_SPEED_HZ command always sets spi->max_speed_hz
to the initial value come from DT.
It leads to set a wrong max speed with IOCTL call.
Fix the logic of a max speed assignment.
Signed-off-by: Oleksandr Suvorov <[email protected]>
---
drivers/spi/spidev.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 1e217e3e9486..b9b3ac70eb18 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -449,11 +449,13 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
spi->max_speed_hz = tmp;
retval = spi_setup(spi);
- if (retval >= 0)
+ if (retval) {
+ spi->max_speed_hz = save;
+ } else {
spidev->speed_hz = tmp;
- else
- dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
- spi->max_speed_hz = save;
+ dev_dbg(&spi->dev, "%d Hz (max)\n",
+ spidev->speed_hz);
+ }
}
break;
--
2.24.1
- replace the array with the shift operation
- remove the extra comparing operation.
Signed-off-by: Oleksandr Suvorov <[email protected]>
---
drivers/spi/spi-fsl-lpspi.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index d0b8cc741a24..298329b781d2 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -86,8 +86,6 @@
#define TCR_RXMSK BIT(19)
#define TCR_TXMSK BIT(18)
-static int clkdivs[] = {1, 2, 4, 8, 16, 32, 64, 128};
-
struct lpspi_config {
u8 bpw;
u8 chip_select;
@@ -331,15 +329,14 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
}
for (prescale = 0; prescale < 8; prescale++) {
- scldiv = perclk_rate /
- (clkdivs[prescale] * config.speed_hz) - 2;
+ scldiv = perclk_rate / config.speed_hz / (1 << prescale) - 2;
if (scldiv < 256) {
fsl_lpspi->config.prescale = prescale;
break;
}
}
- if (prescale == 8 && scldiv >= 256)
+ if (scldiv >= 256)
return -EINVAL;
writel(scldiv | (scldiv << 8) | ((scldiv >> 1) << 16),
--
2.24.1
On Thu, Feb 20, 2020 at 02:11:46PM +0000, Oleksandr Suvorov wrote:
> Oleksandr Suvorov (2):
> spi: fsl-lpspi: remove unneeded array
> spi: spidev: fix a max speed setting
Please don't merge unrelated changes into a patch series, at best it's
confusing at worst it can result in unrelated patches holding each other
up.
On Thu, Feb 20, 2020 at 02:11:51PM +0000, Oleksandr Suvorov wrote:
> SPI_IOC_WR_MAX_SPEED_HZ command always sets spi->max_speed_hz
> to the initial value come from DT.
This is intentional. It's doing a call to spi_setup() then restoring
the original value, the goal being just to run spi_setup() with the new
value - it's not really a good idea to change the maximum speed in the
first place.
> It leads to set a wrong max speed with IOCTL call.
In what way does it lead to the wrong speed being set?
> Fix the logic of a max speed assignment.
If the expectation is that the default speed should be changed for the
device this should be handled at the spidev level rather than in the
core.
Hi Mark,
On Thu, Feb 20, 2020 at 8:42 PM Mark Brown <[email protected]> wrote:
>
> On Thu, Feb 20, 2020 at 02:11:51PM +0000, Oleksandr Suvorov wrote:
> > SPI_IOC_WR_MAX_SPEED_HZ command always sets spi->max_speed_hz
> > the initial value come from DT.
>
> This is intentional. It's doing a call to spi_setup() then restoring
> the original value, the goal being just to run spi_setup() with the new
> value - it's not really a good idea to change the maximum speed in the
> first place.
Now I see it.
>
> > It leads to set a wrong max speed with IOCTL call.
> In what way does it lead to the wrong speed being set?
After all, I reviewed the code and found out that the problem is not
in spidev_ioctl,
the problem is in spidev_message()'s debug message :)
The real code is ok:
drivers/spi/spidev.c: spidev_message():
...
k_tmp->speed_hz = u_tmp->speed_hz;
if (!k_tmp->speed_hz)
k_tmp->speed_hz = spidev->speed_hz;
...
but the debug message takes wrong value:
drivers/spi/spidev.c: spidev_message():
...
dev_info(&spidev->spi->dev,
" xfer len %u %s%s%s%dbits %u usec %uHz
(speed_hz=%d max_speed_hz=%d)\n",
u_tmp->len,
u_tmp->rx_buf ? "rx " : "",
u_tmp->tx_buf ? "tx " : "",
u_tmp->cs_change ? "cs " : "",
u_tmp->bits_per_word ? : spidev->spi->bits_per_word,
u_tmp->delay_usecs,
>>> u_tmp->speed_hz ? : spidev->spi->max_speed_hz);
...
It leads to debug messages like:
[ 1227.512806] spidev spi0.0: setup mode 0, 32 bits/w, 1000000 Hz max --> 0
[ 1227.541749] spidev spi0.0: xfer len 4096 tx 32bits 0 usec 10000000Hz
..
[ 1227.616165] spidev spi0.0: setup mode 0, 32 bits/w, 2000000 Hz max --> 0
[ 1227.645095] spidev spi0.0: xfer len 4096 tx 32bits 0 usec 10000000Hz
...
[ 1227.702714] spidev spi0.0: setup mode 0, 32 bits/w, 20000000 Hz max --> 0
[ 1227.731801] spidev spi0.0: xfer len 4096 tx 32bits 0 usec 10000000Hz
...
So if one passes the message (using ioctl instead of write to fd) with
empty speed_hz,
the debug message tells the wrong real speed. It forced me to think in
the wrong direction.
> > Fix the logic of a max speed assignment.
>
> If the expectation is that the default speed should be changed for the
> device this should be handled at the spidev level rather than in the
> core.
Agree. I fixed the wrong place :)
I'll replace this patch with better one.
Thanx!
--
Best regards
Oleksandr Suvorov
Toradex AG
Altsagenstrasse 5 | 6048 Horw/Luzern | Switzerland | T: +41 41 500
4800 (main line)
The patch
spi: fsl-lpspi: remove unneeded array
has been applied to the spi tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
From 2fa98705a9289c758b6154a22174aa8d4041a285 Mon Sep 17 00:00:00 2001
From: Oleksandr Suvorov <[email protected]>
Date: Thu, 20 Feb 2020 14:11:48 +0000
Subject: [PATCH] spi: fsl-lpspi: remove unneeded array
- replace the array with the shift operation
- remove the extra comparing operation.
Signed-off-by: Oleksandr Suvorov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mark Brown <[email protected]>
---
drivers/spi/spi-fsl-lpspi.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index d0b8cc741a24..298329b781d2 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -86,8 +86,6 @@
#define TCR_RXMSK BIT(19)
#define TCR_TXMSK BIT(18)
-static int clkdivs[] = {1, 2, 4, 8, 16, 32, 64, 128};
-
struct lpspi_config {
u8 bpw;
u8 chip_select;
@@ -331,15 +329,14 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
}
for (prescale = 0; prescale < 8; prescale++) {
- scldiv = perclk_rate /
- (clkdivs[prescale] * config.speed_hz) - 2;
+ scldiv = perclk_rate / config.speed_hz / (1 << prescale) - 2;
if (scldiv < 256) {
fsl_lpspi->config.prescale = prescale;
break;
}
}
- if (prescale == 8 && scldiv >= 256)
+ if (scldiv >= 256)
return -EINVAL;
writel(scldiv | (scldiv << 8) | ((scldiv >> 1) << 16),
--
2.20.1