Index: linux-irq-work/arch/powerpc/platforms/powermac/bootx_init.c =================================================================== --- linux-irq-work.orig/arch/powerpc/platforms/powermac/bootx_init.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/arch/powerpc/platforms/powermac/bootx_init.c 2006-07-02 19:45:01.000000000 +1000 @@ -162,6 +162,8 @@ { u32 val; + bootx_dt_add_prop("linux,bootx", NULL, 0, mem_end); + if (bootx_info->kernelParamsOffset) { char *args = (char *)((unsigned long)bootx_info) + bootx_info->kernelParamsOffset; @@ -211,7 +213,7 @@ if (!strcmp(namep, "/chosen")) { DBG(" detected /chosen ! adding properties names !\n"); - bootx_dt_add_string("linux,platform", mem_end); + bootx_dt_add_string("linux,bootx", mem_end); bootx_dt_add_string("linux,stdout-path", mem_end); bootx_dt_add_string("linux,initrd-start", mem_end); bootx_dt_add_string("linux,initrd-end", mem_end); Index: linux-irq-work/arch/powerpc/platforms/powermac/pic.c =================================================================== --- linux-irq-work.orig/arch/powerpc/platforms/powermac/pic.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/arch/powerpc/platforms/powermac/pic.c 2006-07-02 19:46:06.000000000 +1000 @@ -65,13 +65,11 @@ static DEFINE_SPINLOCK(pmac_pic_lock); -#define GATWICK_IRQ_POOL_SIZE 10 -static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; - #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; static int pmac_irq_cascade = -1; +static struct irq_host *pmac_pic_host; static void __pmac_retrigger(unsigned int irq_nr) { @@ -86,18 +84,16 @@ } } -static void pmac_mask_and_ack_irq(unsigned int irq_nr) +static void pmac_mask_and_ack_irq(unsigned int virq) { - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; + unsigned int src = irq_map[virq].hwirq; + unsigned long bit = 1UL << (virq & 0x1f); + int i = virq >> 5; unsigned long flags; - if ((unsigned)irq_nr >= max_irqs) - return; - spin_lock_irqsave(&pmac_pic_lock, flags); - __clear_bit(irq_nr, ppc_cached_irq_mask); - if (__test_and_clear_bit(irq_nr, ppc_lost_interrupts)) + __clear_bit(src, ppc_cached_irq_mask); + if (__test_and_clear_bit(src, ppc_lost_interrupts)) atomic_dec(&ppc_n_lost_interrupts); out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); out_le32(&pmac_irq_hw[i]->ack, bit); @@ -110,17 +106,15 @@ spin_unlock_irqrestore(&pmac_pic_lock, flags); } -static void pmac_ack_irq(unsigned int irq_nr) +static void pmac_ack_irq(unsigned int virq) { - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; + unsigned int src = irq_map[virq].hwirq; + unsigned long bit = 1UL << (src & 0x1f); + int i = src >> 5; unsigned long flags; - if ((unsigned)irq_nr >= max_irqs) - return; - spin_lock_irqsave(&pmac_pic_lock, flags); - if (__test_and_clear_bit(irq_nr, ppc_lost_interrupts)) + if (__test_and_clear_bit(src, ppc_lost_interrupts)) atomic_dec(&ppc_n_lost_interrupts); out_le32(&pmac_irq_hw[i]->ack, bit); (void)in_le32(&pmac_irq_hw[i]->ack); @@ -157,48 +151,51 @@ /* When an irq gets requested for the first client, if it's an * edge interrupt, we clear any previous one on the controller */ -static unsigned int pmac_startup_irq(unsigned int irq_nr) +static unsigned int pmac_startup_irq(unsigned int virq) { unsigned long flags; - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; + unsigned int src = irq_map[virq].hwirq; + unsigned long bit = 1UL << (src & 0x1f); + int i = src >> 5; spin_lock_irqsave(&pmac_pic_lock, flags); - if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) + if ((irq_desc[virq].status & IRQ_LEVEL) == 0) out_le32(&pmac_irq_hw[i]->ack, bit); - __set_bit(irq_nr, ppc_cached_irq_mask); - __pmac_set_irq_mask(irq_nr, 0); + __set_bit(src, ppc_cached_irq_mask); + __pmac_set_irq_mask(src, 0); spin_unlock_irqrestore(&pmac_pic_lock, flags); return 0; } -static void pmac_mask_irq(unsigned int irq_nr) +static void pmac_mask_irq(unsigned int virq) { unsigned long flags; + unsigned int src = irq_map[virq].hwirq; spin_lock_irqsave(&pmac_pic_lock, flags); - __clear_bit(irq_nr, ppc_cached_irq_mask); - __pmac_set_irq_mask(irq_nr, 0); + __clear_bit(src, ppc_cached_irq_mask); + __pmac_set_irq_mask(src, 0); spin_unlock_irqrestore(&pmac_pic_lock, flags); } -static void pmac_unmask_irq(unsigned int irq_nr) +static void pmac_unmask_irq(unsigned int virq) { unsigned long flags; + unsigned int src = irq_map[virq].hwirq; spin_lock_irqsave(&pmac_pic_lock, flags); - __set_bit(irq_nr, ppc_cached_irq_mask); - __pmac_set_irq_mask(irq_nr, 0); + __set_bit(src, ppc_cached_irq_mask); + __pmac_set_irq_mask(src, 0); spin_unlock_irqrestore(&pmac_pic_lock, flags); } -static int pmac_retrigger(unsigned int irq_nr) +static int pmac_retrigger(unsigned int virq) { unsigned long flags; spin_lock_irqsave(&pmac_pic_lock, flags); - __pmac_retrigger(irq_nr); + __pmac_retrigger(irq_map[virq].hwirq); spin_unlock_irqrestore(&pmac_pic_lock, flags); return 1; } @@ -238,7 +235,7 @@ return rc; } -static int pmac_get_irq(struct pt_regs *regs) +static unsigned int pmac_pic_get_irq(struct pt_regs *regs) { int irq; unsigned long bits = 0; @@ -250,7 +247,7 @@ /* IPI's are a hack on the powersurge -- Cort */ if ( smp_processor_id() != 0 ) { psurge_smp_message_recv(regs); - return -2; /* ignore, already handled */ + return NO_IRQ_IGNORE; /* ignore, already handled */ } #endif /* CONFIG_SMP */ spin_lock_irqsave(&pmac_pic_lock, flags); @@ -266,133 +263,9 @@ break; } spin_unlock_irqrestore(&pmac_pic_lock, flags); - - return irq; -} - -/* This routine will fix some missing interrupt values in the device tree - * on the gatwick mac-io controller used by some PowerBooks - * - * Walking of OF nodes could use a bit more fixing up here, but it's not - * very important as this is all boot time code on static portions of the - * device-tree. - * - * However, the modifications done to "intrs" will have to be removed and - * replaced with proper updates of the "interrupts" properties or - * AAPL,interrupts, yet to be decided, once the dynamic parsing is there. - */ -static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, - int irq_base) -{ - struct device_node *node; - int count; - - memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); - count = 0; - for (node = NULL; (node = of_get_next_child(gw, node)) != NULL;) { - /* Fix SCC */ - if ((strcasecmp(node->name, "escc") == 0) && node->child) { - if (node->child->n_intrs < 3) { - node->child->intrs = &gatwick_int_pool[count]; - count += 3; - } - node->child->n_intrs = 3; - node->child->intrs[0].line = 15+irq_base; - node->child->intrs[1].line = 4+irq_base; - node->child->intrs[2].line = 5+irq_base; - printk(KERN_INFO "irq: fixed SCC on gatwick" - " (%d,%d,%d)\n", - node->child->intrs[0].line, - node->child->intrs[1].line, - node->child->intrs[2].line); - } - /* Fix media-bay & left SWIM */ - if (strcasecmp(node->name, "media-bay") == 0) { - struct device_node* ya_node; - - if (node->n_intrs == 0) - node->intrs = &gatwick_int_pool[count++]; - node->n_intrs = 1; - node->intrs[0].line = 29+irq_base; - printk(KERN_INFO "irq: fixed media-bay on gatwick" - " (%d)\n", node->intrs[0].line); - - ya_node = node->child; - while(ya_node) { - if (strcasecmp(ya_node->name, "floppy") == 0) { - if (ya_node->n_intrs < 2) { - ya_node->intrs = &gatwick_int_pool[count]; - count += 2; - } - ya_node->n_intrs = 2; - ya_node->intrs[0].line = 19+irq_base; - ya_node->intrs[1].line = 1+irq_base; - printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", - ya_node->intrs[0].line, ya_node->intrs[1].line); - } - if (strcasecmp(ya_node->name, "ata4") == 0) { - if (ya_node->n_intrs < 2) { - ya_node->intrs = &gatwick_int_pool[count]; - count += 2; - } - ya_node->n_intrs = 2; - ya_node->intrs[0].line = 14+irq_base; - ya_node->intrs[1].line = 3+irq_base; - printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", - ya_node->intrs[0].line, ya_node->intrs[1].line); - } - ya_node = ya_node->sibling; - } - } - } - if (count > 10) { - printk("WARNING !! Gatwick interrupt pool overflow\n"); - printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); - printk(" requested = %d\n", count); - } -} - -/* - * The PowerBook 3400/2400/3500 can have a combo ethernet/modem - * card which includes an ohare chip that acts as a second interrupt - * controller. If we find this second ohare, set it up and fix the - * interrupt value in the device tree for the ethernet chip. - */ -static void __init enable_second_ohare(struct device_node *np) -{ - unsigned char bus, devfn; - unsigned short cmd; - struct device_node *ether; - - /* This code doesn't strictly belong here, it could be part of - * either the PCI initialisation or the feature code. It's kept - * here for historical reasons. - */ - if (pci_device_from_OF_node(np, &bus, &devfn) == 0) { - struct pci_controller* hose = - pci_find_hose_for_OF_device(np); - if (!hose) { - printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); - return; - } - early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - cmd &= ~PCI_COMMAND_IO; - early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); - } - - /* Fix interrupt for the modem/ethernet combo controller. The number - * in the device tree (27) is bogus (correct for the ethernet-only - * board but not the combo ethernet/modem board). - * The real interrupt is 28 on the second controller -> 28+32 = 60. - */ - ether = of_find_node_by_name(NULL, "pci1011,14"); - if (ether && ether->n_intrs > 0) { - ether->intrs[0].line = 60; - printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", - ether->intrs[0].line); - } - of_node_put(ether); + if (unlikely(irq < 0)) + return NO_IRQ; + return irq_linear_revmap(pmac_pic_host, irq); } #ifdef CONFIG_XMON @@ -411,6 +284,50 @@ .name = "cascade", }; +static int pmac_pic_host_match(struct irq_host *h, struct device_node *node) +{ + /* We match all, we don't always have a node anyway */ + return 1; +} + +static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + struct irq_desc *desc = get_irq_desc(virq); + int level; + + if (hw >= max_irqs) + return -EINVAL; + + /* Mark level interrupts, set delayed disable for edge ones and set + * handlers + */ + level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f))); + if (level) + desc->status |= IRQ_LEVEL; + else + desc->status |= IRQ_DELAYED_DISABLE; + set_irq_chip_and_handler(virq, &pmac_pic, level ? + handle_level_irq : handle_edge_irq); + return 0; +} + +static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, + unsigned int *out_flags) + +{ + *out_hwirq = *intspec; + return 0; +} + +static struct irq_host_ops pmac_pic_host_ops = { + .match = pmac_pic_host_match, + .map = pmac_pic_host_map, + .xlate = pmac_pic_host_xlate, +}; + static void __init pmac_pic_probe_oldstyle(void) { int i; @@ -420,7 +337,7 @@ struct resource r; /* Set our get_irq function */ - ppc_md.get_irq = pmac_get_irq; + ppc_md.get_irq = pmac_pic_get_irq; /* * Find the interrupt controller type & node @@ -438,7 +355,6 @@ if (slave) { max_irqs = 64; level_mask[1] = OHARE_LEVEL_MASK; - enable_second_ohare(slave); } } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) { max_irqs = max_real_irqs = 64; @@ -462,21 +378,18 @@ max_irqs = 128; level_mask[2] = HEATHROW_LEVEL_MASK; level_mask[3] = 0; - pmac_fix_gatwick_interrupts(slave, max_real_irqs); } } BUG_ON(master == NULL); - /* Mark level interrupts and set handlers */ - for (i = 0; i < max_irqs; i++) { - int level = !!(level_mask[i >> 5] & (1UL << (i & 0x1f))); - if (level) - irq_desc[i].status |= IRQ_LEVEL; - else - irq_desc[i].status |= IRQ_DELAYED_DISABLE; - set_irq_chip_and_handler(i, &pmac_pic, level ? - handle_level_irq : handle_edge_irq); - } + /* + * Allocate an irq host + */ + pmac_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, max_irqs, + &pmac_pic_host_ops, + max_irqs); + BUG_ON(pmac_pic_host == NULL); + irq_set_default_host(pmac_pic_host); /* Get addresses of first controller if we have a node for it */ BUG_ON(of_address_to_resource(master, 0, &r)); @@ -503,7 +416,7 @@ pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *) (addr + 0x10); - pmac_irq_cascade = slave->intrs[0].line; + pmac_irq_cascade = irq_of_parse_and_map(slave, 0); printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" " cascade: %d\n", slave->full_name, @@ -516,12 +429,12 @@ out_le32(&pmac_irq_hw[i]->enable, 0); /* Hookup cascade irq */ - if (slave) + if (slave && pmac_irq_cascade != NO_IRQ) setup_irq(pmac_irq_cascade, &gatwick_cascade_action); printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); #ifdef CONFIG_XMON - setup_irq(20, &xmon_action); + setup_irq(irq_create_mapping(NULL, 20, 0), &xmon_action); #endif } #endif /* CONFIG_PPC32 */ @@ -544,12 +457,14 @@ int nmi_irq; pswitch = of_find_node_by_name(NULL, "programmer-switch"); - if (pswitch && pswitch->n_intrs) { - nmi_irq = pswitch->intrs[0].line; - mpic_irq_set_priority(nmi_irq, 9); - setup_irq(nmi_irq, &xmon_action); + if (pswitch) { + nmi_irq = irq_of_parse_and_map(pswitch, 0); + if (nmi_irq != NO_IRQ) { + mpic_irq_set_priority(nmi_irq, 9); + setup_irq(nmi_irq, &xmon_action); + } + of_node_put(pswitch); } - of_node_put(pswitch); #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ } @@ -654,6 +569,19 @@ void __init pmac_pic_init(void) { + unsigned int flags = 0; + + /* We configure the OF parsing based on our oldworld vs. newworld + * platform type and wether we were booted by BootX. + */ +#ifdef CONFIG_PPC32 + if (!pmac_newworld) + flags |= OF_IMAP_OLDWORLD_MAC; + if (get_property(of_chosen, "linux,bootx", NULL) != NULL) + flags |= OF_IMAP_NO_PHANDLE; + of_irq_map_init(flags); +#endif /* CONFIG_PPC_32 */ + /* We first try to detect Apple's new Core99 chipset, since mac-io * is quite different on those machines and contains an IBM MPIC2. */ @@ -676,6 +604,7 @@ /* This used to be passed by the PMU driver but that link got * broken with the new driver model. We use this tweak for now... + * We really want to do things differently though... */ static int pmacpic_find_viaint(void) { @@ -689,7 +618,7 @@ np = of_find_node_by_name(NULL, "via-pmu"); if (np == NULL) goto not_found; - viaint = np->intrs[0].line; + viaint = irq_of_parse_and_map(np, 0);; #endif /* CONFIG_ADB_PMU */ not_found: Index: linux-irq-work/arch/powerpc/platforms/powermac/nvram.c =================================================================== --- linux-irq-work.orig/arch/powerpc/platforms/powermac/nvram.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/arch/powerpc/platforms/powermac/nvram.c 2006-07-02 19:45:01.000000000 +1000 @@ -29,6 +29,8 @@ #include #include +#include "pmac.h" + #define DEBUG #ifdef DEBUG @@ -80,9 +82,6 @@ // XXX Turn that into a sem static DEFINE_SPINLOCK(nv_lock); -extern int pmac_newworld; -extern int system_running; - static int (*core99_write_bank)(int bank, u8* datas); static int (*core99_erase_bank)(int bank); Index: linux-irq-work/arch/powerpc/platforms/powermac/pci.c =================================================================== --- linux-irq-work.orig/arch/powerpc/platforms/powermac/pci.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/arch/powerpc/platforms/powermac/pci.c 2006-07-02 19:45:01.000000000 +1000 @@ -46,6 +46,8 @@ static struct pci_controller *u3_agp; static struct pci_controller *u4_pcie; static struct pci_controller *u3_ht; +#else +static int has_second_ohare; #endif /* CONFIG_PPC64 */ extern u8 pci_cache_line_size; @@ -647,6 +649,33 @@ early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); } +static void __init init_second_ohare(void) +{ + struct device_node *np = of_find_node_by_name(NULL, "pci106b,7"); + unsigned char bus, devfn; + unsigned short cmd; + + if (np == NULL) + return; + + /* This must run before we initialize the PICs since the second + * ohare hosts a PIC that will be accessed there. + */ + if (pci_device_from_OF_node(np, &bus, &devfn) == 0) { + struct pci_controller* hose = + pci_find_hose_for_OF_device(np); + if (!hose) { + printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); + return; + } + early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + cmd &= ~PCI_COMMAND_IO; + early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); + } + has_second_ohare = 1; +} + /* * Some Apple desktop machines have a NEC PD720100A USB2 controller * on the motherboard. Open Firmware, on these, will disable the @@ -688,9 +717,6 @@ " EHCI, fixing up...\n"); data &= ~1UL; early_write_config_dword(hose, bus, devfn, 0xe4, data); - early_write_config_byte(hose, bus, - devfn | 2, PCI_INTERRUPT_LINE, - nec->intrs[0].line); } } } @@ -962,8 +988,22 @@ { struct pci_dev* dev = NULL; - for_each_pci_dev(dev) + for_each_pci_dev(dev) { + /* Read interrupt from the device-tree */ pci_read_irq_line(dev); + + /* Fixup interrupt for the modem/ethernet combo controller. + * on machines with a second ohare chip. + * The number in the device tree (27) is bogus (correct for + * the ethernet-only board but not the combo ethernet/modem + * board). The real interrupt is 28 on the second controller + * -> 28+32 = 60. + */ + if (has_second_ohare && + dev->vendor == PCI_VENDOR_ID_DEC && + dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) + dev->irq = irq_create_mapping(NULL, 60, 0); + } } #ifdef CONFIG_PPC64 @@ -1053,6 +1093,7 @@ #else /* CONFIG_PPC64 */ init_p2pbridge(); + init_second_ohare(); fixup_nec_usb2(); /* We are still having some issues with the Xserve G4, enabling Index: linux-irq-work/arch/powerpc/platforms/powermac/pmac.h =================================================================== --- linux-irq-work.orig/arch/powerpc/platforms/powermac/pmac.h 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/arch/powerpc/platforms/powermac/pmac.h 2006-07-02 19:45:01.000000000 +1000 @@ -12,6 +12,8 @@ struct rtc_time; +extern int pmac_newworld; + extern long pmac_time_init(void); extern unsigned long pmac_get_boot_time(void); extern void pmac_get_rtc_time(struct rtc_time *); Index: linux-irq-work/drivers/macintosh/via-pmu.c =================================================================== --- linux-irq-work.orig/drivers/macintosh/via-pmu.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/drivers/macintosh/via-pmu.c 2006-07-02 19:45:01.000000000 +1000 @@ -64,10 +64,6 @@ #include #endif -#ifdef CONFIG_PPC32 -#include -#endif - #include "via-pmu-event.h" /* Some compile options */ Index: linux-irq-work/drivers/macintosh/macio_asic.c =================================================================== --- linux-irq-work.orig/drivers/macintosh/macio_asic.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/drivers/macintosh/macio_asic.c 2006-07-02 19:45:01.000000000 +1000 @@ -280,49 +280,106 @@ static int macio_resource_quirks(struct device_node *np, struct resource *res, int index) { - if (res->flags & IORESOURCE_MEM) { - /* Grand Central has too large resource 0 on some machines */ - if (index == 0 && !strcmp(np->name, "gc")) - res->end = res->start + 0x1ffff; - - /* Airport has bogus resource 2 */ - if (index >= 2 && !strcmp(np->name, "radio")) - return 1; + /* Only quirks for memory resources for now */ + if ((res->flags & IORESOURCE_MEM) == 0) + return 0; + + /* Grand Central has too large resource 0 on some machines */ + if (index == 0 && !strcmp(np->name, "gc")) + res->end = res->start + 0x1ffff; + + /* Airport has bogus resource 2 */ + if (index >= 2 && !strcmp(np->name, "radio")) + return 1; #ifndef CONFIG_PPC64 - /* DBDMAs may have bogus sizes */ - if ((res->start & 0x0001f000) == 0x00008000) - res->end = res->start + 0xff; + /* DBDMAs may have bogus sizes */ + if ((res->start & 0x0001f000) == 0x00008000) + res->end = res->start + 0xff; #endif /* CONFIG_PPC64 */ - /* ESCC parent eats child resources. We could have added a - * level of hierarchy, but I don't really feel the need - * for it - */ - if (!strcmp(np->name, "escc")) - return 1; + /* ESCC parent eats child resources. We could have added a + * level of hierarchy, but I don't really feel the need + * for it + */ + if (!strcmp(np->name, "escc")) + return 1; - /* ESCC has bogus resources >= 3 */ - if (index >= 3 && !(strcmp(np->name, "ch-a") && - strcmp(np->name, "ch-b"))) - return 1; - - /* Media bay has too many resources, keep only first one */ - if (index > 0 && !strcmp(np->name, "media-bay")) - return 1; - - /* Some older IDE resources have bogus sizes */ - if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && - strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { - if (index == 0 && (res->end - res->start) > 0xfff) - res->end = res->start + 0xfff; - if (index == 1 && (res->end - res->start) > 0xff) - res->end = res->start + 0xff; - } + /* ESCC has bogus resources >= 3 */ + if (index >= 3 && !(strcmp(np->name, "ch-a") && + strcmp(np->name, "ch-b"))) + return 1; + + /* Media bay has too many resources, keep only first one */ + if (index > 0 && !strcmp(np->name, "media-bay")) + return 1; + + /* Some older IDE resources have bogus sizes */ + if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && + strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { + if (index == 0 && (res->end - res->start) > 0xfff) + res->end = res->start + 0xfff; + if (index == 1 && (res->end - res->start) > 0xff) + res->end = res->start + 0xff; } return 0; } +static void macio_create_fixup_irq(struct macio_dev *dev, int index, + unsigned int line) +{ + unsigned int irq; + + irq = irq_create_mapping(NULL, line, 0); + if (irq != NO_IRQ) { + dev->interrupt[index].start = irq; + dev->interrupt[index].flags = IORESOURCE_IRQ; + dev->interrupt[index].name = dev->ofdev.dev.bus_id; + } + if (dev->n_interrupts <= index) + dev->n_interrupts = index + 1; +} + +static void macio_add_missing_resources(struct macio_dev *dev) +{ + struct device_node *np = dev->ofdev.node; + unsigned int irq_base; + + /* Gatwick has some missing interrupts on child nodes */ + if (dev->bus->chip->type != macio_gatwick) + return; + + /* irq_base is always 64 on gatwick. I have no cleaner way to get + * that value from here at this point + */ + irq_base = 64; + + /* Fix SCC */ + if (strcmp(np->name, "ch-a") == 0) { + macio_create_fixup_irq(dev, 0, 15 + irq_base); + macio_create_fixup_irq(dev, 1, 4 + irq_base); + macio_create_fixup_irq(dev, 2, 5 + irq_base); + printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n"); + } + + /* Fix media-bay */ + if (strcmp(np->name, "media-bay") == 0) { + macio_create_fixup_irq(dev, 0, 29 + irq_base); + printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n"); + } + + /* Fix left media bay childs */ + if (dev->media_bay != NULL && strcmp(np->name, "floppy") == 0) { + macio_create_fixup_irq(dev, 0, 19 + irq_base); + macio_create_fixup_irq(dev, 1, 1 + irq_base); + printk(KERN_INFO "macio: fixed left floppy irqs\n"); + } + if (dev->media_bay != NULL && strcasecmp(np->name, "ata4") == 0) { + macio_create_fixup_irq(dev, 0, 14 + irq_base); + macio_create_fixup_irq(dev, 0, 3 + irq_base); + printk(KERN_INFO "macio: fixed left ide irqs\n"); + } +} static void macio_setup_interrupts(struct macio_dev *dev) { @@ -441,6 +498,7 @@ /* Setup interrupts & resources */ macio_setup_interrupts(dev); macio_setup_resources(dev, parent_res); + macio_add_missing_resources(dev); /* Register with core */ if (of_device_register(&dev->ofdev) != 0) { Index: linux-irq-work/drivers/macintosh/via-cuda.c =================================================================== --- linux-irq-work.orig/drivers/macintosh/via-cuda.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/drivers/macintosh/via-cuda.c 2006-07-02 19:45:01.000000000 +1000 @@ -34,13 +34,6 @@ static volatile unsigned char __iomem *via; static DEFINE_SPINLOCK(cuda_lock); -#ifdef CONFIG_MAC -#define CUDA_IRQ IRQ_MAC_ADB -#define eieio() -#else -#define CUDA_IRQ vias->intrs[0].line -#endif - /* VIA registers - spaced 0x200 bytes apart */ #define RS 0x200 /* skip between registers */ #define B 0 /* B-side data */ @@ -189,11 +182,24 @@ static int __init via_cuda_start(void) { + unsigned int irq; + if (via == NULL) return -ENODEV; - if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { - printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); +#ifdef CONFIG_MAC + irq = IRQ_MAC_ADB; +#else /* CONFIG_MAC */ + irq = irq_of_parse_and_map(vias, 0); + if (irq == NO_IRQ) { + printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", + vias->full_name); + return -ENODEV; + } +#endif /* CONFIG_MAP */ + + if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { + printk(KERN_ERR "via-cuda: can't request irq %d\n", irq); return -EAGAIN; } Index: linux-irq-work/drivers/net/mace.c =================================================================== --- linux-irq-work.orig/drivers/net/mace.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/drivers/net/mace.c 2006-07-02 19:45:01.000000000 +1000 @@ -242,12 +242,12 @@ } rc = request_irq(mp->tx_dma_intr, mace_txdma_intr, 0, "MACE-txdma", dev); if (rc) { - printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line); + printk(KERN_ERR "MACE: can't get irq %d\n", mp->tx_dma_intr); goto err_free_irq; } rc = request_irq(mp->rx_dma_intr, mace_rxdma_intr, 0, "MACE-rxdma", dev); if (rc) { - printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line); + printk(KERN_ERR "MACE: can't get irq %d\n", mp->rx_dma_intr); goto err_free_tx_irq; } Index: linux-irq-work/drivers/serial/pmac_zilog.c =================================================================== --- linux-irq-work.orig/drivers/serial/pmac_zilog.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/drivers/serial/pmac_zilog.c 2006-07-02 19:45:01.000000000 +1000 @@ -1443,8 +1443,8 @@ uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; } - uap->tx_dma_irq = np->intrs[1].line; - uap->rx_dma_irq = np->intrs[2].line; + uap->tx_dma_irq = irq_of_parse_and_map(np, 1); + uap->rx_dma_irq = irq_of_parse_and_map(np, 2); } no_dma: @@ -1491,7 +1491,7 @@ * Init remaining bits of "port" structure */ uap->port.iotype = UPIO_MEM; - uap->port.irq = np->intrs[0].line; + uap->port.irq = irq_of_parse_and_map(np, 0); uap->port.uartclk = ZS_CLOCK; uap->port.fifosize = 1; uap->port.ops = &pmz_pops; Index: linux-irq-work/sound/oss/dmasound/dmasound_awacs.c =================================================================== --- linux-irq-work.orig/sound/oss/dmasound/dmasound_awacs.c 2006-07-02 19:44:16.000000000 +1000 +++ linux-irq-work/sound/oss/dmasound/dmasound_awacs.c 2006-07-02 19:45:01.000000000 +1000 @@ -374,10 +374,7 @@ *gpio_pol = *pp; else *gpio_pol = 1; - if (np->n_intrs > 0) - return np->intrs[0].line; - - return 0; + return irq_of_parse_and_map(np, 0); } static inline void @@ -2864,14 +2861,13 @@ * other info if necessary (early AWACS we want to read chip ids) */ - if (of_get_address(io, 2, NULL, NULL) == NULL || io->n_intrs < 3) { + if (of_get_address(io, 2, NULL, NULL) == NULL) { /* OK - maybe we need to use the 'awacs' node (on earlier * machines). */ if (awacs_node) { io = awacs_node ; - if (of_get_address(io, 2, NULL, NULL) == NULL || - io->n_intrs < 3) { + if (of_get_address(io, 2, NULL, NULL) == NULL) { printk("dmasound_pmac: can't use %s\n", io->full_name); return -ENODEV; @@ -2940,9 +2936,9 @@ if (awacs_revision == AWACS_SCREAMER && awacs) awacs_recalibrate(); - awacs_irq = io->intrs[0].line; - awacs_tx_irq = io->intrs[1].line; - awacs_rx_irq = io->intrs[2].line; + awacs_irq = irq_of_parse_and_map(io, 0); + awacs_tx_irq = irq_of_parse_and_map(io, 1); + awacs_rx_irq = irq_of_parse_and_map(io, 2); /* Hack for legacy crap that will be killed someday */ awacs_node = io;