summaryrefslogtreecommitdiff
path: root/drivers/mtd/spi-nor/fsl-quadspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/spi-nor/fsl-quadspi.c')
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c81
1 files changed, 56 insertions, 25 deletions
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c
index a5db7ad8fc20..8a69b2caa792 100644
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -655,6 +655,32 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q)
q->iobase + QUADSPI_BFGENCR);
}
+/* This function was used to prepare and enable QSPI clock */
+static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q)
+{
+ int ret;
+
+ ret = clk_prepare_enable(q->clk_en);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(q->clk);
+ if (ret) {
+ clk_disable_unprepare(q->clk_en);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* This function was used to disable and unprepare QSPI clock */
+static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q)
+{
+ clk_disable_unprepare(q->clk);
+ clk_disable_unprepare(q->clk_en);
+
+}
+
/* We use this function to do some basic init for spi_nor_scan(). */
static int fsl_qspi_nor_setup(struct fsl_qspi *q)
{
@@ -662,11 +688,18 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q)
u32 reg;
int ret;
- /* the default frequency, we will change it in the future.*/
+ /* disable and unprepare clock to avoid glitch pass to controller */
+ fsl_qspi_clk_disable_unprep(q);
+
+ /* the default frequency, we will change it in the future. */
ret = clk_set_rate(q->clk, 66000000);
if (ret)
return ret;
+ ret = fsl_qspi_clk_prep_enable(q);
+ if (ret)
+ return ret;
+
/* Init the LUT table. */
fsl_qspi_init_lut(q);
@@ -698,10 +731,17 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q)
if (needs_4x_clock(q))
rate *= 4;
+ /* disable and unprepare clock to avoid glitch pass to controller */
+ fsl_qspi_clk_disable_unprep(q);
+
ret = clk_set_rate(q->clk, rate);
if (ret)
return ret;
+ ret = fsl_qspi_clk_prep_enable(q);
+ if (ret)
+ return ret;
+
/* Init the LUT table again. */
fsl_qspi_init_lut(q);
@@ -844,22 +884,16 @@ static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
int ret;
mutex_lock(&q->lock);
- ret = clk_enable(q->clk_en);
- if (ret)
- goto err_mutex;
- ret = clk_enable(q->clk);
+ ret = fsl_qspi_clk_prep_enable(q);
if (ret)
- goto err_clk;
+ goto err_mutex;
fsl_qspi_set_base_addr(q, nor);
return 0;
-err_clk:
- clk_disable(q->clk_en);
err_mutex:
mutex_unlock(&q->lock);
-
return ret;
}
@@ -867,8 +901,7 @@ static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
{
struct fsl_qspi *q = nor->priv;
- clk_disable(q->clk);
- clk_disable(q->clk_en);
+ fsl_qspi_clk_disable_unprep(q);
mutex_unlock(&q->lock);
}
@@ -918,15 +951,9 @@ static int fsl_qspi_probe(struct platform_device *pdev)
if (IS_ERR(q->clk))
return PTR_ERR(q->clk);
- ret = clk_prepare_enable(q->clk_en);
+ ret = fsl_qspi_clk_prep_enable(q);
if (ret) {
- dev_err(dev, "cannot enable the qspi_en clock: %d\n", ret);
- return ret;
- }
-
- ret = clk_prepare_enable(q->clk);
- if (ret) {
- dev_err(dev, "cannot enable the qspi clock: %d\n", ret);
+ dev_err(dev, "can not enable the clock\n");
goto clk_failed;
}
@@ -1032,8 +1059,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
if (ret)
goto last_init_failed;
- clk_disable(q->clk);
- clk_disable(q->clk_en);
+ fsl_qspi_clk_disable_unprep(q);
return 0;
last_init_failed:
@@ -1046,9 +1072,9 @@ last_init_failed:
mutex_failed:
mutex_destroy(&q->lock);
irq_failed:
- clk_disable_unprepare(q->clk);
+ fsl_qspi_clk_disable_unprep(q);
clk_failed:
- clk_disable_unprepare(q->clk_en);
+ dev_err(dev, "Freescale QuadSPI probe failed\n");
return ret;
}
@@ -1069,8 +1095,6 @@ static int fsl_qspi_remove(struct platform_device *pdev)
writel(0x0, q->iobase + QUADSPI_RSER);
mutex_destroy(&q->lock);
- clk_unprepare(q->clk);
- clk_unprepare(q->clk_en);
if (q->ahb_addr)
iounmap(q->ahb_addr);
@@ -1085,12 +1109,19 @@ static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state)
static int fsl_qspi_resume(struct platform_device *pdev)
{
+ int ret;
struct fsl_qspi *q = platform_get_drvdata(pdev);
+ ret = fsl_qspi_clk_prep_enable(q);
+ if (ret)
+ return ret;
+
fsl_qspi_nor_setup(q);
fsl_qspi_set_map_addr(q);
fsl_qspi_nor_setup_last(q);
+ fsl_qspi_clk_disable_unprep(q);
+
return 0;
}