aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-07-03 07:36:01 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-03 07:36:01 -0400
commit0ebfff1491ef85d41ddf9c633834838be144f69f (patch)
tree5b469a6d61a9fcfbf94e7b6d411e544dbdec8dec /arch/powerpc/sysdev
parentf63e115fb50db39706b955b81e3375ef6bab2268 (diff)
[POWERPC] Add new interrupt mapping core and change platforms to use it
This adds the new irq remapper core and removes the old one. Because there are some fundamental conflicts with the old code, like the value of NO_IRQ which I'm now setting to 0 (as per discussions with Linus), etc..., this commit also changes the relevant platform and driver code over to use the new remapper (so as not to cause difficulties later in bisecting). This patch removes the old pre-parsing of the open firmware interrupt tree along with all the bogus assumptions it made to try to renumber interrupts according to the platform. This is all to be handled by the new code now. For the pSeries XICS interrupt controller, a single remapper host is created for the whole machine regardless of how many interrupt presentation and source controllers are found, and it's set to match any device node that isn't a 8259. That works fine on pSeries and avoids having to deal with some of the complexities of split source controllers vs. presentation controllers in the pSeries device trees. The powerpc i8259 PIC driver now always requests the legacy interrupt range. It also has the feature of being able to match any device node (including NULL) if passed no device node as an input. That will help porting over platforms with broken device-trees like Pegasos who don't have a proper interrupt tree. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/i8259.c141
-rw-r--r--arch/powerpc/sysdev/mpic.c333
2 files changed, 325 insertions, 149 deletions
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index c2e9465871aa..72c73a6105cd 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -6,11 +6,16 @@
6 * as published by the Free Software Foundation; either version 6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9#undef DEBUG
10
9#include <linux/init.h> 11#include <linux/init.h>
10#include <linux/ioport.h> 12#include <linux/ioport.h>
11#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/delay.h>
12#include <asm/io.h> 16#include <asm/io.h>
13#include <asm/i8259.h> 17#include <asm/i8259.h>
18#include <asm/prom.h>
14 19
15static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */ 20static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */
16 21
@@ -20,7 +25,8 @@ static unsigned char cached_8259[2] = { 0xff, 0xff };
20 25
21static DEFINE_SPINLOCK(i8259_lock); 26static DEFINE_SPINLOCK(i8259_lock);
22 27
23static int i8259_pic_irq_offset; 28static struct device_node *i8259_node;
29static struct irq_host *i8259_host;
24 30
25/* 31/*
26 * Acknowledge the IRQ using either the PCI host bridge's interrupt 32 * Acknowledge the IRQ using either the PCI host bridge's interrupt
@@ -28,16 +34,18 @@ static int i8259_pic_irq_offset;
28 * which is called. It should be noted that polling is broken on some 34 * which is called. It should be noted that polling is broken on some
29 * IBM and Motorola PReP boxes so we must use the int-ack feature on them. 35 * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
30 */ 36 */
31int i8259_irq(struct pt_regs *regs) 37unsigned int i8259_irq(struct pt_regs *regs)
32{ 38{
33 int irq; 39 int irq;
34 40 int lock = 0;
35 spin_lock(&i8259_lock);
36 41
37 /* Either int-ack or poll for the IRQ */ 42 /* Either int-ack or poll for the IRQ */
38 if (pci_intack) 43 if (pci_intack)
39 irq = readb(pci_intack); 44 irq = readb(pci_intack);
40 else { 45 else {
46 spin_lock(&i8259_lock);
47 lock = 1;
48
41 /* Perform an interrupt acknowledge cycle on controller 1. */ 49 /* Perform an interrupt acknowledge cycle on controller 1. */
42 outb(0x0C, 0x20); /* prepare for poll */ 50 outb(0x0C, 0x20); /* prepare for poll */
43 irq = inb(0x20) & 7; 51 irq = inb(0x20) & 7;
@@ -62,11 +70,13 @@ int i8259_irq(struct pt_regs *regs)
62 if (!pci_intack) 70 if (!pci_intack)
63 outb(0x0B, 0x20); /* ISR register */ 71 outb(0x0B, 0x20); /* ISR register */
64 if(~inb(0x20) & 0x80) 72 if(~inb(0x20) & 0x80)
65 irq = -1; 73 irq = NO_IRQ;
66 } 74 } else if (irq == 0xff)
75 irq = NO_IRQ;
67 76
68 spin_unlock(&i8259_lock); 77 if (lock)
69 return irq + i8259_pic_irq_offset; 78 spin_unlock(&i8259_lock);
79 return irq;
70} 80}
71 81
72static void i8259_mask_and_ack_irq(unsigned int irq_nr) 82static void i8259_mask_and_ack_irq(unsigned int irq_nr)
@@ -74,7 +84,6 @@ static void i8259_mask_and_ack_irq(unsigned int irq_nr)
74 unsigned long flags; 84 unsigned long flags;
75 85
76 spin_lock_irqsave(&i8259_lock, flags); 86 spin_lock_irqsave(&i8259_lock, flags);
77 irq_nr -= i8259_pic_irq_offset;
78 if (irq_nr > 7) { 87 if (irq_nr > 7) {
79 cached_A1 |= 1 << (irq_nr-8); 88 cached_A1 |= 1 << (irq_nr-8);
80 inb(0xA1); /* DUMMY */ 89 inb(0xA1); /* DUMMY */
@@ -100,8 +109,9 @@ static void i8259_mask_irq(unsigned int irq_nr)
100{ 109{
101 unsigned long flags; 110 unsigned long flags;
102 111
112 pr_debug("i8259_mask_irq(%d)\n", irq_nr);
113
103 spin_lock_irqsave(&i8259_lock, flags); 114 spin_lock_irqsave(&i8259_lock, flags);
104 irq_nr -= i8259_pic_irq_offset;
105 if (irq_nr < 8) 115 if (irq_nr < 8)
106 cached_21 |= 1 << irq_nr; 116 cached_21 |= 1 << irq_nr;
107 else 117 else
@@ -114,8 +124,9 @@ static void i8259_unmask_irq(unsigned int irq_nr)
114{ 124{
115 unsigned long flags; 125 unsigned long flags;
116 126
127 pr_debug("i8259_unmask_irq(%d)\n", irq_nr);
128
117 spin_lock_irqsave(&i8259_lock, flags); 129 spin_lock_irqsave(&i8259_lock, flags);
118 irq_nr -= i8259_pic_irq_offset;
119 if (irq_nr < 8) 130 if (irq_nr < 8)
120 cached_21 &= ~(1 << irq_nr); 131 cached_21 &= ~(1 << irq_nr);
121 else 132 else
@@ -152,25 +163,84 @@ static struct resource pic_edgectrl_iores = {
152 .flags = IORESOURCE_BUSY, 163 .flags = IORESOURCE_BUSY,
153}; 164};
154 165
155static struct irqaction i8259_irqaction = { 166static int i8259_host_match(struct irq_host *h, struct device_node *node)
156 .handler = no_action, 167{
157 .flags = IRQF_DISABLED, 168 return i8259_node == NULL || i8259_node == node;
158 .mask = CPU_MASK_NONE, 169}
159 .name = "82c59 secondary cascade", 170
171static int i8259_host_map(struct irq_host *h, unsigned int virq,
172 irq_hw_number_t hw, unsigned int flags)
173{
174 pr_debug("i8259_host_map(%d, 0x%lx)\n", virq, hw);
175
176 /* We block the internal cascade */
177 if (hw == 2)
178 get_irq_desc(virq)->status |= IRQ_NOREQUEST;
179
180 /* We use the level stuff only for now, we might want to
181 * be more cautious here but that works for now
182 */
183 get_irq_desc(virq)->status |= IRQ_LEVEL;
184 set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq);
185 return 0;
186}
187
188static void i8259_host_unmap(struct irq_host *h, unsigned int virq)
189{
190 /* Make sure irq is masked in hardware */
191 i8259_mask_irq(virq);
192
193 /* remove chip and handler */
194 set_irq_chip_and_handler(virq, NULL, NULL);
195
196 /* Make sure it's completed */
197 synchronize_irq(virq);
198}
199
200static int i8259_host_xlate(struct irq_host *h, struct device_node *ct,
201 u32 *intspec, unsigned int intsize,
202 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
203{
204 static unsigned char map_isa_senses[4] = {
205 IRQ_TYPE_LEVEL_LOW,
206 IRQ_TYPE_LEVEL_HIGH,
207 IRQ_TYPE_EDGE_FALLING,
208 IRQ_TYPE_EDGE_RISING,
209 };
210
211 *out_hwirq = intspec[0];
212 if (intsize > 1 && intspec[1] < 4)
213 *out_flags = map_isa_senses[intspec[1]];
214 else
215 *out_flags = IRQ_TYPE_NONE;
216
217 return 0;
218}
219
220static struct irq_host_ops i8259_host_ops = {
221 .match = i8259_host_match,
222 .map = i8259_host_map,
223 .unmap = i8259_host_unmap,
224 .xlate = i8259_host_xlate,
160}; 225};
161 226
162/* 227/****
163 * i8259_init() 228 * i8259_init - Initialize the legacy controller
164 * intack_addr - PCI interrupt acknowledge (real) address which will return 229 * @node: device node of the legacy PIC (can be NULL, but then, it will match
165 * the active irq from the 8259 230 * all interrupts, so beware)
231 * @intack_addr: PCI interrupt acknowledge (real) address which will return
232 * the active irq from the 8259
166 */ 233 */
167void __init i8259_init(unsigned long intack_addr, int offset) 234void i8259_init(struct device_node *node, unsigned long intack_addr)
168{ 235{
169 unsigned long flags; 236 unsigned long flags;
170 int i;
171 237
238 /* initialize the controller */
172 spin_lock_irqsave(&i8259_lock, flags); 239 spin_lock_irqsave(&i8259_lock, flags);
173 i8259_pic_irq_offset = offset; 240
241 /* Mask all first */
242 outb(0xff, 0xA1);
243 outb(0xff, 0x21);
174 244
175 /* init master interrupt controller */ 245 /* init master interrupt controller */
176 outb(0x11, 0x20); /* Start init sequence */ 246 outb(0x11, 0x20); /* Start init sequence */
@@ -184,24 +254,36 @@ void __init i8259_init(unsigned long intack_addr, int offset)
184 outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */ 254 outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
185 outb(0x01, 0xA1); /* Select 8086 mode */ 255 outb(0x01, 0xA1); /* Select 8086 mode */
186 256
257 /* That thing is slow */
258 udelay(100);
259
187 /* always read ISR */ 260 /* always read ISR */
188 outb(0x0B, 0x20); 261 outb(0x0B, 0x20);
189 outb(0x0B, 0xA0); 262 outb(0x0B, 0xA0);
190 263
191 /* Mask all interrupts */ 264 /* Unmask the internal cascade */
265 cached_21 &= ~(1 << 2);
266
267 /* Set interrupt masks */
192 outb(cached_A1, 0xA1); 268 outb(cached_A1, 0xA1);
193 outb(cached_21, 0x21); 269 outb(cached_21, 0x21);
194 270
195 spin_unlock_irqrestore(&i8259_lock, flags); 271 spin_unlock_irqrestore(&i8259_lock, flags);
196 272
197 for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) { 273 /* create a legacy host */
198 set_irq_chip_and_handler(offset + i, &i8259_pic, 274 if (node)
199 handle_level_irq); 275 i8259_node = of_node_get(node);
200 irq_desc[offset + i].status |= IRQ_LEVEL; 276 i8259_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &i8259_host_ops, 0);
277 if (i8259_host == NULL) {
278 printk(KERN_ERR "i8259: failed to allocate irq host !\n");
279 return;
201 } 280 }
202 281
203 /* reserve our resources */ 282 /* reserve our resources */
204 setup_irq(offset + 2, &i8259_irqaction); 283 /* XXX should we continue doing that ? it seems to cause problems
284 * with further requesting of PCI IO resources for that range...
285 * need to look into it.
286 */
205 request_resource(&ioport_resource, &pic1_iores); 287 request_resource(&ioport_resource, &pic1_iores);
206 request_resource(&ioport_resource, &pic2_iores); 288 request_resource(&ioport_resource, &pic2_iores);
207 request_resource(&ioport_resource, &pic_edgectrl_iores); 289 request_resource(&ioport_resource, &pic_edgectrl_iores);
@@ -209,4 +291,5 @@ void __init i8259_init(unsigned long intack_addr, int offset)
209 if (intack_addr != 0) 291 if (intack_addr != 0)
210 pci_intack = ioremap(intack_addr, 1); 292 pci_intack = ioremap(intack_addr, 1);
211 293
294 printk(KERN_INFO "i8259 legacy interrupt controller initialized\n");
212} 295}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 9a95f16c19a5..7d31d7cc392d 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -340,27 +340,19 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
340#endif /* CONFIG_MPIC_BROKEN_U3 */ 340#endif /* CONFIG_MPIC_BROKEN_U3 */
341 341
342 342
343#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
344
343/* Find an mpic associated with a given linux interrupt */ 345/* Find an mpic associated with a given linux interrupt */
344static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) 346static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
345{ 347{
346 struct mpic *mpic = mpics; 348 unsigned int src = mpic_irq_to_hw(irq);
347 349
348 while(mpic) { 350 if (irq < NUM_ISA_INTERRUPTS)
349 /* search IPIs first since they may override the main interrupts */ 351 return NULL;
350 if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) { 352 if (is_ipi)
351 if (is_ipi) 353 *is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3);
352 *is_ipi = 1; 354
353 return mpic; 355 return irq_desc[irq].chip_data;
354 }
355 if (irq >= mpic->irq_offset &&
356 irq < (mpic->irq_offset + mpic->irq_count)) {
357 if (is_ipi)
358 *is_ipi = 0;
359 return mpic;
360 }
361 mpic = mpic -> next;
362 }
363 return NULL;
364} 356}
365 357
366/* Convert a cpu mask from logical to physical cpu numbers. */ 358/* Convert a cpu mask from logical to physical cpu numbers. */
@@ -398,9 +390,7 @@ static inline void mpic_eoi(struct mpic *mpic)
398#ifdef CONFIG_SMP 390#ifdef CONFIG_SMP
399static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) 391static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
400{ 392{
401 struct mpic *mpic = dev_id; 393 smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0, regs);
402
403 smp_message_recv(irq - mpic->ipi_offset, regs);
404 return IRQ_HANDLED; 394 return IRQ_HANDLED;
405} 395}
406#endif /* CONFIG_SMP */ 396#endif /* CONFIG_SMP */
@@ -414,7 +404,7 @@ static void mpic_unmask_irq(unsigned int irq)
414{ 404{
415 unsigned int loops = 100000; 405 unsigned int loops = 100000;
416 struct mpic *mpic = mpic_from_irq(irq); 406 struct mpic *mpic = mpic_from_irq(irq);
417 unsigned int src = irq - mpic->irq_offset; 407 unsigned int src = mpic_irq_to_hw(irq);
418 408
419 DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); 409 DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
420 410
@@ -435,7 +425,7 @@ static void mpic_mask_irq(unsigned int irq)
435{ 425{
436 unsigned int loops = 100000; 426 unsigned int loops = 100000;
437 struct mpic *mpic = mpic_from_irq(irq); 427 struct mpic *mpic = mpic_from_irq(irq);
438 unsigned int src = irq - mpic->irq_offset; 428 unsigned int src = mpic_irq_to_hw(irq);
439 429
440 DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); 430 DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
441 431
@@ -472,7 +462,7 @@ static void mpic_end_irq(unsigned int irq)
472static void mpic_unmask_ht_irq(unsigned int irq) 462static void mpic_unmask_ht_irq(unsigned int irq)
473{ 463{
474 struct mpic *mpic = mpic_from_irq(irq); 464 struct mpic *mpic = mpic_from_irq(irq);
475 unsigned int src = irq - mpic->irq_offset; 465 unsigned int src = mpic_irq_to_hw(irq);
476 466
477 mpic_unmask_irq(irq); 467 mpic_unmask_irq(irq);
478 468
@@ -483,7 +473,7 @@ static void mpic_unmask_ht_irq(unsigned int irq)
483static unsigned int mpic_startup_ht_irq(unsigned int irq) 473static unsigned int mpic_startup_ht_irq(unsigned int irq)
484{ 474{
485 struct mpic *mpic = mpic_from_irq(irq); 475 struct mpic *mpic = mpic_from_irq(irq);
486 unsigned int src = irq - mpic->irq_offset; 476 unsigned int src = mpic_irq_to_hw(irq);
487 477
488 mpic_unmask_irq(irq); 478 mpic_unmask_irq(irq);
489 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); 479 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
@@ -494,7 +484,7 @@ static unsigned int mpic_startup_ht_irq(unsigned int irq)
494static void mpic_shutdown_ht_irq(unsigned int irq) 484static void mpic_shutdown_ht_irq(unsigned int irq)
495{ 485{
496 struct mpic *mpic = mpic_from_irq(irq); 486 struct mpic *mpic = mpic_from_irq(irq);
497 unsigned int src = irq - mpic->irq_offset; 487 unsigned int src = mpic_irq_to_hw(irq);
498 488
499 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); 489 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
500 mpic_mask_irq(irq); 490 mpic_mask_irq(irq);
@@ -503,7 +493,7 @@ static void mpic_shutdown_ht_irq(unsigned int irq)
503static void mpic_end_ht_irq(unsigned int irq) 493static void mpic_end_ht_irq(unsigned int irq)
504{ 494{
505 struct mpic *mpic = mpic_from_irq(irq); 495 struct mpic *mpic = mpic_from_irq(irq);
506 unsigned int src = irq - mpic->irq_offset; 496 unsigned int src = mpic_irq_to_hw(irq);
507 497
508#ifdef DEBUG_IRQ 498#ifdef DEBUG_IRQ
509 DBG("%s: end_irq: %d\n", mpic->name, irq); 499 DBG("%s: end_irq: %d\n", mpic->name, irq);
@@ -525,7 +515,7 @@ static void mpic_end_ht_irq(unsigned int irq)
525static void mpic_unmask_ipi(unsigned int irq) 515static void mpic_unmask_ipi(unsigned int irq)
526{ 516{
527 struct mpic *mpic = mpic_from_ipi(irq); 517 struct mpic *mpic = mpic_from_ipi(irq);
528 unsigned int src = irq - mpic->ipi_offset; 518 unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0;
529 519
530 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); 520 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
531 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 521 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
@@ -555,15 +545,46 @@ static void mpic_end_ipi(unsigned int irq)
555static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) 545static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
556{ 546{
557 struct mpic *mpic = mpic_from_irq(irq); 547 struct mpic *mpic = mpic_from_irq(irq);
548 unsigned int src = mpic_irq_to_hw(irq);
558 549
559 cpumask_t tmp; 550 cpumask_t tmp;
560 551
561 cpus_and(tmp, cpumask, cpu_online_map); 552 cpus_and(tmp, cpumask, cpu_online_map);
562 553
563 mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION, 554 mpic_irq_write(src, MPIC_IRQ_DESTINATION,
564 mpic_physmask(cpus_addr(tmp)[0])); 555 mpic_physmask(cpus_addr(tmp)[0]));
565} 556}
566 557
558static unsigned int mpic_flags_to_vecpri(unsigned int flags, int *level)
559{
560 unsigned int vecpri;
561
562 /* Now convert sense value */
563 switch(flags & IRQ_TYPE_SENSE_MASK) {
564 case IRQ_TYPE_EDGE_RISING:
565 vecpri = MPIC_VECPRI_SENSE_EDGE |
566 MPIC_VECPRI_POLARITY_POSITIVE;
567 *level = 0;
568 break;
569 case IRQ_TYPE_EDGE_FALLING:
570 vecpri = MPIC_VECPRI_SENSE_EDGE |
571 MPIC_VECPRI_POLARITY_NEGATIVE;
572 *level = 0;
573 break;
574 case IRQ_TYPE_LEVEL_HIGH:
575 vecpri = MPIC_VECPRI_SENSE_LEVEL |
576 MPIC_VECPRI_POLARITY_POSITIVE;
577 *level = 1;
578 break;
579 case IRQ_TYPE_LEVEL_LOW:
580 default:
581 vecpri = MPIC_VECPRI_SENSE_LEVEL |
582 MPIC_VECPRI_POLARITY_NEGATIVE;
583 *level = 1;
584 }
585 return vecpri;
586}
587
567static struct irq_chip mpic_irq_chip = { 588static struct irq_chip mpic_irq_chip = {
568 .mask = mpic_mask_irq, 589 .mask = mpic_mask_irq,
569 .unmask = mpic_unmask_irq, 590 .unmask = mpic_unmask_irq,
@@ -589,19 +610,111 @@ static struct irq_chip mpic_irq_ht_chip = {
589#endif /* CONFIG_MPIC_BROKEN_U3 */ 610#endif /* CONFIG_MPIC_BROKEN_U3 */
590 611
591 612
613static int mpic_host_match(struct irq_host *h, struct device_node *node)
614{
615 struct mpic *mpic = h->host_data;
616
617 /* Exact match, unless mpic node is NULL */
618 return mpic->of_node == NULL || mpic->of_node == node;
619}
620
621static int mpic_host_map(struct irq_host *h, unsigned int virq,
622 irq_hw_number_t hw, unsigned int flags)
623{
624 struct irq_desc *desc = get_irq_desc(virq);
625 struct irq_chip *chip;
626 struct mpic *mpic = h->host_data;
627 unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL |
628 MPIC_VECPRI_POLARITY_NEGATIVE;
629 int level;
630
631 pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n",
632 virq, hw, flags);
633
634 if (hw == MPIC_VEC_SPURRIOUS)
635 return -EINVAL;
636#ifdef CONFIG_SMP
637 else if (hw >= MPIC_VEC_IPI_0) {
638 WARN_ON(!(mpic->flags & MPIC_PRIMARY));
639
640 pr_debug("mpic: mapping as IPI\n");
641 set_irq_chip_data(virq, mpic);
642 set_irq_chip_and_handler(virq, &mpic->hc_ipi,
643 handle_percpu_irq);
644 return 0;
645 }
646#endif /* CONFIG_SMP */
647
648 if (hw >= mpic->irq_count)
649 return -EINVAL;
650
651 /* If no sense provided, check default sense array */
652 if (((flags & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE) &&
653 mpic->senses && hw < mpic->senses_count)
654 flags |= mpic->senses[hw];
655
656 vecpri = mpic_flags_to_vecpri(flags, &level);
657 if (level)
658 desc->status |= IRQ_LEVEL;
659 chip = &mpic->hc_irq;
660
661#ifdef CONFIG_MPIC_BROKEN_U3
662 /* Check for HT interrupts, override vecpri */
663 if (mpic_is_ht_interrupt(mpic, hw)) {
664 vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
665 MPIC_VECPRI_POLARITY_MASK);
666 vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
667 chip = &mpic->hc_ht_irq;
668 }
669#endif
670
671 /* Reconfigure irq */
672 vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
673 mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
674
675 pr_debug("mpic: mapping as IRQ\n");
676
677 set_irq_chip_data(virq, mpic);
678 set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
679 return 0;
680}
681
682static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
683 u32 *intspec, unsigned int intsize,
684 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
685
686{
687 static unsigned char map_mpic_senses[4] = {
688 IRQ_TYPE_EDGE_RISING,
689 IRQ_TYPE_LEVEL_LOW,
690 IRQ_TYPE_LEVEL_HIGH,
691 IRQ_TYPE_EDGE_FALLING,
692 };
693
694 *out_hwirq = intspec[0];
695 if (intsize > 1 && intspec[1] < 4)
696 *out_flags = map_mpic_senses[intspec[1]];
697 else
698 *out_flags = IRQ_TYPE_NONE;
699
700 return 0;
701}
702
703static struct irq_host_ops mpic_host_ops = {
704 .match = mpic_host_match,
705 .map = mpic_host_map,
706 .xlate = mpic_host_xlate,
707};
708
592/* 709/*
593 * Exported functions 710 * Exported functions
594 */ 711 */
595 712
596 713struct mpic * __init mpic_alloc(struct device_node *node,
597struct mpic * __init mpic_alloc(unsigned long phys_addr, 714 unsigned long phys_addr,
598 unsigned int flags, 715 unsigned int flags,
599 unsigned int isu_size, 716 unsigned int isu_size,
600 unsigned int irq_offset,
601 unsigned int irq_count, 717 unsigned int irq_count,
602 unsigned int ipi_offset,
603 unsigned char *senses,
604 unsigned int senses_count,
605 const char *name) 718 const char *name)
606{ 719{
607 struct mpic *mpic; 720 struct mpic *mpic;
@@ -613,10 +726,19 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
613 if (mpic == NULL) 726 if (mpic == NULL)
614 return NULL; 727 return NULL;
615 728
616
617 memset(mpic, 0, sizeof(struct mpic)); 729 memset(mpic, 0, sizeof(struct mpic));
618 mpic->name = name; 730 mpic->name = name;
731 mpic->of_node = node ? of_node_get(node) : NULL;
619 732
733 mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256,
734 &mpic_host_ops,
735 MPIC_VEC_SPURRIOUS);
736 if (mpic->irqhost == NULL) {
737 of_node_put(node);
738 return NULL;
739 }
740
741 mpic->irqhost->host_data = mpic;
620 mpic->hc_irq = mpic_irq_chip; 742 mpic->hc_irq = mpic_irq_chip;
621 mpic->hc_irq.typename = name; 743 mpic->hc_irq.typename = name;
622 if (flags & MPIC_PRIMARY) 744 if (flags & MPIC_PRIMARY)
@@ -628,18 +750,14 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
628 mpic->hc_ht_irq.set_affinity = mpic_set_affinity; 750 mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
629#endif /* CONFIG_MPIC_BROKEN_U3 */ 751#endif /* CONFIG_MPIC_BROKEN_U3 */
630#ifdef CONFIG_SMP 752#ifdef CONFIG_SMP
631 mpic->hc_ipi.typename = name;
632 mpic->hc_ipi = mpic_ipi_chip; 753 mpic->hc_ipi = mpic_ipi_chip;
754 mpic->hc_ipi.typename = name;
633#endif /* CONFIG_SMP */ 755#endif /* CONFIG_SMP */
634 756
635 mpic->flags = flags; 757 mpic->flags = flags;
636 mpic->isu_size = isu_size; 758 mpic->isu_size = isu_size;
637 mpic->irq_offset = irq_offset;
638 mpic->irq_count = irq_count; 759 mpic->irq_count = irq_count;
639 mpic->ipi_offset = ipi_offset;
640 mpic->num_sources = 0; /* so far */ 760 mpic->num_sources = 0; /* so far */
641 mpic->senses = senses;
642 mpic->senses_count = senses_count;
643 761
644 /* Map the global registers */ 762 /* Map the global registers */
645 mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); 763 mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
@@ -707,8 +825,10 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
707 mpic->next = mpics; 825 mpic->next = mpics;
708 mpics = mpic; 826 mpics = mpic;
709 827
710 if (flags & MPIC_PRIMARY) 828 if (flags & MPIC_PRIMARY) {
711 mpic_primary = mpic; 829 mpic_primary = mpic;
830 irq_set_default_host(mpic->irqhost);
831 }
712 832
713 return mpic; 833 return mpic;
714} 834}
@@ -725,11 +845,22 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
725 mpic->num_sources = isu_first + mpic->isu_size; 845 mpic->num_sources = isu_first + mpic->isu_size;
726} 846}
727 847
848void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
849{
850 mpic->senses = senses;
851 mpic->senses_count = count;
852}
853
728void __init mpic_init(struct mpic *mpic) 854void __init mpic_init(struct mpic *mpic)
729{ 855{
730 int i; 856 int i;
731 857
732 BUG_ON(mpic->num_sources == 0); 858 BUG_ON(mpic->num_sources == 0);
859 WARN_ON(mpic->num_sources > MPIC_VEC_IPI_0);
860
861 /* Sanitize source count */
862 if (mpic->num_sources > MPIC_VEC_IPI_0)
863 mpic->num_sources = MPIC_VEC_IPI_0;
733 864
734 printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); 865 printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
735 866
@@ -753,14 +884,6 @@ void __init mpic_init(struct mpic *mpic)
753 MPIC_VECPRI_MASK | 884 MPIC_VECPRI_MASK |
754 (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 885 (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
755 (MPIC_VEC_IPI_0 + i)); 886 (MPIC_VEC_IPI_0 + i));
756#ifdef CONFIG_SMP
757 if (!(mpic->flags & MPIC_PRIMARY))
758 continue;
759 set_irq_chip_data(mpic->ipi_offset+i, mpic);
760 set_irq_chip_and_handler(mpic->ipi_offset+i,
761 &mpic->hc_ipi,
762 handle_percpu_irq);
763#endif /* CONFIG_SMP */
764 } 887 }
765 888
766 /* Initialize interrupt sources */ 889 /* Initialize interrupt sources */
@@ -777,25 +900,15 @@ void __init mpic_init(struct mpic *mpic)
777 for (i = 0; i < mpic->num_sources; i++) { 900 for (i = 0; i < mpic->num_sources; i++) {
778 /* start with vector = source number, and masked */ 901 /* start with vector = source number, and masked */
779 u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); 902 u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
780 int level = 0; 903 int level = 1;
781 904
782 /* if it's an IPI, we skip it */
783 if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
784 (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4))
785 continue;
786
787 /* do senses munging */ 905 /* do senses munging */
788 if (mpic->senses && i < mpic->senses_count) { 906 if (mpic->senses && i < mpic->senses_count)
789 if (mpic->senses[i] & IRQ_SENSE_LEVEL) 907 vecpri = mpic_flags_to_vecpri(mpic->senses[i],
790 vecpri |= MPIC_VECPRI_SENSE_LEVEL; 908 &level);
791 if (mpic->senses[i] & IRQ_POLARITY_POSITIVE) 909 else
792 vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
793 } else
794 vecpri |= MPIC_VECPRI_SENSE_LEVEL; 910 vecpri |= MPIC_VECPRI_SENSE_LEVEL;
795 911
796 /* remember if it was a level interrupts */
797 level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
798
799 /* deal with broken U3 */ 912 /* deal with broken U3 */
800 if (mpic->flags & MPIC_BROKEN_U3) { 913 if (mpic->flags & MPIC_BROKEN_U3) {
801#ifdef CONFIG_MPIC_BROKEN_U3 914#ifdef CONFIG_MPIC_BROKEN_U3
@@ -816,21 +929,6 @@ void __init mpic_init(struct mpic *mpic)
816 mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); 929 mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
817 mpic_irq_write(i, MPIC_IRQ_DESTINATION, 930 mpic_irq_write(i, MPIC_IRQ_DESTINATION,
818 1 << hard_smp_processor_id()); 931 1 << hard_smp_processor_id());
819
820 /* init linux descriptors */
821 if (i < mpic->irq_count) {
822 struct irq_chip *chip = &mpic->hc_irq;
823
824 irq_desc[mpic->irq_offset+i].status |=
825 level ? IRQ_LEVEL : 0;
826#ifdef CONFIG_MPIC_BROKEN_U3
827 if (mpic_is_ht_interrupt(mpic, i))
828 chip = &mpic->hc_ht_irq;
829#endif /* CONFIG_MPIC_BROKEN_U3 */
830 set_irq_chip_data(mpic->irq_offset+i, mpic);
831 set_irq_chip_and_handler(mpic->irq_offset+i, chip,
832 handle_fasteoi_irq);
833 }
834 } 932 }
835 933
836 /* Init spurrious vector */ 934 /* Init spurrious vector */
@@ -871,19 +969,20 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
871{ 969{
872 int is_ipi; 970 int is_ipi;
873 struct mpic *mpic = mpic_find(irq, &is_ipi); 971 struct mpic *mpic = mpic_find(irq, &is_ipi);
972 unsigned int src = mpic_irq_to_hw(irq);
874 unsigned long flags; 973 unsigned long flags;
875 u32 reg; 974 u32 reg;
876 975
877 spin_lock_irqsave(&mpic_lock, flags); 976 spin_lock_irqsave(&mpic_lock, flags);
878 if (is_ipi) { 977 if (is_ipi) {
879 reg = mpic_ipi_read(irq - mpic->ipi_offset) & 978 reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) &
880 ~MPIC_VECPRI_PRIORITY_MASK; 979 ~MPIC_VECPRI_PRIORITY_MASK;
881 mpic_ipi_write(irq - mpic->ipi_offset, 980 mpic_ipi_write(src - MPIC_VEC_IPI_0,
882 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 981 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
883 } else { 982 } else {
884 reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI) 983 reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
885 & ~MPIC_VECPRI_PRIORITY_MASK; 984 & ~MPIC_VECPRI_PRIORITY_MASK;
886 mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI, 985 mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
887 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 986 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
888 } 987 }
889 spin_unlock_irqrestore(&mpic_lock, flags); 988 spin_unlock_irqrestore(&mpic_lock, flags);
@@ -893,14 +992,15 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
893{ 992{
894 int is_ipi; 993 int is_ipi;
895 struct mpic *mpic = mpic_find(irq, &is_ipi); 994 struct mpic *mpic = mpic_find(irq, &is_ipi);
995 unsigned int src = mpic_irq_to_hw(irq);
896 unsigned long flags; 996 unsigned long flags;
897 u32 reg; 997 u32 reg;
898 998
899 spin_lock_irqsave(&mpic_lock, flags); 999 spin_lock_irqsave(&mpic_lock, flags);
900 if (is_ipi) 1000 if (is_ipi)
901 reg = mpic_ipi_read(irq - mpic->ipi_offset); 1001 reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
902 else 1002 else
903 reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI); 1003 reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
904 spin_unlock_irqrestore(&mpic_lock, flags); 1004 spin_unlock_irqrestore(&mpic_lock, flags);
905 return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; 1005 return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
906} 1006}
@@ -995,29 +1095,20 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
995 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); 1095 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
996} 1096}
997 1097
998int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) 1098unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
999{ 1099{
1000 u32 irq; 1100 u32 src;
1001 1101
1002 irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; 1102 src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
1003#ifdef DEBUG_LOW 1103#ifdef DEBUG_LOW
1004 DBG("%s: get_one_irq(): %d\n", mpic->name, irq); 1104 DBG("%s: get_one_irq(): %d\n", mpic->name, src);
1005#endif
1006 if (unlikely(irq == MPIC_VEC_SPURRIOUS))
1007 return -1;
1008 if (irq < MPIC_VEC_IPI_0) {
1009#ifdef DEBUG_IRQ
1010 DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
1011#endif 1105#endif
1012 return irq + mpic->irq_offset; 1106 if (unlikely(src == MPIC_VEC_SPURRIOUS))
1013 } 1107 return NO_IRQ;
1014#ifdef DEBUG_IPI 1108 return irq_linear_revmap(mpic->irqhost, src);
1015 DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
1016#endif
1017 return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
1018} 1109}
1019 1110
1020int mpic_get_irq(struct pt_regs *regs) 1111unsigned int mpic_get_irq(struct pt_regs *regs)
1021{ 1112{
1022 struct mpic *mpic = mpic_primary; 1113 struct mpic *mpic = mpic_primary;
1023 1114
@@ -1031,25 +1122,27 @@ int mpic_get_irq(struct pt_regs *regs)
1031void mpic_request_ipis(void) 1122void mpic_request_ipis(void)
1032{ 1123{
1033 struct mpic *mpic = mpic_primary; 1124 struct mpic *mpic = mpic_primary;
1034 1125 int i;
1126 static char *ipi_names[] = {
1127 "IPI0 (call function)",
1128 "IPI1 (reschedule)",
1129 "IPI2 (unused)",
1130 "IPI3 (debugger break)",
1131 };
1035 BUG_ON(mpic == NULL); 1132 BUG_ON(mpic == NULL);
1036
1037 printk("requesting IPIs ... \n");
1038 1133
1039 /* 1134 printk(KERN_INFO "mpic: requesting IPIs ... \n");
1040 * IPIs are marked IRQF_DISABLED as they must run with irqs 1135
1041 * disabled 1136 for (i = 0; i < 4; i++) {
1042 */ 1137 unsigned int vipi = irq_create_mapping(mpic->irqhost,
1043 request_irq(mpic->ipi_offset+0, mpic_ipi_action, IRQF_DISABLED, 1138 MPIC_VEC_IPI_0 + i, 0);
1044 "IPI0 (call function)", mpic); 1139 if (vipi == NO_IRQ) {
1045 request_irq(mpic->ipi_offset+1, mpic_ipi_action, IRQF_DISABLED, 1140 printk(KERN_ERR "Failed to map IPI %d\n", i);
1046 "IPI1 (reschedule)", mpic); 1141 break;
1047 request_irq(mpic->ipi_offset+2, mpic_ipi_action, IRQF_DISABLED, 1142 }
1048 "IPI2 (unused)", mpic); 1143 request_irq(vipi, mpic_ipi_action, IRQF_DISABLED,
1049 request_irq(mpic->ipi_offset+3, mpic_ipi_action, IRQF_DISABLED, 1144 ipi_names[i], mpic);
1050 "IPI3 (debugger break)", mpic); 1145 }
1051
1052 printk("IPIs requested... \n");
1053} 1146}
1054 1147
1055void smp_mpic_message_pass(int target, int msg) 1148void smp_mpic_message_pass(int target, int msg)