[PATCH v3] spi: zynq_spi: add chip select decoder support
Nikita Vasilev
vasilevnikitad at gmail.com
Sun Mar 20 21:45:26 CET 2022
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 at gmail.com>
Cc: Jagan Teki <jteki at 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)
--
2.32.0
Changes for v3
- Still had some problems with spaces when sending patch via email. I
hope that I fixed it.
Changes for v2:
- I have made a mistake when was trying to send patch and all tabs
were gone. Since it's my first time when I send patches via email, I
have some problems with it.
More information about the U-Boot
mailing list