[PATCH 02/19] spi: cadence-qspi: reset the ospi controller
Tejas Bhumkar
tejas.arvind.bhumkar at amd.com
Mon Mar 11 18:22:32 CET 2024
From: T Karthik Reddy <t.karthik.reddy at amd.com>
The Cadence driver must switch between SDR and DTR modes as
directed by commands from the spi-nor framework. It should
avoid reinitializing SDR/DTR tuning if it has already been
completed.
Additionally, functionality has been added to reset the
controller when transitioning from DTR to SDR mode. This
reset is achieved using the reset_assert and reset_deassert
APIs for the OSPI controller. In cases where the ZYNQMP_FIRMWARE
configuration is disabled in mini U-Boot, the controller is
reset directly using register writes.
The configuration of the chip select in the Cadence QSPI driver
is now determined based on the flags received from the 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 | 63 ++++++++++++++++++++++++++++---
drivers/spi/cadence_qspi.h | 7 ++++
3 files changed, 94 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c
index 70682490e6..30abb7b431 100644
--- a/drivers/spi/cadence_ospi_versal.c
+++ b/drivers/spi/cadence_ospi_versal.c
@@ -151,6 +151,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 0a1257352a..dd6aef9ab5 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -148,7 +148,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;
}
@@ -173,7 +173,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
@@ -574,6 +574,9 @@ static int cadence_spi_setup_ddrmode(struct spi_slave *spi, const struct spi_mem
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;
@@ -584,7 +587,47 @@ static int cadence_spi_setup_ddrmode(struct spi_slave *spi, const struct spi_mem
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;
}
@@ -598,9 +641,19 @@ 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 (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) {
/*
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 6d7e31da50..d11209ffa8 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
@@ -56,6 +59,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)
****************************************************************************/
@@ -287,6 +292,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;
@@ -360,5 +366,6 @@ int cadence_qspi_versal_flash_reset(struct udevice *dev);
ofnode cadence_qspi_get_subnode(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