msm: pil-q6v5: Update clock calls to fix MSS PIL with full bootchain
LPASS and MSS have different requirements related to the order that
their clocks are enable/disabled and resets are asserted/de-asserted.
Currently, this causes 'clock stuck off' warnings in the kernel logs
when MSS is booted multiple times.
Fix this by reordering the MSS clock calls so that the core_clk reset
is de-asserted prior to enabling its iface_clk. Because doing this
would break LPASS (which requires iface_clk to be on for the core_clk
reset de-assertion to work), we are forced to separate the MSS and
LPASS clock sequences into separate functions and move them into their
respective PIL files.
MSS PIL also requires an additional clock that is added as part of
this fixup. The gcc_mss_q6_bimc_axi_clk is needed for the MSS Q6
to access memory.
Change-Id: Id877781f201a7267f72b52045ed2b87ebf7b4e05
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 5a112da..8ac1c88 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5047,10 +5047,10 @@
"msm-dai-q6.4106"),
CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
- CLK_LOOKUP("bus_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("reg_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "pil-q6v5-mss"),
- CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, ""),
CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "pil-q6v5-lpass"),
CLK_LOOKUP("bus_clk", gcc_lpass_q6_axi_clk.c, "pil-q6v5-lpass"),
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 99223f2..44d8bc6 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -18,13 +18,56 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/clk.h>
-
+#include <mach/clk.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
#define QDSP6SS_RST_EVB 0x010
#define PROXY_TIMEOUT_MS 10000
+static int pil_lpass_enable_clks(struct q6v5_data *drv)
+{
+ int ret;
+
+ ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ goto err_reset;
+ ret = clk_prepare_enable(drv->core_clk);
+ if (ret)
+ goto err_core_clk;
+ ret = clk_prepare_enable(drv->ahb_clk);
+ if (ret)
+ goto err_ahb_clk;
+ ret = clk_prepare_enable(drv->axi_clk);
+ if (ret)
+ goto err_axi_clk;
+ ret = clk_prepare_enable(drv->reg_clk);
+ if (ret)
+ goto err_reg_clk;
+
+ return 0;
+
+err_reg_clk:
+ clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+ clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+ clk_disable_unprepare(drv->core_clk);
+err_core_clk:
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+err_reset:
+ return ret;
+}
+
+static void pil_lpass_disable_clks(struct q6v5_data *drv)
+{
+ clk_disable_unprepare(drv->reg_clk);
+ clk_disable_unprepare(drv->axi_clk);
+ clk_disable_unprepare(drv->ahb_clk);
+ clk_disable_unprepare(drv->core_clk);
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+}
+
static int pil_lpass_shutdown(struct pil_desc *pil)
{
struct q6v5_data *drv = dev_get_drvdata(pil->dev);
@@ -37,10 +80,10 @@
* performed during the shutdown succeed.
*/
if (drv->is_booted == false)
- pil_q6v5_enable_clks(pil);
+ pil_lpass_enable_clks(drv);
pil_q6v5_shutdown(pil);
- pil_q6v5_disable_clks(pil);
+ pil_lpass_disable_clks(drv);
drv->is_booted = false;
@@ -52,7 +95,7 @@
struct q6v5_data *drv = dev_get_drvdata(pil->dev);
int ret;
- ret = pil_q6v5_enable_clks(pil);
+ ret = pil_lpass_enable_clks(drv);
if (ret)
return ret;
@@ -62,7 +105,7 @@
ret = pil_q6v5_reset(pil);
if (ret) {
- pil_q6v5_disable_clks(pil);
+ pil_lpass_disable_clks(drv);
return ret;
}
@@ -96,9 +139,21 @@
desc->owner = THIS_MODULE;
desc->proxy_timeout = PROXY_TIMEOUT_MS;
- drv->ss_clk = devm_clk_get(&pdev->dev, "reg_clk");
- if (IS_ERR(drv->ss_clk))
- return PTR_ERR(drv->ss_clk);
+ drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(drv->core_clk))
+ return PTR_ERR(drv->core_clk);
+
+ drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(drv->ahb_clk))
+ return PTR_ERR(drv->ahb_clk);
+
+ drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+ if (IS_ERR(drv->axi_clk))
+ return PTR_ERR(drv->axi_clk);
+
+ drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
+ if (IS_ERR(drv->reg_clk))
+ return PTR_ERR(drv->reg_clk);
drv->pil = msm_pil_register(desc);
if (IS_ERR(drv->pil))
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 56be717..6a30940 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -74,6 +74,55 @@
return regulator_disable(drv->vreg);
}
+static int pil_mss_enable_clks(struct q6v5_data *drv)
+{
+ int ret;
+
+ ret = clk_prepare_enable(drv->ahb_clk);
+ if (ret)
+ goto err_ahb_clk;
+ ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ goto err_reset;
+ ret = clk_prepare_enable(drv->core_clk);
+ if (ret)
+ goto err_core_clk;
+ ret = clk_prepare_enable(drv->axi_clk);
+ if (ret)
+ goto err_axi_clk;
+ ret = clk_prepare_enable(drv->reg_clk);
+ if (ret)
+ goto err_reg_clk;
+ ret = clk_prepare_enable(drv->rom_clk);
+ if (ret)
+ goto err_rom_clk;
+
+ return 0;
+
+err_rom_clk:
+ clk_disable_unprepare(drv->reg_clk);
+err_reg_clk:
+ clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+ clk_disable_unprepare(drv->core_clk);
+err_core_clk:
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+err_reset:
+ clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+ return ret;
+}
+
+static void pil_mss_disable_clks(struct q6v5_data *drv)
+{
+ clk_disable_unprepare(drv->rom_clk);
+ clk_disable_unprepare(drv->reg_clk);
+ clk_disable_unprepare(drv->axi_clk);
+ clk_disable_unprepare(drv->core_clk);
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+ clk_disable_unprepare(drv->ahb_clk);
+}
+
static int wait_for_mba_ready(struct device *dev)
{
struct q6v5_data *drv = dev_get_drvdata(dev);
@@ -123,11 +172,11 @@
*/
if (drv->is_booted == false) {
pil_mss_power_up(pil->dev);
- pil_q6v5_enable_clks(pil);
+ pil_mss_enable_clks(drv);
}
pil_q6v5_shutdown(pil);
- pil_q6v5_disable_clks(pil);
+ pil_mss_disable_clks(drv);
pil_mss_power_down(pil->dev);
writel_relaxed(1, drv->restart_reg);
@@ -155,7 +204,7 @@
if (ret)
goto err_power;
- ret = pil_q6v5_enable_clks(pil);
+ ret = pil_mss_enable_clks(drv);
if (ret)
goto err_clks;
@@ -190,7 +239,7 @@
err_auth:
pil_q6v5_shutdown(pil);
err_q6v5_reset:
- pil_q6v5_disable_clks(pil);
+ pil_mss_disable_clks(drv);
err_clks:
pil_mss_power_down(pil->dev);
err_power:
@@ -259,9 +308,25 @@
return ret;
}
- drv->ss_clk = devm_clk_get(&pdev->dev, "mem_clk");
- if (IS_ERR(drv->ss_clk))
- return PTR_ERR(drv->ss_clk);
+ drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(drv->ahb_clk))
+ return PTR_ERR(drv->ahb_clk);
+
+ drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(drv->core_clk))
+ return PTR_ERR(drv->core_clk);
+
+ drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+ if (IS_ERR(drv->axi_clk))
+ return PTR_ERR(drv->axi_clk);
+
+ drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
+ if (IS_ERR(drv->reg_clk))
+ return PTR_ERR(drv->reg_clk);
+
+ drv->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(drv->rom_clk))
+ return PTR_ERR(drv->rom_clk);
drv->pil = msm_pil_register(desc);
if (IS_ERR(drv->pil))
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 1ce73b8..772031b 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -20,9 +20,7 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/clk.h>
-
#include <mach/clk.h>
-
#include "peripheral-loader.h"
#include "pil-q6v5.h"
@@ -112,60 +110,6 @@
}
EXPORT_SYMBOL(pil_q6v5_init_image);
-int pil_q6v5_enable_clks(struct pil_desc *pil)
-{
- struct q6v5_data *drv = dev_get_drvdata(pil->dev);
- int ret;
-
- if (drv->ahb_clk) {
- ret = clk_prepare_enable(drv->ahb_clk);
- if (ret)
- goto err_ahb_clk;
- }
- if (drv->axi_clk) {
- ret = clk_prepare_enable(drv->axi_clk);
- if (ret)
- goto err_axi_clk;
- }
- if (drv->ss_clk) {
- ret = clk_prepare_enable(drv->ss_clk);
- if (ret)
- goto err_ss_clk;
- }
- ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
- if (ret)
- goto err_reset;
- ret = clk_prepare_enable(drv->core_clk);
- if (ret)
- goto err_core_clk;
-
- return 0;
-
-err_core_clk:
- clk_reset(drv->core_clk, CLK_RESET_ASSERT);
-err_reset:
- clk_disable_unprepare(drv->ss_clk);
-err_ss_clk:
- clk_disable_unprepare(drv->axi_clk);
-err_axi_clk:
- clk_disable_unprepare(drv->ahb_clk);
-err_ahb_clk:
- return ret;
-}
-EXPORT_SYMBOL(pil_q6v5_enable_clks);
-
-void pil_q6v5_disable_clks(struct pil_desc *pil)
-{
- struct q6v5_data *drv = dev_get_drvdata(pil->dev);
-
- clk_disable_unprepare(drv->core_clk);
- clk_reset(drv->core_clk, CLK_RESET_ASSERT);
- clk_disable_unprepare(drv->ss_clk);
- clk_disable_unprepare(drv->axi_clk);
- clk_disable_unprepare(drv->ahb_clk);
-}
-EXPORT_SYMBOL(pil_q6v5_disable_clks);
-
void pil_q6v5_shutdown(struct pil_desc *pil)
{
u32 val;
@@ -287,18 +231,6 @@
if (IS_ERR(drv->xo))
return ERR_CAST(drv->xo);
- drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
- if (IS_ERR(drv->ahb_clk))
- return ERR_CAST(drv->ahb_clk);
-
- drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
- if (IS_ERR(drv->axi_clk))
- return ERR_CAST(drv->axi_clk);
-
- drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(drv->core_clk))
- return ERR_CAST(drv->core_clk);
-
desc->dev = &pdev->dev;
return desc;
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index 6d08652..03f93fa 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -21,11 +21,12 @@
struct q6v5_data {
void __iomem *reg_base;
- struct clk *xo;
- struct clk *ahb_clk;
- struct clk *axi_clk;
- struct clk *core_clk;
- struct clk *ss_clk;
+ struct clk *xo; /* XO clock source */
+ struct clk *ahb_clk; /* PIL access to registers */
+ struct clk *axi_clk; /* CPU access to memory */
+ struct clk *core_clk; /* CPU core */
+ struct clk *reg_clk; /* CPU access registers */
+ struct clk *rom_clk; /* Boot ROM */
void __iomem *axi_halt_base;
void __iomem *rmb_base;
void __iomem *restart_reg;
@@ -44,8 +45,6 @@
size_t size);
void pil_q6v5_shutdown(struct pil_desc *pil);
int pil_q6v5_reset(struct pil_desc *pil);
-int pil_q6v5_enable_clks(struct pil_desc *pil);
-void pil_q6v5_disable_clks(struct pil_desc *pil);
struct pil_desc *pil_q6v5_init(struct platform_device *pdev);
#endif