diff options
author | Detlev Casanova <detlev.casanova@collabora.com> | 2024-08-29 22:20:47 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2024-09-13 13:01:47 +0200 |
commit | 8b579881de295d49a75f6312547f7813b1551a83 (patch) | |
tree | 716f7b3b545da4f87f6a93549ec87d011dc9fee8 /drivers/pmdomain | |
parent | pmdomain: rockchip: Simplify dropping OF node reference (diff) | |
download | linux-8b579881de295d49a75f6312547f7813b1551a83.tar.xz linux-8b579881de295d49a75f6312547f7813b1551a83.zip |
pmdomain: rockchip: Add gating support
Some rockchip SoC need to ungate power domains before their power status
can be changed.
Each power domain has a gate mask that is set to 1 to ungate it when
manipulating power status, then set back to 0 to gate it again.
Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
Link: https://lore.kernel.org/r/20240829202732.75961-2-detlev.casanova@collabora.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/pmdomain')
-rw-r--r-- | drivers/pmdomain/rockchip/pm-domains.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c index 66e473065b6b..b9e3dc45cb30 100644 --- a/drivers/pmdomain/rockchip/pm-domains.c +++ b/drivers/pmdomain/rockchip/pm-domains.c @@ -46,6 +46,7 @@ struct rockchip_domain_info { bool active_wakeup; int pwr_w_mask; int req_w_mask; + int clk_ungate_mask; int mem_status_mask; int repair_status_mask; u32 pwr_offset; @@ -63,6 +64,7 @@ struct rockchip_pmu_info { u32 chain_status_offset; u32 mem_status_offset; u32 repair_status_offset; + u32 clk_ungate_offset; u32 core_pwrcnt_offset; u32 gpu_pwrcnt_offset; @@ -303,6 +305,26 @@ static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu) return val; } +static int rockchip_pmu_ungate_clk(struct rockchip_pm_domain *pd, bool ungate) +{ + const struct rockchip_domain_info *pd_info = pd->info; + struct rockchip_pmu *pmu = pd->pmu; + unsigned int val; + int clk_ungate_w_mask = pd_info->clk_ungate_mask << 16; + + if (!pd_info->clk_ungate_mask) + return 0; + + if (!pmu->info->clk_ungate_offset) + return 0; + + val = ungate ? (pd_info->clk_ungate_mask | clk_ungate_w_mask) : + clk_ungate_w_mask; + regmap_write(pmu->regmap, pmu->info->clk_ungate_offset, val); + + return 0; +} + static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, bool idle) { @@ -543,6 +565,8 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) return ret; } + rockchip_pmu_ungate_clk(pd, true); + if (!power_on) { rockchip_pmu_save_qos(pd); @@ -559,6 +583,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) rockchip_pmu_restore_qos(pd); } + rockchip_pmu_ungate_clk(pd, false); clk_bulk_disable(pd->num_clks, pd->clks); } |