[PATCH v2 15/30] spi: cadence-qspi: Switch SDR/DTR using SPI_FLASH_DTR_ENABLE config

Tejas Bhumkar tejas.arvind.bhumkar at amd.com
Wed Dec 6 10:31:26 CET 2023


From: T Karthik Reddy <t.karthik.reddy at amd.com>

Cadence driver need to switch from SDR to DTR and vice versa based on
the commands from spi-nor framework and based on SPI_FLASH_DTR_ENABLE
config. If SPI_FLASH_DTR_ENABLE is not defined, do not switch to DTR
mode as it represents that controller does not support DTR. Also do
not reinitilize the SDR/DTR tuning if it is already done.
Also added the functionality to reset the controller when switching
from DTR to STR mode.
Use reset_assert, reset_deassert api's to reset the ospi controller.
In mini U-Boot case as ZYNQMP_FIRMWARE config is disabled, reset the
controller directly using register writes.

The configuration of the chip select in the Cadence QSPI driver is
now determined based on the flags received from SPI-NOR framework.

Signed-off-by: T Karthik Reddy <t.karthik.reddy at amd.com>
Signed-off-by: Tejas Bhumkar <tejas.arvind.bhumkar at amd.com>
---
 drivers/spi/cadence_ospi_versal.c | 29 +++++++++++++
 drivers/spi/cadence_qspi.c        | 69 ++++++++++++++++++++++++++++---
 drivers/spi/cadence_qspi.h        |  7 ++++
 3 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c
index 74994a690d..243de6efaf 100644
--- a/drivers/spi/cadence_ospi_versal.c
+++ b/drivers/spi/cadence_ospi_versal.c
@@ -154,6 +154,35 @@ int cadence_qspi_versal_set_dll_mode(struct udevice *dev)
 	return -ENOTSUPP;
 }
 
+int cadence_spi_versal_ctrl_reset(struct cadence_spi_priv *priv)
+{
+	int ret;
+
+	if (CONFIG_IS_ENABLED(ZYNQMP_FIRMWARE)) {
+		/* Assert ospi controller */
+		ret = reset_assert(priv->resets->resets);
+		if (ret)
+			return ret;
+
+		udelay(10);
+
+		/* Deassert ospi controller */
+		ret = reset_deassert(priv->resets->resets);
+		if (ret)
+			return ret;
+	} else {
+		/* Assert ospi controller */
+		setbits_le32((u32 *)OSPI_CTRL_RST, 1);
+
+		udelay(10);
+
+		/* Deassert ospi controller */
+		clrbits_le32((u32 *)OSPI_CTRL_RST, 1);
+	}
+
+	return 0;
+}
+
 #if defined(CONFIG_DM_GPIO)
 int cadence_qspi_versal_flash_reset(struct udevice *dev)
 {
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 32f91825fd..710c4a532d 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -154,7 +154,7 @@ static int spi_calibration(struct udevice *bus, uint hz)
 
 	/* just to ensure we do once only when speed or chip select change */
 	priv->qspi_calibrated_hz = hz;
-	priv->qspi_calibrated_cs = spi_chip_select(bus);
+	priv->qspi_calibrated_cs = priv->cs;
 
 	return 0;
 }
