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

Nikita Vasilev vasilevnikitad at gmail.com
Fri Mar 18 15:23:02 CET 2022


>From b779cf5353b1544675a3399ee73749906df1bfc3 Mon Sep 17 00:00:00 2001
From: Nikita Vasilev <vasilevnikitad at gmail.com>
Date: Fri, 18 Mar 2022 12:56:27 +0100
Subject: [PATCH] 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 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, &regs->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(&regs->cr, ZYNQ_SPI_CR_CS_MASK);
  cr = readl(&regs->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, &regs->cr);

  if (plat->activate_delay_us)
-- 
2.32.0


More information about the U-Boot mailing list