From: Ian Roberts <ian.robe...@timesys.com>

On some SOCs (eg sc59x), attempting to use too high of a Read
Delay Capture value can cause the controller DMA to lock up. Thus,
add a device tree configuration property to allow controlling
the max Read Delay Capture value.

Co-developed-by: Nathan Barrett-Morrison <nathan.morri...@timesys.com>
Signed-off-by: Nathan Barrett-Morrison <nathan.morri...@timesys.com>
Signed-off-by: Greg Malysa <greg.mal...@timesys.com>
Signed-off-by: Ian Roberts <ian.robe...@timesys.com>
---

 doc/device-tree-bindings/spi/spi-cadence.txt | 2 ++
 drivers/spi/cadence_qspi.c                   | 9 ++++++++-
 drivers/spi/cadence_qspi.h                   | 2 ++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/doc/device-tree-bindings/spi/spi-cadence.txt 
b/doc/device-tree-bindings/spi/spi-cadence.txt
index 69e02c1c4b..9bd7ef8bed 100644
--- a/doc/device-tree-bindings/spi/spi-cadence.txt
+++ b/doc/device-tree-bindings/spi/spi-cadence.txt
@@ -29,3 +29,5 @@ connected flash properties
                          select (n_ss_out).
 - cdns,tslch-ns                : Delay in master reference clocks between 
setting
                          n_ss_out low and first bit transfer
+- cdns,max-read-delay  : Max safe value to use for the read capture delay
+                         during auto calibration.
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index a5e921cae7..3778a469d4 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -104,7 +104,7 @@ static int spi_calibration(struct udevice *bus, uint hz)
 
        /* use back the intended clock and find low range */
        cadence_spi_write_speed(bus, hz);
-       for (i = 0; i < CQSPI_READ_CAPTURE_MAX_DELAY; i++) {
+       for (i = 0; i < priv->max_read_delay; i++) {
                /* Disable QSPI */
                cadence_qspi_apb_controller_disable(base);
 
@@ -246,6 +246,7 @@ static int cadence_spi_probe(struct udevice *bus)
        priv->fifo_depth        = plat->fifo_depth;
        priv->fifo_width        = plat->fifo_width;
        priv->trigger_address   = plat->trigger_address;
+       priv->max_read_delay    = plat->max_read_delay;
        priv->read_delay        = plat->read_delay;
        priv->ahbsize           = plat->ahbsize;
        priv->max_hz            = plat->max_hz;
@@ -456,6 +457,10 @@ static int cadence_spi_of_to_plat(struct udevice *bus)
 
        plat->is_dma = dev_read_bool(bus, "cdns,is-dma");
 
+       plat->max_read_delay = dev_read_u32_default(bus,
+                                                   "cdns,max-read-delay",
+                                                   
CQSPI_READ_CAPTURE_MAX_DELAY);
+
        /* All other parameters are embedded in the child node */
        subnode = cadence_qspi_get_subnode(bus);
        if (!ofnode_valid(subnode)) {
@@ -484,6 +489,8 @@ static int cadence_spi_of_to_plat(struct udevice *bus)
         */
        plat->read_delay = ofnode_read_s32_default(subnode, "cdns,read-delay",
                                                   -1);
+       if (plat->read_delay > plat->max_read_delay)
+               plat->read_delay = plat->max_read_delay;
 
        debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n",
              __func__, plat->regbase, plat->ahbbase, plat->max_hz,
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 9c15d3c6df..d7a02f0870 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -214,6 +214,7 @@ struct cadence_spi_plat {
        fdt_addr_t      ahbsize;
        bool            use_dac_mode;
        int             read_delay;
+       int             max_read_delay;
 
        /* Flash parameters */
        u32             page_size;
@@ -260,6 +261,7 @@ struct cadence_spi_priv {
        unsigned int    previous_hz;
        u32             wr_delay;
        int             read_delay;
+       int             max_read_delay;
 
        struct reset_ctl_bulk *resets;
        u32             page_size;
-- 
2.43.2

Reply via email to