Skip to content
Snippets Groups Projects
Commit 2b4f1e59 authored by Sebastian Reichel's avatar Sebastian Reichel
Browse files

[MERGED] pmdomain: rockchip: forward rockchip_do_pmu_set_power_domain errors


Currently rockchip_do_pmu_set_power_domain prints a warning if there
have been errors turning on the power domain, but it does not return
any errors and rockchip_pd_power() tries to continue setting up the
QOS registers. This usually results in accessing unpowered registers,
which triggers an SError and a full system hang.

This improves the error handling by forwarding the error to avoid
kernel panics.

Reviewed-by: default avatarHeiko Stuebner <heiko@sntech.de>
Tested-by: Adrian Larumbe <adrian.larumbe@collabora.com> # On Rock 5B
Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
parent a7e22330
No related branches found
No related tags found
No related merge requests found
......@@ -533,16 +533,17 @@ static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd)
return ret;
}
static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
bool on)
static int rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
bool on)
{
struct rockchip_pmu *pmu = pd->pmu;
struct generic_pm_domain *genpd = &pd->genpd;
u32 pd_pwr_offset = pd->info->pwr_offset;
bool is_on, is_mem_on = false;
int ret;
if (pd->info->pwr_mask == 0)
return;
return 0;
if (on && pd->info->mem_status_mask)
is_mem_on = rockchip_pmu_domain_is_mem_on(pd);
......@@ -557,16 +558,21 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
wmb();
if (is_mem_on && rockchip_pmu_domain_mem_reset(pd))
return;
if (is_mem_on) {
ret = rockchip_pmu_domain_mem_reset(pd);
if (ret)
return ret;
}
if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
is_on == on, 0, 10000)) {
dev_err(pmu->dev,
"failed to set domain '%s', val=%d\n",
genpd->name, is_on);
return;
ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
is_on == on, 0, 10000);
if (ret) {
dev_err(pmu->dev, "failed to set domain '%s' %s, val=%d\n",
genpd->name, on ? "on" : "off", is_on);
return ret;
}
return 0;
}
static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
......@@ -592,7 +598,11 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
rockchip_pmu_set_idle_request(pd, true);
}
rockchip_do_pmu_set_power_domain(pd, power_on);
ret = rockchip_do_pmu_set_power_domain(pd, power_on);
if (ret < 0) {
clk_bulk_disable(pd->num_clks, pd->clks);
return ret;
}
if (power_on) {
/* if powering up, leave idle mode */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment