Skip to content

Commit

Permalink
spi: sync up initial chipselect state
Browse files Browse the repository at this point in the history
When initially probing the SPI slave device, the call for disabling an
SPI device without the SPI_CS_HIGH flag is not applied, as the
condition for checking whether or not the state to be applied equals the
one currently set evaluates to true.

This however might not necessarily be the case, as the chipselect might
be active.

Add a force flag to spi_set_cs which allows to override this
early exit condition. Set it to false everywhere except when called
from spi_setup to sync up the initial CS state.

Fixes commit d40f0b6 ("spi: Avoid setting the chip select if we don't
need to")

Signed-off-by: David Bauer <mail@david-bauer.net>
Link: https://lore.kernel.org/r/20210416195956.121811-1-mail@david-bauer.net
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
David Bauer authored and Mark Brown committed Apr 19, 2021
1 parent 126bdb6 commit d347b4a
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions drivers/spi/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,15 +786,15 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)

/*-------------------------------------------------------------------------*/

static void spi_set_cs(struct spi_device *spi, bool enable)
static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
{
bool enable1 = enable;

/*
* Avoid calling into the driver (or doing delays) if the chip select
* isn't actually changing from the last time this was called.
*/
if ((spi->controller->last_cs_enable == enable) &&
if (!force && (spi->controller->last_cs_enable == enable) &&
(spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH)))
return;

Expand Down Expand Up @@ -1244,7 +1244,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_statistics *statm = &ctlr->statistics;
struct spi_statistics *stats = &msg->spi->statistics;

spi_set_cs(msg->spi, true);
spi_set_cs(msg->spi, true, false);

SPI_STATISTICS_INCREMENT_FIELD(statm, messages);
SPI_STATISTICS_INCREMENT_FIELD(stats, messages);
Expand Down Expand Up @@ -1312,9 +1312,9 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
&msg->transfers)) {
keep_cs = true;
} else {
spi_set_cs(msg->spi, false);
spi_set_cs(msg->spi, false, false);
_spi_transfer_cs_change_delay(msg, xfer);
spi_set_cs(msg->spi, true);
spi_set_cs(msg->spi, true, false);
}
}

Expand All @@ -1323,7 +1323,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,

out:
if (ret != 0 || !keep_cs)
spi_set_cs(msg->spi, false);
spi_set_cs(msg->spi, false, false);

if (msg->status == -EINPROGRESS)
msg->status = ret;
Expand Down Expand Up @@ -3399,11 +3399,11 @@ int spi_setup(struct spi_device *spi)
*/
status = 0;

spi_set_cs(spi, false);
spi_set_cs(spi, false, true);
pm_runtime_mark_last_busy(spi->controller->dev.parent);
pm_runtime_put_autosuspend(spi->controller->dev.parent);
} else {
spi_set_cs(spi, false);
spi_set_cs(spi, false, true);
}

mutex_unlock(&spi->controller->io_mutex);
Expand Down

0 comments on commit d347b4a

Please sign in to comment.