| From 2fb0420dd6b871c2e1c7d7cf19098a8dc1bb8c5b Mon Sep 17 00:00:00 2001 |
| From: Nicolas Pitre <nicolas.pitre@linaro.org> |
| Date: Tue, 19 Mar 2013 23:59:04 -0400 |
| Subject: drivers: irq-chip: irq-gic: introduce gic_cpu_if_down() |
| |
| When processors are about to hit low power states, the assertion of |
| standbywfi signal, triggered by the wfi instruction, is essential to |
| entering low power modes. If an IRQ is pending on the processor at the |
| time wfi is issued, the wfi instruction completes and the processor |
| restarts execution without asserting the standbywfi signal. Depending |
| on the platform power controller HW this behaviour can be acceptable or |
| not; if this behaviour must be prevented software should be provided |
| with a way to disable the routing of interrupts to the core IRQ pins. |
| |
| On systems where raw GIC distributor interrupts are connected to the power |
| controller as wake-up events (hence the power controller still senses |
| IRQs and can wake up cores upon IRQ pending), the GIC CPU interface can |
| be disabled on power down, so that the GIC CPU IF output is gated and wfi |
| cannot complete, thereby preventing the standbywfi issue. |
| |
| This patch adds a simple function to the GIC driver that allows to |
| disable the GIC CPU IF from power down procedures. |
| |
| Signed-off-by: Nicolas Pitre <nico@linaro.org> |
| Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| [rewrote commit log] |
| |
| Signed-off-by: Olof Johansson <olof@lixom.net> |
| (cherry picked from commit 10d9eb8a17cfb697967928bde06f3e7e530b03ac) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/irqchip/irq-gic.c | 6 ++++++ |
| include/linux/irqchip/arm-gic.h | 1 + |
| 2 files changed, 7 insertions(+) |
| |
| diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c |
| index 19ceaa60..fe44d3e2 100644 |
| --- a/drivers/irqchip/irq-gic.c |
| +++ b/drivers/irqchip/irq-gic.c |
| @@ -453,6 +453,12 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) |
| writel_relaxed(1, base + GIC_CPU_CTRL); |
| } |
| |
| +void gic_cpu_if_down(void) |
| +{ |
| + void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); |
| + writel_relaxed(0, cpu_base + GIC_CPU_CTRL); |
| +} |
| + |
| #ifdef CONFIG_CPU_PM |
| /* |
| * Saves the GIC distributor registers during suspend or idle. Must be called |
| diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h |
| index 3e203eb2..0e5d9ecd 100644 |
| --- a/include/linux/irqchip/arm-gic.h |
| +++ b/include/linux/irqchip/arm-gic.h |
| @@ -66,6 +66,7 @@ extern struct irq_chip gic_arch_extn; |
| void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, |
| u32 offset, struct device_node *); |
| void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); |
| +void gic_cpu_if_down(void); |
| |
| static inline void gic_init(unsigned int nr, int start, |
| void __iomem *dist , void __iomem *cpu) |
| -- |
| 1.8.4.3.gca3854a |
| |