Skip to content

Commit ed14666

Browse files
Nathan Rossibroonie
authored andcommitted
spi: orion: Prevent incorrect chip select behaviour
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 0395be9 commit ed14666

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

drivers/spi/spi-orion.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,16 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
328328
static void orion_spi_set_cs(struct spi_device *spi, bool enable)
329329
{
330330
struct orion_spi *orion_spi;
331+
void __iomem *ctrl_reg;
332+
u32 val;
331333

332334
orion_spi = spi_master_get_devdata(spi->master);
335+
ctrl_reg = spi_reg(orion_spi, ORION_SPI_IF_CTRL_REG);
336+
337+
val = readl(ctrl_reg);
338+
339+
/* Clear existing chip-select and assertion state */
340+
val &= ~(ORION_SPI_CS_MASK | 0x1);
333341

334342
/*
335343
* 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)
338346
* as it is handled by a GPIO, but that doesn't matter. What we need
339347
* is to deassert the old chip select and assert some other chip select.
340348
*/
341-
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK);
342-
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG,
343-
ORION_SPI_CS(spi->chip_select));
349+
val |= ORION_SPI_CS(spi->chip_select);
344350

345351
/*
346352
* 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)
350356
* doesn't matter.
351357
*/
352358
if (!enable)
353-
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
354-
else
355-
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
359+
val |= 0x1;
360+
361+
/*
362+
* To avoid toggling unwanted chip selects update the register
363+
* with a single write.
364+
*/
365+
writel(val, ctrl_reg);
356366
}
357367

358368
static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)

0 commit comments

Comments
 (0)