diff options
Diffstat (limited to 'arch/powerpc/platforms/chrp/setup.c')
-rw-r--r-- | arch/powerpc/platforms/chrp/setup.c | 110 |
1 files changed, 66 insertions, 44 deletions
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index a5dffc8d93a9..bb10171132fa 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -59,7 +59,7 @@ void rtas_indicator_progress(char *, unsigned short); | |||
59 | int _chrp_type; | 59 | int _chrp_type; |
60 | EXPORT_SYMBOL(_chrp_type); | 60 | EXPORT_SYMBOL(_chrp_type); |
61 | 61 | ||
62 | struct mpic *chrp_mpic; | 62 | static struct mpic *chrp_mpic; |
63 | 63 | ||
64 | /* Used for doing CHRP event-scans */ | 64 | /* Used for doing CHRP event-scans */ |
65 | DEFINE_PER_CPU(struct timer_list, heartbeat_timer); | 65 | DEFINE_PER_CPU(struct timer_list, heartbeat_timer); |
@@ -315,19 +315,13 @@ chrp_event_scan(unsigned long unused) | |||
315 | jiffies + event_scan_interval); | 315 | jiffies + event_scan_interval); |
316 | } | 316 | } |
317 | 317 | ||
318 | void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc, | 318 | static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc, |
319 | struct pt_regs *regs) | 319 | struct pt_regs *regs) |
320 | { | 320 | { |
321 | unsigned int max = 100; | 321 | unsigned int cascade_irq = i8259_irq(regs); |
322 | 322 | if (cascade_irq != NO_IRQ) | |
323 | while(max--) { | 323 | generic_handle_irq(cascade_irq, regs); |
324 | int irq = i8259_irq(regs); | 324 | desc->chip->eoi(irq); |
325 | if (max == 99) | ||
326 | desc->chip->eoi(irq); | ||
327 | if (irq < 0) | ||
328 | break; | ||
329 | generic_handle_irq(irq, regs); | ||
330 | }; | ||
331 | } | 325 | } |
332 | 326 | ||
333 | /* | 327 | /* |
@@ -336,18 +330,17 @@ void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc, | |||
336 | static void __init chrp_find_openpic(void) | 330 | static void __init chrp_find_openpic(void) |
337 | { | 331 | { |
338 | struct device_node *np, *root; | 332 | struct device_node *np, *root; |
339 | int len, i, j, irq_count; | 333 | int len, i, j; |
340 | int isu_size, idu_size; | 334 | int isu_size, idu_size; |
341 | unsigned int *iranges, *opprop = NULL; | 335 | unsigned int *iranges, *opprop = NULL; |
342 | int oplen = 0; | 336 | int oplen = 0; |
343 | unsigned long opaddr; | 337 | unsigned long opaddr; |
344 | int na = 1; | 338 | int na = 1; |
345 | unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS]; | ||
346 | 339 | ||
347 | np = find_type_devices("open-pic"); | 340 | np = of_find_node_by_type(NULL, "open-pic"); |
348 | if (np == NULL) | 341 | if (np == NULL) |
349 | return; | 342 | return; |
350 | root = find_path_device("/"); | 343 | root = of_find_node_by_path("/"); |
351 | if (root) { | 344 | if (root) { |
352 | opprop = (unsigned int *) get_property | 345 | opprop = (unsigned int *) get_property |
353 | (root, "platform-open-pic", &oplen); | 346 | (root, "platform-open-pic", &oplen); |
@@ -358,19 +351,15 @@ static void __init chrp_find_openpic(void) | |||
358 | oplen /= na * sizeof(unsigned int); | 351 | oplen /= na * sizeof(unsigned int); |
359 | } else { | 352 | } else { |
360 | struct resource r; | 353 | struct resource r; |
361 | if (of_address_to_resource(np, 0, &r)) | 354 | if (of_address_to_resource(np, 0, &r)) { |
362 | return; | 355 | goto bail; |
356 | } | ||
363 | opaddr = r.start; | 357 | opaddr = r.start; |
364 | oplen = 0; | 358 | oplen = 0; |
365 | } | 359 | } |
366 | 360 | ||
367 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); | 361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); |
368 | 362 | ||
369 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ | ||
370 | prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4); | ||
371 | /* i8259 cascade is always positive level */ | ||
372 | init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE; | ||
373 | |||
374 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); | 363 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); |
375 | if (iranges == NULL) | 364 | if (iranges == NULL) |
376 | len = 0; /* non-distributed mpic */ | 365 | len = 0; /* non-distributed mpic */ |
@@ -397,15 +386,12 @@ static void __init chrp_find_openpic(void) | |||
397 | if (len > 1) | 386 | if (len > 1) |
398 | isu_size = iranges[3]; | 387 | isu_size = iranges[3]; |
399 | 388 | ||
400 | chrp_mpic = mpic_alloc(opaddr, MPIC_PRIMARY, | 389 | chrp_mpic = mpic_alloc(np, opaddr, MPIC_PRIMARY, |
401 | isu_size, NUM_ISA_INTERRUPTS, irq_count, | 390 | isu_size, 0, " MPIC "); |
402 | NR_IRQS - 4, init_senses, irq_count, | ||
403 | " MPIC "); | ||
404 | if (chrp_mpic == NULL) { | 391 | if (chrp_mpic == NULL) { |
405 | printk(KERN_ERR "Failed to allocate MPIC structure\n"); | 392 | printk(KERN_ERR "Failed to allocate MPIC structure\n"); |
406 | return; | 393 | goto bail; |
407 | } | 394 | } |
408 | |||
409 | j = na - 1; | 395 | j = na - 1; |
410 | for (i = 1; i < len; ++i) { | 396 | for (i = 1; i < len; ++i) { |
411 | iranges += 2; | 397 | iranges += 2; |
@@ -417,7 +403,10 @@ static void __init chrp_find_openpic(void) | |||
417 | } | 403 | } |
418 | 404 | ||
419 | mpic_init(chrp_mpic); | 405 | mpic_init(chrp_mpic); |
420 | set_irq_chained_handler(NUM_ISA_INTERRUPTS, chrp_8259_cascade); | 406 | ppc_md.get_irq = mpic_get_irq; |
407 | bail: | ||
408 | of_node_put(root); | ||
409 | of_node_put(np); | ||
421 | } | 410 | } |
422 | 411 | ||
423 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | 412 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) |
@@ -428,14 +417,34 @@ static struct irqaction xmon_irqaction = { | |||
428 | }; | 417 | }; |
429 | #endif | 418 | #endif |
430 | 419 | ||
431 | void __init chrp_init_IRQ(void) | 420 | static void __init chrp_find_8259(void) |
432 | { | 421 | { |
433 | struct device_node *np; | 422 | struct device_node *np, *pic = NULL; |
434 | unsigned long chrp_int_ack = 0; | 423 | unsigned long chrp_int_ack = 0; |
435 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | 424 | unsigned int cascade_irq; |
436 | struct device_node *kbd; | ||
437 | #endif | ||
438 | 425 | ||
426 | /* Look for cascade */ | ||
427 | for_each_node_by_type(np, "interrupt-controller") | ||
428 | if (device_is_compatible(np, "chrp,iic")) { | ||
429 | pic = np; | ||
430 | break; | ||
431 | } | ||
432 | /* Ok, 8259 wasn't found. We need to handle the case where | ||
433 | * we have a pegasos that claims to be chrp but doesn't have | ||
434 | * a proper interrupt tree | ||
435 | */ | ||
436 | if (pic == NULL && chrp_mpic != NULL) { | ||
437 | printk(KERN_ERR "i8259: Not found in device-tree" | ||
438 | " assuming no legacy interrupts\n"); | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | /* Look for intack. In a perfect world, we would look for it on | ||
443 | * the ISA bus that holds the 8259 but heh... Works that way. If | ||
444 | * we ever see a problem, we can try to re-use the pSeries code here. | ||
445 | * Also, Pegasos-type platforms don't have a proper node to start | ||
446 | * from anyway | ||
447 | */ | ||
439 | for (np = find_devices("pci"); np != NULL; np = np->next) { | 448 | for (np = find_devices("pci"); np != NULL; np = np->next) { |
440 | unsigned int *addrp = (unsigned int *) | 449 | unsigned int *addrp = (unsigned int *) |
441 | get_property(np, "8259-interrupt-acknowledge", NULL); | 450 | get_property(np, "8259-interrupt-acknowledge", NULL); |
@@ -446,11 +455,29 @@ void __init chrp_init_IRQ(void) | |||
446 | break; | 455 | break; |
447 | } | 456 | } |
448 | if (np == NULL) | 457 | if (np == NULL) |
449 | printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n"); | 458 | printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" |
459 | " address, polling\n"); | ||
460 | |||
461 | i8259_init(pic, chrp_int_ack); | ||
462 | if (ppc_md.get_irq == NULL) | ||
463 | ppc_md.get_irq = i8259_irq; | ||
464 | if (chrp_mpic != NULL) { | ||
465 | cascade_irq = irq_of_parse_and_map(pic, 0); | ||
466 | if (cascade_irq == NO_IRQ) | ||
467 | printk(KERN_ERR "i8259: failed to map cascade irq\n"); | ||
468 | else | ||
469 | set_irq_chained_handler(cascade_irq, | ||
470 | chrp_8259_cascade); | ||
471 | } | ||
472 | } | ||
450 | 473 | ||
474 | void __init chrp_init_IRQ(void) | ||
475 | { | ||
476 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | ||
477 | struct device_node *kbd; | ||
478 | #endif | ||
451 | chrp_find_openpic(); | 479 | chrp_find_openpic(); |
452 | 480 | chrp_find_8259(); | |
453 | i8259_init(chrp_int_ack, 0); | ||
454 | 481 | ||
455 | if (_chrp_type == _CHRP_Pegasos) | 482 | if (_chrp_type == _CHRP_Pegasos) |
456 | ppc_md.get_irq = i8259_irq; | 483 | ppc_md.get_irq = i8259_irq; |
@@ -535,10 +562,6 @@ static int __init chrp_probe(void) | |||
535 | DMA_MODE_READ = 0x44; | 562 | DMA_MODE_READ = 0x44; |
536 | DMA_MODE_WRITE = 0x48; | 563 | DMA_MODE_WRITE = 0x48; |
537 | isa_io_base = CHRP_ISA_IO_BASE; /* default value */ | 564 | isa_io_base = CHRP_ISA_IO_BASE; /* default value */ |
538 | ppc_do_canonicalize_irqs = 1; | ||
539 | |||
540 | /* Assume we have an 8259... */ | ||
541 | __irq_offset_value = NUM_ISA_INTERRUPTS; | ||
542 | 565 | ||
543 | return 1; | 566 | return 1; |
544 | } | 567 | } |
@@ -550,7 +573,6 @@ define_machine(chrp) { | |||
550 | .init = chrp_init2, | 573 | .init = chrp_init2, |
551 | .show_cpuinfo = chrp_show_cpuinfo, | 574 | .show_cpuinfo = chrp_show_cpuinfo, |
552 | .init_IRQ = chrp_init_IRQ, | 575 | .init_IRQ = chrp_init_IRQ, |
553 | .get_irq = mpic_get_irq, | ||
554 | .pcibios_fixup = chrp_pcibios_fixup, | 576 | .pcibios_fixup = chrp_pcibios_fixup, |
555 | .restart = rtas_restart, | 577 | .restart = rtas_restart, |
556 | .power_off = rtas_power_off, | 578 | .power_off = rtas_power_off, |