diff options
Diffstat (limited to 'drivers/spi/spi-orion.c')
-rw-r--r-- | drivers/spi/spi-orion.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 34b31aba3981..e8de3cbbfb2a 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) |