Commit 5cc66cb7 authored by Frank Li's avatar Frank Li Committed by Brian Norris

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: default avatarFrank Li <Frank.Li@freescale.com>
Signed-off-by: default avatarHan Xu <Han.xu@freescale.com>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent cacbef40
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/mtd/spi-nor.h> #include <linux/mtd/spi-nor.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/pm_qos.h>
/* Controller needs driver to swap endian */ /* Controller needs driver to swap endian */
#define QUADSPI_QUIRK_SWAP_ENDIAN (1 << 0) #define QUADSPI_QUIRK_SWAP_ENDIAN (1 << 0)
...@@ -37,6 +38,8 @@ ...@@ -37,6 +38,8 @@
* trigger data transfer even though extern data will not transferred. * trigger data transfer even though extern data will not transferred.
*/ */
#define QUADSPI_QUIRK_TKT253890 (1 << 2) #define QUADSPI_QUIRK_TKT253890 (1 << 2)
/* Controller cannot wake up from wait mode, TKT245618 */
#define QUADSPI_QUIRK_TKT245618 (1 << 3)
/* The registers */ /* The registers */
#define QUADSPI_MCR 0x00 #define QUADSPI_MCR 0x00
...@@ -232,7 +235,8 @@ static struct fsl_qspi_devtype_data imx6sx_data = { ...@@ -232,7 +235,8 @@ static struct fsl_qspi_devtype_data imx6sx_data = {
.rxfifo = 128, .rxfifo = 128,
.txfifo = 512, .txfifo = 512,
.ahb_buf_size = 1024, .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 = { static struct fsl_qspi_devtype_data imx7d_data = {
...@@ -272,6 +276,7 @@ struct fsl_qspi { ...@@ -272,6 +276,7 @@ struct fsl_qspi {
unsigned int chip_base_addr; /* We may support two chips. */ unsigned int chip_base_addr; /* We may support two chips. */
bool has_second_chip; bool has_second_chip;
struct mutex lock; struct mutex lock;
struct pm_qos_request pm_qos_req;
}; };
static inline int needs_swap_endian(struct fsl_qspi *q) static inline int needs_swap_endian(struct fsl_qspi *q)
...@@ -289,6 +294,11 @@ static inline int needs_fill_txfifo(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; 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. * An IC bug makes us to re-arrange the 32-bit data.
* The following chips, such as IMX6SLX, have fixed this bug. * 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) ...@@ -670,12 +680,18 @@ static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q)
return ret; return ret;
} }
if (needs_wakeup_wait_mode(q))
pm_qos_add_request(&q->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0);
return 0; return 0;
} }
/* This function was used to disable and unprepare QSPI clock */ /* This function was used to disable and unprepare QSPI clock */
static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q) 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);
clk_disable_unprepare(q->clk_en); clk_disable_unprepare(q->clk_en);
...@@ -926,6 +942,10 @@ static int fsl_qspi_probe(struct platform_device *pdev) ...@@ -926,6 +942,10 @@ static int fsl_qspi_probe(struct platform_device *pdev)
if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP) if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP)
return -ENODEV; return -ENODEV;
q->dev = dev;
q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data;
platform_set_drvdata(pdev, q);
/* find the resources */ /* find the resources */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
q->iobase = devm_ioremap_resource(dev, res); q->iobase = devm_ioremap_resource(dev, res);
...@@ -971,10 +991,6 @@ static int fsl_qspi_probe(struct platform_device *pdev) ...@@ -971,10 +991,6 @@ static int fsl_qspi_probe(struct platform_device *pdev)
goto irq_failed; 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); ret = fsl_qspi_nor_setup(q);
if (ret) if (ret)
goto irq_failed; goto irq_failed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment