mtd: spi-nor: fsl-quadspi: workaround qspi can't wakeup from wait mode

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Tue Sep 1 14:59:03 PDT 2015


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=5cc66cb7345d1bac71e94d7fd05dc86506f59dfe
Commit:     5cc66cb7345d1bac71e94d7fd05dc86506f59dfe
Parent:     cacbef40aac478fb25fb7d18ac22d41a11ce06e2
Author:     Frank Li <Frank.Li at freescale.com>
AuthorDate: Tue Aug 4 10:26:04 2015 -0500
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Thu Aug 6 10:07:44 2015 -0700

    mtd: spi-nor: fsl-quadspi: workaround qspi can't wakeup from wait mode
    
    QSPI1 cannot wake up CCM from WAIT mode on SX ARD board, add pmqos to
    let PM NOT enter WAIT mode when accessing QSPI1, refer to TKT245618.
    
    Signed-off-by: Frank Li <Frank.Li at freescale.com>
    Signed-off-by: Han Xu <Han.xu at freescale.com>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/spi-nor/fsl-quadspi.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c
index 8a69b2c..676b363 100644
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -27,6 +27,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/spi-nor.h>
 #include <linux/mutex.h>
+#include <linux/pm_qos.h>
 
 /* Controller needs driver to swap endian */
 #define QUADSPI_QUIRK_SWAP_ENDIAN	(1 << 0)
@@ -37,6 +38,8 @@
  * trigger data transfer even though extern data will not transferred.
  */
 #define QUADSPI_QUIRK_TKT253890		(1 << 2)
+/* Controller cannot wake up from wait mode, TKT245618 */
+#define QUADSPI_QUIRK_TKT245618         (1 << 3)
 
 /* The registers */
 #define QUADSPI_MCR			0x00
@@ -232,7 +235,8 @@ static struct fsl_qspi_devtype_data imx6sx_data = {
 	.rxfifo = 128,
 	.txfifo = 512,
 	.ahb_buf_size = 1024,
-	.driver_data = QUADSPI_QUIRK_4X_INT_CLK,
+	.driver_data = QUADSPI_QUIRK_4X_INT_CLK
+		       | QUADSPI_QUIRK_TKT245618,
 };
 
 static struct fsl_qspi_devtype_data imx7d_data = {
@@ -272,6 +276,7 @@ struct fsl_qspi {
 	unsigned int chip_base_addr; /* We may support two chips. */
 	bool has_second_chip;
 	struct mutex lock;
+	struct pm_qos_request pm_qos_req;
 };
 
 static inline int needs_swap_endian(struct fsl_qspi *q)
@@ -289,6 +294,11 @@ static inline int needs_fill_txfifo(struct fsl_qspi *q)
 	return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT253890;
 }
 
+static inline int needs_wakeup_wait_mode(struct fsl_qspi *q)
+{
+	return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT245618;
+}
+
 /*
  * An IC bug makes us to re-arrange the 32-bit data.
  * The following chips, such as IMX6SLX, have fixed this bug.
@@ -670,12 +680,18 @@ static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q)
 		return ret;
 	}
 
+	if (needs_wakeup_wait_mode(q))
+		pm_qos_add_request(&q->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0);
+
 	return 0;
 }
 
 /* This function was used to disable and unprepare QSPI clock */
 static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q)
 {
+	if (needs_wakeup_wait_mode(q))
+		pm_qos_remove_request(&q->pm_qos_req);
+
 	clk_disable_unprepare(q->clk);
 	clk_disable_unprepare(q->clk_en);
 
@@ -926,6 +942,10 @@ static int fsl_qspi_probe(struct platform_device *pdev)
 	if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP)
 		return -ENODEV;
 
+	q->dev = dev;
+	q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data;
+	platform_set_drvdata(pdev, q);
+
 	/* find the resources */
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
 	q->iobase = devm_ioremap_resource(dev, res);
@@ -971,10 +991,6 @@ static int fsl_qspi_probe(struct platform_device *pdev)
 		goto irq_failed;
 	}
 
-	q->dev = dev;
-	q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data;
-	platform_set_drvdata(pdev, q);
-
 	ret = fsl_qspi_nor_setup(q);
 	if (ret)
 		goto irq_failed;



More information about the linux-mtd-cvs mailing list