|
@@ -655,6 +655,32 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q)
|
|
q->iobase + QUADSPI_BFGENCR);
|
|
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(). */
|
|
/* We use this function to do some basic init for spi_nor_scan(). */
|
|
static int fsl_qspi_nor_setup(struct fsl_qspi *q)
|
|
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;
|
|
u32 reg;
|
|
int ret;
|
|
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);
|
|
ret = clk_set_rate(q->clk, 66000000);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
|
|
+ ret = fsl_qspi_clk_prep_enable(q);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
/* Init the LUT table. */
|
|
/* Init the LUT table. */
|
|
fsl_qspi_init_lut(q);
|
|
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))
|
|
if (needs_4x_clock(q))
|
|
rate *= 4;
|
|
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);
|
|
ret = clk_set_rate(q->clk, rate);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
|
|
+ ret = fsl_qspi_clk_prep_enable(q);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
/* Init the LUT table again. */
|
|
/* Init the LUT table again. */
|
|
fsl_qspi_init_lut(q);
|
|
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;
|
|
int ret;
|
|
|
|
|
|
mutex_lock(&q->lock);
|
|
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)
|
|
if (ret)
|
|
- goto err_clk;
|
|
|
|
|
|
+ goto err_mutex;
|
|
|
|
|
|
fsl_qspi_set_base_addr(q, nor);
|
|
fsl_qspi_set_base_addr(q, nor);
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
-err_clk:
|
|
|
|
- clk_disable(q->clk_en);
|
|
|
|
err_mutex:
|
|
err_mutex:
|
|
mutex_unlock(&q->lock);
|
|
mutex_unlock(&q->lock);
|
|
-
|
|
|
|
return ret;
|
|
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;
|
|
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);
|
|
mutex_unlock(&q->lock);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -918,15 +951,9 @@ static int fsl_qspi_probe(struct platform_device *pdev)
|
|
if (IS_ERR(q->clk))
|
|
if (IS_ERR(q->clk))
|
|
return PTR_ERR(q->clk);
|
|
return PTR_ERR(q->clk);
|
|
|
|
|
|
- ret = clk_prepare_enable(q->clk_en);
|
|
|
|
|
|
+ ret = fsl_qspi_clk_prep_enable(q);
|
|
if (ret) {
|
|
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;
|
|
goto clk_failed;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1032,8 +1059,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
|
|
if (ret)
|
|
if (ret)
|
|
goto last_init_failed;
|
|
goto last_init_failed;
|
|
|
|
|
|
- clk_disable(q->clk);
|
|
|
|
- clk_disable(q->clk_en);
|
|
|
|
|
|
+ fsl_qspi_clk_disable_unprep(q);
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
last_init_failed:
|
|
last_init_failed:
|
|
@@ -1046,9 +1072,9 @@ last_init_failed:
|
|
mutex_failed:
|
|
mutex_failed:
|
|
mutex_destroy(&q->lock);
|
|
mutex_destroy(&q->lock);
|
|
irq_failed:
|
|
irq_failed:
|
|
- clk_disable_unprepare(q->clk);
|
|
|
|
|
|
+ fsl_qspi_clk_disable_unprep(q);
|
|
clk_failed:
|
|
clk_failed:
|
|
- clk_disable_unprepare(q->clk_en);
|
|
|
|
|
|
+ dev_err(dev, "Freescale QuadSPI probe failed\n");
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1069,8 +1095,6 @@ static int fsl_qspi_remove(struct platform_device *pdev)
|
|
writel(0x0, q->iobase + QUADSPI_RSER);
|
|
writel(0x0, q->iobase + QUADSPI_RSER);
|
|
|
|
|
|
mutex_destroy(&q->lock);
|
|
mutex_destroy(&q->lock);
|
|
- clk_unprepare(q->clk);
|
|
|
|
- clk_unprepare(q->clk_en);
|
|
|
|
|
|
|
|
if (q->ahb_addr)
|
|
if (q->ahb_addr)
|
|
iounmap(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)
|
|
static int fsl_qspi_resume(struct platform_device *pdev)
|
|
{
|
|
{
|
|
|
|
+ int ret;
|
|
struct fsl_qspi *q = platform_get_drvdata(pdev);
|
|
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_nor_setup(q);
|
|
fsl_qspi_set_map_addr(q);
|
|
fsl_qspi_set_map_addr(q);
|
|
fsl_qspi_nor_setup_last(q);
|
|
fsl_qspi_nor_setup_last(q);
|
|
|
|
|
|
|
|
+ fsl_qspi_clk_disable_unprep(q);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|