diff options
| author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 2007-11-23 14:34:16 -0500 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2007-11-26 12:26:14 -0500 |
| commit | 68de4803726224a7cfe09c8052f0ce5e532c6847 (patch) | |
| tree | 2f6a9595768f75d417c30d1966012845d477f1ad | |
| parent | cce335ae47e231398269fb05fa48e0e9cbf289e0 (diff) | |
[MIPS] IP22: Fix broken EISA interrupt setup by switching to generic i8259
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -rw-r--r-- | arch/mips/Kconfig | 1 | ||||
| -rw-r--r-- | arch/mips/sgi-ip22/ip22-eisa.c | 134 |
2 files changed, 3 insertions, 132 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4c6ba7b30a68..455bd1f560aa 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -401,6 +401,7 @@ config SGI_IP22 | |||
| 401 | select DMA_NONCOHERENT | 401 | select DMA_NONCOHERENT |
| 402 | select HW_HAS_EISA | 402 | select HW_HAS_EISA |
| 403 | select I8253 | 403 | select I8253 |
| 404 | select I8259 | ||
| 404 | select IP22_CPU_SCACHE | 405 | select IP22_CPU_SCACHE |
| 405 | select IRQ_CPU | 406 | select IRQ_CPU |
| 406 | select GENERIC_ISA_DMA_SUPPORT_BROKEN | 407 | select GENERIC_ISA_DMA_SUPPORT_BROKEN |
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c index 26854fb11e7c..1617241d2737 100644 --- a/arch/mips/sgi-ip22/ip22-eisa.c +++ b/arch/mips/sgi-ip22/ip22-eisa.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <asm/sgi/ioc.h> | 36 | #include <asm/sgi/ioc.h> |
| 37 | #include <asm/sgi/mc.h> | 37 | #include <asm/sgi/mc.h> |
| 38 | #include <asm/sgi/ip22.h> | 38 | #include <asm/sgi/ip22.h> |
| 39 | #include <asm/i8259.h> | ||
| 39 | 40 | ||
| 40 | /* I2 has four EISA slots. */ | 41 | /* I2 has four EISA slots. */ |
| 41 | #define IP22_EISA_MAX_SLOTS 4 | 42 | #define IP22_EISA_MAX_SLOTS 4 |
| @@ -93,126 +94,11 @@ static irqreturn_t ip22_eisa_intr(int irq, void *dev_id) | |||
| 93 | return IRQ_NONE; | 94 | return IRQ_NONE; |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | static void enable_eisa1_irq(unsigned int irq) | ||
| 97 | { | ||
| 98 | u8 mask; | ||
| 99 | |||
| 100 | mask = inb(EISA_INT1_MASK); | ||
| 101 | mask &= ~((u8) (1 << irq)); | ||
| 102 | outb(mask, EISA_INT1_MASK); | ||
| 103 | } | ||
| 104 | |||
| 105 | static unsigned int startup_eisa1_irq(unsigned int irq) | ||
| 106 | { | ||
| 107 | u8 edge; | ||
| 108 | |||
| 109 | /* Only use edge interrupts for EISA */ | ||
| 110 | |||
| 111 | edge = inb(EISA_INT1_EDGE_LEVEL); | ||
| 112 | edge &= ~((u8) (1 << irq)); | ||
| 113 | outb(edge, EISA_INT1_EDGE_LEVEL); | ||
| 114 | |||
| 115 | enable_eisa1_irq(irq); | ||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | static void disable_eisa1_irq(unsigned int irq) | ||
| 120 | { | ||
| 121 | u8 mask; | ||
| 122 | |||
| 123 | mask = inb(EISA_INT1_MASK); | ||
| 124 | mask |= ((u8) (1 << irq)); | ||
| 125 | outb(mask, EISA_INT1_MASK); | ||
| 126 | } | ||
| 127 | |||
| 128 | static void mask_and_ack_eisa1_irq(unsigned int irq) | ||
| 129 | { | ||
| 130 | disable_eisa1_irq(irq); | ||
| 131 | |||
| 132 | outb(0x20, EISA_INT1_CTRL); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void end_eisa1_irq(unsigned int irq) | ||
| 136 | { | ||
| 137 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | ||
| 138 | enable_eisa1_irq(irq); | ||
| 139 | } | ||
| 140 | |||
| 141 | static struct irq_chip ip22_eisa1_irq_type = { | ||
| 142 | .name = "IP22 EISA", | ||
| 143 | .startup = startup_eisa1_irq, | ||
| 144 | .ack = mask_and_ack_eisa1_irq, | ||
| 145 | .mask = disable_eisa1_irq, | ||
| 146 | .mask_ack = mask_and_ack_eisa1_irq, | ||
| 147 | .unmask = enable_eisa1_irq, | ||
| 148 | .end = end_eisa1_irq, | ||
| 149 | }; | ||
| 150 | |||
| 151 | static void enable_eisa2_irq(unsigned int irq) | ||
| 152 | { | ||
| 153 | u8 mask; | ||
| 154 | |||
| 155 | mask = inb(EISA_INT2_MASK); | ||
| 156 | mask &= ~((u8) (1 << (irq - 8))); | ||
| 157 | outb(mask, EISA_INT2_MASK); | ||
| 158 | } | ||
| 159 | |||
| 160 | static unsigned int startup_eisa2_irq(unsigned int irq) | ||
| 161 | { | ||
| 162 | u8 edge; | ||
| 163 | |||
| 164 | /* Only use edge interrupts for EISA */ | ||
| 165 | |||
| 166 | edge = inb(EISA_INT2_EDGE_LEVEL); | ||
| 167 | edge &= ~((u8) (1 << (irq - 8))); | ||
| 168 | outb(edge, EISA_INT2_EDGE_LEVEL); | ||
| 169 | |||
| 170 | enable_eisa2_irq(irq); | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static void disable_eisa2_irq(unsigned int irq) | ||
| 175 | { | ||
| 176 | u8 mask; | ||
| 177 | |||
| 178 | mask = inb(EISA_INT2_MASK); | ||
| 179 | mask |= ((u8) (1 << (irq - 8))); | ||
| 180 | outb(mask, EISA_INT2_MASK); | ||
| 181 | } | ||
| 182 | |||
| 183 | static void mask_and_ack_eisa2_irq(unsigned int irq) | ||
| 184 | { | ||
| 185 | disable_eisa2_irq(irq); | ||
| 186 | |||
| 187 | outb(0x20, EISA_INT2_CTRL); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void end_eisa2_irq(unsigned int irq) | ||
| 191 | { | ||
| 192 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | ||
| 193 | enable_eisa2_irq(irq); | ||
| 194 | } | ||
| 195 | |||
| 196 | static struct irq_chip ip22_eisa2_irq_type = { | ||
| 197 | .name = "IP22 EISA", | ||
| 198 | .startup = startup_eisa2_irq, | ||
| 199 | .ack = mask_and_ack_eisa2_irq, | ||
| 200 | .mask = disable_eisa2_irq, | ||
| 201 | .mask_ack = mask_and_ack_eisa2_irq, | ||
| 202 | .unmask = enable_eisa2_irq, | ||
| 203 | .end = end_eisa2_irq, | ||
| 204 | }; | ||
| 205 | |||
| 206 | static struct irqaction eisa_action = { | 97 | static struct irqaction eisa_action = { |
| 207 | .handler = ip22_eisa_intr, | 98 | .handler = ip22_eisa_intr, |
| 208 | .name = "EISA", | 99 | .name = "EISA", |
| 209 | }; | 100 | }; |
| 210 | 101 | ||
| 211 | static struct irqaction cascade_action = { | ||
| 212 | .handler = no_action, | ||
| 213 | .name = "EISA cascade", | ||
| 214 | }; | ||
| 215 | |||
| 216 | int __init ip22_eisa_init(void) | 102 | int __init ip22_eisa_init(void) |
| 217 | { | 103 | { |
| 218 | int i, c; | 104 | int i, c; |
| @@ -248,29 +134,13 @@ int __init ip22_eisa_init(void) | |||
| 248 | outb(1, EISA_EXT_NMI_RESET_CTRL); | 134 | outb(1, EISA_EXT_NMI_RESET_CTRL); |
| 249 | udelay(50); /* Wait long enough for the dust to settle */ | 135 | udelay(50); /* Wait long enough for the dust to settle */ |
| 250 | outb(0, EISA_EXT_NMI_RESET_CTRL); | 136 | outb(0, EISA_EXT_NMI_RESET_CTRL); |
| 251 | outb(0x11, EISA_INT1_CTRL); | ||
| 252 | outb(0x11, EISA_INT2_CTRL); | ||
| 253 | outb(0, EISA_INT1_MASK); | ||
| 254 | outb(8, EISA_INT2_MASK); | ||
| 255 | outb(4, EISA_INT1_MASK); | ||
| 256 | outb(2, EISA_INT2_MASK); | ||
| 257 | outb(1, EISA_INT1_MASK); | ||
| 258 | outb(1, EISA_INT2_MASK); | ||
| 259 | outb(0xfb, EISA_INT1_MASK); | ||
| 260 | outb(0xff, EISA_INT2_MASK); | ||
| 261 | outb(0, EISA_DMA2_WRITE_SINGLE); | 137 | outb(0, EISA_DMA2_WRITE_SINGLE); |
| 262 | 138 | ||
| 263 | for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) { | 139 | init_i8259_irqs(); |
| 264 | if (i < (SGINT_EISA + 8)) | ||
| 265 | set_irq_chip(i, &ip22_eisa1_irq_type); | ||
| 266 | else | ||
| 267 | set_irq_chip(i, &ip22_eisa2_irq_type); | ||
| 268 | } | ||
| 269 | 140 | ||
| 270 | /* Cannot use request_irq because of kmalloc not being ready at such | 141 | /* Cannot use request_irq because of kmalloc not being ready at such |
| 271 | * an early stage. Yes, I've been bitten... */ | 142 | * an early stage. Yes, I've been bitten... */ |
| 272 | setup_irq(SGI_EISA_IRQ, &eisa_action); | 143 | setup_irq(SGI_EISA_IRQ, &eisa_action); |
| 273 | setup_irq(SGINT_EISA + 2, &cascade_action); | ||
| 274 | 144 | ||
| 275 | EISA_bus = 1; | 145 | EISA_bus = 1; |
| 276 | return 0; | 146 | return 0; |
