aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-07-03 05:32:51 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-03 05:55:12 -0400
commitb9e5b4e6a991a5a6d521f2e20a65835404b4169f (patch)
treea0ac972faae4bf9133f576d842667bb134190341 /arch/powerpc/platforms/powermac
parent5a43a066b11ac2fe84cf67307f20b83bea390f83 (diff)
[POWERPC] Use the genirq framework
This adapts the generic powerpc interrupt handling code, and all of the platforms except for the embedded 6xx machines, to use the new genirq framework. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac')
-rw-r--r--arch/powerpc/platforms/powermac/pic.c170
1 files changed, 103 insertions, 67 deletions
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index c9b09a9e6050..58a4c7b90b8b 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -70,18 +70,19 @@ static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
70 70
71#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 71#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
72static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; 72static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
73static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
74static int pmac_irq_cascade = -1;
73 75
74/* 76static void __pmac_retrigger(unsigned int irq_nr)
75 * Mark an irq as "lost". This is only used on the pmac
76 * since it can lose interrupts (see pmac_set_irq_mask).
77 * -- Cort
78 */
79void __set_lost(unsigned long irq_nr, int nokick)
80{ 77{
81 if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { 78 if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) {
79 __set_bit(irq_nr, ppc_lost_interrupts);
80 irq_nr = pmac_irq_cascade;
81 mb();
82 }
83 if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
82 atomic_inc(&ppc_n_lost_interrupts); 84 atomic_inc(&ppc_n_lost_interrupts);
83 if (!nokick) 85 set_dec(1);
84 set_dec(1);
85 } 86 }
86} 87}
87 88
@@ -94,10 +95,10 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr)
94 if ((unsigned)irq_nr >= max_irqs) 95 if ((unsigned)irq_nr >= max_irqs)
95 return; 96 return;
96 97
97 clear_bit(irq_nr, ppc_cached_irq_mask);
98 if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
99 atomic_dec(&ppc_n_lost_interrupts);
100 spin_lock_irqsave(&pmac_pic_lock, flags); 98 spin_lock_irqsave(&pmac_pic_lock, flags);
99 __clear_bit(irq_nr, ppc_cached_irq_mask);
100 if (__test_and_clear_bit(irq_nr, ppc_lost_interrupts))
101 atomic_dec(&ppc_n_lost_interrupts);
101 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); 102 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
102 out_le32(&pmac_irq_hw[i]->ack, bit); 103 out_le32(&pmac_irq_hw[i]->ack, bit);
103 do { 104 do {
@@ -109,7 +110,7 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr)
109 spin_unlock_irqrestore(&pmac_pic_lock, flags); 110 spin_unlock_irqrestore(&pmac_pic_lock, flags);
110} 111}
111 112
112static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) 113static void pmac_ack_irq(unsigned int irq_nr)
113{ 114{
114 unsigned long bit = 1UL << (irq_nr & 0x1f); 115 unsigned long bit = 1UL << (irq_nr & 0x1f);
115 int i = irq_nr >> 5; 116 int i = irq_nr >> 5;
@@ -118,7 +119,22 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
118 if ((unsigned)irq_nr >= max_irqs) 119 if ((unsigned)irq_nr >= max_irqs)
119 return; 120 return;
120 121
121 spin_lock_irqsave(&pmac_pic_lock, flags); 122 spin_lock_irqsave(&pmac_pic_lock, flags);
123 if (__test_and_clear_bit(irq_nr, ppc_lost_interrupts))
124 atomic_dec(&ppc_n_lost_interrupts);
125 out_le32(&pmac_irq_hw[i]->ack, bit);
126 (void)in_le32(&pmac_irq_hw[i]->ack);
127 spin_unlock_irqrestore(&pmac_pic_lock, flags);
128}
129
130static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
131{
132 unsigned long bit = 1UL << (irq_nr & 0x1f);
133 int i = irq_nr >> 5;
134
135 if ((unsigned)irq_nr >= max_irqs)
136 return;
137
122 /* enable unmasked interrupts */ 138 /* enable unmasked interrupts */
123 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); 139 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
124 140
@@ -135,8 +151,7 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
135 * the bit in the flag register or request another interrupt. 151 * the bit in the flag register or request another interrupt.
136 */ 152 */
137 if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) 153 if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
138 __set_lost((ulong)irq_nr, nokicklost); 154 __pmac_retrigger(irq_nr);
139 spin_unlock_irqrestore(&pmac_pic_lock, flags);
140} 155}
141 156
142/* When an irq gets requested for the first client, if it's an 157/* When an irq gets requested for the first client, if it's an
@@ -144,62 +159,67 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
144 */ 159 */
145static unsigned int pmac_startup_irq(unsigned int irq_nr) 160static unsigned int pmac_startup_irq(unsigned int irq_nr)
146{ 161{
162 unsigned long flags;
147 unsigned long bit = 1UL << (irq_nr & 0x1f); 163 unsigned long bit = 1UL << (irq_nr & 0x1f);
148 int i = irq_nr >> 5; 164 int i = irq_nr >> 5;
149 165
166 spin_lock_irqsave(&pmac_pic_lock, flags);
150 if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) 167 if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
151 out_le32(&pmac_irq_hw[i]->ack, bit); 168 out_le32(&pmac_irq_hw[i]->ack, bit);
152 set_bit(irq_nr, ppc_cached_irq_mask); 169 __set_bit(irq_nr, ppc_cached_irq_mask);
153 pmac_set_irq_mask(irq_nr, 0); 170 __pmac_set_irq_mask(irq_nr, 0);
171 spin_unlock_irqrestore(&pmac_pic_lock, flags);
154 172
155 return 0; 173 return 0;
156} 174}
157 175
158static void pmac_mask_irq(unsigned int irq_nr) 176static void pmac_mask_irq(unsigned int irq_nr)
159{ 177{
160 clear_bit(irq_nr, ppc_cached_irq_mask); 178 unsigned long flags;
161 pmac_set_irq_mask(irq_nr, 0); 179
162 mb(); 180 spin_lock_irqsave(&pmac_pic_lock, flags);
181 __clear_bit(irq_nr, ppc_cached_irq_mask);
182 __pmac_set_irq_mask(irq_nr, 0);
183 spin_unlock_irqrestore(&pmac_pic_lock, flags);
163} 184}
164 185
165static void pmac_unmask_irq(unsigned int irq_nr) 186static void pmac_unmask_irq(unsigned int irq_nr)
166{ 187{
167 set_bit(irq_nr, ppc_cached_irq_mask); 188 unsigned long flags;
168 pmac_set_irq_mask(irq_nr, 0); 189
190 spin_lock_irqsave(&pmac_pic_lock, flags);
191 __set_bit(irq_nr, ppc_cached_irq_mask);
192 __pmac_set_irq_mask(irq_nr, 0);
193 spin_unlock_irqrestore(&pmac_pic_lock, flags);
169} 194}
170 195
171static void pmac_end_irq(unsigned int irq_nr) 196static int pmac_retrigger(unsigned int irq_nr)
172{ 197{
173 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) 198 unsigned long flags;
174 && irq_desc[irq_nr].action) {
175 set_bit(irq_nr, ppc_cached_irq_mask);
176 pmac_set_irq_mask(irq_nr, 1);
177 }
178}
179 199
200 spin_lock_irqsave(&pmac_pic_lock, flags);
201 __pmac_retrigger(irq_nr);
202 spin_unlock_irqrestore(&pmac_pic_lock, flags);
203 return 1;
204}
180 205
181struct hw_interrupt_type pmac_pic = { 206static struct irq_chip pmac_pic = {
182 .typename = " PMAC-PIC ", 207 .typename = " PMAC-PIC ",
183 .startup = pmac_startup_irq, 208 .startup = pmac_startup_irq,
184 .enable = pmac_unmask_irq, 209 .mask = pmac_mask_irq,
185 .disable = pmac_mask_irq, 210 .ack = pmac_ack_irq,
186 .ack = pmac_mask_and_ack_irq, 211 .mask_ack = pmac_mask_and_ack_irq,
187 .end = pmac_end_irq, 212 .unmask = pmac_unmask_irq,
188}; 213 .retrigger = pmac_retrigger,
189
190struct hw_interrupt_type gatwick_pic = {
191 .typename = " GATWICK ",
192 .startup = pmac_startup_irq,
193 .enable = pmac_unmask_irq,
194 .disable = pmac_mask_irq,
195 .ack = pmac_mask_and_ack_irq,
196 .end = pmac_end_irq,
197}; 214};
198 215
199static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) 216static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
200{ 217{
218 unsigned long flags;
201 int irq, bits; 219 int irq, bits;
220 int rc = IRQ_NONE;
202 221
222 spin_lock_irqsave(&pmac_pic_lock, flags);
203 for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { 223 for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
204 int i = irq >> 5; 224 int i = irq >> 5;
205 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; 225 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
@@ -209,17 +229,20 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
209 if (bits == 0) 229 if (bits == 0)
210 continue; 230 continue;
211 irq += __ilog2(bits); 231 irq += __ilog2(bits);
232 spin_unlock_irqrestore(&pmac_pic_lock, flags);
212 __do_IRQ(irq, regs); 233 __do_IRQ(irq, regs);
213 return IRQ_HANDLED; 234 spin_lock_irqsave(&pmac_pic_lock, flags);
235 rc = IRQ_HANDLED;
214 } 236 }
215 printk("gatwick irq not from gatwick pic\n"); 237 spin_unlock_irqrestore(&pmac_pic_lock, flags);
216 return IRQ_NONE; 238 return rc;
217} 239}
218 240
219static int pmac_get_irq(struct pt_regs *regs) 241static int pmac_get_irq(struct pt_regs *regs)
220{ 242{
221 int irq; 243 int irq;
222 unsigned long bits = 0; 244 unsigned long bits = 0;
245 unsigned long flags;
223 246
224#ifdef CONFIG_SMP 247#ifdef CONFIG_SMP
225 void psurge_smp_message_recv(struct pt_regs *); 248 void psurge_smp_message_recv(struct pt_regs *);
@@ -230,6 +253,7 @@ static int pmac_get_irq(struct pt_regs *regs)
230 return -2; /* ignore, already handled */ 253 return -2; /* ignore, already handled */
231 } 254 }
232#endif /* CONFIG_SMP */ 255#endif /* CONFIG_SMP */
256 spin_lock_irqsave(&pmac_pic_lock, flags);
233 for (irq = max_real_irqs; (irq -= 32) >= 0; ) { 257 for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
234 int i = irq >> 5; 258 int i = irq >> 5;
235 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; 259 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
@@ -241,6 +265,7 @@ static int pmac_get_irq(struct pt_regs *regs)
241 irq += __ilog2(bits); 265 irq += __ilog2(bits);
242 break; 266 break;
243 } 267 }
268 spin_unlock_irqrestore(&pmac_pic_lock, flags);
244 269
245 return irq; 270 return irq;
246} 271}
@@ -389,7 +414,6 @@ static struct irqaction gatwick_cascade_action = {
389static void __init pmac_pic_probe_oldstyle(void) 414static void __init pmac_pic_probe_oldstyle(void)
390{ 415{
391 int i; 416 int i;
392 int irq_cascade = -1;
393 struct device_node *master = NULL; 417 struct device_node *master = NULL;
394 struct device_node *slave = NULL; 418 struct device_node *slave = NULL;
395 u8 __iomem *addr; 419 u8 __iomem *addr;
@@ -443,9 +467,16 @@ static void __init pmac_pic_probe_oldstyle(void)
443 } 467 }
444 BUG_ON(master == NULL); 468 BUG_ON(master == NULL);
445 469
446 /* Set the handler for the main PIC */ 470 /* Mark level interrupts and set handlers */
447 for ( i = 0; i < max_real_irqs ; i++ ) 471 for (i = 0; i < max_irqs; i++) {
448 irq_desc[i].chip = &pmac_pic; 472 int level = !!(level_mask[i >> 5] & (1UL << (i & 0x1f)));
473 if (level)
474 irq_desc[i].status |= IRQ_LEVEL;
475 else
476 irq_desc[i].status |= IRQ_DELAYED_DISABLE;
477 set_irq_chip_and_handler(i, &pmac_pic, level ?
478 handle_level_irq : handle_edge_irq);
479 }
449 480
450 /* Get addresses of first controller if we have a node for it */ 481 /* Get addresses of first controller if we have a node for it */
451 BUG_ON(of_address_to_resource(master, 0, &r)); 482 BUG_ON(of_address_to_resource(master, 0, &r));
@@ -472,29 +503,22 @@ static void __init pmac_pic_probe_oldstyle(void)
472 pmac_irq_hw[i++] = 503 pmac_irq_hw[i++] =
473 (volatile struct pmac_irq_hw __iomem *) 504 (volatile struct pmac_irq_hw __iomem *)
474 (addr + 0x10); 505 (addr + 0x10);
475 irq_cascade = slave->intrs[0].line; 506 pmac_irq_cascade = slave->intrs[0].line;
476 507
477 printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" 508 printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs"
478 " cascade: %d\n", slave->full_name, 509 " cascade: %d\n", slave->full_name,
479 max_irqs - max_real_irqs, irq_cascade); 510 max_irqs - max_real_irqs, pmac_irq_cascade);
480 } 511 }
481 of_node_put(slave); 512 of_node_put(slave);
482 513
483 /* disable all interrupts in all controllers */ 514 /* Disable all interrupts in all controllers */
484 for (i = 0; i * 32 < max_irqs; ++i) 515 for (i = 0; i * 32 < max_irqs; ++i)
485 out_le32(&pmac_irq_hw[i]->enable, 0); 516 out_le32(&pmac_irq_hw[i]->enable, 0);
486 517
487 /* mark level interrupts */ 518 /* Hookup cascade irq */
488 for (i = 0; i < max_irqs; i++) 519 if (slave)
489 if (level_mask[i >> 5] & (1UL << (i & 0x1f))) 520 setup_irq(pmac_irq_cascade, &gatwick_cascade_action);
490 irq_desc[i].status = IRQ_LEVEL;
491 521
492 /* Setup handlers for secondary controller and hook cascade irq*/
493 if (slave) {
494 for ( i = max_real_irqs ; i < max_irqs ; i++ )
495 irq_desc[i].chip = &gatwick_pic;
496 setup_irq(irq_cascade, &gatwick_cascade_action);
497 }
498 printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); 522 printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);
499#ifdef CONFIG_XMON 523#ifdef CONFIG_XMON
500 setup_irq(20, &xmon_action); 524 setup_irq(20, &xmon_action);
@@ -502,9 +526,20 @@ static void __init pmac_pic_probe_oldstyle(void)
502} 526}
503#endif /* CONFIG_PPC32 */ 527#endif /* CONFIG_PPC32 */
504 528
505static int pmac_u3_cascade(struct pt_regs *regs, void *data) 529static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc,
530 struct pt_regs *regs)
506{ 531{
507 return mpic_get_one_irq((struct mpic *)data, regs); 532 struct mpic *mpic = desc->handler_data;
533 unsigned int max = 100;
534
535 while(max--) {
536 int cascade_irq = mpic_get_one_irq(mpic, regs);
537 if (max == 99)
538 desc->chip->eoi(irq);
539 if (irq < 0)
540 break;
541 generic_handle_irq(cascade_irq, regs);
542 };
508} 543}
509 544
510static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) 545static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
@@ -612,7 +647,8 @@ static int __init pmac_pic_probe_mpic(void)
612 of_node_put(slave); 647 of_node_put(slave);
613 return 0; 648 return 0;
614 } 649 }
615 mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); 650 set_irq_data(slave->intrs[0].line, mpic2);
651 set_irq_chained_handler(slave->intrs[0].line, pmac_u3_cascade);
616 652
617 of_node_put(slave); 653 of_node_put(slave);
618 return 0; 654 return 0;