1
0
Fork 0

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: 75fcb5ca4b ("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>
hifive-unleashed-5.1
Neil Armstrong 2017-11-03 16:43:24 +01:00 committed by Arnd Bergmann
parent ad54c3e75d
commit 339cd0ea08
1 changed files with 19 additions and 10 deletions

View File

@ -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[] = {