blob: 01a623d8e59f7f3b4926acdd2b442e5782a27893 [file] [log] [blame]
Russell Kingf27ecac2005-08-18 21:31:00 +01001/*
Russell Kingf27ecac2005-08-18 21:31:00 +01002 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Interrupt architecture for the GIC:
9 *
10 * o There is one Interrupt Distributor, which receives interrupts
11 * from system devices and sends them to the Interrupt Controllers.
12 *
13 * o There is one CPU Interface per CPU, which sends interrupts sent
14 * by the Distributor, and interrupts generated locally, to the
Catalin Marinasb3a1bde2007-02-14 19:14:56 +010015 * associated CPU. The base address of the CPU interface is usually
16 * aliased so that the same address points to different chips depending
17 * on the CPU it is accessed from.
Russell Kingf27ecac2005-08-18 21:31:00 +010018 *
19 * Note that IRQs 0-31 are special - they are local to each CPU.
20 * As such, the enable set/clear, pending set/clear and active bit
21 * registers are banked per-cpu for these sources.
22 */
23#include <linux/init.h>
24#include <linux/kernel.h>
Rob Herringf37a53c2011-10-21 17:14:27 -050025#include <linux/err.h>
Arnd Bergmann7e1efcf2011-11-01 00:28:37 +010026#include <linux/module.h>
Russell Kingf27ecac2005-08-18 21:31:00 +010027#include <linux/list.h>
28#include <linux/smp.h>
Catalin Marinasc0114702013-01-14 18:05:37 +000029#include <linux/cpu.h>
Colin Cross254056f2011-02-10 12:54:10 -080030#include <linux/cpu_pm.h>
Catalin Marinasdcb86e82005-08-31 21:45:14 +010031#include <linux/cpumask.h>
Russell Kingfced80c2008-09-06 12:10:45 +010032#include <linux/io.h>
Rob Herringb3f7ed02011-09-28 21:27:52 -050033#include <linux/of.h>
34#include <linux/of_address.h>
35#include <linux/of_irq.h>
Rob Herring4294f8b2011-09-28 21:25:31 -050036#include <linux/irqdomain.h>
Marc Zyngier292b2932011-07-20 16:24:14 +010037#include <linux/interrupt.h>
38#include <linux/percpu.h>
39#include <linux/slab.h>
Catalin Marinasde88cbb2013-01-18 15:31:37 +000040#include <linux/irqchip/chained_irq.h>
Rob Herring520f7bd2012-12-27 13:10:24 -060041#include <linux/irqchip/arm-gic.h>
Russell Kingf27ecac2005-08-18 21:31:00 +010042
43#include <asm/irq.h>
Marc Zyngier562e0022011-09-06 09:56:17 +010044#include <asm/exception.h>
Will Deaconeb504392012-01-20 12:01:12 +010045#include <asm/smp_plat.h>
Russell Kingf27ecac2005-08-18 21:31:00 +010046
Rob Herring81243e42012-11-20 21:21:40 -060047#include "irqchip.h"
Russell Kingf27ecac2005-08-18 21:31:00 +010048
Marc Zyngierdb0d4db2011-11-12 16:09:49 +000049union gic_base {
50 void __iomem *common_base;
Stephen Boyd7c284952014-03-04 17:02:01 -080051 void __percpu * __iomem *percpu_base;
Marc Zyngierdb0d4db2011-11-12 16:09:49 +000052};
53
54struct gic_chip_data {
Marc Zyngierdb0d4db2011-11-12 16:09:49 +000055 union gic_base dist_base;
56 union gic_base cpu_base;
57#ifdef CONFIG_CPU_PM
58 u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
59 u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
60 u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
61 u32 __percpu *saved_ppi_enable;
62 u32 __percpu *saved_ppi_conf;
63#endif
Grant Likely75294952012-02-14 14:06:57 -070064 struct irq_domain *domain;
Marc Zyngierdb0d4db2011-11-12 16:09:49 +000065 unsigned int gic_irqs;
66#ifdef CONFIG_GIC_NON_BANKED
67 void __iomem *(*get_base)(union gic_base *);
68#endif
69};
70
Thomas Gleixnerbd31b852009-07-03 08:44:46 -050071static DEFINE_RAW_SPINLOCK(irq_controller_lock);
Russell Kingf27ecac2005-08-18 21:31:00 +010072
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +010073/*
Nicolas Pitre384a2902012-04-11 18:55:48 -040074 * The GIC mapping of CPU interfaces does not necessarily match
75 * the logical CPU numbering. Let's use a mapping as returned
76 * by the GIC itself.
77 */
78#define NR_GIC_CPU_IF 8
79static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
80
81/*
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +010082 * Supported arch specific GIC irq extension.
83 * Default make them NULL.
84 */
85struct irq_chip gic_arch_extn = {
Will Deacon1a017532011-02-09 12:01:12 +000086 .irq_eoi = NULL,
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +010087 .irq_mask = NULL,
88 .irq_unmask = NULL,
89 .irq_retrigger = NULL,
90 .irq_set_type = NULL,
91 .irq_set_wake = NULL,
92};
93
Catalin Marinasb3a1bde2007-02-14 19:14:56 +010094#ifndef MAX_GIC_NR
95#define MAX_GIC_NR 1
96#endif
97
Russell Kingbef8f9e2010-12-04 16:50:58 +000098static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
Catalin Marinasb3a1bde2007-02-14 19:14:56 +010099
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000100#ifdef CONFIG_GIC_NON_BANKED
101static void __iomem *gic_get_percpu_base(union gic_base *base)
102{
103 return *__this_cpu_ptr(base->percpu_base);
104}
105
106static void __iomem *gic_get_common_base(union gic_base *base)
107{
108 return base->common_base;
109}
110
111static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data)
112{
113 return data->get_base(&data->dist_base);
114}
115
116static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data)
117{
118 return data->get_base(&data->cpu_base);
119}
120
121static inline void gic_set_base_accessor(struct gic_chip_data *data,
122 void __iomem *(*f)(union gic_base *))
123{
124 data->get_base = f;
125}
126#else
127#define gic_data_dist_base(d) ((d)->dist_base.common_base)
128#define gic_data_cpu_base(d) ((d)->cpu_base.common_base)
Sachin Kamat46f101d2013-03-13 15:05:15 +0530129#define gic_set_base_accessor(d, f)
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000130#endif
131
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100132static inline void __iomem *gic_dist_base(struct irq_data *d)
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100133{
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100134 struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000135 return gic_data_dist_base(gic_data);
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100136}
137
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100138static inline void __iomem *gic_cpu_base(struct irq_data *d)
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100139{
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100140 struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000141 return gic_data_cpu_base(gic_data);
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100142}
143
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100144static inline unsigned int gic_irq(struct irq_data *d)
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100145{
Rob Herring4294f8b2011-09-28 21:25:31 -0500146 return d->hwirq;
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100147}
148
Russell Kingf27ecac2005-08-18 21:31:00 +0100149/*
150 * Routines to acknowledge, disable and enable interrupts
Russell Kingf27ecac2005-08-18 21:31:00 +0100151 */
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100152static void gic_mask_irq(struct irq_data *d)
Russell Kingf27ecac2005-08-18 21:31:00 +0100153{
Rob Herring4294f8b2011-09-28 21:25:31 -0500154 u32 mask = 1 << (gic_irq(d) % 32);
Thomas Gleixnerc4bfa282006-07-01 22:32:14 +0100155
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500156 raw_spin_lock(&irq_controller_lock);
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530157 writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100158 if (gic_arch_extn.irq_mask)
159 gic_arch_extn.irq_mask(d);
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500160 raw_spin_unlock(&irq_controller_lock);
Russell Kingf27ecac2005-08-18 21:31:00 +0100161}
162
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100163static void gic_unmask_irq(struct irq_data *d)
Russell Kingf27ecac2005-08-18 21:31:00 +0100164{
Rob Herring4294f8b2011-09-28 21:25:31 -0500165 u32 mask = 1 << (gic_irq(d) % 32);
Thomas Gleixnerc4bfa282006-07-01 22:32:14 +0100166
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500167 raw_spin_lock(&irq_controller_lock);
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100168 if (gic_arch_extn.irq_unmask)
169 gic_arch_extn.irq_unmask(d);
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530170 writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500171 raw_spin_unlock(&irq_controller_lock);
Russell Kingf27ecac2005-08-18 21:31:00 +0100172}
173
Will Deacon1a017532011-02-09 12:01:12 +0000174static void gic_eoi_irq(struct irq_data *d)
175{
176 if (gic_arch_extn.irq_eoi) {
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500177 raw_spin_lock(&irq_controller_lock);
Will Deacon1a017532011-02-09 12:01:12 +0000178 gic_arch_extn.irq_eoi(d);
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500179 raw_spin_unlock(&irq_controller_lock);
Will Deacon1a017532011-02-09 12:01:12 +0000180 }
181
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530182 writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
Will Deacon1a017532011-02-09 12:01:12 +0000183}
184
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100185static int gic_set_type(struct irq_data *d, unsigned int type)
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100186{
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100187 void __iomem *base = gic_dist_base(d);
188 unsigned int gicirq = gic_irq(d);
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100189 u32 enablemask = 1 << (gicirq % 32);
190 u32 enableoff = (gicirq / 32) * 4;
191 u32 confmask = 0x2 << ((gicirq % 16) * 2);
192 u32 confoff = (gicirq / 16) * 4;
193 bool enabled = false;
194 u32 val;
195
196 /* Interrupt configuration for SGIs can't be changed */
197 if (gicirq < 16)
198 return -EINVAL;
199
200 if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
201 return -EINVAL;
202
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500203 raw_spin_lock(&irq_controller_lock);
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100204
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100205 if (gic_arch_extn.irq_set_type)
206 gic_arch_extn.irq_set_type(d, type);
207
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530208 val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100209 if (type == IRQ_TYPE_LEVEL_HIGH)
210 val &= ~confmask;
211 else if (type == IRQ_TYPE_EDGE_RISING)
212 val |= confmask;
213
214 /*
215 * As recommended by the spec, disable the interrupt before changing
216 * the configuration
217 */
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530218 if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
219 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100220 enabled = true;
221 }
222
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530223 writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100224
225 if (enabled)
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530226 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100227
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500228 raw_spin_unlock(&irq_controller_lock);
Rabin Vincent5c0c1f02010-05-28 04:37:38 +0100229
230 return 0;
231}
232
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100233static int gic_retrigger(struct irq_data *d)
234{
235 if (gic_arch_extn.irq_retrigger)
236 return gic_arch_extn.irq_retrigger(d);
237
Abhijeet Dharmapurikarbad9a432013-03-19 16:05:49 -0700238 /* the genirq layer expects 0 if we can't retrigger in hardware */
239 return 0;
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100240}
241
Catalin Marinasa06f5462005-09-30 16:07:05 +0100242#ifdef CONFIG_SMP
Russell Kingc1917892011-01-23 12:12:01 +0000243static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
244 bool force)
Russell Kingf27ecac2005-08-18 21:31:00 +0100245{
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100246 void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
Rob Herring4294f8b2011-09-28 21:25:31 -0500247 unsigned int shift = (gic_irq(d) % 4) * 8;
Russell King5dfc54e2011-07-21 15:00:57 +0100248 unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
Russell Kingc1917892011-01-23 12:12:01 +0000249 u32 val, mask, bit;
250
Nicolas Pitre384a2902012-04-11 18:55:48 -0400251 if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
Russell Kingc1917892011-01-23 12:12:01 +0000252 return -EINVAL;
253
Nicolas Pitre176c78d2012-04-12 01:40:31 -0400254 raw_spin_lock(&irq_controller_lock);
Russell Kingc1917892011-01-23 12:12:01 +0000255 mask = 0xff << shift;
Nicolas Pitre384a2902012-04-11 18:55:48 -0400256 bit = gic_cpu_map[cpu] << shift;
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530257 val = readl_relaxed(reg) & ~mask;
258 writel_relaxed(val | bit, reg);
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500259 raw_spin_unlock(&irq_controller_lock);
Yinghai Lud5dedd42009-04-27 17:59:21 -0700260
Russell King5dfc54e2011-07-21 15:00:57 +0100261 return IRQ_SET_MASK_OK;
Russell Kingf27ecac2005-08-18 21:31:00 +0100262}
Catalin Marinasa06f5462005-09-30 16:07:05 +0100263#endif
Russell Kingf27ecac2005-08-18 21:31:00 +0100264
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100265#ifdef CONFIG_PM
266static int gic_set_wake(struct irq_data *d, unsigned int on)
267{
268 int ret = -ENXIO;
269
270 if (gic_arch_extn.irq_set_wake)
271 ret = gic_arch_extn.irq_set_wake(d, on);
272
273 return ret;
274}
275
276#else
277#define gic_set_wake NULL
278#endif
279
Stephen Boydc0627e32014-03-04 16:40:30 -0800280static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
Marc Zyngier562e0022011-09-06 09:56:17 +0100281{
282 u32 irqstat, irqnr;
283 struct gic_chip_data *gic = &gic_data[0];
284 void __iomem *cpu_base = gic_data_cpu_base(gic);
285
286 do {
287 irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
Haojian Zhuang03c2fd42014-05-11 16:05:58 +0800288 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
Marc Zyngier562e0022011-09-06 09:56:17 +0100289
290 if (likely(irqnr > 15 && irqnr < 1021)) {
Grant Likely75294952012-02-14 14:06:57 -0700291 irqnr = irq_find_mapping(gic->domain, irqnr);
Marc Zyngier562e0022011-09-06 09:56:17 +0100292 handle_IRQ(irqnr, regs);
293 continue;
294 }
295 if (irqnr < 16) {
296 writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
297#ifdef CONFIG_SMP
298 handle_IPI(irqnr, regs);
299#endif
300 continue;
301 }
302 break;
303 } while (1);
304}
305
Russell King0f347bb2007-05-17 10:11:34 +0100306static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100307{
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100308 struct gic_chip_data *chip_data = irq_get_handler_data(irq);
309 struct irq_chip *chip = irq_get_chip(irq);
Russell King0f347bb2007-05-17 10:11:34 +0100310 unsigned int cascade_irq, gic_irq;
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100311 unsigned long status;
312
Will Deacon1a017532011-02-09 12:01:12 +0000313 chained_irq_enter(chip, desc);
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100314
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500315 raw_spin_lock(&irq_controller_lock);
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000316 status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK);
Thomas Gleixnerbd31b852009-07-03 08:44:46 -0500317 raw_spin_unlock(&irq_controller_lock);
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100318
Russell King0f347bb2007-05-17 10:11:34 +0100319 gic_irq = (status & 0x3ff);
320 if (gic_irq == 1023)
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100321 goto out;
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100322
Grant Likely75294952012-02-14 14:06:57 -0700323 cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
324 if (unlikely(gic_irq < 32 || gic_irq > 1020))
Catalin Marinasaec00952013-01-14 17:53:39 +0000325 handle_bad_irq(cascade_irq, desc);
Russell King0f347bb2007-05-17 10:11:34 +0100326 else
327 generic_handle_irq(cascade_irq);
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100328
329 out:
Will Deacon1a017532011-02-09 12:01:12 +0000330 chained_irq_exit(chip, desc);
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100331}
332
David Brownell38c677c2006-08-01 22:26:25 +0100333static struct irq_chip gic_chip = {
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100334 .name = "GIC",
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100335 .irq_mask = gic_mask_irq,
336 .irq_unmask = gic_unmask_irq,
Will Deacon1a017532011-02-09 12:01:12 +0000337 .irq_eoi = gic_eoi_irq,
Lennert Buytenhek7d1f4282010-11-29 10:18:20 +0100338 .irq_set_type = gic_set_type,
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100339 .irq_retrigger = gic_retrigger,
Russell Kingf27ecac2005-08-18 21:31:00 +0100340#ifdef CONFIG_SMP
Russell Kingc1917892011-01-23 12:12:01 +0000341 .irq_set_affinity = gic_set_affinity,
Russell Kingf27ecac2005-08-18 21:31:00 +0100342#endif
Santosh Shilimkard7ed36a2011-03-02 08:03:22 +0100343 .irq_set_wake = gic_set_wake,
Russell Kingf27ecac2005-08-18 21:31:00 +0100344};
345
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100346void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
347{
348 if (gic_nr >= MAX_GIC_NR)
349 BUG();
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100350 if (irq_set_handler_data(irq, &gic_data[gic_nr]) != 0)
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100351 BUG();
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100352 irq_set_chained_handler(irq, gic_handle_cascade_irq);
Catalin Marinasb3a1bde2007-02-14 19:14:56 +0100353}
354
Russell King2bb31352013-01-30 23:49:57 +0000355static u8 gic_get_cpumask(struct gic_chip_data *gic)
356{
357 void __iomem *base = gic_data_dist_base(gic);
358 u32 mask, i;
359
360 for (i = mask = 0; i < 32; i += 4) {
361 mask = readl_relaxed(base + GIC_DIST_TARGET + i);
362 mask |= mask >> 16;
363 mask |= mask >> 8;
364 if (mask)
365 break;
366 }
367
368 if (!mask)
369 pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
370
371 return mask;
372}
373
Rob Herring4294f8b2011-09-28 21:25:31 -0500374static void __init gic_dist_init(struct gic_chip_data *gic)
Russell Kingf27ecac2005-08-18 21:31:00 +0100375{
Grant Likely75294952012-02-14 14:06:57 -0700376 unsigned int i;
Will Deacon267840f2011-08-23 22:20:03 +0100377 u32 cpumask;
Rob Herring4294f8b2011-09-28 21:25:31 -0500378 unsigned int gic_irqs = gic->gic_irqs;
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000379 void __iomem *base = gic_data_dist_base(gic);
Russell Kingf27ecac2005-08-18 21:31:00 +0100380
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530381 writel_relaxed(0, base + GIC_DIST_CTRL);
Russell Kingf27ecac2005-08-18 21:31:00 +0100382
383 /*
Russell Kingf27ecac2005-08-18 21:31:00 +0100384 * Set all global interrupts to be level triggered, active low.
385 */
Pawel Molle6afec92010-11-26 13:45:43 +0100386 for (i = 32; i < gic_irqs; i += 16)
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530387 writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
Russell Kingf27ecac2005-08-18 21:31:00 +0100388
389 /*
390 * Set all global interrupts to this CPU only.
391 */
Russell King2bb31352013-01-30 23:49:57 +0000392 cpumask = gic_get_cpumask(gic);
393 cpumask |= cpumask << 8;
394 cpumask |= cpumask << 16;
Pawel Molle6afec92010-11-26 13:45:43 +0100395 for (i = 32; i < gic_irqs; i += 4)
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530396 writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
Russell Kingf27ecac2005-08-18 21:31:00 +0100397
398 /*
Russell King9395f6e2010-11-11 23:10:30 +0000399 * Set priority on all global interrupts.
Russell Kingf27ecac2005-08-18 21:31:00 +0100400 */
Pawel Molle6afec92010-11-26 13:45:43 +0100401 for (i = 32; i < gic_irqs; i += 4)
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530402 writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
Russell Kingf27ecac2005-08-18 21:31:00 +0100403
404 /*
Russell King9395f6e2010-11-11 23:10:30 +0000405 * Disable all interrupts. Leave the PPI and SGIs alone
406 * as these enables are banked registers.
Russell Kingf27ecac2005-08-18 21:31:00 +0100407 */
Pawel Molle6afec92010-11-26 13:45:43 +0100408 for (i = 32; i < gic_irqs; i += 32)
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530409 writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
Russell Kingf27ecac2005-08-18 21:31:00 +0100410
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530411 writel_relaxed(1, base + GIC_DIST_CTRL);
Russell Kingf27ecac2005-08-18 21:31:00 +0100412}
413
Russell Kingbef8f9e2010-12-04 16:50:58 +0000414static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
Russell Kingf27ecac2005-08-18 21:31:00 +0100415{
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000416 void __iomem *dist_base = gic_data_dist_base(gic);
417 void __iomem *base = gic_data_cpu_base(gic);
Nicolas Pitre384a2902012-04-11 18:55:48 -0400418 unsigned int cpu_mask, cpu = smp_processor_id();
Russell King9395f6e2010-11-11 23:10:30 +0000419 int i;
420
Russell King9395f6e2010-11-11 23:10:30 +0000421 /*
Nicolas Pitre384a2902012-04-11 18:55:48 -0400422 * Get what the GIC says our CPU mask is.
423 */
424 BUG_ON(cpu >= NR_GIC_CPU_IF);
Russell King2bb31352013-01-30 23:49:57 +0000425 cpu_mask = gic_get_cpumask(gic);
Nicolas Pitre384a2902012-04-11 18:55:48 -0400426 gic_cpu_map[cpu] = cpu_mask;
427
428 /*
429 * Clear our mask from the other map entries in case they're
430 * still undefined.
431 */
432 for (i = 0; i < NR_GIC_CPU_IF; i++)
433 if (i != cpu)
434 gic_cpu_map[i] &= ~cpu_mask;
435
436 /*
Russell King9395f6e2010-11-11 23:10:30 +0000437 * Deal with the banked PPI and SGI interrupts - disable all
438 * PPI interrupts, ensure all SGI interrupts are enabled.
439 */
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530440 writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
441 writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
Russell King9395f6e2010-11-11 23:10:30 +0000442
443 /*
444 * Set priority on PPI and SGI interrupts
445 */
446 for (i = 0; i < 32; i += 4)
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530447 writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
Russell King9395f6e2010-11-11 23:10:30 +0000448
Santosh Shilimkar6ac77e42011-03-28 19:27:46 +0530449 writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
450 writel_relaxed(1, base + GIC_CPU_CTRL);
Russell Kingf27ecac2005-08-18 21:31:00 +0100451}
452
Nicolas Pitre0f4e18f2013-03-19 23:59:04 -0400453void gic_cpu_if_down(void)
454{
455 void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]);
456 writel_relaxed(0, cpu_base + GIC_CPU_CTRL);
457}
458
Colin Cross254056f2011-02-10 12:54:10 -0800459#ifdef CONFIG_CPU_PM
460/*
461 * Saves the GIC distributor registers during suspend or idle. Must be called
462 * with interrupts disabled but before powering down the GIC. After calling
463 * this function, no interrupts will be delivered by the GIC, and another
464 * platform-specific wakeup source must be enabled.
465 */
466static void gic_dist_save(unsigned int gic_nr)
467{
468 unsigned int gic_irqs;
469 void __iomem *dist_base;
470 int i;
471
472 if (gic_nr >= MAX_GIC_NR)
473 BUG();
474
475 gic_irqs = gic_data[gic_nr].gic_irqs;
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000476 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
Colin Cross254056f2011-02-10 12:54:10 -0800477
478 if (!dist_base)
479 return;
480
481 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
482 gic_data[gic_nr].saved_spi_conf[i] =
483 readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
484
485 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
486 gic_data[gic_nr].saved_spi_target[i] =
487 readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
488
489 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
490 gic_data[gic_nr].saved_spi_enable[i] =
491 readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
492}
493
494/*
495 * Restores the GIC distributor registers during resume or when coming out of
496 * idle. Must be called before enabling interrupts. If a level interrupt
497 * that occured while the GIC was suspended is still present, it will be
498 * handled normally, but any edge interrupts that occured will not be seen by
499 * the GIC and need to be handled by the platform-specific wakeup source.
500 */
501static void gic_dist_restore(unsigned int gic_nr)
502{
503 unsigned int gic_irqs;
504 unsigned int i;
505 void __iomem *dist_base;
506
507 if (gic_nr >= MAX_GIC_NR)
508 BUG();
509
510 gic_irqs = gic_data[gic_nr].gic_irqs;
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000511 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
Colin Cross254056f2011-02-10 12:54:10 -0800512
513 if (!dist_base)
514 return;
515
516 writel_relaxed(0, dist_base + GIC_DIST_CTRL);
517
518 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
519 writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
520 dist_base + GIC_DIST_CONFIG + i * 4);
521
522 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
523 writel_relaxed(0xa0a0a0a0,
524 dist_base + GIC_DIST_PRI + i * 4);
525
526 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
527 writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
528 dist_base + GIC_DIST_TARGET + i * 4);
529
530 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
531 writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
532 dist_base + GIC_DIST_ENABLE_SET + i * 4);
533
534 writel_relaxed(1, dist_base + GIC_DIST_CTRL);
535}
536
537static void gic_cpu_save(unsigned int gic_nr)
538{
539 int i;
540 u32 *ptr;
541 void __iomem *dist_base;
542 void __iomem *cpu_base;
543
544 if (gic_nr >= MAX_GIC_NR)
545 BUG();
546
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000547 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
548 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
Colin Cross254056f2011-02-10 12:54:10 -0800549
550 if (!dist_base || !cpu_base)
551 return;
552
553 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
554 for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
555 ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
556
557 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
558 for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
559 ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
560
561}
562
563static void gic_cpu_restore(unsigned int gic_nr)
564{
565 int i;
566 u32 *ptr;
567 void __iomem *dist_base;
568 void __iomem *cpu_base;
569
570 if (gic_nr >= MAX_GIC_NR)
571 BUG();
572
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000573 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
574 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
Colin Cross254056f2011-02-10 12:54:10 -0800575
576 if (!dist_base || !cpu_base)
577 return;
578
579 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
580 for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
581 writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
582
583 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
584 for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
585 writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
586
587 for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
588 writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
589
590 writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
591 writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
592}
593
594static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
595{
596 int i;
597
598 for (i = 0; i < MAX_GIC_NR; i++) {
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000599#ifdef CONFIG_GIC_NON_BANKED
600 /* Skip over unused GICs */
601 if (!gic_data[i].get_base)
602 continue;
603#endif
Colin Cross254056f2011-02-10 12:54:10 -0800604 switch (cmd) {
605 case CPU_PM_ENTER:
606 gic_cpu_save(i);
607 break;
608 case CPU_PM_ENTER_FAILED:
609 case CPU_PM_EXIT:
610 gic_cpu_restore(i);
611 break;
612 case CPU_CLUSTER_PM_ENTER:
613 gic_dist_save(i);
614 break;
615 case CPU_CLUSTER_PM_ENTER_FAILED:
616 case CPU_CLUSTER_PM_EXIT:
617 gic_dist_restore(i);
618 break;
619 }
620 }
621
622 return NOTIFY_OK;
623}
624
625static struct notifier_block gic_notifier_block = {
626 .notifier_call = gic_notifier,
627};
628
629static void __init gic_pm_init(struct gic_chip_data *gic)
630{
631 gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
632 sizeof(u32));
633 BUG_ON(!gic->saved_ppi_enable);
634
635 gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
636 sizeof(u32));
637 BUG_ON(!gic->saved_ppi_conf);
638
Marc Zyngierabdd7b92011-11-25 17:58:19 +0100639 if (gic == &gic_data[0])
640 cpu_pm_register_notifier(&gic_notifier_block);
Colin Cross254056f2011-02-10 12:54:10 -0800641}
642#else
643static void __init gic_pm_init(struct gic_chip_data *gic)
644{
645}
646#endif
647
Rob Herringb1cffeb2012-11-26 15:05:48 -0600648#ifdef CONFIG_SMP
Stephen Boyd7c284952014-03-04 17:02:01 -0800649static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
Rob Herringb1cffeb2012-11-26 15:05:48 -0600650{
651 int cpu;
Nicolas Pitre176c78d2012-04-12 01:40:31 -0400652 unsigned long flags, map = 0;
653
654 raw_spin_lock_irqsave(&irq_controller_lock, flags);
Rob Herringb1cffeb2012-11-26 15:05:48 -0600655
656 /* Convert our logical CPU mask into a physical one. */
657 for_each_cpu(cpu, mask)
Javi Merino91bdf0d2013-02-19 13:52:22 +0000658 map |= gic_cpu_map[cpu];
Rob Herringb1cffeb2012-11-26 15:05:48 -0600659
660 /*
661 * Ensure that stores to Normal memory are visible to the
Will Deacon32fd0492014-02-20 17:42:07 +0000662 * other CPUs before they observe us issuing the IPI.
Rob Herringb1cffeb2012-11-26 15:05:48 -0600663 */
Will Deacon32fd0492014-02-20 17:42:07 +0000664 dmb(ishst);
Rob Herringb1cffeb2012-11-26 15:05:48 -0600665
666 /* this always happens on GIC0 */
667 writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
Nicolas Pitre176c78d2012-04-12 01:40:31 -0400668
669 raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
670}
671#endif
672
673#ifdef CONFIG_BL_SWITCHER
674/*
Nicolas Pitre43eafb42012-11-28 18:48:19 -0500675 * gic_send_sgi - send a SGI directly to given CPU interface number
676 *
677 * cpu_id: the ID for the destination CPU interface
678 * irq: the IPI number to send a SGI for
679 */
680void gic_send_sgi(unsigned int cpu_id, unsigned int irq)
681{
682 BUG_ON(cpu_id >= NR_GIC_CPU_IF);
683 cpu_id = 1 << cpu_id;
684 /* this always happens on GIC0 */
685 writel_relaxed((cpu_id << 16) | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
686}
687
688/*
Christoffer Dall0284d572014-10-02 09:29:59 +0200689 * gic_get_cpu_id - get the CPU interface ID for the specified CPU
690 *
691 * @cpu: the logical CPU number to get the GIC ID for.
692 *
693 * Return the CPU interface ID for the given logical CPU number,
694 * or -1 if the CPU number is too large or the interface ID is
695 * unknown (more than one bit set).
696 */
697int gic_get_cpu_id(unsigned int cpu)
698{
699 unsigned int cpu_bit;
700
701 if (cpu >= NR_GIC_CPU_IF)
702 return -1;
703 cpu_bit = gic_cpu_map[cpu];
704 if (cpu_bit & (cpu_bit - 1))
705 return -1;
706 return __ffs(cpu_bit);
707}
708
709/*
Nicolas Pitre176c78d2012-04-12 01:40:31 -0400710 * gic_migrate_target - migrate IRQs to another CPU interface
711 *
712 * @new_cpu_id: the CPU target ID to migrate IRQs to
713 *
714 * Migrate all peripheral interrupts with a target matching the current CPU
715 * to the interface corresponding to @new_cpu_id. The CPU interface mapping
716 * is also updated. Targets to other CPU interfaces are unchanged.
717 * This must be called with IRQs locally disabled.
718 */
719void gic_migrate_target(unsigned int new_cpu_id)
720{
721 unsigned int cur_cpu_id, gic_irqs, gic_nr = 0;
722 void __iomem *dist_base;
723 int i, ror_val, cpu = smp_processor_id();
724 u32 val, cur_target_mask, active_mask;
725
726 if (gic_nr >= MAX_GIC_NR)
727 BUG();
728
729 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
730 if (!dist_base)
731 return;
732 gic_irqs = gic_data[gic_nr].gic_irqs;
733
734 cur_cpu_id = __ffs(gic_cpu_map[cpu]);
735 cur_target_mask = 0x01010101 << cur_cpu_id;
736 ror_val = (cur_cpu_id - new_cpu_id) & 31;
737
738 raw_spin_lock(&irq_controller_lock);
739
740 /* Update the target interface for this logical CPU */
741 gic_cpu_map[cpu] = 1 << new_cpu_id;
742
743 /*
744 * Find all the peripheral interrupts targetting the current
745 * CPU interface and migrate them to the new CPU interface.
746 * We skip DIST_TARGET 0 to 7 as they are read-only.
747 */
748 for (i = 8; i < DIV_ROUND_UP(gic_irqs, 4); i++) {
749 val = readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
750 active_mask = val & cur_target_mask;
751 if (active_mask) {
752 val &= ~active_mask;
753 val |= ror32(active_mask, ror_val);
754 writel_relaxed(val, dist_base + GIC_DIST_TARGET + i*4);
755 }
756 }
757
758 raw_spin_unlock(&irq_controller_lock);
759
760 /*
761 * Now let's migrate and clear any potential SGIs that might be
762 * pending for us (cur_cpu_id). Since GIC_DIST_SGI_PENDING_SET
763 * is a banked register, we can only forward the SGI using
764 * GIC_DIST_SOFTINT. The original SGI source is lost but Linux
765 * doesn't use that information anyway.
766 *
767 * For the same reason we do not adjust SGI source information
768 * for previously sent SGIs by us to other CPUs either.
769 */
770 for (i = 0; i < 16; i += 4) {
771 int j;
772 val = readl_relaxed(dist_base + GIC_DIST_SGI_PENDING_SET + i);
773 if (!val)
774 continue;
775 writel_relaxed(val, dist_base + GIC_DIST_SGI_PENDING_CLEAR + i);
776 for (j = i; j < i + 4; j++) {
777 if (val & 0xff)
778 writel_relaxed((1 << (new_cpu_id + 16)) | j,
779 dist_base + GIC_DIST_SOFTINT);
780 val >>= 8;
781 }
782 }
Rob Herringb1cffeb2012-11-26 15:05:48 -0600783}
Nicolas Pitref4bf1bf2012-11-28 18:17:25 -0500784
785/*
786 * gic_get_sgir_physaddr - get the physical address for the SGI register
787 *
788 * REturn the physical address of the SGI register to be used
789 * by some early assembly code when the kernel is not yet available.
790 */
791static unsigned long gic_dist_physaddr;
792
793unsigned long gic_get_sgir_physaddr(void)
794{
795 if (!gic_dist_physaddr)
796 return 0;
797 return gic_dist_physaddr + GIC_DIST_SOFTINT;
798}
799
800void __init gic_init_physaddr(struct device_node *node)
801{
802 struct resource res;
803 if (of_address_to_resource(node, 0, &res) == 0) {
804 gic_dist_physaddr = res.start;
805 pr_info("GIC physical location is %#lx\n", gic_dist_physaddr);
806 }
807}
808
809#else
810#define gic_init_physaddr(node) do { } while (0)
Rob Herringb1cffeb2012-11-26 15:05:48 -0600811#endif
812
Grant Likely75294952012-02-14 14:06:57 -0700813static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
814 irq_hw_number_t hw)
815{
816 if (hw < 32) {
817 irq_set_percpu_devid(irq);
818 irq_set_chip_and_handler(irq, &gic_chip,
819 handle_percpu_devid_irq);
820 set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
821 } else {
822 irq_set_chip_and_handler(irq, &gic_chip,
823 handle_fasteoi_irq);
824 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
Sricharan Rbd09b642013-12-03 15:57:22 +0530825
826 gic_routable_irq_domain_ops->map(d, irq, hw);
Grant Likely75294952012-02-14 14:06:57 -0700827 }
828 irq_set_chip_data(irq, d->host_data);
829 return 0;
830}
831
Sricharan Rbd09b642013-12-03 15:57:22 +0530832static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
833{
834 gic_routable_irq_domain_ops->unmap(d, irq);
835}
836
Grant Likely7bb69ba2012-02-14 14:06:48 -0700837static int gic_irq_domain_xlate(struct irq_domain *d,
838 struct device_node *controller,
839 const u32 *intspec, unsigned int intsize,
840 unsigned long *out_hwirq, unsigned int *out_type)
Rob Herringb3f7ed02011-09-28 21:27:52 -0500841{
Sricharan Rbd09b642013-12-03 15:57:22 +0530842 unsigned long ret = 0;
843
Rob Herringb3f7ed02011-09-28 21:27:52 -0500844 if (d->of_node != controller)
845 return -EINVAL;
846 if (intsize < 3)
847 return -EINVAL;
848
849 /* Get the interrupt number and add 16 to skip over SGIs */
850 *out_hwirq = intspec[1] + 16;
851
852 /* For SPIs, we need to add 16 more to get the GIC irq ID number */
Sricharan Rbd09b642013-12-03 15:57:22 +0530853 if (!intspec[0]) {
854 ret = gic_routable_irq_domain_ops->xlate(d, controller,
855 intspec,
856 intsize,
857 out_hwirq,
858 out_type);
859
860 if (IS_ERR_VALUE(ret))
861 return ret;
862 }
Rob Herringb3f7ed02011-09-28 21:27:52 -0500863
864 *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
Sricharan Rbd09b642013-12-03 15:57:22 +0530865
866 return ret;
Rob Herringb3f7ed02011-09-28 21:27:52 -0500867}
Rob Herringb3f7ed02011-09-28 21:27:52 -0500868
Catalin Marinasc0114702013-01-14 18:05:37 +0000869#ifdef CONFIG_SMP
870static int __cpuinit gic_secondary_init(struct notifier_block *nfb,
871 unsigned long action, void *hcpu)
872{
Shawn Guo8b6fd652013-06-12 19:30:27 +0800873 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
Catalin Marinasc0114702013-01-14 18:05:37 +0000874 gic_cpu_init(&gic_data[0]);
875 return NOTIFY_OK;
876}
877
878/*
879 * Notifier for enabling the GIC CPU interface. Set an arbitrarily high
880 * priority because the GIC needs to be up before the ARM generic timers.
881 */
882static struct notifier_block __cpuinitdata gic_cpu_notifier = {
883 .notifier_call = gic_secondary_init,
884 .priority = 100,
885};
886#endif
887
Stephen Boyd7c284952014-03-04 17:02:01 -0800888static const struct irq_domain_ops gic_irq_domain_ops = {
Grant Likely75294952012-02-14 14:06:57 -0700889 .map = gic_irq_domain_map,
Sricharan Rbd09b642013-12-03 15:57:22 +0530890 .unmap = gic_irq_domain_unmap,
Grant Likely7bb69ba2012-02-14 14:06:48 -0700891 .xlate = gic_irq_domain_xlate,
Rob Herring4294f8b2011-09-28 21:25:31 -0500892};
893
Sricharan Rbd09b642013-12-03 15:57:22 +0530894/* Default functions for routable irq domain */
895static int gic_routable_irq_domain_map(struct irq_domain *d, unsigned int irq,
896 irq_hw_number_t hw)
897{
898 return 0;
899}
900
901static void gic_routable_irq_domain_unmap(struct irq_domain *d,
902 unsigned int irq)
903{
904}
905
906static int gic_routable_irq_domain_xlate(struct irq_domain *d,
907 struct device_node *controller,
908 const u32 *intspec, unsigned int intsize,
909 unsigned long *out_hwirq,
910 unsigned int *out_type)
911{
912 *out_hwirq += 16;
913 return 0;
914}
915
916const struct irq_domain_ops gic_default_routable_irq_domain_ops = {
917 .map = gic_routable_irq_domain_map,
918 .unmap = gic_routable_irq_domain_unmap,
919 .xlate = gic_routable_irq_domain_xlate,
920};
921
922const struct irq_domain_ops *gic_routable_irq_domain_ops =
923 &gic_default_routable_irq_domain_ops;
924
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000925void __init gic_init_bases(unsigned int gic_nr, int irq_start,
926 void __iomem *dist_base, void __iomem *cpu_base,
Grant Likely75294952012-02-14 14:06:57 -0700927 u32 percpu_offset, struct device_node *node)
Russell Kingb580b892010-12-04 15:55:14 +0000928{
Grant Likely75294952012-02-14 14:06:57 -0700929 irq_hw_number_t hwirq_base;
Russell Kingbef8f9e2010-12-04 16:50:58 +0000930 struct gic_chip_data *gic;
Nicolas Pitre384a2902012-04-11 18:55:48 -0400931 int gic_irqs, irq_base, i;
Sricharan Rbd09b642013-12-03 15:57:22 +0530932 int nr_routable_irqs;
Russell Kingbef8f9e2010-12-04 16:50:58 +0000933
934 BUG_ON(gic_nr >= MAX_GIC_NR);
935
936 gic = &gic_data[gic_nr];
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000937#ifdef CONFIG_GIC_NON_BANKED
938 if (percpu_offset) { /* Frankein-GIC without banked registers... */
939 unsigned int cpu;
940
941 gic->dist_base.percpu_base = alloc_percpu(void __iomem *);
942 gic->cpu_base.percpu_base = alloc_percpu(void __iomem *);
943 if (WARN_ON(!gic->dist_base.percpu_base ||
944 !gic->cpu_base.percpu_base)) {
945 free_percpu(gic->dist_base.percpu_base);
946 free_percpu(gic->cpu_base.percpu_base);
947 return;
948 }
949
950 for_each_possible_cpu(cpu) {
951 unsigned long offset = percpu_offset * cpu_logical_map(cpu);
952 *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
953 *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
954 }
955
956 gic_set_base_accessor(gic, gic_get_percpu_base);
957 } else
958#endif
959 { /* Normal, sane GIC... */
960 WARN(percpu_offset,
961 "GIC_NON_BANKED not enabled, ignoring %08x offset!",
962 percpu_offset);
963 gic->dist_base.common_base = dist_base;
964 gic->cpu_base.common_base = cpu_base;
965 gic_set_base_accessor(gic, gic_get_common_base);
966 }
Russell Kingbef8f9e2010-12-04 16:50:58 +0000967
Rob Herring4294f8b2011-09-28 21:25:31 -0500968 /*
Nicolas Pitre384a2902012-04-11 18:55:48 -0400969 * Initialize the CPU interface map to all CPUs.
970 * It will be refined as each CPU probes its ID.
971 */
972 for (i = 0; i < NR_GIC_CPU_IF; i++)
973 gic_cpu_map[i] = 0xff;
974
975 /*
Rob Herring4294f8b2011-09-28 21:25:31 -0500976 * For primary GICs, skip over SGIs.
977 * For secondary GICs, skip over PPIs, too.
978 */
Will Deacone0b823e2012-02-03 14:52:14 +0100979 if (gic_nr == 0 && (irq_start & 31) > 0) {
Linus Torvalds12679a22012-03-29 16:53:48 -0700980 hwirq_base = 16;
Will Deacone0b823e2012-02-03 14:52:14 +0100981 if (irq_start != -1)
982 irq_start = (irq_start & ~31) + 16;
983 } else {
Linus Torvalds12679a22012-03-29 16:53:48 -0700984 hwirq_base = 32;
Will Deaconfe41db72011-11-25 19:23:36 +0100985 }
Rob Herring4294f8b2011-09-28 21:25:31 -0500986
987 /*
988 * Find out how many interrupts are supported.
989 * The GIC only supports up to 1020 interrupt sources.
990 */
Marc Zyngierdb0d4db2011-11-12 16:09:49 +0000991 gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f;
Rob Herring4294f8b2011-09-28 21:25:31 -0500992 gic_irqs = (gic_irqs + 1) * 32;
993 if (gic_irqs > 1020)
994 gic_irqs = 1020;
995 gic->gic_irqs = gic_irqs;
996
Grant Likely75294952012-02-14 14:06:57 -0700997 gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */
Sricharan Rbd09b642013-12-03 15:57:22 +0530998
999 if (of_property_read_u32(node, "arm,routable-irqs",
1000 &nr_routable_irqs)) {
1001 irq_base = irq_alloc_descs(irq_start, 16, gic_irqs,
1002 numa_node_id());
1003 if (IS_ERR_VALUE(irq_base)) {
1004 WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
1005 irq_start);
1006 irq_base = irq_start;
1007 }
1008
1009 gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
1010 hwirq_base, &gic_irq_domain_ops, gic);
1011 } else {
1012 gic->domain = irq_domain_add_linear(node, nr_routable_irqs,
1013 &gic_irq_domain_ops,
1014 gic);
Rob Herringf37a53c2011-10-21 17:14:27 -05001015 }
Sricharan Rbd09b642013-12-03 15:57:22 +05301016
Grant Likely75294952012-02-14 14:06:57 -07001017 if (WARN_ON(!gic->domain))
1018 return;
Russell Kingbef8f9e2010-12-04 16:50:58 +00001019
Mark Rutland893fe6d2013-11-28 14:21:40 +00001020 if (gic_nr == 0) {
Rob Herringb1cffeb2012-11-26 15:05:48 -06001021#ifdef CONFIG_SMP
Mark Rutland893fe6d2013-11-28 14:21:40 +00001022 set_smp_cross_call(gic_raise_softirq);
1023 register_cpu_notifier(&gic_cpu_notifier);
Rob Herringb1cffeb2012-11-26 15:05:48 -06001024#endif
Mark Rutland893fe6d2013-11-28 14:21:40 +00001025 set_handle_irq(gic_handle_irq);
1026 }
Rob Herringcfed7d62012-11-03 12:59:51 -05001027
Colin Cross9c128452011-06-13 00:45:59 +00001028 gic_chip.flags |= gic_arch_extn.flags;
Rob Herring4294f8b2011-09-28 21:25:31 -05001029 gic_dist_init(gic);
Russell Kingbef8f9e2010-12-04 16:50:58 +00001030 gic_cpu_init(gic);
Colin Cross254056f2011-02-10 12:54:10 -08001031 gic_pm_init(gic);
Russell Kingb580b892010-12-04 15:55:14 +00001032}
1033
Rob Herringb3f7ed02011-09-28 21:27:52 -05001034#ifdef CONFIG_OF
Sachin Kamat46f101d2013-03-13 15:05:15 +05301035static int gic_cnt __initdata;
Rob Herringb3f7ed02011-09-28 21:27:52 -05001036
Stephen Boyd7c284952014-03-04 17:02:01 -08001037static int __init
1038gic_of_init(struct device_node *node, struct device_node *parent)
Rob Herringb3f7ed02011-09-28 21:27:52 -05001039{
1040 void __iomem *cpu_base;
1041 void __iomem *dist_base;
Marc Zyngierdb0d4db2011-11-12 16:09:49 +00001042 u32 percpu_offset;
Rob Herringb3f7ed02011-09-28 21:27:52 -05001043 int irq;
Rob Herringb3f7ed02011-09-28 21:27:52 -05001044
1045 if (WARN_ON(!node))
1046 return -ENODEV;
1047
1048 dist_base = of_iomap(node, 0);
1049 WARN(!dist_base, "unable to map gic dist registers\n");
1050
1051 cpu_base = of_iomap(node, 1);
1052 WARN(!cpu_base, "unable to map gic cpu registers\n");
1053
Marc Zyngierdb0d4db2011-11-12 16:09:49 +00001054 if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
1055 percpu_offset = 0;
1056
Grant Likely75294952012-02-14 14:06:57 -07001057 gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
Nicolas Pitref4bf1bf2012-11-28 18:17:25 -05001058 if (!gic_cnt)
1059 gic_init_physaddr(node);
Rob Herringb3f7ed02011-09-28 21:27:52 -05001060
1061 if (parent) {
1062 irq = irq_of_parse_and_map(node, 0);
1063 gic_cascade_irq(gic_cnt, irq);
1064 }
1065 gic_cnt++;
1066 return 0;
1067}
Rob Herring81243e42012-11-20 21:21:40 -06001068IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
1069IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
1070IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
1071IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
1072
Rob Herringb3f7ed02011-09-28 21:27:52 -05001073#endif