]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
pmdomain: rockchip: Add gating support
authorDetlev Casanova <detlev.casanova@collabora.com>
Thu, 29 Aug 2024 20:20:47 +0000 (16:20 -0400)
committerUlf Hansson <ulf.hansson@linaro.org>
Fri, 13 Sep 2024 11:01:47 +0000 (13:01 +0200)
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>
drivers/pmdomain/rockchip/pm-domains.c

index 66e473065b6bfbf8d1839a3f99f471fe3c4b2a35..b9e3dc45cb30fc8fb5e824bf0c3b14dedff48fce 100644 (file)
@@ -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);
        }