@@ -179,7 +179,7 @@ static int cadence_spi_set_speed(struct udevice *bus, uint hz)
 						  priv->read_delay);
 	} else if (priv->previous_hz != hz ||
 		   priv->qspi_calibrated_hz != hz ||
-		   priv->qspi_calibrated_cs != spi_chip_select(bus)) {
+		   priv->qspi_calibrated_cs != priv->cs) {
 		/*
 		 * Calibration required for different current SCLK speed,
 		 * requested SCLK speed or chip select
@@ -580,6 +580,9 @@ static int cadence_spi_setup_ddrmode(struct udevice *bus)
 	struct cadence_spi_priv *priv = dev_get_priv(bus);
 	int ret;
 
+	if (priv->ddr_init)
+		return 0;
+
 	ret = priv_setup_ddrmode(bus);
 	if (ret)
 		return ret;
@@ -590,7 +593,47 @@ static int cadence_spi_setup_ddrmode(struct udevice *bus)
 		printf("DDR tuning failed with error %d\n", ret);
 		return ret;
 	}
-	priv->ddr_init = 1;
+	priv->ddr_init = true;
+
+	return 0;
+}
+
+static int cadence_spi_setup_strmode(struct udevice *bus)
+{
+	struct cadence_spi_priv *priv = dev_get_priv(bus);
+	void *base = priv->regbase;
+	int ret;
+
+	if (!priv->ddr_init)
+		return 0;
+
+	/* Reset ospi controller */
+	ret = cadence_spi_versal_ctrl_reset(priv);
+	if (ret) {
+		printf("Cadence ctrl reset failed err: %d\n", ret);
+		return ret;
+	}
+
+	ret = wait_for_bit_le32(base + CQSPI_REG_CONFIG,
+				BIT(CQSPI_REG_CONFIG_IDLE_LSB),
+				1, CQSPI_TIMEOUT_MS, 0);
+	if (ret) {
+		printf("spi_wait_idle error : 0x%x\n", ret);
+		return ret;
+	}
+
+	cadence_qspi_apb_controller_init(priv);
+	priv->edge_mode = CQSPI_EDGE_MODE_SDR;
+	priv->extra_dummy = 0;
+	priv->previous_hz = 0;
+	priv->qspi_calibrated_hz = 0;
+
+	/* Setup default speed and calibrate */
+	ret = cadence_spi_set_speed(bus, 0);
+	if (ret)
+		return ret;
+
+	priv->ddr_init = false;
 
 	return 0;
 }
@@ -604,9 +647,22 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi,
 	int err = 0;
 	u32 mode;
 
+	if (!op->cmd.dtr) {
+		err = cadence_spi_setup_strmode(bus);
+		if (err)
+			return err;
+	}
+
+	if (!CONFIG_IS_ENABLED(SPI_FLASH_DTR_ENABLE) && op->cmd.dtr)
+		return 0;
+
+	if (spi->flags & SPI_XFER_U_PAGE)
+		priv->cs = CQSPI_CS1;
+	else
+		priv->cs = CQSPI_CS0;
+
 	/* Set Chip select */
-	cadence_qspi_apb_chipselect(base, spi_chip_select(spi->dev),
-				    priv->is_decoded_cs);
+	cadence_qspi_apb_chipselect(base, priv->cs, priv->is_decoded_cs);
 
 	if (op->data.dir == SPI_MEM_DATA_IN && op->data.buf.in) {
 		/*
@@ -655,7 +711,8 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi,
 		break;
 	}
 
-	if (!priv->ddr_init && (spi->flags & SPI_XFER_SET_DDR))
+	if (CONFIG_IS_ENABLED(SPI_FLASH_DTR_ENABLE) &&
+	    (spi->flags & SPI_XFER_SET_DDR))
 		err = cadence_spi_setup_ddrmode(bus);
 
 	return err;
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index eec090a7ed..505f59bed9 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -18,6 +18,9 @@
 #define CQSPI_DECODER_MAX_CS		16
 #define CQSPI_READ_CAPTURE_MAX_DELAY	16
 
+#define CQSPI_CS0				0
+#define CQSPI_CS1				1
+
 #define CQSPI_REG_POLL_US                       1 /* 1us */
 #define CQSPI_REG_RETRY                         10000
 #define CQSPI_POLL_IDLE_RETRY                   3
@@ -53,6 +56,8 @@
 #define CQSPI_READID_LOOP_MAX			10
 #define TERA_MACRO				1000000000000l
 
+#define OSPI_CTRL_RST				0xF1260304
+
 /****************************************************************************
  * Controller's configuration and status register (offset from QSPI_BASE)
  ****************************************************************************/
@@ -284,6 +289,7 @@ struct cadence_spi_priv {
 	size_t		data_len;
 
 	int		qspi_is_init;
+	unsigned int    cs;
 	unsigned int	qspi_calibrated_hz;
 	unsigned int	qspi_calibrated_cs;
 	unsigned int	previous_hz;
@@ -357,5 +363,6 @@ int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg);
 int cadence_qspi_versal_flash_reset(struct udevice *dev);
 int cadence_qspi_versal_set_dll_mode(struct udevice *dev);
 void cadence_qspi_apb_enable_linear_mode(bool enable);
+int cadence_spi_versal_ctrl_reset(struct cadence_spi_priv *priv);
 
 #endif /* __CADENCE_QSPI_H__ */
-- 
2.27.0



More information about the U-Boot mailing list