@@ -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)
{
@@ -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) {
/*
@@ -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__ */