summaryrefslogtreecommitdiff
path: root/arch/arm/mach-shmobile/pm-sh7372.c
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-07-10 12:39:32 +0400
committerRafael J. Wysocki <rjw@sisk.pl>2011-07-10 12:39:32 +0400
commit775b8ae8707592af9275b8b216c2bf056b3f5d82 (patch)
tree45547ece2b4012199e1a51f4cde3f9de640398fc /arch/arm/mach-shmobile/pm-sh7372.c
parent18b4f3f5d058b590e7189027eeb5d897742ade0a (diff)
downloadlinux-775b8ae8707592af9275b8b216c2bf056b3f5d82.tar.xz
ARM: mach-shmobile: sh7372 A3RV requires A4LC
Add a power domain workaround for the VPU and A3RV on sh7372. The sh7372 data sheet mentions that the VPU is located in the A3RV power domain. The A3RV power domain is not related to A4LC in any way, but testing shows that unless A3RV _and_ A4LC are powered on the VPU test program will bomb out. This issue may be caused by a more or less undocumented dependency on the MERAM block that happens to be located in A4LC. So now we know that the out-of-reset requirement of the VPU is that the MERAM is powered on. This patch adds a workaround for A3RV to make sure A4LC is powered on - this so we can use the VPU even though the LCDCs are in blanking state and A4LC is supposed to be off. Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'arch/arm/mach-shmobile/pm-sh7372.c')
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 9ad3b610f0fe..71400eae2b68 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -91,6 +91,36 @@ static int pd_power_up(struct generic_pm_domain *genpd)
return ret;
}
+static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
+{
+ int ret = pd_power_up(genpd);
+
+ /* force A4LC on after A3RV has been requested on */
+ pm_genpd_poweron(&sh7372_a4lc.genpd);
+
+ return ret;
+}
+
+static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
+{
+ int ret = pd_power_down(genpd);
+
+ /* try to power down A4LC after A3RV is requested off */
+ pm_genpd_poweron(&sh7372_a4lc.genpd);
+ queue_work(pm_wq, &sh7372_a4lc.genpd.power_off_work);
+
+ return ret;
+}
+
+static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
+{
+ /* only power down A4LC if A3RV is off */
+ if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
+ return pd_power_down(genpd);
+
+ return 0;
+}
+
static bool pd_active_wakeup(struct device *dev)
{
return true;
@@ -115,9 +145,18 @@ void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
genpd->stop_device = pm_clk_suspend;
genpd->start_device = pm_clk_resume;
genpd->active_wakeup = pd_active_wakeup;
- genpd->power_off = pd_power_down;
- genpd->power_on = pd_power_up;
- pd_power_up(&sh7372_pd->genpd);
+
+ if (sh7372_pd == &sh7372_a4lc) {
+ genpd->power_off = pd_power_down_a4lc;
+ genpd->power_on = pd_power_up;
+ } else if (sh7372_pd == &sh7372_a3rv) {
+ genpd->power_off = pd_power_down_a3rv;
+ genpd->power_on = pd_power_up_a3rv;
+ } else {
+ genpd->power_off = pd_power_down;
+ genpd->power_on = pd_power_up;
+ }
+ genpd->power_on(&sh7372_pd->genpd);
shmobile_runtime_pm_late_init = sh7372_late_pm_domain_off;
}