summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Li <Frank.Li@freescale.com>2015-08-04 18:26:04 +0300
committerBrian Norris <computersforpeace@gmail.com>2015-08-06 20:07:44 +0300
commit5cc66cb7345d1bac71e94d7fd05dc86506f59dfe (patch)
tree78c40dbfe87b36331c9dc29c4a2ea7bc04fb39db
parentcacbef40aac478fb25fb7d18ac22d41a11ce06e2 (diff)
downloadlinux-5cc66cb7345d1bac71e94d7fd05dc86506f59dfe.tar.xz
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@freescale.com> Signed-off-by: Han Xu <Han.xu@freescale.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c26
1 files 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 <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;