summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-26 17:19:06 +1000
committerPaul Mackerras <paulus@samba.org>2005-10-26 17:19:06 +1000
commit6d0124fc06be40deafca043c73a8203c78bbfe45 (patch)
treea2db556568bb9ecc698d1e8ea3f88fd0c022aa01
parent830825d6c37a28061c0b6ca538a6411001cf3b2a (diff)
powerpc: Fix interrupt-tree parsing
The interrupt-tree parsing code wasn't offsetting interrupt numbers by 16 on 32-bit platforms with an i8259 interrupt controller, and it was confused about the encoding of interrupt sense and level (which is different for i8259 and openpic interrupt controllers, just to make things interesting). Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/prom.c40
-rw-r--r--include/asm-powerpc/irq.h2
2 files changed, 28 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 16ac15e73b4..ab9b291dda5 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -296,13 +296,28 @@ static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictr
return nintrc;
}
+static unsigned char map_isa_senses[4] = {
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
+ IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
+ IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE
+};
+
+static unsigned char map_mpic_senses[4] = {
+ IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE,
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
+ /* 2 seems to be used for the 8259 cascade... */
+ IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
+ IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
+};
+
static int __devinit finish_node_interrupts(struct device_node *np,
unsigned long *mem_start,
int measure_only)
{
unsigned int *ints;
int intlen, intrcells, intrcount;
- int i, j, n;
+ int i, j, n, sense;
unsigned int *irq, virq;
struct device_node *ic;
@@ -332,7 +347,8 @@ static int __devinit finish_node_interrupts(struct device_node *np,
for (i = 0; i < np->n_intrs; ++i) {
np->intrs[i].line = *ints++;
- np->intrs[i].sense = 1;
+ np->intrs[i].sense = IRQ_SENSE_LEVEL
+ | IRQ_POLARITY_NEGATIVE;
}
return 0;
}
@@ -359,19 +375,20 @@ static int __devinit finish_node_interrupts(struct device_node *np,
/* don't map IRQ numbers under a cascaded 8259 controller */
if (ic && device_is_compatible(ic, "chrp,iic")) {
np->intrs[intrcount].line = irq[0];
+ sense = (n > 1)? (irq[1] & 3): 3;
+ np->intrs[intrcount].sense = map_isa_senses[sense];
} else {
-#ifdef CONFIG_PPC64
virq = virt_irq_create_mapping(irq[0]);
+#ifdef CONFIG_PPC64
if (virq == NO_IRQ) {
printk(KERN_CRIT "Could not allocate interrupt"
" number for %s\n", np->full_name);
continue;
}
- virq = irq_offset_up(virq);
-#else
- virq = irq[0];
#endif
- np->intrs[intrcount].line = virq;
+ np->intrs[intrcount].line = irq_offset_up(virq);
+ sense = (n > 1)? (irq[1] & 3): 1;
+ np->intrs[intrcount].sense = map_mpic_senses[sense];
}
#ifdef CONFIG_PPC64
@@ -386,9 +403,6 @@ static int __devinit finish_node_interrupts(struct device_node *np,
break;
}
#endif
- np->intrs[intrcount].sense = 1;
- if (n > 1)
- np->intrs[intrcount].sense = irq[1];
if (n > 2) {
printk("hmmm, got %d intr cells for %s:", n,
np->full_name);
@@ -1401,15 +1415,13 @@ void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
int i, j;
/* default to level-triggered */
- memset(senses, 1, max - off);
+ memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off);
for (np = allnodes; np != 0; np = np->allnext) {
for (j = 0; j < np->n_intrs; j++) {
i = np->intrs[j].line;
if (i >= off && i < max)
- senses[i-off] = np->intrs[j].sense ?
- IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
- IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
+ senses[i-off] = np->intrs[j].sense;
}
}
}
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 07c2b3fc4c6..c7c3f912a3c 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -432,6 +432,8 @@ extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
extern atomic_t ppc_n_lost_interrupts;
+#define virt_irq_create_mapping(x) (x)
+
#endif
/*