107 lines
3.3 KiB
Diff
107 lines
3.3 KiB
Diff
From 339cd0ea082287ea8e2b7e7159a5a33665a2cbe3 Mon Sep 17 00:00:00 2001
|
|
From: Neil Armstrong <narmstrong@baylibre.com>
|
|
Date: Fri, 3 Nov 2017 16:43:24 +0100
|
|
Subject: soc: amlogic: meson-gx-pwrc-vpu: fix power-off when powered by
|
|
bootloader
|
|
|
|
In the case the VPU power domain has been powered on by the bootloader
|
|
and no driver are attached to this power domain, the genpd will power it
|
|
off after a certain amount of time, but the clocks hasn't been enabled
|
|
by the kernel itself and the power-off will trigger some faults.
|
|
This patch enable the clocks to have a coherent state for an eventual
|
|
poweroff and switches to the pm_domain_always_on_gov governor.
|
|
|
|
Fixes: 75fcb5ca4b46 ("soc: amlogic: add Meson GX VPU Domains driver")
|
|
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
|
Tested-by: Kevin Hilman <khilman@baylibre.com>
|
|
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
|
---
|
|
drivers/soc/amlogic/meson-gx-pwrc-vpu.c | 29 +++++++++++++++++++----------
|
|
1 file changed, 19 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c
|
|
index bf5190b..2bdeebc 100644
|
|
--- a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c
|
|
+++ b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c
|
|
@@ -34,7 +34,6 @@ struct meson_gx_pwrc_vpu {
|
|
struct reset_control *rstc;
|
|
struct clk *vpu_clk;
|
|
struct clk *vapb_clk;
|
|
- bool powered;
|
|
};
|
|
|
|
static inline
|
|
@@ -78,8 +77,6 @@ static int meson_gx_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
|
|
clk_disable_unprepare(pd->vpu_clk);
|
|
clk_disable_unprepare(pd->vapb_clk);
|
|
|
|
- pd->powered = false;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -91,7 +88,11 @@ static int meson_gx_pwrc_vpu_setup_clk(struct meson_gx_pwrc_vpu *pd)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- return clk_prepare_enable(pd->vapb_clk);
|
|
+ ret = clk_prepare_enable(pd->vapb_clk);
|
|
+ if (ret)
|
|
+ clk_disable_unprepare(pd->vpu_clk);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
|
|
@@ -139,8 +140,6 @@ static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- pd->powered = true;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -167,6 +166,8 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
|
|
struct reset_control *rstc;
|
|
struct clk *vpu_clk;
|
|
struct clk *vapb_clk;
|
|
+ bool powered_off;
|
|
+ int ret;
|
|
|
|
regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
|
|
if (IS_ERR(regmap_ao)) {
|
|
@@ -205,8 +206,17 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
|
|
vpu_hdmi_pd.vpu_clk = vpu_clk;
|
|
vpu_hdmi_pd.vapb_clk = vapb_clk;
|
|
|
|
- pm_genpd_init(&vpu_hdmi_pd.genpd, &simple_qos_governor,
|
|
- meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd));
|
|
+ powered_off = meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd);
|
|
+
|
|
+ /* If already powered, sync the clock states */
|
|
+ if (!powered_off) {
|
|
+ ret = meson_gx_pwrc_vpu_setup_clk(&vpu_hdmi_pd);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ pm_genpd_init(&vpu_hdmi_pd.genpd, &pm_domain_always_on_gov,
|
|
+ powered_off);
|
|
|
|
return of_genpd_add_provider_simple(pdev->dev.of_node,
|
|
&vpu_hdmi_pd.genpd);
|
|
@@ -214,8 +224,7 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
|
|
|
|
static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev)
|
|
{
|
|
- if (vpu_hdmi_pd.powered)
|
|
- meson_gx_pwrc_vpu_power_off(&vpu_hdmi_pd.genpd);
|
|
+ meson_gx_pwrc_vpu_power_off(&vpu_hdmi_pd.genpd);
|
|
}
|
|
|
|
static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = {
|
|
--
|
|
cgit v1.1
|
|
|