diff mbox series

spi: orion: Prevent incorrect chip select behaviour

Message ID 20210816050228.3223661-1-nathan@nathanrossi.com (mailing list archive)
State Accepted
Commit ed14666c3f877c4c2a428a92bfeebfba3a4cfe2e
Headers show
Series spi: orion: Prevent incorrect chip select behaviour | expand

Commit Message

Nathan Rossi Aug. 16, 2021, 5:02 a.m. UTC
From: Nathan Rossi <nathan.rossi@digi.com>

When clearing the chip-select mask, the controller will switch to chip
selecting the native CS0 line. Because the control register chip-select
mask is not updated in a single write this will cause undesirable
chip-selection of CS0 even when requesting to select other native
chip-select lines. This is additionally problematic as the chip-select
may still be asserted. With the ARMADA 38x SoC the controller will
assert both the desired native chip-select and CS0.

To avoid any undesirable behaviour with the chip-select lines, update
the control register with a single write. This avoids selecting CS0 and
causes the (de-)assert to apply at the same time.

Signed-off-by: Nathan Rossi <nathan.rossi@digi.com>
---
 drivers/spi/spi-orion.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

---
2.32.0

Comments

Mark Brown Aug. 16, 2021, 5:04 p.m. UTC | #1
On Mon, 16 Aug 2021 05:02:28 +0000, Nathan Rossi wrote:
> From: Nathan Rossi <nathan.rossi@digi.com>
> 
> When clearing the chip-select mask, the controller will switch to chip
> selecting the native CS0 line. Because the control register chip-select
> mask is not updated in a single write this will cause undesirable
> chip-selection of CS0 even when requesting to select other native
> chip-select lines. This is additionally problematic as the chip-select
> may still be asserted. With the ARMADA 38x SoC the controller will
> assert both the desired native chip-select and CS0.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: orion: Prevent incorrect chip select behaviour
      commit: ed14666c3f877c4c2a428a92bfeebfba3a4cfe2e

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
diff mbox series

Patch

diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 34b31aba39..e8de3cbbfb 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -328,8 +328,16 @@  orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 static void orion_spi_set_cs(struct spi_device *spi, bool enable)
 {
 	struct orion_spi *orion_spi;
+	void __iomem *ctrl_reg;
+	u32 val;
 
 	orion_spi = spi_master_get_devdata(spi->master);
+	ctrl_reg = spi_reg(orion_spi, ORION_SPI_IF_CTRL_REG);
+
+	val = readl(ctrl_reg);
+
+	/* Clear existing chip-select and assertion state */
+	val &= ~(ORION_SPI_CS_MASK | 0x1);
 
 	/*
 	 * If this line is using a GPIO to control chip select, this internal
@@ -338,9 +346,7 @@  static void orion_spi_set_cs(struct spi_device *spi, bool enable)
 	 * as it is handled by a GPIO, but that doesn't matter. What we need
 	 * is to deassert the old chip select and assert some other chip select.
 	 */
-	orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK);
-	orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG,
-			  ORION_SPI_CS(spi->chip_select));
+	val |= ORION_SPI_CS(spi->chip_select);
 
 	/*
 	 * Chip select logic is inverted from spi_set_cs(). For lines using a
@@ -350,9 +356,13 @@  static void orion_spi_set_cs(struct spi_device *spi, bool enable)
 	 * doesn't matter.
 	 */
 	if (!enable)
-		orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
-	else
-		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+		val |= 0x1;
+
+	/*
+	 * To avoid toggling unwanted chip selects update the register
+	 * with a single write.
+	 */
+	writel(val, ctrl_reg);
 }
 
 static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)