diff options
author | Scott Williams <scwilliams@nvidia.com> | 2012-02-01 17:06:50 -0800 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2012-06-22 18:29:54 +0530 |
commit | 7a2e5ae3e6c26ca91281787913fa1c547285cceb (patch) | |
tree | e02415b59db194e2b2052bf57b8da7ecedb3f4ac /arch/arm/mach-tegra/gic.c | |
parent | 513162b825d2034cbfcd6623ce9537caf69d270c (diff) |
ARM: tegra: Reprogram GIC CPU interface on CPU PM entry
To prevent race conditions and ensure proper interrupt routing on
Cortex-A15 CPUs when they are power-gated, add a CPU PM notifier
call-back to reprogram the GIC CPU interface on PM entry. The
GIC CPU interface will be reset back to its normal state by
the common GIC CPU PM exit callback when the CPU wakes up.
BUG 929216
Change-Id: I2280468a001b41ca2a9db8edfcd7bd65f82b1fcd
Signed-off-by: Scott Williams <scwilliams@nvidia.com>
Reviewed-on: http://git-master/r/79091
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-by: Jin Qian <jqian@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/gic.c')
-rw-r--r-- | arch/arm/mach-tegra/gic.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/gic.c b/arch/arm/mach-tegra/gic.c index 5162c6331598..2b21effe7977 100644 --- a/arch/arm/mach-tegra/gic.c +++ b/arch/arm/mach-tegra/gic.c @@ -18,6 +18,7 @@ #include <linux/irqnr.h> #include <asm/hardware/gic.h> +#include <asm/cpu_pm.h> #include <mach/iomap.h> #include <mach/irqs.h> @@ -128,6 +129,27 @@ void tegra_gic_affinity_to_cpu0(void) wmb(); } #endif + +static int tegra_gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) +{ + u32 gic_cpu_ctrl; + + switch (cmd) { + case CPU_PM_ENTER: + gic_cpu_ctrl = readl(tegra_gic_cpu_base + GIC_CPU_CTRL); + if (gic_cpu_ctrl & 1) { + gic_cpu_ctrl |= 0x1E0; + writel(gic_cpu_ctrl, tegra_gic_cpu_base + GIC_CPU_CTRL); + } + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block tegra_gic_notifier_block = { + .notifier_call = tegra_gic_notifier, +}; #endif void __init tegra_gic_init(void) @@ -146,4 +168,9 @@ void __init tegra_gic_init(void) gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), tegra_gic_cpu_base); + +#ifdef CONFIG_PM_SLEEP + if (is_vgic) + cpu_pm_register_notifier(&tegra_gic_notifier_block); +#endif } |