mtd: spi-nor: cadence-quadspi: add a delay in write sequence
authorVignesh R <vigneshr@ti.com>
Tue, 3 Oct 2017 05:19:21 +0000 (10:49 +0530)
committerCyrille Pitchen <cyrille.pitchen@wedev4u.fr>
Tue, 17 Oct 2017 18:38:27 +0000 (20:38 +0200)
As per 66AK2G02 TRM[1] SPRUHY8F section 11.15.5.3 Indirect Access
Controller programming sequence, a delay equal to couple of QSPI master
clock(~5ns) is required after setting CQSPI_REG_INDIRECTWR_START bit and
writing data to the flash. Introduce a quirk flag CQSPI_NEEDS_WR_DELAY
to handle this and set this flag for TI 66AK2G SoC.

[1]http://www.ti.com/lit/ug/spruhy8f/spruhy8f.pdf

Signed-off-by: Vignesh R <vigneshr@ti.com>
Acked-by: Marek Vasut <marek.vasut@gmail.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
drivers/mtd/spi-nor/cadence-quadspi.c

index 53c7d8e0327aa4376bdbb3cb00d78babf70349a4..5cd5d6f7303f33d751cd9ff8084bb32e85f0286b 100644 (file)
@@ -38,6 +38,9 @@
 #define CQSPI_NAME                     "cadence-qspi"
 #define CQSPI_MAX_CHIPSELECT           16
 
+/* Quirks */
+#define CQSPI_NEEDS_WR_DELAY           BIT(0)
+
 struct cqspi_st;
 
 struct cqspi_flash_pdata {
@@ -76,6 +79,7 @@ struct cqspi_st {
        u32                     fifo_depth;
        u32                     fifo_width;
        u32                     trigger_address;
+       u32                     wr_delay;
        struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
 };
 
@@ -608,6 +612,15 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor,
        reinit_completion(&cqspi->transfer_complete);
        writel(CQSPI_REG_INDIRECTWR_START_MASK,
               reg_base + CQSPI_REG_INDIRECTWR);
+       /*
+        * As per 66AK2G02 TRM SPRUHY8F section 11.15.5.3 Indirect Access
+        * Controller programming sequence, couple of cycles of
+        * QSPI_REF_CLK delay is required for the above bit to
+        * be internally synchronized by the QSPI module. Provide 5
+        * cycles of delay.
+        */
+       if (cqspi->wr_delay)
+               ndelay(cqspi->wr_delay);
 
        while (remaining > 0) {
                write_bytes = remaining > page_size ? page_size : remaining;
@@ -1156,6 +1169,7 @@ static int cqspi_probe(struct platform_device *pdev)
        struct cqspi_st *cqspi;
        struct resource *res;
        struct resource *res_ahb;
+       unsigned long data;
        int ret;
        int irq;
 
@@ -1213,6 +1227,10 @@ static int cqspi_probe(struct platform_device *pdev)
        }
 
        cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk);
+       data  = (unsigned long)of_device_get_match_data(dev);
+       if (data & CQSPI_NEEDS_WR_DELAY)
+               cqspi->wr_delay = 5 * DIV_ROUND_UP(NSEC_PER_SEC,
+                                                  cqspi->master_ref_clk_hz);
 
        ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0,
                               pdev->name, cqspi);
@@ -1284,7 +1302,14 @@ static const struct dev_pm_ops cqspi__dev_pm_ops = {
 #endif
 
 static const struct of_device_id cqspi_dt_ids[] = {
-       {.compatible = "cdns,qspi-nor",},
+       {
+               .compatible = "cdns,qspi-nor",
+               .data = (void *)0,
+       },
+       {
+               .compatible = "ti,k2g-qspi",
+               .data = (void *)CQSPI_NEEDS_WR_DELAY,
+       },
        { /* end of table */ }
 };