* better
[mascara-docs.git] / i386 / linux-2.3.21 / arch / ppc / kernel / pmac_pic.c
blob683aac568282d70abbbd4c3e45bdcf10c62efcdb
1 #include <linux/config.h>
2 #include <linux/stddef.h>
3 #include <linux/init.h>
4 #include <linux/sched.h>
5 #include <linux/signal.h>
7 #include <asm/init.h>
8 #include <asm/io.h>
9 #include <asm/smp.h>
10 #include <asm/prom.h>
11 #include "pmac_pic.h"
13 /* pmac */struct pmac_irq_hw {
14 unsigned int flag;
15 unsigned int enable;
16 unsigned int ack;
17 unsigned int level;
20 /* XXX these addresses should be obtained from the device tree */
21 static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
22 (struct pmac_irq_hw *) 0xf3000020,
23 (struct pmac_irq_hw *) 0xf3000010,
24 (struct pmac_irq_hw *) 0xf4000020,
25 (struct pmac_irq_hw *) 0xf4000010,
28 static int max_irqs;
29 static int max_real_irqs;
31 #define MAXCOUNT 10000000
33 #define GATWICK_IRQ_POOL_SIZE 10
34 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
36 static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
38 unsigned long bit = 1UL << (irq_nr & 0x1f);
39 int i = irq_nr >> 5;
41 if ((unsigned)irq_nr >= max_irqs)
42 return;
44 clear_bit(irq_nr, ppc_cached_irq_mask);
45 if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
46 atomic_dec(&ppc_n_lost_interrupts);
47 out_le32(&pmac_irq_hw[i]->ack, bit);
48 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
49 out_le32(&pmac_irq_hw[i]->ack, bit);
50 do {
51 /* make sure ack gets to controller before we enable
52 interrupts */
53 mb();
54 } while(in_le32(&pmac_irq_hw[i]->flag) & bit);
57 static void __pmac pmac_set_irq_mask(unsigned int irq_nr)
59 unsigned long bit = 1UL << (irq_nr & 0x1f);
60 int i = irq_nr >> 5;
62 if ((unsigned)irq_nr >= max_irqs)
63 return;
65 /* enable unmasked interrupts */
66 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
68 do {
69 /* make sure mask gets to controller before we
70 return to user */
71 mb();
72 } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
73 != (ppc_cached_irq_mask[i] & bit));
76 * Unfortunately, setting the bit in the enable register
77 * when the device interrupt is already on *doesn't* set
78 * the bit in the flag register or request another interrupt.
80 if ((bit & ppc_cached_irq_mask[i])
81 && (ld_le32(&pmac_irq_hw[i]->level) & bit)
82 && !(ld_le32(&pmac_irq_hw[i]->flag) & bit)) {
83 if (!test_and_set_bit(irq_nr, ppc_lost_interrupts))
84 atomic_inc(&ppc_n_lost_interrupts);
88 static void __pmac pmac_mask_irq(unsigned int irq_nr)
90 clear_bit(irq_nr, ppc_cached_irq_mask);
91 pmac_set_irq_mask(irq_nr);
92 mb();
95 static void __pmac pmac_unmask_irq(unsigned int irq_nr)
97 set_bit(irq_nr, ppc_cached_irq_mask);
98 pmac_set_irq_mask(irq_nr);
101 struct hw_interrupt_type pmac_pic = {
102 " PMAC-PIC ",
103 NULL,
104 NULL,
105 pmac_unmask_irq,
106 pmac_mask_irq,
107 pmac_mask_and_ack_irq,
111 struct hw_interrupt_type gatwick_pic = {
112 " GATWICK ",
113 NULL,
114 NULL,
115 pmac_unmask_irq,
116 pmac_mask_irq,
117 pmac_mask_and_ack_irq,
121 static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
123 int irq, bits;
125 for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
126 int i = irq >> 5;
127 bits = ld_le32(&pmac_irq_hw[i]->flag)
128 | ppc_lost_interrupts[i];
129 if (bits == 0)
130 continue;
131 irq -= cntlzw(bits);
132 break;
134 /* The previous version of this code allowed for this case, we
135 * don't. Put this here to check for it.
136 * -- Cort
138 if ( irq_desc[irq].ctl != &gatwick_pic )
139 printk("gatwick irq not from gatwick pic\n");
140 else
141 ppc_irq_dispatch_handler( regs, irq );
144 #if 0
145 void
146 pmac_do_IRQ(struct pt_regs *regs,
147 int cpu,
148 int isfake)
150 int irq;
151 unsigned long bits = 0;
153 #ifdef __SMP__
154 /* IPI's are a hack on the powersurge -- Cort */
155 if ( cpu != 0 )
157 #ifdef CONFIG_XMON
158 static int xmon_2nd;
159 if (xmon_2nd)
160 xmon(regs);
161 #endif
162 smp_message_recv();
163 return -1;
167 unsigned int loops = MAXCOUNT;
168 while (test_bit(0, &global_irq_lock)) {
169 if (smp_processor_id() == global_irq_holder) {
170 printk("uh oh, interrupt while we hold global irq lock!\n");
171 #ifdef CONFIG_XMON
172 xmon(0);
173 #endif
174 break;
176 if (loops-- == 0) {
177 printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
178 #ifdef CONFIG_XMON
179 xmon(0);
180 #endif
184 #endif /* __SMP__ */
186 for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
187 int i = irq >> 5;
188 bits = ld_le32(&pmac_irq_hw[i]->flag)
189 | ppc_lost_interrupts[i];
190 if (bits == 0)
191 continue;
192 irq -= cntlzw(bits);
193 break;
196 if (irq < 0)
198 printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
199 irq, regs->nip);
200 ppc_spurious_interrupts++;
202 else
204 ppc_irq_dispatch_handler( regs, irq );
206 #ifdef CONFIG_SMP
207 out:
208 #endif /* CONFIG_SMP */
210 #endif
213 pmac_get_irq(struct pt_regs *regs)
215 int irq;
216 unsigned long bits = 0;
218 #ifdef __SMP__
219 /* IPI's are a hack on the powersurge -- Cort */
220 if ( smp_processor_id() != 0 )
222 #ifdef CONFIG_XMON
223 static int xmon_2nd;
224 if (xmon_2nd)
225 xmon(regs);
226 #endif
227 smp_message_recv();
228 return -1;
232 unsigned int loops = MAXCOUNT;
233 while (test_bit(0, &global_irq_lock)) {
234 if (smp_processor_id() == global_irq_holder) {
235 printk("uh oh, interrupt while we hold global irq lock!\n");
236 #ifdef CONFIG_XMON
237 xmon(0);
238 #endif
239 break;
241 if (loops-- == 0) {
242 printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
243 #ifdef CONFIG_XMON
244 xmon(0);
245 #endif
249 #endif /* __SMP__ */
251 for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
252 int i = irq >> 5;
253 bits = ld_le32(&pmac_irq_hw[i]->flag)
254 | ppc_lost_interrupts[i];
255 if (bits == 0)
256 continue;
257 irq -= cntlzw(bits);
258 break;
261 return irq;
264 /* This routine will fix some missing interrupt values in the device tree
265 * on the gatwick mac-io controller used by some PowerBooks
267 static void __init
268 pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
270 struct device_node *node;
271 int count;
273 memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
274 node = gw->child;
275 count = 0;
276 while(node)
278 /* Fix SCC */
279 if (strcasecmp(node->name, "escc") == 0)
280 if (node->child) {
281 if (node->child->n_intrs < 3) {
282 node->child->intrs = &gatwick_int_pool[count];
283 count += 3;
285 node->child->n_intrs = 3;
286 node->child->intrs[0].line = 15+irq_base;
287 node->child->intrs[1].line = 4+irq_base;
288 node->child->intrs[2].line = 5+irq_base;
289 printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
290 node->child->intrs[0].line,
291 node->child->intrs[1].line,
292 node->child->intrs[2].line);
294 /* Fix media-bay & left SWIM */
295 if (strcasecmp(node->name, "media-bay") == 0) {
296 struct device_node* ya_node;
298 if (node->n_intrs == 0)
299 node->intrs = &gatwick_int_pool[count++];
300 node->n_intrs = 1;
301 node->intrs[0].line = 29+irq_base;
302 printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
303 node->intrs[0].line);
305 ya_node = node->child;
306 while(ya_node)
308 if (strcasecmp(ya_node->name, "floppy") == 0) {
309 if (ya_node->n_intrs < 2) {
310 ya_node->intrs = &gatwick_int_pool[count];
311 count += 2;
313 ya_node->n_intrs = 2;
314 ya_node->intrs[0].line = 19+irq_base;
315 ya_node->intrs[1].line = 1+irq_base;
316 printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
317 ya_node->intrs[0].line, ya_node->intrs[1].line);
319 if (strcasecmp(ya_node->name, "ata4") == 0) {
320 if (ya_node->n_intrs < 2) {
321 ya_node->intrs = &gatwick_int_pool[count];
322 count += 2;
324 ya_node->n_intrs = 2;
325 ya_node->intrs[0].line = 14+irq_base;
326 ya_node->intrs[1].line = 3+irq_base;
327 printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
328 ya_node->intrs[0].line, ya_node->intrs[1].line);
330 ya_node = ya_node->sibling;
333 node = node->sibling;
335 if (count > 10) {
336 printk("WARNING !! Gatwick interrupt pool overflow\n");
337 printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
338 printk(" requested = %d\n", count);
342 void __init
343 pmac_pic_init(void)
345 int i;
346 struct device_node *irqctrler;
347 unsigned long addr;
348 int second_irq = -999;
351 /* G3 powermacs have 64 interrupts, G3 Series PowerBook have 128,
352 others have 32 */
353 max_irqs = max_real_irqs = 32;
354 irqctrler = find_devices("mac-io");
355 if (irqctrler)
357 max_real_irqs = 64;
358 if (irqctrler->next)
359 max_irqs = 128;
360 else
361 max_irqs = 64;
363 for ( i = 0; i < max_real_irqs ; i++ )
364 irq_desc[i].ctl = &pmac_pic;
366 /* get addresses of first controller */
367 if (irqctrler) {
368 if (irqctrler->n_addrs > 0) {
369 addr = (unsigned long)
370 ioremap(irqctrler->addrs[0].address, 0x40);
371 for (i = 0; i < 2; ++i)
372 pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
373 (addr + (2 - i) * 0x10);
376 /* get addresses of second controller */
377 irqctrler = (irqctrler->next) ? irqctrler->next : NULL;
378 if (irqctrler && irqctrler->n_addrs > 0) {
379 addr = (unsigned long)
380 ioremap(irqctrler->addrs[0].address, 0x40);
381 for (i = 2; i < 4; ++i)
382 pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
383 (addr + (4 - i) * 0x10);
387 /* disable all interrupts in all controllers */
388 for (i = 0; i * 32 < max_irqs; ++i)
389 out_le32(&pmac_irq_hw[i]->enable, 0);
391 /* get interrupt line of secondary interrupt controller */
392 if (irqctrler) {
393 second_irq = irqctrler->intrs[0].line;
394 printk(KERN_INFO "irq: secondary controller on irq %d\n",
395 (int)second_irq);
396 if (device_is_compatible(irqctrler, "gatwick"))
397 pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
398 for ( i = max_real_irqs ; i < max_irqs ; i++ )
399 irq_desc[i].ctl = &gatwick_pic;
400 request_irq( second_irq, gatwick_action, SA_INTERRUPT,
401 "gatwick cascade", 0 );
403 printk("System has %d possible interrupts\n", max_irqs);
404 if (max_irqs != max_real_irqs)
405 printk(KERN_DEBUG "%d interrupts on main controller\n",
406 max_real_irqs);
408 #ifdef CONFIG_XMON
409 request_irq(20, xmon_irq, 0, "NMI - XMON", 0);
410 #endif /* CONFIG_XMON */
413 #ifdef CONFIG_PMAC_PBOOK
415 * These procedures are used in implementing sleep on the powerbooks.
416 * sleep_save_intrs() saves the states of all interrupt enables
417 * and disables all interupts except for the nominated one.
418 * sleep_restore_intrs() restores the states of all interrupt enables.
420 unsigned int sleep_save_mask[2];
422 void
423 sleep_save_intrs(int viaint)
425 sleep_save_mask[0] = ppc_cached_irq_mask[0];
426 sleep_save_mask[1] = ppc_cached_irq_mask[1];
427 ppc_cached_irq_mask[0] = 0;
428 ppc_cached_irq_mask[1] = 0;
429 set_bit(viaint, ppc_cached_irq_mask);
430 out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
431 if (max_real_irqs > 32)
432 out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
433 mb();
436 void
437 sleep_restore_intrs(void)
439 int i;
441 out_le32(&pmac_irq_hw[0]->enable, 0);
442 if (max_real_irqs > 32)
443 out_le32(&pmac_irq_hw[1]->enable, 0);
444 mb();
445 for (i = 0; i < max_real_irqs; ++i)
446 if (test_bit(i, sleep_save_mask))
447 pmac_unmask_irq(i);
449 #endif /* CONFIG_PMAC_PBOOK */