Skip to content

Commit

Permalink
soc: amlogic: meson-gx-pwrc-vpu: fix power-off when powered by bootlo…
Browse files Browse the repository at this point in the history
…ader

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: 75fcb5c ("soc: amlogic: add Meson GX VPU Domains driver")
Signed-off-by: Neil Armstrong <[email protected]>
Tested-by: Kevin Hilman <[email protected]>
Signed-off-by: Arnd Bergmann <[email protected]>
  • Loading branch information
superna9999 authored and arndb committed Nov 9, 2017
1 parent ad54c3e commit 339cd0e
Showing 1 changed file with 19 additions and 10 deletions.
29 changes: 19 additions & 10 deletions drivers/soc/amlogic/meson-gx-pwrc-vpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

Expand All @@ -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)) {
Expand Down Expand Up @@ -205,17 +206,25 @@ 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);
}

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

0 comments on commit 339cd0e

Please sign in to comment.