diff options
author | Yun Zhou <yun.zhou@windriver.com> | 2022-02-17 22:12:34 +0800 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2022-02-28 13:36:16 +0000 |
commit | 6bb477df04366e0f69dd2f49e1ae1099069326bc (patch) | |
tree | 20f6f83702e1a8ace0991f1e20f2a46946ebc913 /drivers/spi/spi.c | |
parent | fcaaf76ed5f3bbf346db9e49d9d9c0978d8f8dce (diff) | |
download | linux-6bb477df04366e0f69dd2f49e1ae1099069326bc.tar.bz2 |
spi: use specific last_cs instead of last_cs_enable
Commit d40f0b6f2e21 instroduced last_cs_enable to avoid setting
chipselect if it's not necessary, but it also introduces a bug. The
chipselect may not be set correctly on multi-device SPI busses. The
reason is that we can't judge the chipselect by bool last_cs_enable,
since chipselect may be modified after other devices were accessed.
So we should record the specific state of chipselect in case of
confusion.
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Link: https://lore.kernel.org/r/20220217141234.72737-1-yun.zhou@windriver.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index cd4dc3131e17..6326e592fcfd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -926,13 +926,14 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) * Avoid calling into the driver (or doing delays) if the chip select * isn't actually changing from the last time this was called. */ - if (!force && (spi->controller->last_cs_enable == enable) && + if (!force && ((enable && spi->controller->last_cs == spi->chip_select) || + (!enable && spi->controller->last_cs != spi->chip_select)) && (spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH))) return; trace_spi_set_cs(spi, activate); - spi->controller->last_cs_enable = enable; + spi->controller->last_cs = enable ? spi->chip_select : -1; spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH; if ((spi->cs_gpiod || !spi->controller->set_cs_timing) && !activate) { @@ -3016,6 +3017,9 @@ int spi_register_controller(struct spi_controller *ctlr) goto free_bus_id; } + /* setting last_cs to -1 means no chip selected */ + ctlr->last_cs = -1; + status = device_add(&ctlr->dev); if (status < 0) goto free_bus_id; |