aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Armstrong <narmstrong@baylibre.com>2017-11-03 11:43:24 -0400
committerArnd Bergmann <arnd@arndb.de>2017-11-09 05:42:17 -0500
commit339cd0ea082287ea8e2b7e7159a5a33665a2cbe3 (patch)
tree89bc267e8b8c913e870179216027325dd4e0dda2
parentad54c3e75d27686ac7e97e17d242fbc568f6c2e3 (diff)
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>
-rw-r--r--drivers/soc/amlogic/meson-gx-pwrc-vpu.c29
1 files 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 bf5190b65ad9..2bdeebc48901 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 {
34 struct reset_control *rstc; 34 struct reset_control *rstc;
35 struct clk *vpu_clk; 35 struct clk *vpu_clk;
36 struct clk *vapb_clk; 36 struct clk *vapb_clk;
37 bool powered;
38}; 37};
39 38
40static inline 39static inline
@@ -78,8 +77,6 @@ static int meson_gx_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
78 clk_disable_unprepare(pd->vpu_clk); 77 clk_disable_unprepare(pd->vpu_clk);
79 clk_disable_unprepare(pd->vapb_clk); 78 clk_disable_unprepare(pd->vapb_clk);
80 79
81 pd->powered = false;
82
83 return 0; 80 return 0;
84} 81}
85 82
@@ -91,7 +88,11 @@ static int meson_gx_pwrc_vpu_setup_clk(struct meson_gx_pwrc_vpu *pd)
91 if (ret) 88 if (ret)
92 return ret; 89 return ret;
93 90
94 return clk_prepare_enable(pd->vapb_clk); 91 ret = clk_prepare_enable(pd->vapb_clk);
92 if (ret)
93 clk_disable_unprepare(pd->vpu_clk);
94
95 return ret;
95} 96}
96 97
97static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd) 98static 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)
139 if (ret) 140 if (ret)
140 return ret; 141 return ret;
141 142
142 pd->powered = true;
143
144 return 0; 143 return 0;
145} 144}
146 145
@@ -167,6 +166,8 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
167 struct reset_control *rstc; 166 struct reset_control *rstc;
168 struct clk *vpu_clk; 167 struct clk *vpu_clk;
169 struct clk *vapb_clk; 168 struct clk *vapb_clk;
169 bool powered_off;
170 int ret;
170 171
171 regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node)); 172 regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
172 if (IS_ERR(regmap_ao)) { 173 if (IS_ERR(regmap_ao)) {
@@ -205,8 +206,17 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
205 vpu_hdmi_pd.vpu_clk = vpu_clk; 206 vpu_hdmi_pd.vpu_clk = vpu_clk;
206 vpu_hdmi_pd.vapb_clk = vapb_clk; 207 vpu_hdmi_pd.vapb_clk = vapb_clk;
207 208
208 pm_genpd_init(&vpu_hdmi_pd.genpd, &simple_qos_governor, 209 powered_off = meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd);
209 meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd)); 210
211 /* If already powered, sync the clock states */
212 if (!powered_off) {
213 ret = meson_gx_pwrc_vpu_setup_clk(&vpu_hdmi_pd);
214 if (ret)
215 return ret;
216 }
217
218 pm_genpd_init(&vpu_hdmi_pd.genpd, &pm_domain_always_on_gov,
219 powered_off);
210 220
211 return of_genpd_add_provider_simple(pdev->dev.of_node, 221 return of_genpd_add_provider_simple(pdev->dev.of_node,
212 &vpu_hdmi_pd.genpd); 222 &vpu_hdmi_pd.genpd);
@@ -214,8 +224,7 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
214 224
215static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev) 225static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev)
216{ 226{
217 if (vpu_hdmi_pd.powered) 227 meson_gx_pwrc_vpu_power_off(&vpu_hdmi_pd.genpd);
218 meson_gx_pwrc_vpu_power_off(&vpu_hdmi_pd.genpd);
219} 228}
220 229
221static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = { 230static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = {