[PATCH v3] spi: zynq_spi: add chip select decoder support

Since zynq_spi device is compatible with Linux Cadence SPI driver, which supports chip select (CS) decoder, this patch adds the same logic for u-boot Zynq SPI driver. As a reference, I have used Xilinx Linux kernel 93dc4dbd16d (xilinx-v2020.2).
The SPI decoder feature has been tested on ZynqMP ARM processor and result has been compared with Linux Cadence SPI driver.
Signed-off-by: Nikita Vasilev vasilevnikitad@gmail.com Cc: Jagan Teki jteki@openedev.com --- drivers/spi/zynq_spi.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index b3e0858eb9..40a43612fb 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -29,6 +29,7 @@ DECLARE_GLOBAL_DATA_PTR; #define ZYNQ_SPI_CR_CPHA_MASK BIT(2) /* Clock phase */ #define ZYNQ_SPI_CR_CPOL_MASK BIT(1) /* Clock polarity */ #define ZYNQ_SPI_CR_MSTREN_MASK BIT(0) /* Mode select */ +#define ZYNQ_SPI_CR_PERI_SEL BIT(9) /* Peripheral select decode */ #define ZYNQ_SPI_IXR_RXNEMPTY_MASK BIT(4) /* RX_FIFO_not_empty */ #define ZYNQ_SPI_IXR_TXOW_MASK BIT(2) /* TX_FIFO_not_full */ #define ZYNQ_SPI_IXR_ALL_MASK GENMASK(6, 0) /* All IXR bits */ @@ -62,6 +63,7 @@ struct zynq_spi_plat { u32 speed_hz; uint deactivate_delay_us; /* Delay to wait after deactivate */ uint activate_delay_us; /* Delay to wait after activate */ + u32 is_decoded_cs; }; /* zynq spi priv */ @@ -87,10 +89,13 @@ static int zynq_spi_of_to_plat(struct udevice *bus) plat->activate_delay_us = fdtdec_get_int(blob, node, "spi-activate-delay", 0); + plat->is_decoded_cs = dev_read_u32_default(bus, "is-decoded-cs", 0); + return 0; } -static void zynq_spi_init_hw(struct zynq_spi_priv *priv) +static void zynq_spi_init_hw(struct zynq_spi_priv *priv, + struct zynq_spi_platdata const *plat) { struct zynq_spi_regs *regs = priv->regs; u32 confr; @@ -114,6 +119,10 @@ static void zynq_spi_init_hw(struct zynq_spi_priv *priv) confr = ZYNQ_SPI_CR_MCS_MASK | ZYNQ_SPI_CR_CS_MASK | ZYNQ_SPI_CR_MSTREN_MASK; confr &= ~ZYNQ_SPI_CR_MSA_MASK; + + if (plat->is_decoded_cs) + confr |= ZYNQ_SPI_CR_PERI_SEL; + writel(confr, ®s->cr); /* Enable SPI */ @@ -150,7 +159,7 @@ static int zynq_spi_probe(struct udevice *bus) } /* init the zynq spi hw */ - zynq_spi_init_hw(priv); + zynq_spi_init_hw(priv, plat); plat->frequency = clock; plat->speed_hz = plat->frequency / 2; @@ -178,13 +187,19 @@ static void spi_cs_activate(struct udevice *dev) clrbits_le32(®s->cr, ZYNQ_SPI_CR_CS_MASK); cr = readl(®s->cr); - /* - * CS cal logic: CS[13:10] - * xxx0 - cs0 - * xx01 - cs1 - * x011 - cs2 - */ - cr |= (~(1 << priv->cs) << ZYNQ_SPI_CR_SS_SHIFT) & ZYNQ_SPI_CR_CS_MASK; + + if (plat->is_decoded_cs) { + cr |= (priv->cs << ZYNQ_SPI_CR_SS_SHIFT) & ZYNQ_SPI_CR_CS_MASK; + } else { + /* + * CS cal logic: CS[13:10] + * xxx0 - cs0 + * xx01 - cs1 + * x011 - cs2 + */ + cr |= (~(1 << priv->cs) << ZYNQ_SPI_CR_SS_SHIFT) & ZYNQ_SPI_CR_CS_MASK; + } + writel(cr, ®s->cr); if (plat->activate_delay_us)
participants (1)
-
Nikita Vasilev