The RTL838x and RTL839x SoCs have 4 chip selects, the RTL93xx SoCs 2. Configure the CS for a given transfer. The logic of the RTL_SPI_SFCSR_CSBx bits is that if the value of the bit is 0, then the corresponding CS line is pulled low, which activates/selects the chip. Signed-off-by: Birger Koblitz <mail@xxxxxxxxxxxxxxxxx> --- drivers/spi/spi-realtek-rtl.c | 39 ++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-realtek-rtl.c b/drivers/spi/spi-realtek-rtl.c index 287ecc34e1cc..5979233522f4 100644 --- a/drivers/spi/spi-realtek-rtl.c +++ b/drivers/spi/spi-realtek-rtl.c @@ -9,6 +9,7 @@ struct rtspi { void __iomem *base; u32 dev_flags; + u32 cs_all; }; /* SPI Flash Configuration Register */ @@ -20,6 +21,8 @@ struct rtspi { #define RTL_SPI_SFCSR 0x08 #define RTL_SPI_SFCSR_CSB0 BIT(31) #define RTL_SPI_SFCSR_CSB1 BIT(30) +#define RTL_SPI_SFCSR_CSB2 BIT(15) +#define RTL_SPI_SFCSR_CSB3 BIT(14) #define RTL_SPI_SFCSR_RDY BIT(27) #define RTL_SPI_SFCSR_CS BIT(24) #define RTL_SPI_SFCSR_LEN_MASK ~(0x03 << 28) @@ -38,14 +41,34 @@ struct rtspi { static void rt_set_cs(struct spi_device *spi, bool active) { struct rtspi *rtspi = spi_controller_get_devdata(spi->controller); + int cs = spi->chip_select; u32 value; + u32 cs_mask; - /* CS0 bit is active low */ value = readl(REG(RTL_SPI_SFCSR)); + value |= rtspi->cs_all | RTL_SPI_SFCSR_CS; + + switch (cs) { + case 0: + cs_mask = RTL_SPI_SFCSR_CSB0; + break; + case 1: + cs_mask = RTL_SPI_SFCSR_CSB1; + break; + case 2: + cs_mask = RTL_SPI_SFCSR_CSB2; + break; + case 3: + cs_mask = RTL_SPI_SFCSR_CSB3; + break; + } + + /* CS bits are active low */ if (active) - value |= RTL_SPI_SFCSR_CSB0; + value |= cs_mask; else - value &= ~RTL_SPI_SFCSR_CSB0; + value &= ~cs_mask; + writel(value, REG(RTL_SPI_SFCSR)); } @@ -144,11 +167,8 @@ static void init_hw(struct rtspi *rtspi) value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO; writel(value, REG(RTL_SPI_SFCR)); - value = readl(REG(RTL_SPI_SFCSR)); - /* Permanently disable CS1, since it's never used */ - value |= RTL_SPI_SFCSR_CSB1; - /* Select CS0 for use */ - value &= RTL_SPI_SFCSR_CS; + /* Disable CS0-CS3, enable CS */ + value = rtspi->cs_all | RTL_SPI_SFCSR_CS; writel(value, REG(RTL_SPI_SFCSR)); } @@ -183,6 +203,9 @@ static int realtek_rtl_spi_probe(struct platform_device *pdev) ctrl->set_cs = rt_set_cs; ctrl->transfer_one = transfer_one; ctrl->num_chipselect = rtspi->dev_flags & SPI_CSMAX_3?4:2; + rtspi->cs_all = RTL_SPI_SFCSR_CSB0 | RTL_SPI_SFCSR_CSB1; + if (rtspi->dev_flags & SPI_CSMAX_3) + rtspi->cs_all |= RTL_SPI_SFCSR_CSB2 | RTL_SPI_SFCSR_CSB3; err = devm_spi_register_controller(&pdev->dev, ctrl); if (err) { -- 2.25.1