diff options
Diffstat (limited to 'arch/powerpc/platforms/chrp/setup.c')
-rw-r--r-- | arch/powerpc/platforms/chrp/setup.c | 103 |
1 files changed, 70 insertions, 33 deletions
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 1f1771b212b4..538e337d63e2 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/reboot.h> | 24 | #include <linux/reboot.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/version.h> | 27 | #include <linux/utsrelease.h> |
28 | #include <linux/adb.h> | 28 | #include <linux/adb.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
@@ -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,24 +315,32 @@ chrp_event_scan(unsigned long unused) | |||
315 | jiffies + event_scan_interval); | 315 | jiffies + event_scan_interval); |
316 | } | 316 | } |
317 | 317 | ||
318 | static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc, | ||
319 | struct pt_regs *regs) | ||
320 | { | ||
321 | unsigned int cascade_irq = i8259_irq(regs); | ||
322 | if (cascade_irq != NO_IRQ) | ||
323 | generic_handle_irq(cascade_irq, regs); | ||
324 | desc->chip->eoi(irq); | ||
325 | } | ||
326 | |||
318 | /* | 327 | /* |
319 | * Finds the open-pic node and sets up the mpic driver. | 328 | * Finds the open-pic node and sets up the mpic driver. |
320 | */ | 329 | */ |
321 | static void __init chrp_find_openpic(void) | 330 | static void __init chrp_find_openpic(void) |
322 | { | 331 | { |
323 | struct device_node *np, *root; | 332 | struct device_node *np, *root; |
324 | int len, i, j, irq_count; | 333 | int len, i, j; |
325 | int isu_size, idu_size; | 334 | int isu_size, idu_size; |
326 | unsigned int *iranges, *opprop = NULL; | 335 | unsigned int *iranges, *opprop = NULL; |
327 | int oplen = 0; | 336 | int oplen = 0; |
328 | unsigned long opaddr; | 337 | unsigned long opaddr; |
329 | int na = 1; | 338 | int na = 1; |
330 | unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS]; | ||
331 | 339 | ||
332 | np = find_type_devices("open-pic"); | 340 | np = of_find_node_by_type(NULL, "open-pic"); |
333 | if (np == NULL) | 341 | if (np == NULL) |
334 | return; | 342 | return; |
335 | root = find_path_device("/"); | 343 | root = of_find_node_by_path("/"); |
336 | if (root) { | 344 | if (root) { |
337 | opprop = (unsigned int *) get_property | 345 | opprop = (unsigned int *) get_property |
338 | (root, "platform-open-pic", &oplen); | 346 | (root, "platform-open-pic", &oplen); |
@@ -343,19 +351,15 @@ static void __init chrp_find_openpic(void) | |||
343 | oplen /= na * sizeof(unsigned int); | 351 | oplen /= na * sizeof(unsigned int); |
344 | } else { | 352 | } else { |
345 | struct resource r; | 353 | struct resource r; |
346 | if (of_address_to_resource(np, 0, &r)) | 354 | if (of_address_to_resource(np, 0, &r)) { |
347 | return; | 355 | goto bail; |
356 | } | ||
348 | opaddr = r.start; | 357 | opaddr = r.start; |
349 | oplen = 0; | 358 | oplen = 0; |
350 | } | 359 | } |
351 | 360 | ||
352 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); | 361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); |
353 | 362 | ||
354 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ | ||
355 | prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4); | ||
356 | /* i8259 cascade is always positive level */ | ||
357 | init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE; | ||
358 | |||
359 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); | 363 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); |
360 | if (iranges == NULL) | 364 | if (iranges == NULL) |
361 | len = 0; /* non-distributed mpic */ | 365 | len = 0; /* non-distributed mpic */ |
@@ -382,15 +386,12 @@ static void __init chrp_find_openpic(void) | |||
382 | if (len > 1) | 386 | if (len > 1) |
383 | isu_size = iranges[3]; | 387 | isu_size = iranges[3]; |
384 | 388 | ||
385 | chrp_mpic = mpic_alloc(opaddr, MPIC_PRIMARY, | 389 | chrp_mpic = mpic_alloc(np, opaddr, MPIC_PRIMARY, |
386 | isu_size, NUM_ISA_INTERRUPTS, irq_count, | 390 | isu_size, 0, " MPIC "); |
387 | NR_IRQS - 4, init_senses, irq_count, | ||
388 | " MPIC "); | ||
389 | if (chrp_mpic == NULL) { | 391 | if (chrp_mpic == NULL) { |
390 | printk(KERN_ERR "Failed to allocate MPIC structure\n"); | 392 | printk(KERN_ERR "Failed to allocate MPIC structure\n"); |
391 | return; | 393 | goto bail; |
392 | } | 394 | } |
393 | |||
394 | j = na - 1; | 395 | j = na - 1; |
395 | for (i = 1; i < len; ++i) { | 396 | for (i = 1; i < len; ++i) { |
396 | iranges += 2; | 397 | iranges += 2; |
@@ -402,7 +403,10 @@ static void __init chrp_find_openpic(void) | |||
402 | } | 403 | } |
403 | 404 | ||
404 | mpic_init(chrp_mpic); | 405 | mpic_init(chrp_mpic); |
405 | mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL); | 406 | ppc_md.get_irq = mpic_get_irq; |
407 | bail: | ||
408 | of_node_put(root); | ||
409 | of_node_put(np); | ||
406 | } | 410 | } |
407 | 411 | ||
408 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | 412 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) |
@@ -413,14 +417,34 @@ static struct irqaction xmon_irqaction = { | |||
413 | }; | 417 | }; |
414 | #endif | 418 | #endif |
415 | 419 | ||
416 | void __init chrp_init_IRQ(void) | 420 | static void __init chrp_find_8259(void) |
417 | { | 421 | { |
418 | struct device_node *np; | 422 | struct device_node *np, *pic = NULL; |
419 | unsigned long chrp_int_ack = 0; | 423 | unsigned long chrp_int_ack = 0; |
420 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | 424 | unsigned int cascade_irq; |
421 | struct device_node *kbd; | 425 | |
422 | #endif | 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 | } | ||
423 | 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 | */ | ||
424 | for (np = find_devices("pci"); np != NULL; np = np->next) { | 448 | for (np = find_devices("pci"); np != NULL; np = np->next) { |
425 | unsigned int *addrp = (unsigned int *) | 449 | unsigned int *addrp = (unsigned int *) |
426 | get_property(np, "8259-interrupt-acknowledge", NULL); | 450 | get_property(np, "8259-interrupt-acknowledge", NULL); |
@@ -431,11 +455,29 @@ void __init chrp_init_IRQ(void) | |||
431 | break; | 455 | break; |
432 | } | 456 | } |
433 | if (np == NULL) | 457 | if (np == NULL) |
434 | 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 | } | ||
435 | 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 | ||
436 | chrp_find_openpic(); | 479 | chrp_find_openpic(); |
437 | 480 | chrp_find_8259(); | |
438 | i8259_init(chrp_int_ack, 0); | ||
439 | 481 | ||
440 | if (_chrp_type == _CHRP_Pegasos) | 482 | if (_chrp_type == _CHRP_Pegasos) |
441 | ppc_md.get_irq = i8259_irq; | 483 | ppc_md.get_irq = i8259_irq; |
@@ -520,10 +562,6 @@ static int __init chrp_probe(void) | |||
520 | DMA_MODE_READ = 0x44; | 562 | DMA_MODE_READ = 0x44; |
521 | DMA_MODE_WRITE = 0x48; | 563 | DMA_MODE_WRITE = 0x48; |
522 | isa_io_base = CHRP_ISA_IO_BASE; /* default value */ | 564 | isa_io_base = CHRP_ISA_IO_BASE; /* default value */ |
523 | ppc_do_canonicalize_irqs = 1; | ||
524 | |||
525 | /* Assume we have an 8259... */ | ||
526 | __irq_offset_value = NUM_ISA_INTERRUPTS; | ||
527 | 565 | ||
528 | return 1; | 566 | return 1; |
529 | } | 567 | } |
@@ -535,7 +573,6 @@ define_machine(chrp) { | |||
535 | .init = chrp_init2, | 573 | .init = chrp_init2, |
536 | .show_cpuinfo = chrp_show_cpuinfo, | 574 | .show_cpuinfo = chrp_show_cpuinfo, |
537 | .init_IRQ = chrp_init_IRQ, | 575 | .init_IRQ = chrp_init_IRQ, |
538 | .get_irq = mpic_get_irq, | ||
539 | .pcibios_fixup = chrp_pcibios_fixup, | 576 | .pcibios_fixup = chrp_pcibios_fixup, |
540 | .restart = rtas_restart, | 577 | .restart = rtas_restart, |
541 | .power_off = rtas_power_off, | 578 | .power_off = rtas_power_off, |