diff options
author | Alex Frid <afrid@nvidia.com> | 2011-08-08 21:02:51 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:48:24 -0800 |
commit | 311dd1c318b70e93bcefec15456a10ff2b9eb0ff (patch) | |
tree | 4846c9ee915e1e7ca9700055eb6253ad5472907c /arch/arm/mach-tegra/powergate.c | |
parent | 6611d8bec94a5b8b667bd8ca2d8205b4416b7e7e (diff) |
ARM: tegra: power: Wait for power-gate toggle completion
Bug 857044
Original-Change-Id: I80c8c2183426fbaa8b7d5316c09709c9de7ea39d
Reviewed-on: http://git-master/r/45970
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: Karan Jhavar <kjhavar@nvidia.com>
Reviewed-by: Narendra Damahe <ndamahe@nvidia.com>
Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Rebase-Id: Rd8c46b56d4ca22e05e40c664329d64f7bd6710f7
Diffstat (limited to 'arch/arm/mach-tegra/powergate.c')
-rw-r--r-- | arch/arm/mach-tegra/powergate.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 23b065c09e12..2e3abef55f86 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -413,6 +413,11 @@ static int tegra_powergate_set(int id, bool new_state) { bool status; unsigned long flags; + /* 10us timeout for toggle operation if it takes affect*/ + int toggle_timeout = 10; + /* 100 * 10 = 1000us timeout for toggle command to take affect in case + of contention with h/w initiated CPU power gating */ + int contention_timeout = 100; spin_lock_irqsave(&tegra_powergate_lock, flags); @@ -423,10 +428,33 @@ static int tegra_powergate_set(int id, bool new_state) return -EINVAL; } - pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); + if (TEGRA_IS_CPU_POWERGATE_ID(id)) { + /* CPU ungated in s/w only during boot/resume with outer + waiting loop and no contention from other CPUs */ + pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); + spin_unlock_irqrestore(&tegra_powergate_lock, flags); + return 0; + } + + do { + pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); + do { + udelay(1); + status = !!(pmc_read(PWRGATE_STATUS) & (1 << id)); + + toggle_timeout--; + } while ((status != new_state) && (toggle_timeout > 0)); + + contention_timeout--; + } while ((status != new_state) && (contention_timeout > 0)); spin_unlock_irqrestore(&tegra_powergate_lock, flags); + if (status != new_state) { + WARN(1, "Could not set powergate %d to %d", id, new_state); + return -EBUSY; + } + return 0; } |