From: 黄涛 Date: Wed, 21 Mar 2012 11:15:36 +0000 (+0800) Subject: rk30: pmu: support idle request X-Git-Tag: firefly_0821_release~9595^2~44 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=bc7a9bc32b8a25b98eff9c840da6c0eb438c847e;p=firefly-linux-kernel-4.4.55.git rk30: pmu: support idle request --- diff --git a/arch/arm/mach-rk30/include/mach/pmu.h b/arch/arm/mach-rk30/include/mach/pmu.h index 51b2a7d03b06..8433d79fd196 100644 --- a/arch/arm/mach-rk30/include/mach/pmu.h +++ b/arch/arm/mach-rk30/include/mach/pmu.h @@ -34,6 +34,7 @@ enum pmu_power_domain { PD_PERI = 6, PD_VIO, PD_VIDEO, + PD_VCODEC = PD_VIDEO, PD_GPU, PD_DBG, }; @@ -45,4 +46,14 @@ static inline bool pmu_power_domain_is_on(enum pmu_power_domain pd) void pmu_set_power_domain(enum pmu_power_domain pd, bool on); +enum pmu_idle_req { + IDLE_REQ_CPU = 0, + IDLE_REQ_PERI, + IDLE_REQ_GPU, + IDLE_REQ_VIDEO, + IDLE_REQ_VIO, +}; + +void pmu_set_idle_request(enum pmu_idle_req req, bool idle); + #endif diff --git a/arch/arm/mach-rk30/pmu.c b/arch/arm/mach-rk30/pmu.c index ec26036dba3a..7a244318c852 100644 --- a/arch/arm/mach-rk30/pmu.c +++ b/arch/arm/mach-rk30/pmu.c @@ -39,6 +39,48 @@ void pmu_set_power_domain(enum pmu_power_domain pd, bool on) unsigned long flags; spin_lock_irqsave(&pmu_pd_lock, flags); + if (!on) { + /* if power down, idle request to NIU first */ + if (pd == PD_VIO) + pmu_set_idle_request(IDLE_REQ_VIO, true); + else if (pd == PD_VIDEO) + pmu_set_idle_request(IDLE_REQ_VIDEO, true); + else if (pd == PD_GPU) + pmu_set_idle_request(IDLE_REQ_GPU, true); + } do_pmu_set_power_domain(pd, on); + if (on) { + /* if power up, idle request release to NIU */ + if (pd == PD_VIO) + pmu_set_idle_request(IDLE_REQ_VIO, false); + else if (pd == PD_VIDEO) + pmu_set_idle_request(IDLE_REQ_VIDEO, false); + else if (pd == PD_GPU) + pmu_set_idle_request(IDLE_REQ_GPU, false); + } spin_unlock_irqrestore(&pmu_pd_lock, flags); } + +static DEFINE_SPINLOCK(pmu_misc_con1_lock); + +void pmu_set_idle_request(enum pmu_idle_req req, bool idle) +{ + u32 idle_mask = 1 << (26 - req); + u32 idle_target = idle << (26 - req); + u32 mask = 1 << (req + 1); + u32 val; + unsigned long flags; + + spin_lock_irqsave(&pmu_misc_con1_lock, flags); + val = readl_relaxed(RK30_PMU_BASE + PMU_MISC_CON1); + if (idle) + val |= mask; + else + val &= ~mask; + writel_relaxed(val, RK30_PMU_BASE + PMU_MISC_CON1); + dsb(); + + while ((readl_relaxed(RK30_PMU_BASE + PMU_PWRDN_ST) & idle_mask) != idle_target) + ; + spin_unlock_irqrestore(&pmu_misc_con1_lock, flags); +}