ath79: replace chipselect workaround with a proper patch

Debugging the SPI CS issue with kernel 5.10 resulted in a better
understanding for the root cause and a proper patch with a better
explanation.

Exchange the old hack patch with a more efficient (and upstreamable)
solution.

Signed-off-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
David Bauer 2021-03-03 17:23:16 +01:00
parent f3f630145a
commit 82b9713ce8
2 changed files with 89 additions and 31 deletions

View File

@ -1,31 +0,0 @@
Upstream commit d40f0b6f2e21 ("spi: Avoid settingthe chip select if
we don't need to") causes the SPI CS only to be asserted once and not
if it's state stays the same.
This seems to cause problems with the SPI on the AR724x and the AR913x
(but not the AR71xx). AR934x and subsequent chips do not look affected.
ToDo:
- Analyze if this is a hardware bug or a bug in the software.
- Send a cleaned up patch upstream.
Signed-off-by: David Bauer <mail@david-bauer.net>
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -791,6 +791,7 @@ static void spi_set_cs(struct spi_device
{
bool enable1 = enable;
+#if 0
/*
* Avoid calling into the driver (or doing delays) if the chip select
* isn't actually changing from the last time this was called.
@@ -801,6 +802,7 @@ static void spi_set_cs(struct spi_device
spi->controller->last_cs_enable = enable;
spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH;
+#endif
if (!spi->controller->set_cs_timing) {
if (enable1)

View File

@ -0,0 +1,89 @@
From 4b7d7f85abac1e7ad9e8b745694e470f0729f527 Mon Sep 17 00:00:00 2001
From: David Bauer <mail@david-bauer.net>
Date: Wed, 3 Mar 2021 17:11:34 +0100
Subject: [PATCH] spi: sync up initial chipselect state
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 access condition. Set it to false everywhere except when called
from spi_setup to sync up the initial CS state.
Fixes commit d40f0b6f2e21 ("spi: Avoid setting the chip select if we don't
need to")
Signed-off-by: David Bauer <mail@david-bauer.net>
---
drivers/spi/spi.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -787,7 +787,7 @@ int spi_register_board_info(struct spi_b
/*-------------------------------------------------------------------------*/
-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;
@@ -795,7 +795,7 @@ static void spi_set_cs(struct spi_device
* 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;
@@ -1243,7 +1243,7 @@ static int spi_transfer_one_message(stru
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);
@@ -1311,9 +1311,9 @@ fallback_pio:
&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);
}
}
@@ -1322,7 +1322,7 @@ fallback_pio:
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;
@@ -3400,11 +3400,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);