Blame view
arch/mips/mti-malta/malta-int.c
20.4 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/* * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc. * Copyright (C) 2001 Ralf Baechle * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Routines for generic manipulation of the interrupts found on the MIPS * Malta board. * The interrupt controller is located in the South Bridge a PIIX4 device * with two internal 82C95 interrupt controllers. */ #include <linux/init.h> #include <linux/irq.h> #include <linux/sched.h> |
631330f58 MIPS: Build fix -... |
27 |
#include <linux/smp.h> |
1da177e4c Linux-2.6.12-rc2 |
28 |
#include <linux/interrupt.h> |
54bf038e2 [MIPS] Malta: inc... |
29 |
#include <linux/io.h> |
1da177e4c Linux-2.6.12-rc2 |
30 |
#include <linux/kernel_stat.h> |
25b8ac3ba [MIPS] Use ARRAY_... |
31 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
#include <linux/random.h> |
39b8d5254 [MIPS] Add suppor... |
33 |
#include <asm/traps.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
#include <asm/i8259.h> |
e01402b11 More AP / SP bits... |
35 |
#include <asm/irq_cpu.h> |
ba38cdf94 [MIPS] Malta: Fix... |
36 |
#include <asm/irq_regs.h> |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 40 41 42 |
#include <asm/mips-boards/malta.h> #include <asm/mips-boards/maltaint.h> #include <asm/mips-boards/piix4.h> #include <asm/gt64120.h> #include <asm/mips-boards/generic.h> #include <asm/mips-boards/msc01_pci.h> |
e01402b11 More AP / SP bits... |
43 |
#include <asm/msc01_ic.h> |
39b8d5254 [MIPS] Add suppor... |
44 45 46 47 48 49 50 51 |
#include <asm/gic.h> #include <asm/gcmpregs.h> int gcmp_present = -1; int gic_present; static unsigned long _msc01_biu_base; static unsigned long _gcmp_base; static unsigned int ipi_map[NR_CPUS]; |
1da177e4c Linux-2.6.12-rc2 |
52 |
|
a963dc70a MIPS: Malta: Conv... |
53 |
static DEFINE_RAW_SPINLOCK(mips_irq_lock); |
1da177e4c Linux-2.6.12-rc2 |
54 55 56 57 |
static inline int mips_pcibios_iack(void) { int irq; |
1da177e4c Linux-2.6.12-rc2 |
58 59 60 61 62 |
/* * Determine highest priority pending interrupt by performing * a PCI Interrupt Acknowledge cycle. */ |
b72c05262 [MIPS] Malta: Fix... |
63 64 65 66 67 |
switch (mips_revision_sconid) { case MIPS_REVISION_SCON_SOCIT: case MIPS_REVISION_SCON_ROCIT: case MIPS_REVISION_SCON_SOCITSC: case MIPS_REVISION_SCON_SOCITSCP: |
af825586c [MIPS] Malta: use... |
68 |
MSC_READ(MSC01_PCI_IACK, irq); |
1da177e4c Linux-2.6.12-rc2 |
69 70 |
irq &= 0xff; break; |
b72c05262 [MIPS] Malta: Fix... |
71 |
case MIPS_REVISION_SCON_GT64120: |
1da177e4c Linux-2.6.12-rc2 |
72 73 74 |
irq = GT_READ(GT_PCI0_IACK_OFS); irq &= 0xff; break; |
b72c05262 [MIPS] Malta: Fix... |
75 |
case MIPS_REVISION_SCON_BONITO: |
1da177e4c Linux-2.6.12-rc2 |
76 77 78 79 80 81 82 83 |
/* The following will generate a PCI IACK cycle on the * Bonito controller. It's a little bit kludgy, but it * was the easiest way to implement it in hardware at * the given time. */ BONITO_PCIMAP_CFG = 0x20000; /* Flush Bonito register block */ |
6be63bbbd MIPS: Malta: Fix ... |
84 |
(void) BONITO_PCIMAP_CFG; |
1da177e4c Linux-2.6.12-rc2 |
85 |
iob(); /* sync */ |
accfd35a4 MIPS: MTI: Fix ac... |
86 |
irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg); |
1da177e4c Linux-2.6.12-rc2 |
87 88 89 90 91 |
iob(); /* sync */ irq &= 0xff; BONITO_PCIMAP_CFG = 0; break; default: |
8216d348e [MIPS] Malta: use... |
92 93 |
printk(KERN_WARNING "Unknown system controller. "); |
1da177e4c Linux-2.6.12-rc2 |
94 95 96 97 |
return -1; } return irq; } |
e01402b11 More AP / SP bits... |
98 |
static inline int get_int(void) |
1da177e4c Linux-2.6.12-rc2 |
99 100 |
{ unsigned long flags; |
e01402b11 More AP / SP bits... |
101 |
int irq; |
a963dc70a MIPS: Malta: Conv... |
102 |
raw_spin_lock_irqsave(&mips_irq_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
103 |
|
e01402b11 More AP / SP bits... |
104 |
irq = mips_pcibios_iack(); |
1da177e4c Linux-2.6.12-rc2 |
105 106 |
/* |
479a0e3e0 Support for CoreF... |
107 108 109 |
* The only way we can decide if an interrupt is spurious * is by checking the 8259 registers. This needs a spinlock * on an SMP system, so leave it up to the generic code... |
1da177e4c Linux-2.6.12-rc2 |
110 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
111 |
|
a963dc70a MIPS: Malta: Conv... |
112 |
raw_spin_unlock_irqrestore(&mips_irq_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
113 |
|
e01402b11 More AP / SP bits... |
114 |
return irq; |
1da177e4c Linux-2.6.12-rc2 |
115 |
} |
937a80157 [MIPS] Complete f... |
116 |
static void malta_hw0_irqdispatch(void) |
1da177e4c Linux-2.6.12-rc2 |
117 118 |
{ int irq; |
e01402b11 More AP / SP bits... |
119 |
irq = get_int(); |
41c594ab6 [MIPS] MT: Improv... |
120 |
if (irq < 0) { |
cd80d5485 [MIPS] Malta: fix... |
121 122 |
/* interrupt has already been cleared */ return; |
41c594ab6 [MIPS] MT: Improv... |
123 |
} |
1da177e4c Linux-2.6.12-rc2 |
124 |
|
937a80157 [MIPS] Complete f... |
125 |
do_IRQ(MALTA_INT_BASE + irq); |
1da177e4c Linux-2.6.12-rc2 |
126 |
} |
39b8d5254 [MIPS] Add suppor... |
127 128 129 130 131 132 133 134 135 136 |
static void malta_ipi_irqdispatch(void) { int irq; irq = gic_get_int(); if (irq < 0) return; /* interrupt has already been cleared */ do_IRQ(MIPS_GIC_IRQ_BASE + irq); } |
937a80157 [MIPS] Complete f... |
137 |
static void corehi_irqdispatch(void) |
1da177e4c Linux-2.6.12-rc2 |
138 |
{ |
937a80157 [MIPS] Complete f... |
139 |
unsigned int intedge, intsteer, pcicmd, pcibadaddr; |
af825586c [MIPS] Malta: use... |
140 |
unsigned int pcimstat, intisr, inten, intpol; |
21a151d8c [MIPS] checkfiles... |
141 |
unsigned int intrcause, datalo, datahi; |
ba38cdf94 [MIPS] Malta: Fix... |
142 |
struct pt_regs *regs = get_irq_regs(); |
1da177e4c Linux-2.6.12-rc2 |
143 |
|
8216d348e [MIPS] Malta: use... |
144 145 146 147 148 |
printk(KERN_EMERG "CoreHI interrupt, shouldn't happen, we die here! "); printk(KERN_EMERG "epc : %08lx Status: %08lx " |
af825586c [MIPS] Malta: use... |
149 150 151 152 153 |
"Cause : %08lx badVaddr : %08lx ", regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr); |
e01402b11 More AP / SP bits... |
154 155 156 157 158 |
/* Read all the registers and then print them as there is a problem with interspersed printk's upsetting the Bonito controller. Do it for the others too. */ |
b72c05262 [MIPS] Malta: Fix... |
159 |
switch (mips_revision_sconid) { |
af825586c [MIPS] Malta: use... |
160 |
case MIPS_REVISION_SCON_SOCIT: |
b72c05262 [MIPS] Malta: Fix... |
161 162 163 |
case MIPS_REVISION_SCON_ROCIT: case MIPS_REVISION_SCON_SOCITSC: case MIPS_REVISION_SCON_SOCITSCP: |
af825586c [MIPS] Malta: use... |
164 165 166 167 168 169 |
ll_msc_irq(); break; case MIPS_REVISION_SCON_GT64120: intrcause = GT_READ(GT_INTRCAUSE_OFS); datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); |
8216d348e [MIPS] Malta: use... |
170 171 172 173 174 |
printk(KERN_EMERG "GT_INTRCAUSE = %08x ", intrcause); printk(KERN_EMERG "GT_CPUERR_ADDR = %02x%08x ", datahi, datalo); |
af825586c [MIPS] Malta: use... |
175 176 177 178 179 180 181 182 183 184 |
break; case MIPS_REVISION_SCON_BONITO: pcibadaddr = BONITO_PCIBADADDR; pcimstat = BONITO_PCIMSTAT; intisr = BONITO_INTISR; inten = BONITO_INTEN; intpol = BONITO_INTPOL; intedge = BONITO_INTEDGE; intsteer = BONITO_INTSTEER; pcicmd = BONITO_PCICMD; |
8216d348e [MIPS] Malta: use... |
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
printk(KERN_EMERG "BONITO_INTISR = %08x ", intisr); printk(KERN_EMERG "BONITO_INTEN = %08x ", inten); printk(KERN_EMERG "BONITO_INTPOL = %08x ", intpol); printk(KERN_EMERG "BONITO_INTEDGE = %08x ", intedge); printk(KERN_EMERG "BONITO_INTSTEER = %08x ", intsteer); printk(KERN_EMERG "BONITO_PCICMD = %08x ", pcicmd); printk(KERN_EMERG "BONITO_PCIBADADDR = %08x ", pcibadaddr); printk(KERN_EMERG "BONITO_PCIMSTAT = %08x ", pcimstat); |
af825586c [MIPS] Malta: use... |
201 202 |
break; } |
1da177e4c Linux-2.6.12-rc2 |
203 |
|
af825586c [MIPS] Malta: use... |
204 |
die("CoreHi interrupt", regs); |
1da177e4c Linux-2.6.12-rc2 |
205 |
} |
e4ac58afd [MIPS] Rewrite al... |
206 207 |
static inline int clz(unsigned long x) { |
49a89efbb [MIPS] Fix "no sp... |
208 |
__asm__( |
e4ac58afd [MIPS] Rewrite al... |
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
" .set push " " .set mips32 " " clz %0, %1 " " .set pop " : "=r" (x) : "r" (x)); return x; } /* * Version of ffs that only looks at bits 12..15. */ static inline unsigned int irq_ffs(unsigned int pending) { #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) return -clz(pending) + 31 - CAUSEB_IP; #else unsigned int a0 = 7; unsigned int t0; |
0118c3ca9 [MIPS] Malta: Fix... |
233 |
t0 = pending & 0xf000; |
e4ac58afd [MIPS] Rewrite al... |
234 235 236 |
t0 = t0 < 1; t0 = t0 << 2; a0 = a0 - t0; |
0118c3ca9 [MIPS] Malta: Fix... |
237 |
pending = pending << t0; |
e4ac58afd [MIPS] Rewrite al... |
238 |
|
0118c3ca9 [MIPS] Malta: Fix... |
239 |
t0 = pending & 0xc000; |
e4ac58afd [MIPS] Rewrite al... |
240 241 242 |
t0 = t0 < 1; t0 = t0 << 1; a0 = a0 - t0; |
0118c3ca9 [MIPS] Malta: Fix... |
243 |
pending = pending << t0; |
e4ac58afd [MIPS] Rewrite al... |
244 |
|
0118c3ca9 [MIPS] Malta: Fix... |
245 |
t0 = pending & 0x8000; |
e4ac58afd [MIPS] Rewrite al... |
246 |
t0 = t0 < 1; |
ae9cef0b7 [MIPS] Malta: Use... |
247 |
/* t0 = t0 << 2; */ |
e4ac58afd [MIPS] Rewrite al... |
248 |
a0 = a0 - t0; |
ae9cef0b7 [MIPS] Malta: Use... |
249 |
/* pending = pending << t0; */ |
e4ac58afd [MIPS] Rewrite al... |
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
return a0; #endif } /* * IRQs on the Malta board look basically (barring software IRQs which we * don't use at all and all external interrupt sources are combined together * on hardware interrupt 0 (MIPS IRQ 2)) like: * * MIPS IRQ Source * -------- ------ * 0 Software (ignored) * 1 Software (ignored) * 2 Combined hardware interrupt (hw0) * 3 Hardware (ignored) * 4 Hardware (ignored) * 5 Hardware (ignored) * 6 Hardware (ignored) * 7 R4k timer (what we use) * * We handle the IRQ according to _our_ priority which is: * * Highest ---- R4k Timer * Lowest ---- Combined hardware interrupt * * then we just return, if multiple IRQs are pending then we will just take * another exception, big deal. */ |
937a80157 [MIPS] Complete f... |
279 |
asmlinkage void plat_irq_dispatch(void) |
e4ac58afd [MIPS] Rewrite al... |
280 281 282 283 284 285 286 |
{ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; irq = irq_ffs(pending); if (irq == MIPSCPU_INT_I8259A) |
937a80157 [MIPS] Complete f... |
287 |
malta_hw0_irqdispatch(); |
39b8d5254 [MIPS] Add suppor... |
288 289 |
else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) malta_ipi_irqdispatch(); |
48d480b0b [MIPS] Malta: Fix... |
290 |
else if (irq >= 0) |
3b1d4ed53 [MIPS] Don't drag... |
291 |
do_IRQ(MIPS_CPU_IRQ_BASE + irq); |
e4ac58afd [MIPS] Rewrite al... |
292 |
else |
937a80157 [MIPS] Complete f... |
293 |
spurious_interrupt(); |
e4ac58afd [MIPS] Rewrite al... |
294 |
} |
39b8d5254 [MIPS] Add suppor... |
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
#ifdef CONFIG_MIPS_MT_SMP #define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3 #define GIC_MIPS_CPU_IPI_CALL_IRQ 4 #define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */ #define C_RESCHED C_SW0 #define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for resched */ #define C_CALL C_SW1 static int cpu_ipi_resched_irq, cpu_ipi_call_irq; static void ipi_resched_dispatch(void) { do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); } static void ipi_call_dispatch(void) { do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); } static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) { |
184748cc5 sched: Provide sc... |
319 |
scheduler_ipi(); |
39b8d5254 [MIPS] Add suppor... |
320 321 322 323 324 325 326 327 328 329 330 331 |
return IRQ_HANDLED; } static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) { smp_call_function_interrupt(); return IRQ_HANDLED; } static struct irqaction irq_resched = { .handler = ipi_resched_interrupt, |
8b5690f88 MIPS: irq: Remove... |
332 |
.flags = IRQF_PERCPU, |
39b8d5254 [MIPS] Add suppor... |
333 334 335 336 337 |
.name = "IPI_resched" }; static struct irqaction irq_call = { .handler = ipi_call_interrupt, |
8b5690f88 MIPS: irq: Remove... |
338 |
.flags = IRQF_PERCPU, |
39b8d5254 [MIPS] Add suppor... |
339 340 |
.name = "IPI_call" }; |
008ee96f1 [PATCH] MIPS: SMT... |
341 |
#endif /* CONFIG_MIPS_MT_SMP */ |
a214cef9a MIPS: CMP: Extend... |
342 343 344 345 346 |
static int gic_resched_int_base; static int gic_call_int_base; #define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) #define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) |
0365070f0 MIPS: CMP: activa... |
347 348 349 350 351 352 353 354 355 356 |
unsigned int plat_ipi_call_int_xlate(unsigned int cpu) { return GIC_CALL_INT(cpu); } unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) { return GIC_RESCHED_INT(cpu); } |
39b8d5254 [MIPS] Add suppor... |
357 |
|
e01402b11 More AP / SP bits... |
358 359 |
static struct irqaction i8259irq = { .handler = no_action, |
5a4a4ad85 MIPS: Mark cascad... |
360 361 |
.name = "XT-PIC cascade", .flags = IRQF_NO_THREAD, |
e01402b11 More AP / SP bits... |
362 363 364 365 |
}; static struct irqaction corehi_irqaction = { .handler = no_action, |
5a4a4ad85 MIPS: Mark cascad... |
366 367 |
.name = "CoreHi", .flags = IRQF_NO_THREAD, |
e01402b11 More AP / SP bits... |
368 |
}; |
b57c1913b [MIPS] malta_int.... |
369 |
static msc_irqmap_t __initdata msc_irqmap[] = { |
e01402b11 More AP / SP bits... |
370 371 372 |
{MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, }; |
b57c1913b [MIPS] malta_int.... |
373 |
static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap); |
e01402b11 More AP / SP bits... |
374 |
|
b57c1913b [MIPS] malta_int.... |
375 |
static msc_irqmap_t __initdata msc_eicirqmap[] = { |
e01402b11 More AP / SP bits... |
376 377 378 379 380 381 382 383 384 385 386 |
{MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_SMI, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_COREHI, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_CORELO, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0}, {MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} }; |
39b8d5254 [MIPS] Add suppor... |
387 |
|
b57c1913b [MIPS] malta_int.... |
388 |
static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); |
e01402b11 More AP / SP bits... |
389 |
|
39b8d5254 [MIPS] Add suppor... |
390 391 392 393 394 |
/* * This GIC specific tabular array defines the association between External * Interrupts and CPUs/Core Interrupts. The nature of the External * Interrupts is also defined here - polarity/trigger. */ |
7098f7482 MIPS: GIC: Random... |
395 396 |
#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK |
863cb9bad MIPS: GIC: Remove... |
397 |
#define X GIC_UNUSED |
a214cef9a MIPS: CMP: Extend... |
398 |
static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { |
7098f7482 MIPS: GIC: Random... |
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
{ X, X, X, X, 0 }, { X, X, X, X, 0 }, { X, X, X, X, 0 }, { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { X, X, X, X, 0 }, { X, X, X, X, 0 }, { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, { X, X, X, X, 0 }, /* The remainder of this table is initialised by fill_ipi_map */ |
39b8d5254 [MIPS] Add suppor... |
416 |
}; |
863cb9bad MIPS: GIC: Remove... |
417 |
#undef X |
39b8d5254 [MIPS] Add suppor... |
418 419 420 421 |
/* * GCMP needs to be detected before any SMP initialisation */ |
47b178bb6 MIPS: CMP: Move g... |
422 |
int __init gcmp_probe(unsigned long addr, unsigned long size) |
39b8d5254 [MIPS] Add suppor... |
423 |
{ |
05cf20790 MIPS: GCMP: Avoid... |
424 425 426 427 |
if (mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) { gcmp_present = 0; return gcmp_present; } |
39b8d5254 [MIPS] Add suppor... |
428 429 430 431 432 433 434 435 |
if (gcmp_present >= 0) return gcmp_present; _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR; if (gcmp_present) |
7098f7482 MIPS: GIC: Random... |
436 437 |
pr_debug("GCMP present "); |
39b8d5254 [MIPS] Add suppor... |
438 439 |
return gcmp_present; } |
7098f7482 MIPS: GIC: Random... |
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
/* Return the number of IOCU's present */ int __init gcmp_niocu(void) { return gcmp_present ? (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF : 0; } /* Set GCMP region attributes */ void __init gcmp_setregion(int region, unsigned long base, unsigned long mask, int type) { GCMPGCBn(CMxBASE, region) = base; GCMPGCBn(CMxMASK, region) = mask | type; } |
7afed6a6c [MIPS] A few clea... |
455 |
#if defined(CONFIG_MIPS_MT_SMP) |
a214cef9a MIPS: CMP: Extend... |
456 457 458 |
static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) { int intr = baseintr + cpu; |
a214cef9a MIPS: CMP: Extend... |
459 460 461 462 |
gic_intr_map[intr].cpunum = cpu; gic_intr_map[intr].pin = cpupin; gic_intr_map[intr].polarity = GIC_POL_POS; gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; |
7098f7482 MIPS: GIC: Random... |
463 |
gic_intr_map[intr].flags = GIC_FLAG_IPI; |
a214cef9a MIPS: CMP: Extend... |
464 465 |
ipi_map[cpu] |= (1 << (cpupin + 2)); } |
7afed6a6c [MIPS] A few clea... |
466 |
static void __init fill_ipi_map(void) |
39b8d5254 [MIPS] Add suppor... |
467 |
{ |
a214cef9a MIPS: CMP: Extend... |
468 |
int cpu; |
39b8d5254 [MIPS] Add suppor... |
469 |
|
a214cef9a MIPS: CMP: Extend... |
470 471 472 |
for (cpu = 0; cpu < NR_CPUS; cpu++) { fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1); fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2); |
39b8d5254 [MIPS] Add suppor... |
473 474 |
} } |
7afed6a6c [MIPS] A few clea... |
475 |
#endif |
39b8d5254 [MIPS] Add suppor... |
476 |
|
7098f7482 MIPS: GIC: Random... |
477 478 479 |
void __init arch_init_ipiirq(int irq, struct irqaction *action) { setup_irq(irq, action); |
e4ec7989b MIPS: Convert the... |
480 |
irq_set_handler(irq, handle_percpu_irq); |
7098f7482 MIPS: GIC: Random... |
481 |
} |
1da177e4c Linux-2.6.12-rc2 |
482 483 |
void __init arch_init_irq(void) { |
1da177e4c Linux-2.6.12-rc2 |
484 |
init_i8259_irqs(); |
e01402b11 More AP / SP bits... |
485 486 |
if (!cpu_has_veic) |
97dcb82de [MIPS] Define MIP... |
487 |
mips_cpu_irq_init(); |
e01402b11 More AP / SP bits... |
488 |
|
39b8d5254 [MIPS] Add suppor... |
489 490 491 492 |
if (gcmp_present) { GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK; gic_present = 1; } else { |
05cf20790 MIPS: GCMP: Avoid... |
493 494 495 496 497 498 499 500 |
if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) { _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) & MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF; } |
39b8d5254 [MIPS] Add suppor... |
501 502 |
} if (gic_present) |
7098f7482 MIPS: GIC: Random... |
503 504 |
pr_debug("GIC present "); |
39b8d5254 [MIPS] Add suppor... |
505 |
|
af825586c [MIPS] Malta: use... |
506 507 508 |
switch (mips_revision_sconid) { case MIPS_REVISION_SCON_SOCIT: case MIPS_REVISION_SCON_ROCIT: |
d725cf381 [MIPS] MT: Reenab... |
509 |
if (cpu_has_veic) |
f80714966 [MIPS] Malta: fix... |
510 511 512 |
init_msc_irqs(MIPS_MSC01_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); |
d725cf381 [MIPS] MT: Reenab... |
513 |
else |
f80714966 [MIPS] Malta: fix... |
514 515 516 |
init_msc_irqs(MIPS_MSC01_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); |
d725cf381 [MIPS] MT: Reenab... |
517 |
break; |
af825586c [MIPS] Malta: use... |
518 519 |
case MIPS_REVISION_SCON_SOCITSC: case MIPS_REVISION_SCON_SOCITSCP: |
e01402b11 More AP / SP bits... |
520 |
if (cpu_has_veic) |
f80714966 [MIPS] Malta: fix... |
521 522 523 |
init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); |
e01402b11 More AP / SP bits... |
524 |
else |
f80714966 [MIPS] Malta: fix... |
525 526 527 |
init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); |
e01402b11 More AP / SP bits... |
528 529 530 |
} if (cpu_has_veic) { |
49a89efbb [MIPS] Fix "no sp... |
531 532 533 534 |
set_vi_handler(MSC01E_INT_I8259A, malta_hw0_irqdispatch); set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch); setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); |
52b3fc04b [MIPS] Malta: els... |
535 |
} else if (cpu_has_vint) { |
49a89efbb [MIPS] Fix "no sp... |
536 537 |
set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); |
41c594ab6 [MIPS] MT: Improv... |
538 |
#ifdef CONFIG_MIPS_MT_SMTC |
49a89efbb [MIPS] Fix "no sp... |
539 |
setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq, |
41c594ab6 [MIPS] MT: Improv... |
540 |
(0x100 << MIPSCPU_INT_I8259A)); |
49a89efbb [MIPS] Fix "no sp... |
541 |
setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, |
41c594ab6 [MIPS] MT: Improv... |
542 |
&corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI)); |
c3a005f4b [MIPS] SMTC: Safe... |
543 544 545 546 547 548 549 550 551 552 553 554 |
/* * Temporary hack to ensure that the subsidiary device * interrupts coing in via the i8259A, but associated * with low IRQ numbers, will restore the Status.IM * value associated with the i8259A. */ { int i; for (i = 0; i < 16; i++) irq_hwmask[i] = (0x100 << MIPSCPU_INT_I8259A); } |
41c594ab6 [MIPS] MT: Improv... |
555 |
#else /* Not SMTC */ |
49a89efbb [MIPS] Fix "no sp... |
556 |
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); |
f80714966 [MIPS] Malta: fix... |
557 558 |
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); |
41c594ab6 [MIPS] MT: Improv... |
559 |
#endif /* CONFIG_MIPS_MT_SMTC */ |
52b3fc04b [MIPS] Malta: els... |
560 |
} else { |
49a89efbb [MIPS] Fix "no sp... |
561 |
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); |
f80714966 [MIPS] Malta: fix... |
562 563 |
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); |
e01402b11 More AP / SP bits... |
564 |
} |
39b8d5254 [MIPS] Add suppor... |
565 |
|
39b8d5254 [MIPS] Add suppor... |
566 567 568 |
if (gic_present) { /* FIXME */ int i; |
7098f7482 MIPS: GIC: Random... |
569 |
#if defined(CONFIG_MIPS_MT_SMP) |
a214cef9a MIPS: CMP: Extend... |
570 571 |
gic_call_int_base = GIC_NUM_INTRS - NR_CPUS; gic_resched_int_base = gic_call_int_base - NR_CPUS; |
39b8d5254 [MIPS] Add suppor... |
572 |
fill_ipi_map(); |
7098f7482 MIPS: GIC: Random... |
573 574 575 |
#endif gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); |
39b8d5254 [MIPS] Add suppor... |
576 577 578 579 580 581 582 583 |
if (!gcmp_present) { /* Enable the GIC */ i = REG(_msc01_biu_base, MSC01_SC_CFG); REG(_msc01_biu_base, MSC01_SC_CFG) = (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); pr_debug("GIC Enabled "); } |
7098f7482 MIPS: GIC: Random... |
584 |
#if defined(CONFIG_MIPS_MT_SMP) |
39b8d5254 [MIPS] Add suppor... |
585 586 587 588 589 590 591 592 593 594 595 596 597 598 |
/* set up ipi interrupts */ if (cpu_has_vint) { set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch); set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch); } /* Argh.. this really needs sorting out.. */ printk("CPU%d: status register was %08x ", smp_processor_id(), read_c0_status()); write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4); printk("CPU%d: status register now %08x ", smp_processor_id(), read_c0_status()); write_c0_status(0x1100dc00); printk("CPU%d: status register frc %08x ", smp_processor_id(), read_c0_status()); |
a214cef9a MIPS: CMP: Extend... |
599 |
for (i = 0; i < NR_CPUS; i++) { |
7098f7482 MIPS: GIC: Random... |
600 601 602 603 |
arch_init_ipiirq(MIPS_GIC_IRQ_BASE + GIC_RESCHED_INT(i), &irq_resched); arch_init_ipiirq(MIPS_GIC_IRQ_BASE + GIC_CALL_INT(i), &irq_call); |
39b8d5254 [MIPS] Add suppor... |
604 |
} |
7098f7482 MIPS: GIC: Random... |
605 |
#endif |
39b8d5254 [MIPS] Add suppor... |
606 |
} else { |
7098f7482 MIPS: GIC: Random... |
607 |
#if defined(CONFIG_MIPS_MT_SMP) |
39b8d5254 [MIPS] Add suppor... |
608 609 610 611 612 613 614 615 616 617 618 619 620 621 |
/* set up ipi interrupts */ if (cpu_has_veic) { set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch); set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch); cpu_ipi_resched_irq = MSC01E_INT_SW0; cpu_ipi_call_irq = MSC01E_INT_SW1; } else { if (cpu_has_vint) { set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); } cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; } |
7098f7482 MIPS: GIC: Random... |
622 623 |
arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); |
39b8d5254 [MIPS] Add suppor... |
624 |
#endif |
7098f7482 MIPS: GIC: Random... |
625 |
} |
39b8d5254 [MIPS] Add suppor... |
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 |
} void malta_be_init(void) { if (gcmp_present) { /* Could change CM error mask register */ } } static char *tr[8] = { "mem", "gcr", "gic", "mmio", "0x04", "0x05", "0x06", "0x07" }; static char *mcmd[32] = { [0x00] = "0x00", [0x01] = "Legacy Write", [0x02] = "Legacy Read", [0x03] = "0x03", [0x04] = "0x04", [0x05] = "0x05", [0x06] = "0x06", [0x07] = "0x07", [0x08] = "Coherent Read Own", [0x09] = "Coherent Read Share", [0x0a] = "Coherent Read Discard", [0x0b] = "Coherent Ready Share Always", [0x0c] = "Coherent Upgrade", [0x0d] = "Coherent Writeback", [0x0e] = "0x0e", [0x0f] = "0x0f", [0x10] = "Coherent Copyback", [0x11] = "Coherent Copyback Invalidate", [0x12] = "Coherent Invalidate", [0x13] = "Coherent Write Invalidate", [0x14] = "Coherent Completion Sync", [0x15] = "0x15", [0x16] = "0x16", [0x17] = "0x17", [0x18] = "0x18", [0x19] = "0x19", [0x1a] = "0x1a", [0x1b] = "0x1b", [0x1c] = "0x1c", [0x1d] = "0x1d", [0x1e] = "0x1e", [0x1f] = "0x1f" }; static char *core[8] = { "Invalid/OK", "Invalid/Data", "Shared/OK", "Shared/Data", "Modified/OK", "Modified/Data", "Exclusive/OK", "Exclusive/Data" }; static char *causes[32] = { "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR", "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07", "0x08", "0x09", "0x0a", "0x0b", "0x0c", "0x0d", "0x0e", "0x0f", "0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "INTVN_WR_ERR", "INTVN_RD_ERR", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f" }; int malta_be_handler(struct pt_regs *regs, int is_fixup) { /* This duplicates the handling in do_be which seems wrong */ int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL; if (gcmp_present) { unsigned long cm_error = GCMPGCB(GCMEC); unsigned long cm_addr = GCMPGCB(GCMEA); unsigned long cm_other = GCMPGCB(GCMEO); unsigned long cause, ocause; char buf[256]; cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK); if (cause != 0) { cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF; if (cause < 16) { unsigned long cca_bits = (cm_error >> 15) & 7; unsigned long tr_bits = (cm_error >> 12) & 7; unsigned long mcmd_bits = (cm_error >> 7) & 0x1f; unsigned long stag_bits = (cm_error >> 3) & 15; unsigned long sport_bits = (cm_error >> 0) & 7; snprintf(buf, sizeof(buf), "CCA=%lu TR=%s MCmd=%s STag=%lu " "SPort=%lu ", cca_bits, tr[tr_bits], mcmd[mcmd_bits], stag_bits, sport_bits); } else { /* glob state & sresp together */ unsigned long c3_bits = (cm_error >> 18) & 7; unsigned long c2_bits = (cm_error >> 15) & 7; unsigned long c1_bits = (cm_error >> 12) & 7; unsigned long c0_bits = (cm_error >> 9) & 7; unsigned long sc_bit = (cm_error >> 8) & 1; unsigned long mcmd_bits = (cm_error >> 3) & 0x1f; unsigned long sport_bits = (cm_error >> 0) & 7; snprintf(buf, sizeof(buf), "C3=%s C2=%s C1=%s C0=%s SC=%s " "MCmd=%s SPort=%lu ", core[c3_bits], core[c2_bits], core[c1_bits], core[c0_bits], sc_bit ? "True" : "False", mcmd[mcmd_bits], sport_bits); } ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >> GCMP_GCB_GMEO_ERROR_2ND_SHF; printk("CM_ERROR=%08lx %s <%s> ", cm_error, causes[cause], buf); printk("CM_ADDR =%08lx ", cm_addr); printk("CM_OTHER=%08lx %s ", cm_other, causes[ocause]); /* reprime cause register */ GCMPGCB(GCMEC) = 0; } } return retval; |
1da177e4c Linux-2.6.12-rc2 |
758 |
} |