diff options
author | Andrew Bresticker <abrestic@chromium.org> | 2014-09-18 17:47:24 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:44:56 -0500 |
commit | 18743d2781d01d34d132f952a2e16353ccb4c3de (patch) | |
tree | 42df699518d3b44c08ef49fa3d893dc38d8ddc5e | |
parent | c49581a4dfaade3a483f3db85581a2cdb6bb85a0 (diff) |
irqchip: mips-gic: Stop using per-platform mapping tables
Now that the GIC properly uses IRQ domains, kill off the per-platform
routing tables that were used to make the GIC appear transparent.
This includes:
- removing the mapping tables and the support for applying them,
- moving GIC IPI support to the GIC driver,
- properly routing the i8259 through the GIC on Malta, and
- updating IRQ assignments on SEAD-3 when the GIC is present.
Platforms no longer will pass an interrupt mapping table to gic_init.
Instead, they will pass the CPU interrupt vector (2 - 7) that they
expect the GIC to route interrupts to. Note that in EIC mode this
value is ignored and all GIC interrupts are routed to EIC vector 1.
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jeffrey Deans <jeffrey.deans@imgtec.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Jonas Gorski <jogo@openwrt.org>
Cc: John Crispin <blogic@openwrt.org>
Cc: David Daney <ddaney.cavm@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/7816/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/include/asm/gic.h | 35 | ||||
-rw-r--r-- | arch/mips/include/asm/mips-boards/maltaint.h | 14 | ||||
-rw-r--r-- | arch/mips/include/asm/mips-boards/sead3int.h | 13 | ||||
-rw-r--r-- | arch/mips/kernel/cevt-gic.c | 3 | ||||
-rw-r--r-- | arch/mips/mti-malta/malta-int.c | 189 | ||||
-rw-r--r-- | arch/mips/mti-sead3/sead3-ehci.c | 8 | ||||
-rw-r--r-- | arch/mips/mti-sead3/sead3-int.c | 28 | ||||
-rw-r--r-- | arch/mips/mti-sead3/sead3-net.c | 14 | ||||
-rw-r--r-- | arch/mips/mti-sead3/sead3-platform.c | 18 | ||||
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 201 |
10 files changed, 198 insertions, 325 deletions
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index efcf4dec1229..cfbf907ebfa5 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h | |||
@@ -316,31 +316,6 @@ | |||
316 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \ | 316 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \ |
317 | GIC_SH_MAP_TO_VPE_REG_BIT(vpe)) | 317 | GIC_SH_MAP_TO_VPE_REG_BIT(vpe)) |
318 | 318 | ||
319 | /* | ||
320 | * Interrupt Meta-data specification. The ipiflag helps | ||
321 | * in building ipi_map. | ||
322 | */ | ||
323 | struct gic_intr_map { | ||
324 | unsigned int cpunum; /* Directed to this CPU */ | ||
325 | #define GIC_UNUSED 0xdead /* Dummy data */ | ||
326 | unsigned int pin; /* Directed to this Pin */ | ||
327 | unsigned int polarity; /* Polarity : +/- */ | ||
328 | unsigned int trigtype; /* Trigger : Edge/Levl */ | ||
329 | unsigned int flags; /* Misc flags */ | ||
330 | #define GIC_FLAG_TRANSPARENT 0x01 | ||
331 | }; | ||
332 | |||
333 | /* | ||
334 | * This is only used in EIC mode. This helps to figure out which | ||
335 | * shared interrupts we need to process when we get a vector interrupt. | ||
336 | */ | ||
337 | #define GIC_MAX_SHARED_INTR 0x5 | ||
338 | struct gic_shared_intr_map { | ||
339 | unsigned int num_shared_intr; | ||
340 | unsigned int intr_list[GIC_MAX_SHARED_INTR]; | ||
341 | unsigned int local_intr_mask; | ||
342 | }; | ||
343 | |||
344 | /* GIC nomenclature for Core Interrupt Pins. */ | 319 | /* GIC nomenclature for Core Interrupt Pins. */ |
345 | #define GIC_CPU_INT0 0 /* Core Interrupt 2 */ | 320 | #define GIC_CPU_INT0 0 /* Core Interrupt 2 */ |
346 | #define GIC_CPU_INT1 1 /* . */ | 321 | #define GIC_CPU_INT1 1 /* . */ |
@@ -349,6 +324,9 @@ struct gic_shared_intr_map { | |||
349 | #define GIC_CPU_INT4 4 /* . */ | 324 | #define GIC_CPU_INT4 4 /* . */ |
350 | #define GIC_CPU_INT5 5 /* Core Interrupt 7 */ | 325 | #define GIC_CPU_INT5 5 /* Core Interrupt 7 */ |
351 | 326 | ||
327 | /* Add 2 to convert GIC CPU pin to core interrupt */ | ||
328 | #define GIC_CPU_PIN_OFFSET 2 | ||
329 | |||
352 | /* Local GIC interrupts. */ | 330 | /* Local GIC interrupts. */ |
353 | #define GIC_INT_TMR (GIC_CPU_INT5) | 331 | #define GIC_INT_TMR (GIC_CPU_INT5) |
354 | #define GIC_INT_PERFCTR (GIC_CPU_INT5) | 332 | #define GIC_INT_PERFCTR (GIC_CPU_INT5) |
@@ -365,13 +343,12 @@ struct gic_shared_intr_map { | |||
365 | extern unsigned int gic_present; | 343 | extern unsigned int gic_present; |
366 | extern unsigned int gic_frequency; | 344 | extern unsigned int gic_frequency; |
367 | extern unsigned long _gic_base; | 345 | extern unsigned long _gic_base; |
368 | extern unsigned int gic_irq_base; | ||
369 | extern unsigned int gic_irq_flags[]; | 346 | extern unsigned int gic_irq_flags[]; |
370 | extern struct gic_shared_intr_map gic_shared_intr_map[]; | 347 | extern unsigned int gic_cpu_pin; |
371 | 348 | ||
372 | extern void gic_init(unsigned long gic_base_addr, | 349 | extern void gic_init(unsigned long gic_base_addr, |
373 | unsigned long gic_addrspace_size, struct gic_intr_map *intrmap, | 350 | unsigned long gic_addrspace_size, unsigned int cpu_vec, |
374 | unsigned int intrmap_size, unsigned int irqbase); | 351 | unsigned int irqbase); |
375 | extern void gic_clocksource_init(unsigned int); | 352 | extern void gic_clocksource_init(unsigned int); |
376 | extern unsigned int gic_compare_int (void); | 353 | extern unsigned int gic_compare_int (void); |
377 | extern cycle_t gic_read_count(void); | 354 | extern cycle_t gic_read_count(void); |
diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h index d741628e3397..bdd6f392f160 100644 --- a/arch/mips/include/asm/mips-boards/maltaint.h +++ b/arch/mips/include/asm/mips-boards/maltaint.h | |||
@@ -20,11 +20,10 @@ | |||
20 | #define MIPSCPU_INT_SW1 1 | 20 | #define MIPSCPU_INT_SW1 1 |
21 | #define MIPSCPU_INT_MB0 2 | 21 | #define MIPSCPU_INT_MB0 2 |
22 | #define MIPSCPU_INT_I8259A MIPSCPU_INT_MB0 | 22 | #define MIPSCPU_INT_I8259A MIPSCPU_INT_MB0 |
23 | #define MIPSCPU_INT_GIC MIPSCPU_INT_MB0 /* GIC chained interrupt */ | ||
23 | #define MIPSCPU_INT_MB1 3 | 24 | #define MIPSCPU_INT_MB1 3 |
24 | #define MIPSCPU_INT_SMI MIPSCPU_INT_MB1 | 25 | #define MIPSCPU_INT_SMI MIPSCPU_INT_MB1 |
25 | #define MIPSCPU_INT_IPI0 MIPSCPU_INT_MB1 /* GIC IPI */ | ||
26 | #define MIPSCPU_INT_MB2 4 | 26 | #define MIPSCPU_INT_MB2 4 |
27 | #define MIPSCPU_INT_IPI1 MIPSCPU_INT_MB2 /* GIC IPI */ | ||
28 | #define MIPSCPU_INT_MB3 5 | 27 | #define MIPSCPU_INT_MB3 5 |
29 | #define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3 | 28 | #define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3 |
30 | #define MIPSCPU_INT_MB4 6 | 29 | #define MIPSCPU_INT_MB4 6 |
@@ -61,14 +60,7 @@ | |||
61 | #define MSC01E_INT_PERFCTR 10 | 60 | #define MSC01E_INT_PERFCTR 10 |
62 | #define MSC01E_INT_CPUCTR 11 | 61 | #define MSC01E_INT_CPUCTR 11 |
63 | 62 | ||
64 | /* External Interrupts used for IPI */ | 63 | /* GIC external interrupts */ |
65 | #define GIC_IPI_EXT_INTR_RESCHED_VPE0 16 | 64 | #define GIC_INT_I8259A 3 |
66 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17 | ||
67 | #define GIC_IPI_EXT_INTR_RESCHED_VPE1 18 | ||
68 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE1 19 | ||
69 | #define GIC_IPI_EXT_INTR_RESCHED_VPE2 20 | ||
70 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE2 21 | ||
71 | #define GIC_IPI_EXT_INTR_RESCHED_VPE3 22 | ||
72 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23 | ||
73 | 65 | ||
74 | #endif /* !(_MIPS_MALTAINT_H) */ | 66 | #endif /* !(_MIPS_MALTAINT_H) */ |
diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h index 11ebec94f807..a2e0095440fe 100644 --- a/arch/mips/include/asm/mips-boards/sead3int.h +++ b/arch/mips/include/asm/mips-boards/sead3int.h | |||
@@ -14,4 +14,17 @@ | |||
14 | #define GIC_BASE_ADDR 0x1b1c0000 | 14 | #define GIC_BASE_ADDR 0x1b1c0000 |
15 | #define GIC_ADDRSPACE_SZ (128 * 1024) | 15 | #define GIC_ADDRSPACE_SZ (128 * 1024) |
16 | 16 | ||
17 | /* CPU interrupt offsets */ | ||
18 | #define CPU_INT_GIC 2 | ||
19 | #define CPU_INT_EHCI 2 | ||
20 | #define CPU_INT_UART0 4 | ||
21 | #define CPU_INT_UART1 4 | ||
22 | #define CPU_INT_NET 6 | ||
23 | |||
24 | /* GIC interrupt offsets */ | ||
25 | #define GIC_INT_NET 0 | ||
26 | #define GIC_INT_UART1 2 | ||
27 | #define GIC_INT_UART0 3 | ||
28 | #define GIC_INT_EHCI 5 | ||
29 | |||
17 | #endif /* !(_MIPS_SEAD3INT_H) */ | 30 | #endif /* !(_MIPS_SEAD3INT_H) */ |
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c index 6093716980b9..a90bd4c81c7d 100644 --- a/arch/mips/kernel/cevt-gic.c +++ b/arch/mips/kernel/cevt-gic.c | |||
@@ -91,7 +91,8 @@ int gic_clockevent_init(void) | |||
91 | 91 | ||
92 | clockevents_register_device(cd); | 92 | clockevents_register_device(cd); |
93 | 93 | ||
94 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP), 0x80000002); | 94 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP), |
95 | GIC_MAP_TO_PIN_MSK | gic_cpu_pin); | ||
95 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), GIC_VPE_SMASK_CMP_MSK); | 96 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), GIC_VPE_SMASK_CMP_MSK); |
96 | 97 | ||
97 | if (gic_timer_irq_installed) | 98 | if (gic_timer_irq_installed) |
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index e56563c6f89e..3b3bc1d9ebf9 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c | |||
@@ -38,14 +38,9 @@ | |||
38 | #include <asm/rtlx.h> | 38 | #include <asm/rtlx.h> |
39 | 39 | ||
40 | static unsigned long _msc01_biu_base; | 40 | static unsigned long _msc01_biu_base; |
41 | static unsigned int ipi_map[NR_CPUS]; | ||
42 | 41 | ||
43 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); | 42 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); |
44 | 43 | ||
45 | #ifdef CONFIG_MIPS_GIC_IPI | ||
46 | DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS); | ||
47 | #endif | ||
48 | |||
49 | static inline int mips_pcibios_iack(void) | 44 | static inline int mips_pcibios_iack(void) |
50 | { | 45 | { |
51 | int irq; | 46 | int irq; |
@@ -127,24 +122,10 @@ static void malta_hw0_irqdispatch(void) | |||
127 | #endif | 122 | #endif |
128 | } | 123 | } |
129 | 124 | ||
130 | static void malta_ipi_irqdispatch(void) | 125 | static irqreturn_t i8259_handler(int irq, void *dev_id) |
131 | { | 126 | { |
132 | #ifdef CONFIG_MIPS_GIC_IPI | 127 | malta_hw0_irqdispatch(); |
133 | unsigned long irq; | 128 | return IRQ_HANDLED; |
134 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); | ||
135 | |||
136 | gic_get_int_mask(pending, ipi_ints); | ||
137 | |||
138 | irq = find_first_bit(pending, GIC_NUM_INTRS); | ||
139 | |||
140 | while (irq < GIC_NUM_INTRS) { | ||
141 | do_IRQ(MIPS_GIC_IRQ_BASE + irq); | ||
142 | |||
143 | irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1); | ||
144 | } | ||
145 | #endif | ||
146 | if (gic_compare_int()) | ||
147 | do_IRQ(MIPS_GIC_IRQ_BASE); | ||
148 | } | 129 | } |
149 | 130 | ||
150 | static void corehi_irqdispatch(void) | 131 | static void corehi_irqdispatch(void) |
@@ -203,6 +184,12 @@ static void corehi_irqdispatch(void) | |||
203 | die("CoreHi interrupt", regs); | 184 | die("CoreHi interrupt", regs); |
204 | } | 185 | } |
205 | 186 | ||
187 | static irqreturn_t corehi_handler(int irq, void *dev_id) | ||
188 | { | ||
189 | corehi_irqdispatch(); | ||
190 | return IRQ_HANDLED; | ||
191 | } | ||
192 | |||
206 | static inline int clz(unsigned long x) | 193 | static inline int clz(unsigned long x) |
207 | { | 194 | { |
208 | __asm__( | 195 | __asm__( |
@@ -286,10 +273,9 @@ asmlinkage void plat_irq_dispatch(void) | |||
286 | 273 | ||
287 | irq = irq_ffs(pending); | 274 | irq = irq_ffs(pending); |
288 | 275 | ||
289 | if (irq == MIPSCPU_INT_I8259A) | 276 | /* HACK: GIC doesn't properly dispatch local interrupts yet */ |
290 | malta_hw0_irqdispatch(); | 277 | if (gic_present && irq == MIPSCPU_INT_GIC && gic_compare_int()) |
291 | else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) | 278 | do_IRQ(MIPS_GIC_IRQ_BASE); |
292 | malta_ipi_irqdispatch(); | ||
293 | else | 279 | else |
294 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | 280 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); |
295 | } | 281 | } |
@@ -312,13 +298,6 @@ static void ipi_call_dispatch(void) | |||
312 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); | 298 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); |
313 | } | 299 | } |
314 | 300 | ||
315 | #endif /* CONFIG_MIPS_MT_SMP */ | ||
316 | |||
317 | #ifdef CONFIG_MIPS_GIC_IPI | ||
318 | |||
319 | #define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3 | ||
320 | #define GIC_MIPS_CPU_IPI_CALL_IRQ 4 | ||
321 | |||
322 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) | 301 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) |
323 | { | 302 | { |
324 | #ifdef CONFIG_MIPS_VPE_APSP_API_CMP | 303 | #ifdef CONFIG_MIPS_VPE_APSP_API_CMP |
@@ -349,31 +328,16 @@ static struct irqaction irq_call = { | |||
349 | .flags = IRQF_PERCPU, | 328 | .flags = IRQF_PERCPU, |
350 | .name = "IPI_call" | 329 | .name = "IPI_call" |
351 | }; | 330 | }; |
352 | #endif /* CONFIG_MIPS_GIC_IPI */ | 331 | #endif /* CONFIG_MIPS_MT_SMP */ |
353 | |||
354 | static int gic_resched_int_base; | ||
355 | static int gic_call_int_base; | ||
356 | #define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) | ||
357 | #define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) | ||
358 | |||
359 | unsigned int plat_ipi_call_int_xlate(unsigned int cpu) | ||
360 | { | ||
361 | return GIC_CALL_INT(cpu); | ||
362 | } | ||
363 | |||
364 | unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) | ||
365 | { | ||
366 | return GIC_RESCHED_INT(cpu); | ||
367 | } | ||
368 | 332 | ||
369 | static struct irqaction i8259irq = { | 333 | static struct irqaction i8259irq = { |
370 | .handler = no_action, | 334 | .handler = i8259_handler, |
371 | .name = "XT-PIC cascade", | 335 | .name = "XT-PIC cascade", |
372 | .flags = IRQF_NO_THREAD, | 336 | .flags = IRQF_NO_THREAD, |
373 | }; | 337 | }; |
374 | 338 | ||
375 | static struct irqaction corehi_irqaction = { | 339 | static struct irqaction corehi_irqaction = { |
376 | .handler = no_action, | 340 | .handler = corehi_handler, |
377 | .name = "CoreHi", | 341 | .name = "CoreHi", |
378 | .flags = IRQF_NO_THREAD, | 342 | .flags = IRQF_NO_THREAD, |
379 | }; | 343 | }; |
@@ -399,60 +363,6 @@ static msc_irqmap_t msc_eicirqmap[] __initdata = { | |||
399 | 363 | ||
400 | static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); | 364 | static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); |
401 | 365 | ||
402 | /* | ||
403 | * This GIC specific tabular array defines the association between External | ||
404 | * Interrupts and CPUs/Core Interrupts. The nature of the External | ||
405 | * Interrupts is also defined here - polarity/trigger. | ||
406 | */ | ||
407 | |||
408 | #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK | ||
409 | #define X GIC_UNUSED | ||
410 | |||
411 | static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { | ||
412 | { X, X, X, X, 0 }, | ||
413 | { X, X, X, X, 0 }, | ||
414 | { X, X, X, X, 0 }, | ||
415 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
416 | { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
417 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
418 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
419 | { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
420 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
421 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
422 | { X, X, X, X, 0 }, | ||
423 | { X, X, X, X, 0 }, | ||
424 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
425 | { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
426 | { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
427 | { X, X, X, X, 0 }, | ||
428 | /* The remainder of this table is initialised by fill_ipi_map */ | ||
429 | }; | ||
430 | #undef X | ||
431 | |||
432 | #ifdef CONFIG_MIPS_GIC_IPI | ||
433 | static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) | ||
434 | { | ||
435 | int intr = baseintr + cpu; | ||
436 | gic_intr_map[intr].cpunum = cpu; | ||
437 | gic_intr_map[intr].pin = cpupin; | ||
438 | gic_intr_map[intr].polarity = GIC_POL_POS; | ||
439 | gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; | ||
440 | gic_intr_map[intr].flags = 0; | ||
441 | ipi_map[cpu] |= (1 << (cpupin + 2)); | ||
442 | bitmap_set(ipi_ints, intr, 1); | ||
443 | } | ||
444 | |||
445 | static void __init fill_ipi_map(void) | ||
446 | { | ||
447 | int cpu; | ||
448 | |||
449 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { | ||
450 | fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1); | ||
451 | fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2); | ||
452 | } | ||
453 | } | ||
454 | #endif | ||
455 | |||
456 | void __init arch_init_ipiirq(int irq, struct irqaction *action) | 366 | void __init arch_init_ipiirq(int irq, struct irqaction *action) |
457 | { | 367 | { |
458 | setup_irq(irq, action); | 368 | setup_irq(irq, action); |
@@ -461,6 +371,8 @@ void __init arch_init_ipiirq(int irq, struct irqaction *action) | |||
461 | 371 | ||
462 | void __init arch_init_irq(void) | 372 | void __init arch_init_irq(void) |
463 | { | 373 | { |
374 | int corehi_irq, i8259_irq; | ||
375 | |||
464 | init_i8259_irqs(); | 376 | init_i8259_irqs(); |
465 | 377 | ||
466 | if (!cpu_has_veic) | 378 | if (!cpu_has_veic) |
@@ -507,34 +419,11 @@ void __init arch_init_irq(void) | |||
507 | msc_nr_irqs); | 419 | msc_nr_irqs); |
508 | } | 420 | } |
509 | 421 | ||
510 | if (cpu_has_veic) { | ||
511 | set_vi_handler(MSC01E_INT_I8259A, malta_hw0_irqdispatch); | ||
512 | set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch); | ||
513 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); | ||
514 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); | ||
515 | } else if (cpu_has_vint) { | ||
516 | set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); | ||
517 | set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); | ||
518 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
519 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, | ||
520 | &corehi_irqaction); | ||
521 | } else { | ||
522 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
523 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, | ||
524 | &corehi_irqaction); | ||
525 | } | ||
526 | |||
527 | if (gic_present) { | 422 | if (gic_present) { |
528 | /* FIXME */ | ||
529 | int i; | 423 | int i; |
530 | #if defined(CONFIG_MIPS_GIC_IPI) | 424 | |
531 | gic_call_int_base = GIC_NUM_INTRS - | 425 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, MIPSCPU_INT_GIC, |
532 | (NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids; | 426 | MIPS_GIC_IRQ_BASE); |
533 | gic_resched_int_base = gic_call_int_base - nr_cpu_ids; | ||
534 | fill_ipi_map(); | ||
535 | #endif | ||
536 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, | ||
537 | ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); | ||
538 | if (!mips_cm_present()) { | 427 | if (!mips_cm_present()) { |
539 | /* Enable the GIC */ | 428 | /* Enable the GIC */ |
540 | i = REG(_msc01_biu_base, MSC01_SC_CFG); | 429 | i = REG(_msc01_biu_base, MSC01_SC_CFG); |
@@ -542,28 +431,8 @@ void __init arch_init_irq(void) | |||
542 | (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); | 431 | (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); |
543 | pr_debug("GIC Enabled\n"); | 432 | pr_debug("GIC Enabled\n"); |
544 | } | 433 | } |
545 | #if defined(CONFIG_MIPS_GIC_IPI) | 434 | i8259_irq = MIPS_GIC_IRQ_BASE + GIC_INT_I8259A; |
546 | /* set up ipi interrupts */ | 435 | corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; |
547 | if (cpu_has_vint) { | ||
548 | set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch); | ||
549 | set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch); | ||
550 | } | ||
551 | /* Argh.. this really needs sorting out.. */ | ||
552 | pr_info("CPU%d: status register was %08x\n", | ||
553 | smp_processor_id(), read_c0_status()); | ||
554 | write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4); | ||
555 | pr_info("CPU%d: status register now %08x\n", | ||
556 | smp_processor_id(), read_c0_status()); | ||
557 | write_c0_status(0x1100dc00); | ||
558 | pr_info("CPU%d: status register frc %08x\n", | ||
559 | smp_processor_id(), read_c0_status()); | ||
560 | for (i = 0; i < nr_cpu_ids; i++) { | ||
561 | arch_init_ipiirq(MIPS_GIC_IRQ_BASE + | ||
562 | GIC_RESCHED_INT(i), &irq_resched); | ||
563 | arch_init_ipiirq(MIPS_GIC_IRQ_BASE + | ||
564 | GIC_CALL_INT(i), &irq_call); | ||
565 | } | ||
566 | #endif | ||
567 | } else { | 436 | } else { |
568 | #if defined(CONFIG_MIPS_MT_SMP) | 437 | #if defined(CONFIG_MIPS_MT_SMP) |
569 | /* set up ipi interrupts */ | 438 | /* set up ipi interrupts */ |
@@ -587,7 +456,21 @@ void __init arch_init_irq(void) | |||
587 | arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); | 456 | arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); |
588 | arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); | 457 | arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); |
589 | #endif | 458 | #endif |
459 | if (cpu_has_veic) { | ||
460 | set_vi_handler(MSC01E_INT_I8259A, | ||
461 | malta_hw0_irqdispatch); | ||
462 | set_vi_handler(MSC01E_INT_COREHI, | ||
463 | corehi_irqdispatch); | ||
464 | i8259_irq = MSC01E_INT_BASE + MSC01E_INT_I8259A; | ||
465 | corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI; | ||
466 | } else { | ||
467 | i8259_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_I8259A; | ||
468 | corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; | ||
469 | } | ||
590 | } | 470 | } |
471 | |||
472 | setup_irq(i8259_irq, &i8259irq); | ||
473 | setup_irq(corehi_irq, &corehi_irqaction); | ||
591 | } | 474 | } |
592 | 475 | ||
593 | void malta_be_init(void) | 476 | void malta_be_init(void) |
diff --git a/arch/mips/mti-sead3/sead3-ehci.c b/arch/mips/mti-sead3/sead3-ehci.c index 772fc056a92d..4ddaa0fd5804 100644 --- a/arch/mips/mti-sead3/sead3-ehci.c +++ b/arch/mips/mti-sead3/sead3-ehci.c | |||
@@ -10,6 +10,9 @@ | |||
10 | #include <linux/dma-mapping.h> | 10 | #include <linux/dma-mapping.h> |
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | 12 | ||
13 | #include <asm/gic.h> | ||
14 | #include <asm/mips-boards/sead3int.h> | ||
15 | |||
13 | struct resource ehci_resources[] = { | 16 | struct resource ehci_resources[] = { |
14 | { | 17 | { |
15 | .start = 0x1b200000, | 18 | .start = 0x1b200000, |
@@ -17,7 +20,6 @@ struct resource ehci_resources[] = { | |||
17 | .flags = IORESOURCE_MEM | 20 | .flags = IORESOURCE_MEM |
18 | }, | 21 | }, |
19 | { | 22 | { |
20 | .start = MIPS_CPU_IRQ_BASE + 2, | ||
21 | .flags = IORESOURCE_IRQ | 23 | .flags = IORESOURCE_IRQ |
22 | } | 24 | } |
23 | }; | 25 | }; |
@@ -37,6 +39,10 @@ static struct platform_device ehci_device = { | |||
37 | 39 | ||
38 | static int __init ehci_init(void) | 40 | static int __init ehci_init(void) |
39 | { | 41 | { |
42 | if (gic_present) | ||
43 | ehci_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_EHCI; | ||
44 | else | ||
45 | ehci_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_EHCI; | ||
40 | return platform_device_register(&ehci_device); | 46 | return platform_device_register(&ehci_device); |
41 | } | 47 | } |
42 | 48 | ||
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c index 8f3634281ed9..cb06cd954a13 100644 --- a/arch/mips/mti-sead3/sead3-int.c +++ b/arch/mips/mti-sead3/sead3-int.c | |||
@@ -22,30 +22,6 @@ | |||
22 | 22 | ||
23 | static unsigned long sead3_config_reg; | 23 | static unsigned long sead3_config_reg; |
24 | 24 | ||
25 | /* | ||
26 | * This table defines the setup for each external GIC interrupt. It is | ||
27 | * indexed by interrupt number. | ||
28 | */ | ||
29 | #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK | ||
30 | static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { | ||
31 | { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
32 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
33 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
34 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
35 | { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
36 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
37 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
38 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
39 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
40 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
41 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
42 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
43 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
44 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
45 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
46 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
47 | }; | ||
48 | |||
49 | asmlinkage void plat_irq_dispatch(void) | 25 | asmlinkage void plat_irq_dispatch(void) |
50 | { | 26 | { |
51 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | 27 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; |
@@ -81,7 +57,7 @@ void __init arch_init_irq(void) | |||
81 | (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off"); | 57 | (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off"); |
82 | 58 | ||
83 | if (gic_present) | 59 | if (gic_present) |
84 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, | 60 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, CPU_INT_GIC, |
85 | ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); | 61 | MIPS_GIC_IRQ_BASE); |
86 | } | 62 | } |
87 | 63 | ||
diff --git a/arch/mips/mti-sead3/sead3-net.c b/arch/mips/mti-sead3/sead3-net.c index dd11e7eb771c..c9f728a41bdb 100644 --- a/arch/mips/mti-sead3/sead3-net.c +++ b/arch/mips/mti-sead3/sead3-net.c | |||
@@ -10,6 +10,9 @@ | |||
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/smsc911x.h> | 11 | #include <linux/smsc911x.h> |
12 | 12 | ||
13 | #include <asm/gic.h> | ||
14 | #include <asm/mips-boards/sead3int.h> | ||
15 | |||
13 | static struct smsc911x_platform_config sead3_smsc911x_data = { | 16 | static struct smsc911x_platform_config sead3_smsc911x_data = { |
14 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, | 17 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, |
15 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | 18 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, |
@@ -17,14 +20,13 @@ static struct smsc911x_platform_config sead3_smsc911x_data = { | |||
17 | .phy_interface = PHY_INTERFACE_MODE_MII, | 20 | .phy_interface = PHY_INTERFACE_MODE_MII, |
18 | }; | 21 | }; |
19 | 22 | ||
20 | struct resource sead3_net_resourcess[] = { | 23 | struct resource sead3_net_resources[] = { |
21 | { | 24 | { |
22 | .start = 0x1f010000, | 25 | .start = 0x1f010000, |
23 | .end = 0x1f01ffff, | 26 | .end = 0x1f01ffff, |
24 | .flags = IORESOURCE_MEM | 27 | .flags = IORESOURCE_MEM |
25 | }, | 28 | }, |
26 | { | 29 | { |
27 | .start = MIPS_CPU_IRQ_BASE + 6, | ||
28 | .flags = IORESOURCE_IRQ | 30 | .flags = IORESOURCE_IRQ |
29 | } | 31 | } |
30 | }; | 32 | }; |
@@ -35,12 +37,16 @@ static struct platform_device sead3_net_device = { | |||
35 | .dev = { | 37 | .dev = { |
36 | .platform_data = &sead3_smsc911x_data, | 38 | .platform_data = &sead3_smsc911x_data, |
37 | }, | 39 | }, |
38 | .num_resources = ARRAY_SIZE(sead3_net_resourcess), | 40 | .num_resources = ARRAY_SIZE(sead3_net_resources), |
39 | .resource = sead3_net_resourcess | 41 | .resource = sead3_net_resources |
40 | }; | 42 | }; |
41 | 43 | ||
42 | static int __init sead3_net_init(void) | 44 | static int __init sead3_net_init(void) |
43 | { | 45 | { |
46 | if (gic_present) | ||
47 | sead3_net_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_NET; | ||
48 | else | ||
49 | sead3_net_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_NET; | ||
44 | return platform_device_register(&sead3_net_device); | 50 | return platform_device_register(&sead3_net_device); |
45 | } | 51 | } |
46 | 52 | ||
diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c index 6c3b33dbed18..d9661eb6fd6d 100644 --- a/arch/mips/mti-sead3/sead3-platform.c +++ b/arch/mips/mti-sead3/sead3-platform.c | |||
@@ -9,10 +9,13 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/serial_8250.h> | 10 | #include <linux/serial_8250.h> |
11 | 11 | ||
12 | #define UART(base, int) \ | 12 | #include <asm/gic.h> |
13 | #include <asm/mips-boards/sead3int.h> | ||
14 | |||
15 | #define UART(base) \ | ||
13 | { \ | 16 | { \ |
14 | .mapbase = base, \ | 17 | .mapbase = base, \ |
15 | .irq = int, \ | 18 | .irq = -1, \ |
16 | .uartclk = 14745600, \ | 19 | .uartclk = 14745600, \ |
17 | .iotype = UPIO_MEM32, \ | 20 | .iotype = UPIO_MEM32, \ |
18 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \ | 21 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \ |
@@ -20,8 +23,8 @@ | |||
20 | } | 23 | } |
21 | 24 | ||
22 | static struct plat_serial8250_port uart8250_data[] = { | 25 | static struct plat_serial8250_port uart8250_data[] = { |
23 | UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */ | 26 | UART(0x1f000900), /* ttyS0 = USB */ |
24 | UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */ | 27 | UART(0x1f000800), /* ttyS1 = RS232 */ |
25 | { }, | 28 | { }, |
26 | }; | 29 | }; |
27 | 30 | ||
@@ -35,6 +38,13 @@ static struct platform_device uart8250_device = { | |||
35 | 38 | ||
36 | static int __init uart8250_init(void) | 39 | static int __init uart8250_init(void) |
37 | { | 40 | { |
41 | if (gic_present) { | ||
42 | uart8250_data[0].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART0; | ||
43 | uart8250_data[1].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART1; | ||
44 | } else { | ||
45 | uart8250_data[0].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART0; | ||
46 | uart8250_data[1].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART1; | ||
47 | } | ||
38 | return platform_device_register(&uart8250_device); | 48 | return platform_device_register(&uart8250_device); |
39 | } | 49 | } |
40 | 50 | ||
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 79ab99781534..633a34639388 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -8,6 +8,8 @@ | |||
8 | */ | 8 | */ |
9 | #include <linux/bitmap.h> | 9 | #include <linux/bitmap.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/sched.h> | ||
11 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
12 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
13 | #include <linux/clocksource.h> | 15 | #include <linux/clocksource.h> |
@@ -22,11 +24,8 @@ | |||
22 | unsigned int gic_frequency; | 24 | unsigned int gic_frequency; |
23 | unsigned int gic_present; | 25 | unsigned int gic_present; |
24 | unsigned long _gic_base; | 26 | unsigned long _gic_base; |
25 | unsigned int gic_irq_base; | ||
26 | unsigned int gic_irq_flags[GIC_NUM_INTRS]; | 27 | unsigned int gic_irq_flags[GIC_NUM_INTRS]; |
27 | 28 | unsigned int gic_cpu_pin; | |
28 | /* The index into this array is the vector # of the interrupt. */ | ||
29 | struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS]; | ||
30 | 29 | ||
31 | struct gic_pcpu_mask { | 30 | struct gic_pcpu_mask { |
32 | DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); | 31 | DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); |
@@ -46,6 +45,8 @@ static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; | |||
46 | static DEFINE_SPINLOCK(gic_lock); | 45 | static DEFINE_SPINLOCK(gic_lock); |
47 | static struct irq_domain *gic_irq_domain; | 46 | static struct irq_domain *gic_irq_domain; |
48 | 47 | ||
48 | static void __gic_irq_dispatch(void); | ||
49 | |||
49 | #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC) | 50 | #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC) |
50 | cycle_t gic_read_count(void) | 51 | cycle_t gic_read_count(void) |
51 | { | 52 | { |
@@ -117,21 +118,6 @@ void gic_send_ipi(unsigned int intr) | |||
117 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); | 118 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); |
118 | } | 119 | } |
119 | 120 | ||
120 | static void gic_eic_irq_dispatch(void) | ||
121 | { | ||
122 | unsigned int cause = read_c0_cause(); | ||
123 | int irq; | ||
124 | |||
125 | irq = (cause & ST0_IM) >> STATUSB_IP2; | ||
126 | if (irq == 0) | ||
127 | irq = -1; | ||
128 | |||
129 | if (irq >= 0) | ||
130 | do_IRQ(gic_irq_base + irq); | ||
131 | else | ||
132 | spurious_interrupt(); | ||
133 | } | ||
134 | |||
135 | static void __init vpe_local_setup(unsigned int numvpes) | 121 | static void __init vpe_local_setup(unsigned int numvpes) |
136 | { | 122 | { |
137 | unsigned long timer_intr = GIC_INT_TMR; | 123 | unsigned long timer_intr = GIC_INT_TMR; |
@@ -166,16 +152,15 @@ static void __init vpe_local_setup(unsigned int numvpes) | |||
166 | GIC_MAP_TO_PIN_MSK | timer_intr); | 152 | GIC_MAP_TO_PIN_MSK | timer_intr); |
167 | if (cpu_has_veic) { | 153 | if (cpu_has_veic) { |
168 | set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET, | 154 | set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET, |
169 | gic_eic_irq_dispatch); | 155 | __gic_irq_dispatch); |
170 | gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK; | ||
171 | } | 156 | } |
172 | 157 | ||
173 | if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) | 158 | if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) |
174 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), | 159 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), |
175 | GIC_MAP_TO_PIN_MSK | perf_intr); | 160 | GIC_MAP_TO_PIN_MSK | perf_intr); |
176 | if (cpu_has_veic) { | 161 | if (cpu_has_veic) { |
177 | set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch); | 162 | set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, |
178 | gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK; | 163 | __gic_irq_dispatch); |
179 | } | 164 | } |
180 | } | 165 | } |
181 | } | 166 | } |
@@ -343,64 +328,100 @@ static struct irq_chip gic_irq_controller = { | |||
343 | #endif | 328 | #endif |
344 | }; | 329 | }; |
345 | 330 | ||
346 | static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, | 331 | static void __gic_irq_dispatch(void) |
347 | unsigned int pin, unsigned int polarity, unsigned int trigtype, | ||
348 | unsigned int flags) | ||
349 | { | 332 | { |
350 | struct gic_shared_intr_map *map_ptr; | 333 | unsigned int intr, virq; |
351 | int i; | ||
352 | |||
353 | /* Setup Intr to Pin mapping */ | ||
354 | if (pin & GIC_MAP_TO_NMI_MSK) { | ||
355 | int i; | ||
356 | 334 | ||
357 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); | 335 | while ((intr = gic_get_int()) != GIC_NUM_INTRS) { |
358 | /* FIXME: hack to route NMI to all cpu's */ | 336 | virq = irq_linear_revmap(gic_irq_domain, intr); |
359 | for (i = 0; i < NR_CPUS; i += 32) { | 337 | do_IRQ(virq); |
360 | GICWRITE(GIC_REG_ADDR(SHARED, | ||
361 | GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)), | ||
362 | 0xffffffff); | ||
363 | } | ||
364 | } else { | ||
365 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), | ||
366 | GIC_MAP_TO_PIN_MSK | pin); | ||
367 | /* Setup Intr to CPU mapping */ | ||
368 | GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); | ||
369 | if (cpu_has_veic) { | ||
370 | set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET, | ||
371 | gic_eic_irq_dispatch); | ||
372 | map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET]; | ||
373 | if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR) | ||
374 | BUG(); | ||
375 | map_ptr->intr_list[map_ptr->num_shared_intr++] = intr; | ||
376 | } | ||
377 | } | 338 | } |
339 | } | ||
378 | 340 | ||
379 | /* Setup Intr Polarity */ | 341 | static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc) |
380 | GIC_SET_POLARITY(intr, polarity); | 342 | { |
343 | __gic_irq_dispatch(); | ||
344 | } | ||
345 | |||
346 | #ifdef CONFIG_MIPS_GIC_IPI | ||
347 | static int gic_resched_int_base; | ||
348 | static int gic_call_int_base; | ||
349 | |||
350 | unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) | ||
351 | { | ||
352 | return gic_resched_int_base + cpu; | ||
353 | } | ||
381 | 354 | ||
382 | /* Setup Intr Trigger Type */ | 355 | unsigned int plat_ipi_call_int_xlate(unsigned int cpu) |
383 | GIC_SET_TRIGGER(intr, trigtype); | 356 | { |
357 | return gic_call_int_base + cpu; | ||
358 | } | ||
384 | 359 | ||
385 | /* Init Intr Masks */ | 360 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) |
386 | GIC_CLR_INTR_MASK(intr); | 361 | { |
362 | scheduler_ipi(); | ||
363 | |||
364 | return IRQ_HANDLED; | ||
365 | } | ||
366 | |||
367 | static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) | ||
368 | { | ||
369 | smp_call_function_interrupt(); | ||
370 | |||
371 | return IRQ_HANDLED; | ||
372 | } | ||
387 | 373 | ||
388 | /* Initialise per-cpu Interrupt software masks */ | 374 | static struct irqaction irq_resched = { |
375 | .handler = ipi_resched_interrupt, | ||
376 | .flags = IRQF_PERCPU, | ||
377 | .name = "IPI resched" | ||
378 | }; | ||
379 | |||
380 | static struct irqaction irq_call = { | ||
381 | .handler = ipi_call_interrupt, | ||
382 | .flags = IRQF_PERCPU, | ||
383 | .name = "IPI call" | ||
384 | }; | ||
385 | |||
386 | static __init void gic_ipi_init_one(unsigned int intr, int cpu, | ||
387 | struct irqaction *action) | ||
388 | { | ||
389 | int virq = irq_create_mapping(gic_irq_domain, intr); | ||
390 | int i; | ||
391 | |||
392 | GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); | ||
389 | for (i = 0; i < NR_CPUS; i++) | 393 | for (i = 0; i < NR_CPUS; i++) |
390 | clear_bit(intr, pcpu_masks[i].pcpu_mask); | 394 | clear_bit(intr, pcpu_masks[i].pcpu_mask); |
391 | set_bit(intr, pcpu_masks[cpu].pcpu_mask); | 395 | set_bit(intr, pcpu_masks[cpu].pcpu_mask); |
392 | 396 | ||
393 | if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0)) | 397 | irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING); |
394 | GIC_SET_INTR_MASK(intr); | 398 | |
395 | if (trigtype == GIC_TRIG_EDGE) | 399 | irq_set_handler(virq, handle_percpu_irq); |
396 | gic_irq_flags[intr] |= GIC_TRIG_EDGE; | 400 | setup_irq(virq, action); |
397 | } | 401 | } |
398 | 402 | ||
399 | static void __init gic_basic_init(int numintrs, int numvpes, | 403 | static __init void gic_ipi_init(void) |
400 | struct gic_intr_map *intrmap, int mapsize) | ||
401 | { | 404 | { |
402 | unsigned int i, cpu; | 405 | int i; |
403 | unsigned int pin_offset = 0; | 406 | |
407 | /* Use last 2 * NR_CPUS interrupts as IPIs */ | ||
408 | gic_resched_int_base = GIC_NUM_INTRS - nr_cpu_ids; | ||
409 | gic_call_int_base = gic_resched_int_base - nr_cpu_ids; | ||
410 | |||
411 | for (i = 0; i < nr_cpu_ids; i++) { | ||
412 | gic_ipi_init_one(gic_call_int_base + i, i, &irq_call); | ||
413 | gic_ipi_init_one(gic_resched_int_base + i, i, &irq_resched); | ||
414 | } | ||
415 | } | ||
416 | #else | ||
417 | static inline void gic_ipi_init(void) | ||
418 | { | ||
419 | } | ||
420 | #endif | ||
421 | |||
422 | static void __init gic_basic_init(int numintrs, int numvpes) | ||
423 | { | ||
424 | unsigned int i; | ||
404 | 425 | ||
405 | board_bind_eic_interrupt = &gic_bind_eic_interrupt; | 426 | board_bind_eic_interrupt = &gic_bind_eic_interrupt; |
406 | 427 | ||
@@ -409,31 +430,8 @@ static void __init gic_basic_init(int numintrs, int numvpes, | |||
409 | GIC_SET_POLARITY(i, GIC_POL_POS); | 430 | GIC_SET_POLARITY(i, GIC_POL_POS); |
410 | GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); | 431 | GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); |
411 | GIC_CLR_INTR_MASK(i); | 432 | GIC_CLR_INTR_MASK(i); |
412 | if (i < GIC_NUM_INTRS) { | 433 | if (i < GIC_NUM_INTRS) |
413 | gic_irq_flags[i] = 0; | 434 | gic_irq_flags[i] = 0; |
414 | gic_shared_intr_map[i].num_shared_intr = 0; | ||
415 | gic_shared_intr_map[i].local_intr_mask = 0; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract | ||
421 | * one because the GIC will add one (since 0=no intr). | ||
422 | */ | ||
423 | if (cpu_has_veic) | ||
424 | pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); | ||
425 | |||
426 | /* Setup specifics */ | ||
427 | for (i = 0; i < mapsize; i++) { | ||
428 | cpu = intrmap[i].cpunum; | ||
429 | if (cpu == GIC_UNUSED) | ||
430 | continue; | ||
431 | gic_setup_intr(i, | ||
432 | intrmap[i].cpunum, | ||
433 | intrmap[i].pin + pin_offset, | ||
434 | intrmap[i].polarity, | ||
435 | intrmap[i].trigtype, | ||
436 | intrmap[i].flags); | ||
437 | } | 435 | } |
438 | 436 | ||
439 | vpe_local_setup(numvpes); | 437 | vpe_local_setup(numvpes); |
@@ -448,7 +446,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
448 | 446 | ||
449 | spin_lock_irqsave(&gic_lock, flags); | 447 | spin_lock_irqsave(&gic_lock, flags); |
450 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)), | 448 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)), |
451 | GIC_MAP_TO_PIN_MSK | 0); | 449 | GIC_MAP_TO_PIN_MSK | gic_cpu_pin); |
452 | /* Map to VPE 0 by default */ | 450 | /* Map to VPE 0 by default */ |
453 | GIC_SH_MAP_TO_VPE_SMASK(hw, 0); | 451 | GIC_SH_MAP_TO_VPE_SMASK(hw, 0); |
454 | set_bit(hw, pcpu_masks[0].pcpu_mask); | 452 | set_bit(hw, pcpu_masks[0].pcpu_mask); |
@@ -463,8 +461,7 @@ static struct irq_domain_ops gic_irq_domain_ops = { | |||
463 | }; | 461 | }; |
464 | 462 | ||
465 | void __init gic_init(unsigned long gic_base_addr, | 463 | void __init gic_init(unsigned long gic_base_addr, |
466 | unsigned long gic_addrspace_size, | 464 | unsigned long gic_addrspace_size, unsigned int cpu_vec, |
467 | struct gic_intr_map *intr_map, unsigned int intr_map_size, | ||
468 | unsigned int irqbase) | 465 | unsigned int irqbase) |
469 | { | 466 | { |
470 | unsigned int gicconfig; | 467 | unsigned int gicconfig; |
@@ -472,7 +469,6 @@ void __init gic_init(unsigned long gic_base_addr, | |||
472 | 469 | ||
473 | _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, | 470 | _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, |
474 | gic_addrspace_size); | 471 | gic_addrspace_size); |
475 | gic_irq_base = irqbase; | ||
476 | 472 | ||
477 | GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); | 473 | GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); |
478 | numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> | 474 | numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> |
@@ -483,10 +479,23 @@ void __init gic_init(unsigned long gic_base_addr, | |||
483 | GIC_SH_CONFIG_NUMVPES_SHF; | 479 | GIC_SH_CONFIG_NUMVPES_SHF; |
484 | numvpes = numvpes + 1; | 480 | numvpes = numvpes + 1; |
485 | 481 | ||
482 | if (cpu_has_veic) { | ||
483 | /* Always use vector 1 in EIC mode */ | ||
484 | gic_cpu_pin = 0; | ||
485 | set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET, | ||
486 | __gic_irq_dispatch); | ||
487 | } else { | ||
488 | gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET; | ||
489 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec, | ||
490 | gic_irq_dispatch); | ||
491 | } | ||
492 | |||
486 | gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_INTRS, irqbase, | 493 | gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_INTRS, irqbase, |
487 | &gic_irq_domain_ops, NULL); | 494 | &gic_irq_domain_ops, NULL); |
488 | if (!gic_irq_domain) | 495 | if (!gic_irq_domain) |
489 | panic("Failed to add GIC IRQ domain"); | 496 | panic("Failed to add GIC IRQ domain"); |
490 | 497 | ||
491 | gic_basic_init(numintrs, numvpes, intr_map, intr_map_size); | 498 | gic_basic_init(numintrs, numvpes); |
499 | |||
500 | gic_ipi_init(); | ||
492 | } | 501 | } |