summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-07-03 21:36:01 +1000
committerPaul Mackerras <paulus@samba.org>2006-07-03 21:36:01 +1000
commit0ebfff1491ef85d41ddf9c633834838be144f69f (patch)
tree5b469a6d61a9fcfbf94e7b6d411e544dbdec8dec /arch/powerpc/platforms/powermac
parentf63e115fb50db39706b955b81e3375ef6bab2268 (diff)
[POWERPC] Add new interrupt mapping core and change platforms to use it
This adds the new irq remapper core and removes the old one. Because there are some fundamental conflicts with the old code, like the value of NO_IRQ which I'm now setting to 0 (as per discussions with Linus), etc..., this commit also changes the relevant platform and driver code over to use the new remapper (so as not to cause difficulties later in bisecting). This patch removes the old pre-parsing of the open firmware interrupt tree along with all the bogus assumptions it made to try to renumber interrupts according to the platform. This is all to be handled by the new code now. For the pSeries XICS interrupt controller, a single remapper host is created for the whole machine regardless of how many interrupt presentation and source controllers are found, and it's set to match any device node that isn't a 8259. That works fine on pSeries and avoids having to deal with some of the complexities of split source controllers vs. presentation controllers in the pSeries device trees. The powerpc i8259 PIC driver now always requests the legacy interrupt range. It also has the feature of being able to match any device node (including NULL) if passed no device node as an input. That will help porting over platforms with broken device-trees like Pegasos who don't have a proper interrupt tree. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac')
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c4
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c9
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c5
-rw-r--r--arch/powerpc/platforms/powermac/pci.c68
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c13
-rw-r--r--arch/powerpc/platforms/powermac/pic.c328
-rw-r--r--arch/powerpc/platforms/powermac/pmac.h2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c3
8 files changed, 191 insertions, 241 deletions
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index 5685ad9e88e..e63d52f227e 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -162,6 +162,8 @@ static void __init bootx_add_chosen_props(unsigned long base,
{
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;
@@ -228,7 +230,7 @@ static void __init bootx_scan_dt_build_strings(unsigned long base,
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);
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index ceafaf52a66..8677f50c258 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -522,10 +522,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
host->speed = KW_I2C_MODE_25KHZ;
break;
}
- if (np->n_intrs > 0)
- host->irq = np->intrs[0].line;
- else
- host->irq = NO_IRQ;
+ host->irq = irq_of_parse_and_map(np, 0);
+ if (host->irq == NO_IRQ)
+ printk(KERN_WARNING
+ "low_i2c: Failed to map interrupt for %s\n",
+ np->full_name);
host->base = ioremap((*addrp), 0x1000);
if (host->base == NULL) {
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 41fa2409482..6a36ea9bf67 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -29,6 +29,8 @@
#include <asm/machdep.h>
#include <asm/nvram.h>
+#include "pmac.h"
+
#define DEBUG
#ifdef DEBUG
@@ -80,9 +82,6 @@ static int nvram_partitions[3];
// 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);
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index d524a915aa8..556b349797e 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -46,6 +46,9 @@ static int has_uninorth;
static struct pci_controller *u3_agp;
static struct pci_controller *u4_pcie;
static struct pci_controller *u3_ht;
+#define has_second_ohare 0
+#else
+static int has_second_ohare;
#endif /* CONFIG_PPC64 */
extern u8 pci_cache_line_size;
@@ -647,6 +650,33 @@ static void __init init_p2pbridge(void)
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 +718,6 @@ static void __init fixup_nec_usb2(void)
" 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);
}
}
}
@@ -958,32 +985,28 @@ static int __init add_bridge(struct device_node *dev)
return 0;
}
-static void __init pcibios_fixup_OF_interrupts(void)
+void __init pmac_pcibios_fixup(void)
{
struct pci_dev* dev = NULL;
- /*
- * Open Firmware often doesn't initialize the
- * PCI_INTERRUPT_LINE config register properly, so we
- * should find the device node and apply the interrupt
- * obtained from the OF device-tree
- */
for_each_pci_dev(dev) {
- struct device_node *node;
- node = pci_device_to_OF_node(dev);
- /* this is the node, see if it has interrupts */
- if (node && node->n_intrs > 0)
- dev->irq = node->intrs[0].line;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ /* 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);
}
}
-void __init pmac_pcibios_fixup(void)
-{
- /* Fixup interrupts according to OF tree */
- pcibios_fixup_OF_interrupts();
-}
-
#ifdef CONFIG_PPC64
static void __init pmac_fixup_phb_resources(void)
{
@@ -1071,6 +1094,7 @@ void __init pmac_pci_init(void)
#else /* CONFIG_PPC64 */
init_p2pbridge();
+ init_second_ohare();
fixup_nec_usb2();
/* We are still having some issues with the Xserve G4, enabling
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index d6eab8b3f7d..6d66359ec8c 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -24,19 +24,18 @@ static irqreturn_t macio_gpio_irq(int irq, void *data, struct pt_regs *regs)
static int macio_do_gpio_irq_enable(struct pmf_function *func)
{
- if (func->node->n_intrs < 1)
+ unsigned int irq = irq_of_parse_and_map(func->node, 0);
+ if (irq == NO_IRQ)
return -EINVAL;
-
- return request_irq(func->node->intrs[0].line, macio_gpio_irq, 0,
- func->node->name, func);
+ return request_irq(irq, macio_gpio_irq, 0, func->node->name, func);
}
static int macio_do_gpio_irq_disable(struct pmf_function *func)
{
- if (func->node->n_intrs < 1)
+ unsigned int irq = irq_of_parse_and_map(func->node, 0);
+ if (irq == NO_IRQ)
return -EINVAL;
-
- free_irq(func->node->intrs[0].line, func);
+ free_irq(irq, func);
return 0;
}
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 58a4c7b90b8..3d328bc1f7e 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -65,13 +65,11 @@ static u32 level_mask[4];
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_retrigger(unsigned int irq_nr)
}
}
-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 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr)
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 @@ static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
/* 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 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
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 @@ static int pmac_get_irq(struct pt_regs *regs)
/* 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 @@ static int pmac_get_irq(struct pt_regs *regs)
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 @@ static struct irqaction gatwick_cascade_action = {
.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 @@ static void __init pmac_pic_probe_oldstyle(void)
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 @@ static void __init pmac_pic_probe_oldstyle(void)
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 @@ static void __init pmac_pic_probe_oldstyle(void)
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 @@ static void __init pmac_pic_probe_oldstyle(void)
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 @@ static void __init pmac_pic_probe_oldstyle(void)
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 */
@@ -530,16 +443,11 @@ static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc,
struct pt_regs *regs)
{
struct mpic *mpic = desc->handler_data;
- unsigned int max = 100;
- while(max--) {
- int cascade_irq = mpic_get_one_irq(mpic, regs);
- if (max == 99)
- desc->chip->eoi(irq);
- if (irq < 0)
- break;
+ unsigned int cascade_irq = mpic_get_one_irq(mpic, regs);
+ if (cascade_irq != NO_IRQ)
generic_handle_irq(cascade_irq, regs);
- };
+ desc->chip->eoi(irq);
}
static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
@@ -549,21 +457,20 @@ static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
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) */
}
static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
int master)
{
- unsigned char senses[128];
- int offset = master ? 0 : 128;
- int count = master ? 128 : 124;
const char *name = master ? " MPIC 1 " : " MPIC 2 ";
struct resource r;
struct mpic *mpic;
@@ -576,8 +483,6 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
- prom_get_irq_senses(senses, offset, offset + count);
-
flags |= MPIC_WANTS_RESET;
if (get_property(np, "big-endian", NULL))
flags |= MPIC_BIG_ENDIAN;
@@ -588,8 +493,7 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
if (master && (flags & MPIC_BIG_ENDIAN))
flags |= MPIC_BROKEN_U3;
- mpic = mpic_alloc(r.start, flags, 0, offset, count, master ? 252 : 0,
- senses, count, name);
+ mpic = mpic_alloc(np, r.start, flags, 0, 0, name);
if (mpic == NULL)
return NULL;
@@ -602,6 +506,7 @@ static int __init pmac_pic_probe_mpic(void)
{
struct mpic *mpic1, *mpic2;
struct device_node *np, *master = NULL, *slave = NULL;
+ unsigned int cascade;
/* We can have up to 2 MPICs cascaded */
for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
@@ -638,8 +543,15 @@ static int __init pmac_pic_probe_mpic(void)
of_node_put(master);
/* No slave, let's go out */
- if (slave == NULL || slave->n_intrs < 1)
+ if (slave == NULL)
+ return 0;
+
+ /* Get/Map slave interrupt */
+ cascade = irq_of_parse_and_map(slave, 0);
+ if (cascade == NO_IRQ) {
+ printk(KERN_ERR "Failed to map cascade IRQ\n");
return 0;
+ }
mpic2 = pmac_setup_one_mpic(slave, 0);
if (mpic2 == NULL) {
@@ -647,8 +559,8 @@ static int __init pmac_pic_probe_mpic(void)
of_node_put(slave);
return 0;
}
- set_irq_data(slave->intrs[0].line, mpic2);
- set_irq_chained_handler(slave->intrs[0].line, pmac_u3_cascade);
+ set_irq_data(cascade, mpic2);
+ set_irq_chained_handler(cascade, pmac_u3_cascade);
of_node_put(slave);
return 0;
@@ -657,6 +569,19 @@ static int __init pmac_pic_probe_mpic(void)
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.
*/
@@ -679,6 +604,7 @@ unsigned long sleep_save_mask[2];
/* 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)
{
@@ -692,7 +618,7 @@ static int pmacpic_find_viaint(void)
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:
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index 21c7b0f8f32..94e7b24b840 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -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 *);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 8654b5f0783..31a9da769fa 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -613,9 +613,6 @@ static void __init pmac_init_early(void)
udbg_adb_init(!!strstr(cmd_line, "btextdbg"));
#ifdef CONFIG_PPC64
- /* Setup interrupt mapping options */
- ppc64_interrupt_controller = IC_OPEN_PIC;
-
iommu_init_early_dart();
#endif
}