Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <nathan.rossi@digi.com>
Link: https://lore.kernel.org/r/20210816050228.3223661-1-nathan@nathanrossi.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Nathan Rossi and committed by
Mark Brown
ed14666c 0395be96

+16 -6
+16 -6
drivers/spi/spi-orion.c
··· 328 328 static void orion_spi_set_cs(struct spi_device *spi, bool enable) 329 329 { 330 330 struct orion_spi *orion_spi; 331 + void __iomem *ctrl_reg; 332 + u32 val; 331 333 332 334 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); 333 341 334 342 /* 335 343 * If this line is using a GPIO to control chip select, this internal ··· 346 338 * as it is handled by a GPIO, but that doesn't matter. What we need 347 339 * is to deassert the old chip select and assert some other chip select. 348 340 */ 349 - orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK); 350 - orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 351 - ORION_SPI_CS(spi->chip_select)); 341 + val |= ORION_SPI_CS(spi->chip_select); 352 342 353 343 /* 354 344 * Chip select logic is inverted from spi_set_cs(). For lines using a ··· 356 350 * doesn't matter. 357 351 */ 358 352 if (!enable) 359 - orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1); 360 - else 361 - orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1); 353 + val |= 0x1; 354 + 355 + /* 356 + * To avoid toggling unwanted chip selects update the register 357 + * with a single write. 358 + */ 359 + writel(val, ctrl_reg); 362 360 } 363 361 364 362 static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)