diff options
| -rw-r--r-- | arch/sparc/kernel/sun4m_irq.c | 145 | ||||
| -rw-r--r-- | arch/sparc/kernel/traps.c | 17 |
2 files changed, 91 insertions, 71 deletions
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index ec66d4aab098..f10317179ee6 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c | |||
| @@ -71,8 +71,9 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; | |||
| 71 | 71 | ||
| 72 | #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ | 72 | #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ |
| 73 | #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ | 73 | #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ |
| 74 | #define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ | 74 | #define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ |
| 75 | #define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ | 75 | #define SUN4M_INT_ECC_ERR 0x10000000 /* ecc memory error */ |
| 76 | #define SUN4M_INT_VME_ERR 0x08000000 /* vme async error */ | ||
| 76 | #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ | 77 | #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ |
| 77 | #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ | 78 | #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ |
| 78 | #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ | 79 | #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ |
| @@ -83,10 +84,22 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; | |||
| 83 | #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ | 84 | #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ |
| 84 | #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ | 85 | #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ |
| 85 | #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ | 86 | #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ |
| 87 | #define SUN4M_INT_VMEBITS 0x0000007F /* vme int bits */ | ||
| 88 | |||
| 89 | #define SUN4M_INT_ERROR (SUN4M_INT_MODULE_ERR | \ | ||
| 90 | SUN4M_INT_M2S_WRITE_ERR | \ | ||
| 91 | SUN4M_INT_ECC_ERR | \ | ||
| 92 | SUN4M_INT_VME_ERR) | ||
| 86 | 93 | ||
| 87 | #define SUN4M_INT_SBUS(x) (1 << (x+7)) | 94 | #define SUN4M_INT_SBUS(x) (1 << (x+7)) |
| 88 | #define SUN4M_INT_VME(x) (1 << (x)) | 95 | #define SUN4M_INT_VME(x) (1 << (x)) |
| 89 | 96 | ||
| 97 | /* Interrupt levels used by OBP */ | ||
| 98 | #define OBP_INT_LEVEL_SOFT 0x10 | ||
| 99 | #define OBP_INT_LEVEL_ONBOARD 0x20 | ||
| 100 | #define OBP_INT_LEVEL_SBUS 0x30 | ||
| 101 | #define OBP_INT_LEVEL_VME 0x40 | ||
| 102 | |||
| 90 | /* Interrupt level assignment on sun4m: | 103 | /* Interrupt level assignment on sun4m: |
| 91 | * | 104 | * |
| 92 | * level source | 105 | * level source |
| @@ -140,59 +153,57 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; | |||
| 140 | * power: 0x22 onboard power device (XXX unknown mask bit XXX) | 153 | * power: 0x22 onboard power device (XXX unknown mask bit XXX) |
| 141 | */ | 154 | */ |
| 142 | 155 | ||
| 143 | /* These tables only apply for interrupts greater than 15.. | 156 | static unsigned long irq_mask[0x50] = { |
| 144 | * | 157 | /* SMP */ |
| 145 | * any intr value below 0x10 is considered to be a soft-int | 158 | 0, SUN4M_SOFT_INT(1), |
| 146 | * this may be useful or it may not.. but that's how I've done it. | 159 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
| 147 | * and it won't clash with what OBP is telling us about devices. | 160 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
| 148 | * | 161 | SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7), |
| 149 | * take an encoded intr value and lookup if it's valid | 162 | SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9), |
| 150 | * then get the mask bits that match from irq_mask | 163 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), |
| 151 | * | 164 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), |
| 152 | * P3: Translation from irq 0x0d to mask 0x2000 is for MrCoffee. | 165 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), |
| 153 | */ | 166 | /* soft */ |
| 154 | static unsigned char irq_xlate[32] = { | 167 | 0, SUN4M_SOFT_INT(1), |
| 155 | /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f */ | 168 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
| 156 | 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 5, 6, 14, 0, 7, | 169 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
| 157 | 0, 0, 8, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 0 | 170 | SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7), |
| 158 | }; | 171 | SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9), |
| 159 | 172 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), | |
| 160 | static unsigned long irq_mask[] = { | 173 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), |
| 161 | 0, /* illegal index */ | 174 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), |
| 162 | SUN4M_INT_SCSI, /* 1 irq 4 */ | 175 | /* onboard */ |
| 163 | SUN4M_INT_ETHERNET, /* 2 irq 6 */ | 176 | 0, 0, 0, 0, |
| 164 | SUN4M_INT_VIDEO, /* 3 irq 8 */ | 177 | SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0, |
| 165 | SUN4M_INT_REALTIME, /* 4 irq 10 */ | 178 | SUN4M_INT_VIDEO, SUN4M_INT_MODULE, |
| 166 | SUN4M_INT_FLOPPY, /* 5 irq 11 */ | 179 | SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, |
| 167 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), /* 6 irq 12 */ | 180 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), |
| 168 | SUN4M_INT_MODULE_ERR, /* 7 irq 15 */ | 181 | SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, |
| 169 | SUN4M_INT_SBUS(0), /* 8 irq 2 */ | 182 | /* sbus */ |
| 170 | SUN4M_INT_SBUS(1), /* 9 irq 3 */ | 183 | 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), |
| 171 | SUN4M_INT_SBUS(2), /* 10 irq 5 */ | 184 | 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), |
| 172 | SUN4M_INT_SBUS(3), /* 11 irq 7 */ | 185 | 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5), |
| 173 | SUN4M_INT_SBUS(4), /* 12 irq 9 */ | 186 | 0, SUN4M_INT_SBUS(6), 0, 0, |
| 174 | SUN4M_INT_SBUS(5), /* 13 irq 11 */ | 187 | /* vme */ |
| 175 | SUN4M_INT_SBUS(6) /* 14 irq 13 */ | 188 | 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1), |
| 189 | 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3), | ||
| 190 | 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5), | ||
| 191 | 0, SUN4M_INT_VME(6), 0, 0 | ||
| 176 | }; | 192 | }; |
| 177 | 193 | ||
| 178 | static unsigned long sun4m_get_irqmask(unsigned int irq) | 194 | static unsigned long sun4m_get_irqmask(unsigned int irq) |
| 179 | { | 195 | { |
| 180 | unsigned long mask; | 196 | unsigned long mask; |
| 181 | 197 | ||
| 182 | if (irq > 0x20) { | 198 | if (irq < 0x50) |
| 183 | /* OBIO/SBUS interrupts */ | 199 | mask = irq_mask[irq]; |
| 184 | irq &= 0x1f; | 200 | else |
| 185 | mask = irq_mask[irq_xlate[irq]]; | 201 | mask = 0; |
| 186 | if (!mask) | 202 | |
| 187 | printk("sun4m_get_irqmask: IRQ%d has no valid mask!\n",irq); | 203 | if (!mask) |
| 188 | } else { | 204 | printk(KERN_ERR "sun4m_get_irqmask: IRQ%d has no valid mask!\n", |
| 189 | /* Soft Interrupts will come here. | 205 | irq); |
| 190 | * Currently there is no way to trigger them but I'm sure | 206 | |
| 191 | * something could be cooked up. | ||
| 192 | */ | ||
| 193 | irq &= 0xf; | ||
| 194 | mask = SUN4M_SOFT_INT(irq); | ||
| 195 | } | ||
| 196 | return mask; | 207 | return mask; |
| 197 | } | 208 | } |
| 198 | 209 | ||
| @@ -247,10 +258,10 @@ static unsigned long cpu_pil_to_imask[16] = { | |||
| 247 | /*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR, | 258 | /*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR, |
| 248 | /*10*/ SUN4M_INT_REALTIME, | 259 | /*10*/ SUN4M_INT_REALTIME, |
| 249 | /*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY, | 260 | /*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY, |
| 250 | /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, | 261 | /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, |
| 251 | /*13*/ SUN4M_INT_AUDIO, | 262 | /*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, |
| 252 | /*14*/ SUN4M_INT_E14, | 263 | /*14*/ SUN4M_INT_E14, |
| 253 | /*15*/ 0x00000000 | 264 | /*15*/ SUN4M_INT_ERROR |
| 254 | }; | 265 | }; |
| 255 | 266 | ||
| 256 | /* We assume the caller has disabled local interrupts when these are called, | 267 | /* We assume the caller has disabled local interrupts when these are called, |
| @@ -304,8 +315,7 @@ struct sun4m_timer_global { | |||
| 304 | 315 | ||
| 305 | static struct sun4m_timer_global __iomem *timers_global; | 316 | static struct sun4m_timer_global __iomem *timers_global; |
| 306 | 317 | ||
| 307 | #define OBIO_INTR 0x20 | 318 | #define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) |
| 308 | #define TIMER_IRQ (OBIO_INTR | 10) | ||
| 309 | 319 | ||
| 310 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); | 320 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); |
| 311 | 321 | ||
| @@ -314,6 +324,33 @@ static void sun4m_clear_clock_irq(void) | |||
| 314 | sbus_readl(&timers_global->l10_limit); | 324 | sbus_readl(&timers_global->l10_limit); |
| 315 | } | 325 | } |
| 316 | 326 | ||
| 327 | void sun4m_nmi(struct pt_regs *regs) | ||
| 328 | { | ||
| 329 | unsigned long afsr, afar, si; | ||
| 330 | |||
| 331 | printk(KERN_ERR "Aieee: sun4m NMI received!\n"); | ||
| 332 | /* XXX HyperSparc hack XXX */ | ||
| 333 | __asm__ __volatile__("mov 0x500, %%g1\n\t" | ||
| 334 | "lda [%%g1] 0x4, %0\n\t" | ||
| 335 | "mov 0x600, %%g1\n\t" | ||
| 336 | "lda [%%g1] 0x4, %1\n\t" : | ||
| 337 | "=r" (afsr), "=r" (afar)); | ||
| 338 | printk(KERN_ERR "afsr=%08lx afar=%08lx\n", afsr, afar); | ||
| 339 | si = sbus_readl(&sun4m_irq_global->pending); | ||
| 340 | printk(KERN_ERR "si=%08lx\n", si); | ||
| 341 | if (si & SUN4M_INT_MODULE_ERR) | ||
| 342 | printk(KERN_ERR "Module async error\n"); | ||
| 343 | if (si & SUN4M_INT_M2S_WRITE_ERR) | ||
| 344 | printk(KERN_ERR "MBus/SBus async error\n"); | ||
| 345 | if (si & SUN4M_INT_ECC_ERR) | ||
| 346 | printk(KERN_ERR "ECC memory error\n"); | ||
| 347 | if (si & SUN4M_INT_VME_ERR) | ||
| 348 | printk(KERN_ERR "VME async error\n"); | ||
| 349 | printk(KERN_ERR "you lose buddy boy...\n"); | ||
| 350 | show_regs(regs); | ||
| 351 | prom_halt(); | ||
| 352 | } | ||
| 353 | |||
| 317 | /* Exported for sun4m_smp.c */ | 354 | /* Exported for sun4m_smp.c */ |
| 318 | void sun4m_clear_profile_irq(int cpu) | 355 | void sun4m_clear_profile_irq(int cpu) |
| 319 | { | 356 | { |
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index 5d45d5fd8c99..2b7d50659036 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c | |||
| @@ -43,23 +43,6 @@ void syscall_trace_exit(struct pt_regs *regs) | |||
| 43 | { | 43 | { |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | void sun4m_nmi(struct pt_regs *regs) | ||
| 47 | { | ||
| 48 | unsigned long afsr, afar; | ||
| 49 | |||
| 50 | printk("Aieee: sun4m NMI received!\n"); | ||
| 51 | /* XXX HyperSparc hack XXX */ | ||
| 52 | __asm__ __volatile__("mov 0x500, %%g1\n\t" | ||
| 53 | "lda [%%g1] 0x4, %0\n\t" | ||
| 54 | "mov 0x600, %%g1\n\t" | ||
| 55 | "lda [%%g1] 0x4, %1\n\t" : | ||
| 56 | "=r" (afsr), "=r" (afar)); | ||
| 57 | printk("afsr=%08lx afar=%08lx\n", afsr, afar); | ||
| 58 | printk("you lose buddy boy...\n"); | ||
| 59 | show_regs(regs); | ||
| 60 | prom_halt(); | ||
| 61 | } | ||
| 62 | |||
| 63 | void sun4d_nmi(struct pt_regs *regs) | 46 | void sun4d_nmi(struct pt_regs *regs) |
| 64 | { | 47 | { |
| 65 | printk("Aieee: sun4d NMI received!\n"); | 48 | printk("Aieee: sun4d NMI received!\n"); |
