From 5cc66cb7345d1bac71e94d7fd05dc86506f59dfe Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 4 Aug 2015 10:26:04 -0500 Subject: [PATCH] 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 Signed-off-by: Han Xu Signed-off-by: Brian Norris --- 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 8a69b2caa792..676b36361076 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -27,6 +27,7 @@ #include #include #include +#include /* 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; -- 2.39.5