diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-12-13 02:01:21 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 22:53:55 -0500 |
commit | cc5d0189b9ba95260857a5018a1c2fef90008507 (patch) | |
tree | 1202c94b6b3cb81a96d0a0e54424cad10eef68bb /arch/powerpc/platforms/powermac/pic.c | |
parent | 9cf84d7c97992dbe5360b241327341c07ce30fc9 (diff) |
[PATCH] powerpc: Remove device_node addrs/n_addr
The pre-parsed addrs/n_addrs fields in struct device_node are finally
gone. Remove the dodgy heuristics that did that parsing at boot and
remove the fields themselves since we now have a good replacement with
the new OF parsing code. This patch also fixes a bunch of drivers to use
the new code instead, so that at least pmac32, pseries, iseries and g5
defconfigs build.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac/pic.c')
-rw-r--r-- | arch/powerpc/platforms/powermac/pic.c | 456 |
1 files changed, 246 insertions, 210 deletions
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index a36527c98133..dbb524a851aa 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -5,8 +5,8 @@ | |||
5 | * in a separate file | 5 | * in a separate file |
6 | * | 6 | * |
7 | * Copyright (C) 1997 Paul Mackerras (paulus@samba.org) | 7 | * Copyright (C) 1997 Paul Mackerras (paulus@samba.org) |
8 | * | 8 | * Copyright (C) 2005 Benjamin Herrenschmidt (benh@kernel.crashing.org) |
9 | * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) | 9 | * IBM, Corp. |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
@@ -54,12 +54,7 @@ struct pmac_irq_hw { | |||
54 | }; | 54 | }; |
55 | 55 | ||
56 | /* Default addresses */ | 56 | /* Default addresses */ |
57 | static volatile struct pmac_irq_hw *pmac_irq_hw[4] = { | 57 | static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4]; |
58 | (struct pmac_irq_hw *) 0xf3000020, | ||
59 | (struct pmac_irq_hw *) 0xf3000010, | ||
60 | (struct pmac_irq_hw *) 0xf4000020, | ||
61 | (struct pmac_irq_hw *) 0xf4000010, | ||
62 | }; | ||
63 | 58 | ||
64 | #define GC_LEVEL_MASK 0x3ff00000 | 59 | #define GC_LEVEL_MASK 0x3ff00000 |
65 | #define OHARE_LEVEL_MASK 0x1ff00000 | 60 | #define OHARE_LEVEL_MASK 0x1ff00000 |
@@ -82,8 +77,7 @@ static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | |||
82 | * since it can lose interrupts (see pmac_set_irq_mask). | 77 | * since it can lose interrupts (see pmac_set_irq_mask). |
83 | * -- Cort | 78 | * -- Cort |
84 | */ | 79 | */ |
85 | void | 80 | void __set_lost(unsigned long irq_nr, int nokick) |
86 | __set_lost(unsigned long irq_nr, int nokick) | ||
87 | { | 81 | { |
88 | if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { | 82 | if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { |
89 | atomic_inc(&ppc_n_lost_interrupts); | 83 | atomic_inc(&ppc_n_lost_interrupts); |
@@ -92,8 +86,7 @@ __set_lost(unsigned long irq_nr, int nokick) | |||
92 | } | 86 | } |
93 | } | 87 | } |
94 | 88 | ||
95 | static void | 89 | static void pmac_mask_and_ack_irq(unsigned int irq_nr) |
96 | pmac_mask_and_ack_irq(unsigned int irq_nr) | ||
97 | { | 90 | { |
98 | unsigned long bit = 1UL << (irq_nr & 0x1f); | 91 | unsigned long bit = 1UL << (irq_nr & 0x1f); |
99 | int i = irq_nr >> 5; | 92 | int i = irq_nr >> 5; |
@@ -224,8 +217,7 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) | |||
224 | return IRQ_NONE; | 217 | return IRQ_NONE; |
225 | } | 218 | } |
226 | 219 | ||
227 | int | 220 | static int pmac_get_irq(struct pt_regs *regs) |
228 | pmac_get_irq(struct pt_regs *regs) | ||
229 | { | 221 | { |
230 | int irq; | 222 | int irq; |
231 | unsigned long bits = 0; | 223 | unsigned long bits = 0; |
@@ -256,34 +248,40 @@ pmac_get_irq(struct pt_regs *regs) | |||
256 | 248 | ||
257 | /* This routine will fix some missing interrupt values in the device tree | 249 | /* This routine will fix some missing interrupt values in the device tree |
258 | * on the gatwick mac-io controller used by some PowerBooks | 250 | * on the gatwick mac-io controller used by some PowerBooks |
251 | * | ||
252 | * Walking of OF nodes could use a bit more fixing up here, but it's not | ||
253 | * very important as this is all boot time code on static portions of the | ||
254 | * device-tree. | ||
255 | * | ||
256 | * However, the modifications done to "intrs" will have to be removed and | ||
257 | * replaced with proper updates of the "interrupts" properties or | ||
258 | * AAPL,interrupts, yet to be decided, once the dynamic parsing is there. | ||
259 | */ | 259 | */ |
260 | static void __init | 260 | static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, |
261 | pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) | 261 | int irq_base) |
262 | { | 262 | { |
263 | struct device_node *node; | 263 | struct device_node *node; |
264 | int count; | 264 | int count; |
265 | 265 | ||
266 | memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); | 266 | memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); |
267 | node = gw->child; | ||
268 | count = 0; | 267 | count = 0; |
269 | while(node) | 268 | for (node = NULL; (node = of_get_next_child(gw, node)) != NULL;) { |
270 | { | ||
271 | /* Fix SCC */ | 269 | /* Fix SCC */ |
272 | if (strcasecmp(node->name, "escc") == 0) | 270 | if ((strcasecmp(node->name, "escc") == 0) && node->child) { |
273 | if (node->child) { | 271 | if (node->child->n_intrs < 3) { |
274 | if (node->child->n_intrs < 3) { | 272 | node->child->intrs = &gatwick_int_pool[count]; |
275 | node->child->intrs = &gatwick_int_pool[count]; | 273 | count += 3; |
276 | count += 3; | ||
277 | } | ||
278 | node->child->n_intrs = 3; | ||
279 | node->child->intrs[0].line = 15+irq_base; | ||
280 | node->child->intrs[1].line = 4+irq_base; | ||
281 | node->child->intrs[2].line = 5+irq_base; | ||
282 | printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n", | ||
283 | node->child->intrs[0].line, | ||
284 | node->child->intrs[1].line, | ||
285 | node->child->intrs[2].line); | ||
286 | } | 274 | } |
275 | node->child->n_intrs = 3; | ||
276 | node->child->intrs[0].line = 15+irq_base; | ||
277 | node->child->intrs[1].line = 4+irq_base; | ||
278 | node->child->intrs[2].line = 5+irq_base; | ||
279 | printk(KERN_INFO "irq: fixed SCC on gatwick" | ||
280 | " (%d,%d,%d)\n", | ||
281 | node->child->intrs[0].line, | ||
282 | node->child->intrs[1].line, | ||
283 | node->child->intrs[2].line); | ||
284 | } | ||
287 | /* Fix media-bay & left SWIM */ | 285 | /* Fix media-bay & left SWIM */ |
288 | if (strcasecmp(node->name, "media-bay") == 0) { | 286 | if (strcasecmp(node->name, "media-bay") == 0) { |
289 | struct device_node* ya_node; | 287 | struct device_node* ya_node; |
@@ -292,12 +290,11 @@ pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) | |||
292 | node->intrs = &gatwick_int_pool[count++]; | 290 | node->intrs = &gatwick_int_pool[count++]; |
293 | node->n_intrs = 1; | 291 | node->n_intrs = 1; |
294 | node->intrs[0].line = 29+irq_base; | 292 | node->intrs[0].line = 29+irq_base; |
295 | printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n", | 293 | printk(KERN_INFO "irq: fixed media-bay on gatwick" |
296 | node->intrs[0].line); | 294 | " (%d)\n", node->intrs[0].line); |
297 | 295 | ||
298 | ya_node = node->child; | 296 | ya_node = node->child; |
299 | while(ya_node) | 297 | while(ya_node) { |
300 | { | ||
301 | if (strcasecmp(ya_node->name, "floppy") == 0) { | 298 | if (strcasecmp(ya_node->name, "floppy") == 0) { |
302 | if (ya_node->n_intrs < 2) { | 299 | if (ya_node->n_intrs < 2) { |
303 | ya_node->intrs = &gatwick_int_pool[count]; | 300 | ya_node->intrs = &gatwick_int_pool[count]; |
@@ -323,7 +320,6 @@ pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) | |||
323 | ya_node = ya_node->sibling; | 320 | ya_node = ya_node->sibling; |
324 | } | 321 | } |
325 | } | 322 | } |
326 | node = node->sibling; | ||
327 | } | 323 | } |
328 | if (count > 10) { | 324 | if (count > 10) { |
329 | printk("WARNING !! Gatwick interrupt pool overflow\n"); | 325 | printk("WARNING !! Gatwick interrupt pool overflow\n"); |
@@ -338,45 +334,41 @@ pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) | |||
338 | * controller. If we find this second ohare, set it up and fix the | 334 | * controller. If we find this second ohare, set it up and fix the |
339 | * interrupt value in the device tree for the ethernet chip. | 335 | * interrupt value in the device tree for the ethernet chip. |
340 | */ | 336 | */ |
341 | static int __init enable_second_ohare(void) | 337 | static void __init enable_second_ohare(struct device_node *np) |
342 | { | 338 | { |
343 | unsigned char bus, devfn; | 339 | unsigned char bus, devfn; |
344 | unsigned short cmd; | 340 | unsigned short cmd; |
345 | unsigned long addr; | ||
346 | struct device_node *irqctrler = find_devices("pci106b,7"); | ||
347 | struct device_node *ether; | 341 | struct device_node *ether; |
348 | 342 | ||
349 | if (irqctrler == NULL || irqctrler->n_addrs <= 0) | 343 | /* This code doesn't strictly belong here, it could be part of |
350 | return -1; | 344 | * either the PCI initialisation or the feature code. It's kept |
351 | addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); | 345 | * here for historical reasons. |
352 | pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); | 346 | */ |
353 | max_irqs = 64; | 347 | if (pci_device_from_OF_node(np, &bus, &devfn) == 0) { |
354 | if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) { | 348 | struct pci_controller* hose = |
355 | struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler); | 349 | pci_find_hose_for_OF_device(np); |
356 | if (!hose) | 350 | if (!hose) { |
357 | printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); | 351 | printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); |
358 | else { | 352 | return; |
359 | early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); | ||
360 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | ||
361 | cmd &= ~PCI_COMMAND_IO; | ||
362 | early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); | ||
363 | } | 353 | } |
354 | early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); | ||
355 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | ||
356 | cmd &= ~PCI_COMMAND_IO; | ||
357 | early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); | ||
364 | } | 358 | } |
365 | 359 | ||
366 | /* Fix interrupt for the modem/ethernet combo controller. The number | 360 | /* Fix interrupt for the modem/ethernet combo controller. The number |
367 | in the device tree (27) is bogus (correct for the ethernet-only | 361 | * in the device tree (27) is bogus (correct for the ethernet-only |
368 | board but not the combo ethernet/modem board). | 362 | * board but not the combo ethernet/modem board). |
369 | The real interrupt is 28 on the second controller -> 28+32 = 60. | 363 | * The real interrupt is 28 on the second controller -> 28+32 = 60. |
370 | */ | 364 | */ |
371 | ether = find_devices("pci1011,14"); | 365 | ether = of_find_node_by_name(NULL, "pci1011,14"); |
372 | if (ether && ether->n_intrs > 0) { | 366 | if (ether && ether->n_intrs > 0) { |
373 | ether->intrs[0].line = 60; | 367 | ether->intrs[0].line = 60; |
374 | printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", | 368 | printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", |
375 | ether->intrs[0].line); | 369 | ether->intrs[0].line); |
376 | } | 370 | } |
377 | 371 | of_node_put(ether); | |
378 | /* Return the interrupt number of the cascade */ | ||
379 | return irqctrler->intrs[0].line; | ||
380 | } | 372 | } |
381 | 373 | ||
382 | #ifdef CONFIG_XMON | 374 | #ifdef CONFIG_XMON |
@@ -394,189 +386,233 @@ static struct irqaction gatwick_cascade_action = { | |||
394 | .mask = CPU_MASK_NONE, | 386 | .mask = CPU_MASK_NONE, |
395 | .name = "cascade", | 387 | .name = "cascade", |
396 | }; | 388 | }; |
397 | #endif /* CONFIG_PPC32 */ | ||
398 | 389 | ||
399 | static int pmac_u3_cascade(struct pt_regs *regs, void *data) | 390 | static void __init pmac_pic_probe_oldstyle(void) |
400 | { | 391 | { |
401 | return mpic_get_one_irq((struct mpic *)data, regs); | ||
402 | } | ||
403 | |||
404 | void __init pmac_pic_init(void) | ||
405 | { | ||
406 | struct device_node *irqctrler = NULL; | ||
407 | struct device_node *irqctrler2 = NULL; | ||
408 | struct device_node *np; | ||
409 | #ifdef CONFIG_PPC32 | ||
410 | int i; | 392 | int i; |
411 | unsigned long addr; | ||
412 | int irq_cascade = -1; | 393 | int irq_cascade = -1; |
413 | #endif | 394 | struct device_node *master = NULL; |
414 | struct mpic *mpic1, *mpic2; | 395 | struct device_node *slave = NULL; |
396 | u8 __iomem *addr; | ||
397 | struct resource r; | ||
415 | 398 | ||
416 | /* We first try to detect Apple's new Core99 chipset, since mac-io | 399 | /* Set our get_irq function */ |
417 | * is quite different on those machines and contains an IBM MPIC2. | 400 | ppc_md.get_irq = pmac_get_irq; |
418 | */ | ||
419 | np = find_type_devices("open-pic"); | ||
420 | while (np) { | ||
421 | if (np->parent && !strcmp(np->parent->name, "u3")) | ||
422 | irqctrler2 = np; | ||
423 | else | ||
424 | irqctrler = np; | ||
425 | np = np->next; | ||
426 | } | ||
427 | if (irqctrler != NULL && irqctrler->n_addrs > 0) { | ||
428 | unsigned char senses[128]; | ||
429 | |||
430 | printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n", | ||
431 | (unsigned int)irqctrler->addrs[0].address); | ||
432 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0); | ||
433 | |||
434 | prom_get_irq_senses(senses, 0, 128); | ||
435 | mpic1 = mpic_alloc(irqctrler->addrs[0].address, | ||
436 | MPIC_PRIMARY | MPIC_WANTS_RESET, | ||
437 | 0, 0, 128, 252, senses, 128, " OpenPIC "); | ||
438 | BUG_ON(mpic1 == NULL); | ||
439 | mpic_init(mpic1); | ||
440 | |||
441 | if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && | ||
442 | irqctrler2->n_addrs > 0) { | ||
443 | printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", | ||
444 | (u32)irqctrler2->addrs[0].address, | ||
445 | irqctrler2->intrs[0].line); | ||
446 | |||
447 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); | ||
448 | prom_get_irq_senses(senses, 128, 128 + 124); | ||
449 | |||
450 | /* We don't need to set MPIC_BROKEN_U3 here since we don't have | ||
451 | * hypertransport interrupts routed to it | ||
452 | */ | ||
453 | mpic2 = mpic_alloc(irqctrler2->addrs[0].address, | ||
454 | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET, | ||
455 | 0, 128, 124, 0, senses, 124, | ||
456 | " U3-MPIC "); | ||
457 | BUG_ON(mpic2 == NULL); | ||
458 | mpic_init(mpic2); | ||
459 | mpic_setup_cascade(irqctrler2->intrs[0].line, | ||
460 | pmac_u3_cascade, mpic2); | ||
461 | } | ||
462 | #if defined(CONFIG_XMON) && defined(CONFIG_PPC32) | ||
463 | { | ||
464 | struct device_node* pswitch; | ||
465 | int nmi_irq; | ||
466 | |||
467 | pswitch = find_devices("programmer-switch"); | ||
468 | if (pswitch && pswitch->n_intrs) { | ||
469 | nmi_irq = pswitch->intrs[0].line; | ||
470 | mpic_irq_set_priority(nmi_irq, 9); | ||
471 | setup_irq(nmi_irq, &xmon_action); | ||
472 | } | ||
473 | } | ||
474 | #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ | ||
475 | return; | ||
476 | } | ||
477 | irqctrler = NULL; | ||
478 | 401 | ||
479 | #ifdef CONFIG_PPC32 | 402 | /* |
480 | /* Get the level/edge settings, assume if it's not | 403 | * Find the interrupt controller type & node |
481 | * a Grand Central nor an OHare, then it's an Heathrow | ||
482 | * (or Paddington). | ||
483 | */ | 404 | */ |
484 | ppc_md.get_irq = pmac_get_irq; | 405 | |
485 | if (find_devices("gc")) | 406 | if ((master = of_find_node_by_name(NULL, "gc")) != NULL) { |
407 | max_irqs = max_real_irqs = 32; | ||
486 | level_mask[0] = GC_LEVEL_MASK; | 408 | level_mask[0] = GC_LEVEL_MASK; |
487 | else if (find_devices("ohare")) { | 409 | } else if ((master = of_find_node_by_name(NULL, "ohare")) != NULL) { |
410 | max_irqs = max_real_irqs = 32; | ||
488 | level_mask[0] = OHARE_LEVEL_MASK; | 411 | level_mask[0] = OHARE_LEVEL_MASK; |
412 | |||
489 | /* We might have a second cascaded ohare */ | 413 | /* We might have a second cascaded ohare */ |
490 | level_mask[1] = OHARE_LEVEL_MASK; | 414 | slave = of_find_node_by_name(NULL, "pci106b,7"); |
491 | } else { | 415 | if (slave) { |
416 | max_irqs = 64; | ||
417 | level_mask[1] = OHARE_LEVEL_MASK; | ||
418 | enable_second_ohare(slave); | ||
419 | } | ||
420 | } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) { | ||
421 | max_irqs = max_real_irqs = 64; | ||
492 | level_mask[0] = HEATHROW_LEVEL_MASK; | 422 | level_mask[0] = HEATHROW_LEVEL_MASK; |
493 | level_mask[1] = 0; | 423 | level_mask[1] = 0; |
424 | |||
494 | /* We might have a second cascaded heathrow */ | 425 | /* We might have a second cascaded heathrow */ |
495 | level_mask[2] = HEATHROW_LEVEL_MASK; | 426 | slave = of_find_node_by_name(master, "mac-io"); |
496 | level_mask[3] = 0; | 427 | |
497 | } | 428 | /* Check ordering of master & slave */ |
429 | if (device_is_compatible(master, "gatwick")) { | ||
430 | struct device_node *tmp; | ||
431 | BUG_ON(slave == NULL); | ||
432 | tmp = master; | ||
433 | master = slave; | ||
434 | slave = tmp; | ||
435 | } | ||
498 | 436 | ||
499 | /* | 437 | /* We found a slave */ |
500 | * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts, | 438 | if (slave) { |
501 | * 1998 G3 Series PowerBooks have 128, | ||
502 | * other powermacs have 32. | ||
503 | * The combo ethernet/modem card for the Powerstar powerbooks | ||
504 | * (2400/3400/3500, ohare based) has a second ohare chip | ||
505 | * effectively making a total of 64. | ||
506 | */ | ||
507 | max_irqs = max_real_irqs = 32; | ||
508 | irqctrler = find_devices("mac-io"); | ||
509 | if (irqctrler) | ||
510 | { | ||
511 | max_real_irqs = 64; | ||
512 | if (irqctrler->next) | ||
513 | max_irqs = 128; | 439 | max_irqs = 128; |
514 | else | 440 | level_mask[2] = HEATHROW_LEVEL_MASK; |
515 | max_irqs = 64; | 441 | level_mask[3] = 0; |
442 | pmac_fix_gatwick_interrupts(slave, max_real_irqs); | ||
443 | } | ||
516 | } | 444 | } |
445 | BUG_ON(master == NULL); | ||
446 | |||
447 | /* Set the handler for the main PIC */ | ||
517 | for ( i = 0; i < max_real_irqs ; i++ ) | 448 | for ( i = 0; i < max_real_irqs ; i++ ) |
518 | irq_desc[i].handler = &pmac_pic; | 449 | irq_desc[i].handler = &pmac_pic; |
519 | 450 | ||
520 | /* get addresses of first controller */ | 451 | /* Get addresses of first controller if we have a node for it */ |
521 | if (irqctrler) { | 452 | BUG_ON(of_address_to_resource(master, 0, &r)); |
522 | if (irqctrler->n_addrs > 0) { | ||
523 | addr = (unsigned long) | ||
524 | ioremap(irqctrler->addrs[0].address, 0x40); | ||
525 | for (i = 0; i < 2; ++i) | ||
526 | pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) | ||
527 | (addr + (2 - i) * 0x10); | ||
528 | } | ||
529 | 453 | ||
530 | /* get addresses of second controller */ | 454 | /* Map interrupts of primary controller */ |
531 | irqctrler = irqctrler->next; | 455 | addr = (u8 __iomem *) ioremap(r.start, 0x40); |
532 | if (irqctrler && irqctrler->n_addrs > 0) { | 456 | i = 0; |
533 | addr = (unsigned long) | 457 | pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *) |
534 | ioremap(irqctrler->addrs[0].address, 0x40); | 458 | (addr + 0x20); |
535 | for (i = 2; i < 4; ++i) | 459 | if (max_real_irqs > 32) |
536 | pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) | 460 | pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *) |
537 | (addr + (4 - i) * 0x10); | 461 | (addr + 0x10); |
538 | irq_cascade = irqctrler->intrs[0].line; | 462 | of_node_put(master); |
539 | if (device_is_compatible(irqctrler, "gatwick")) | 463 | |
540 | pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); | 464 | printk(KERN_INFO "irq: Found primary Apple PIC %s for %d irqs\n", |
541 | } | 465 | master->full_name, max_real_irqs); |
542 | } else { | 466 | |
543 | /* older powermacs have a GC (grand central) or ohare at | 467 | /* Map interrupts of cascaded controller */ |
544 | f3000000, with interrupt control registers at f3000020. */ | 468 | if (slave && !of_address_to_resource(slave, 0, &r)) { |
545 | addr = (unsigned long) ioremap(0xf3000000, 0x40); | 469 | addr = (u8 __iomem *)ioremap(r.start, 0x40); |
546 | pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20); | 470 | pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *) |
471 | (addr + 0x20); | ||
472 | if (max_irqs > 64) | ||
473 | pmac_irq_hw[i++] = | ||
474 | (volatile struct pmac_irq_hw __iomem *) | ||
475 | (addr + 0x10); | ||
476 | irq_cascade = slave->intrs[0].line; | ||
477 | |||
478 | printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" | ||
479 | " cascade: %d\n", slave->full_name, | ||
480 | max_irqs - max_real_irqs, irq_cascade); | ||
547 | } | 481 | } |
548 | 482 | of_node_put(slave); | |
549 | /* PowerBooks 3400 and 3500 can have a second controller in a second | ||
550 | ohare chip, on the combo ethernet/modem card */ | ||
551 | if (machine_is_compatible("AAPL,3400/2400") | ||
552 | || machine_is_compatible("AAPL,3500")) | ||
553 | irq_cascade = enable_second_ohare(); | ||
554 | 483 | ||
555 | /* disable all interrupts in all controllers */ | 484 | /* disable all interrupts in all controllers */ |
556 | for (i = 0; i * 32 < max_irqs; ++i) | 485 | for (i = 0; i * 32 < max_irqs; ++i) |
557 | out_le32(&pmac_irq_hw[i]->enable, 0); | 486 | out_le32(&pmac_irq_hw[i]->enable, 0); |
487 | |||
558 | /* mark level interrupts */ | 488 | /* mark level interrupts */ |
559 | for (i = 0; i < max_irqs; i++) | 489 | for (i = 0; i < max_irqs; i++) |
560 | if (level_mask[i >> 5] & (1UL << (i & 0x1f))) | 490 | if (level_mask[i >> 5] & (1UL << (i & 0x1f))) |
561 | irq_desc[i].status = IRQ_LEVEL; | 491 | irq_desc[i].status = IRQ_LEVEL; |
562 | 492 | ||
563 | /* get interrupt line of secondary interrupt controller */ | 493 | /* Setup handlers for secondary controller and hook cascade irq*/ |
564 | if (irq_cascade >= 0) { | 494 | if (slave) { |
565 | printk(KERN_INFO "irq: secondary controller on irq %d\n", | ||
566 | (int)irq_cascade); | ||
567 | for ( i = max_real_irqs ; i < max_irqs ; i++ ) | 495 | for ( i = max_real_irqs ; i < max_irqs ; i++ ) |
568 | irq_desc[i].handler = &gatwick_pic; | 496 | irq_desc[i].handler = &gatwick_pic; |
569 | setup_irq(irq_cascade, &gatwick_cascade_action); | 497 | setup_irq(irq_cascade, &gatwick_cascade_action); |
570 | } | 498 | } |
571 | printk("System has %d possible interrupts\n", max_irqs); | 499 | printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); |
572 | if (max_irqs != max_real_irqs) | ||
573 | printk(KERN_DEBUG "%d interrupts on main controller\n", | ||
574 | max_real_irqs); | ||
575 | |||
576 | #ifdef CONFIG_XMON | 500 | #ifdef CONFIG_XMON |
577 | setup_irq(20, &xmon_action); | 501 | setup_irq(20, &xmon_action); |
578 | #endif /* CONFIG_XMON */ | 502 | #endif |
579 | #endif /* CONFIG_PPC32 */ | 503 | } |
504 | #endif /* CONFIG_PPC32 */ | ||
505 | |||
506 | static int pmac_u3_cascade(struct pt_regs *regs, void *data) | ||
507 | { | ||
508 | return mpic_get_one_irq((struct mpic *)data, regs); | ||
509 | } | ||
510 | |||
511 | static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) | ||
512 | { | ||
513 | #if defined(CONFIG_XMON) && defined(CONFIG_PPC32) | ||
514 | struct device_node* pswitch; | ||
515 | int nmi_irq; | ||
516 | |||
517 | pswitch = of_find_node_by_name(NULL, "programmer-switch"); | ||
518 | if (pswitch && pswitch->n_intrs) { | ||
519 | nmi_irq = pswitch->intrs[0].line; | ||
520 | mpic_irq_set_priority(nmi_irq, 9); | ||
521 | setup_irq(nmi_irq, &xmon_action); | ||
522 | } | ||
523 | of_node_put(pswitch); | ||
524 | #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ | ||
525 | } | ||
526 | |||
527 | static int __init pmac_pic_probe_mpic(void) | ||
528 | { | ||
529 | struct mpic *mpic1, *mpic2; | ||
530 | struct device_node *np, *master = NULL, *slave = NULL; | ||
531 | unsigned char senses[128]; | ||
532 | struct resource r; | ||
533 | |||
534 | /* We can have up to 2 MPICs cascaded */ | ||
535 | for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) | ||
536 | != NULL;) { | ||
537 | if (master == NULL && | ||
538 | get_property(np, "interrupt-parent", NULL) != NULL) | ||
539 | master = of_node_get(np); | ||
540 | else if (slave == NULL) | ||
541 | slave = of_node_get(np); | ||
542 | if (master && slave) | ||
543 | break; | ||
544 | } | ||
545 | |||
546 | /* Check for bogus setups */ | ||
547 | if (master == NULL && slave != NULL) { | ||
548 | master = slave; | ||
549 | slave = NULL; | ||
550 | } | ||
551 | |||
552 | /* Not found, default to good old pmac pic */ | ||
553 | if (master == NULL) | ||
554 | return -ENODEV; | ||
555 | |||
556 | /* Set master handler */ | ||
557 | ppc_md.get_irq = mpic_get_irq; | ||
558 | |||
559 | /* Setup master */ | ||
560 | BUG_ON(of_address_to_resource(master, 0, &r)); | ||
561 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, master, 0, 0); | ||
562 | prom_get_irq_senses(senses, 0, 128); | ||
563 | mpic1 = mpic_alloc(r.start, MPIC_PRIMARY | MPIC_WANTS_RESET, | ||
564 | 0, 0, 128, 252, senses, 128, " OpenPIC "); | ||
565 | BUG_ON(mpic1 == NULL); | ||
566 | mpic_init(mpic1); | ||
567 | |||
568 | /* Install NMI if any */ | ||
569 | pmac_pic_setup_mpic_nmi(mpic1); | ||
570 | |||
571 | of_node_put(master); | ||
572 | |||
573 | /* No slave, let's go out */ | ||
574 | if (slave == NULL || slave->n_intrs < 1) | ||
575 | return 0; | ||
576 | |||
577 | /* Setup slave, failures are non-fatal */ | ||
578 | if (of_address_to_resource(slave, 0, &r)) { | ||
579 | printk(KERN_ERR "Can't get address of MPIC %s\n", | ||
580 | slave->full_name); | ||
581 | return 0; | ||
582 | } | ||
583 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, slave, 0, 0); | ||
584 | prom_get_irq_senses(senses, 128, 128 + 124); | ||
585 | |||
586 | /* We don't need to set MPIC_BROKEN_U3 here since we don't have | ||
587 | * hypertransport interrupts routed to it, at least not on currently | ||
588 | * supported machines, that may change. | ||
589 | */ | ||
590 | mpic2 = mpic_alloc(r.start, MPIC_BIG_ENDIAN | MPIC_WANTS_RESET, | ||
591 | 0, 128, 124, 0, senses, 124, " U3-MPIC "); | ||
592 | if (mpic2 == NULL) { | ||
593 | printk(KERN_ERR "Can't create slave MPIC %s\n", | ||
594 | slave->full_name); | ||
595 | return 0; | ||
596 | } | ||
597 | mpic_init(mpic2); | ||
598 | mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); | ||
599 | |||
600 | of_node_put(slave); | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | |||
605 | void __init pmac_pic_init(void) | ||
606 | { | ||
607 | /* We first try to detect Apple's new Core99 chipset, since mac-io | ||
608 | * is quite different on those machines and contains an IBM MPIC2. | ||
609 | */ | ||
610 | if (pmac_pic_probe_mpic() == 0) | ||
611 | return; | ||
612 | |||
613 | #ifdef CONFIG_PPC32 | ||
614 | pmac_pic_probe_oldstyle(); | ||
615 | #endif | ||
580 | } | 616 | } |
581 | 617 | ||
582 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) | 618 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) |