aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-10-23 09:42:30 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-10-23 09:42:30 -0400
commit34471a9168c8bfd7f0d00989a7b0797ad27d585e (patch)
tree847af3ec746c6357902cf57c7e12ba55a35eed30 /arch/arm/common
parentcefd3e71efca6f4ef7f06f1fc507771d76072741 (diff)
parent28af690a284dfcb627bd69d0963db1c0f412cb8c (diff)
Merge branch 'ppi-irq-core-for-rmk' of git://github.com/mzyngier/arm-platforms into devel-stable
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/gic.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 734db99eaee7..016c1aeb847c 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -29,6 +29,9 @@
29#include <linux/cpu_pm.h> 29#include <linux/cpu_pm.h>
30#include <linux/cpumask.h> 30#include <linux/cpumask.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/interrupt.h>
33#include <linux/percpu.h>
34#include <linux/slab.h>
32 35
33#include <asm/irq.h> 36#include <asm/irq.h>
34#include <asm/mach/irq.h> 37#include <asm/mach/irq.h>
@@ -181,7 +184,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
181 return -EINVAL; 184 return -EINVAL;
182 185
183 mask = 0xff << shift; 186 mask = 0xff << shift;
184 bit = 1 << (cpu + shift); 187 bit = 1 << (cpu_logical_map(cpu) + shift);
185 188
186 spin_lock(&irq_controller_lock); 189 spin_lock(&irq_controller_lock);
187 val = readl_relaxed(reg) & ~mask; 190 val = readl_relaxed(reg) & ~mask;
@@ -260,9 +263,16 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
260 unsigned int irq_start) 263 unsigned int irq_start)
261{ 264{
262 unsigned int gic_irqs, irq_limit, i; 265 unsigned int gic_irqs, irq_limit, i;
266 u32 cpumask;
263 void __iomem *base = gic->dist_base; 267 void __iomem *base = gic->dist_base;
264 u32 cpumask = 1 << smp_processor_id(); 268 u32 cpu = 0;
269 u32 nrppis = 0, ppi_base = 0;
265 270
271#ifdef CONFIG_SMP
272 cpu = cpu_logical_map(smp_processor_id());
273#endif
274
275 cpumask = 1 << cpu;
266 cpumask |= cpumask << 8; 276 cpumask |= cpumask << 8;
267 cpumask |= cpumask << 16; 277 cpumask |= cpumask << 16;
268 278
@@ -280,6 +290,23 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
280 gic->gic_irqs = gic_irqs; 290 gic->gic_irqs = gic_irqs;
281 291
282 /* 292 /*
293 * Nobody would be insane enough to use PPIs on a secondary
294 * GIC, right?
295 */
296 if (gic == &gic_data[0]) {
297 nrppis = (32 - irq_start) & 31;
298
299 /* The GIC only supports up to 16 PPIs. */
300 if (nrppis > 16)
301 BUG();
302
303 ppi_base = gic->irq_offset + 32 - nrppis;
304 }
305
306 pr_info("Configuring GIC with %d sources (%d PPIs)\n",
307 gic_irqs, (gic == &gic_data[0]) ? nrppis : 0);
308
309 /*
283 * Set all global interrupts to be level triggered, active low. 310 * Set all global interrupts to be level triggered, active low.
284 */ 311 */
285 for (i = 32; i < gic_irqs; i += 16) 312 for (i = 32; i < gic_irqs; i += 16)
@@ -314,7 +341,17 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
314 /* 341 /*
315 * Setup the Linux IRQ subsystem. 342 * Setup the Linux IRQ subsystem.
316 */ 343 */
317 for (i = irq_start; i < irq_limit; i++) { 344 for (i = 0; i < nrppis; i++) {
345 int ppi = i + ppi_base;
346
347 irq_set_percpu_devid(ppi);
348 irq_set_chip_and_handler(ppi, &gic_chip,
349 handle_percpu_devid_irq);
350 irq_set_chip_data(ppi, gic);
351 set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN);
352 }
353
354 for (i = irq_start + nrppis; i < irq_limit; i++) {
318 irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq); 355 irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
319 irq_set_chip_data(i, gic); 356 irq_set_chip_data(i, gic);
320 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 357 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
@@ -557,20 +594,15 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr)
557 gic_cpu_init(&gic_data[gic_nr]); 594 gic_cpu_init(&gic_data[gic_nr]);
558} 595}
559 596
560void __cpuinit gic_enable_ppi(unsigned int irq)
561{
562 unsigned long flags;
563
564 local_irq_save(flags);
565 irq_set_status_flags(irq, IRQ_NOPROBE);
566 gic_unmask_irq(irq_get_irq_data(irq));
567 local_irq_restore(flags);
568}
569
570#ifdef CONFIG_SMP 597#ifdef CONFIG_SMP
571void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) 598void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
572{ 599{
573 unsigned long map = *cpus_addr(*mask); 600 int cpu;
601 unsigned long map = 0;
602
603 /* Convert our logical CPU mask into a physical one. */
604 for_each_cpu(cpu, mask)
605 map |= 1 << cpu_logical_map(cpu);
574 606
575 /* 607 /*
576 * Ensure that stores to Normal memory are visible to the 608 * Ensure that stores to Normal memory are visible to the