diff options
author | John Crispin <blogic@openwrt.org> | 2012-04-30 05:33:05 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-05-15 11:49:21 -0400 |
commit | a8d096ef78c4d9a664754e1fad5e82dec2feec68 (patch) | |
tree | 21a261fc21492c49be446e30902acb3db5ff95de /arch/mips | |
parent | 59c115798430f644b43123250ae4e1d820c3c18d (diff) |
MIPS: lantiq: add ipi handlers to make vsmp work
Add IPI handlers to the interrupt code. This patch makes MIPS_MT_SMP work
on lantiq socs. The code is based on the malta implementation.
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3704/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/lantiq/irq.c | 60 | ||||
-rw-r--r-- | arch/mips/lantiq/prom.c | 5 |
2 files changed, 65 insertions, 0 deletions
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index bfd4ad180aac..d227be1c3c4d 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c | |||
@@ -54,6 +54,14 @@ | |||
54 | #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y)) | 54 | #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y)) |
55 | #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x)) | 55 | #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x)) |
56 | 56 | ||
57 | /* our 2 ipi interrupts for VSMP */ | ||
58 | #define MIPS_CPU_IPI_RESCHED_IRQ 0 | ||
59 | #define MIPS_CPU_IPI_CALL_IRQ 1 | ||
60 | |||
61 | #if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) | ||
62 | int gic_present; | ||
63 | #endif | ||
64 | |||
57 | static unsigned short ltq_eiu_irq[MAX_EIU] = { | 65 | static unsigned short ltq_eiu_irq[MAX_EIU] = { |
58 | LTQ_EIU_IR0, | 66 | LTQ_EIU_IR0, |
59 | LTQ_EIU_IR1, | 67 | LTQ_EIU_IR1, |
@@ -219,6 +227,47 @@ static void ltq_hw5_irqdispatch(void) | |||
219 | do_IRQ(MIPS_CPU_TIMER_IRQ); | 227 | do_IRQ(MIPS_CPU_TIMER_IRQ); |
220 | } | 228 | } |
221 | 229 | ||
230 | #ifdef CONFIG_MIPS_MT_SMP | ||
231 | void __init arch_init_ipiirq(int irq, struct irqaction *action) | ||
232 | { | ||
233 | setup_irq(irq, action); | ||
234 | irq_set_handler(irq, handle_percpu_irq); | ||
235 | } | ||
236 | |||
237 | static void ltq_sw0_irqdispatch(void) | ||
238 | { | ||
239 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); | ||
240 | } | ||
241 | |||
242 | static void ltq_sw1_irqdispatch(void) | ||
243 | { | ||
244 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); | ||
245 | } | ||
246 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) | ||
247 | { | ||
248 | scheduler_ipi(); | ||
249 | return IRQ_HANDLED; | ||
250 | } | ||
251 | |||
252 | static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) | ||
253 | { | ||
254 | smp_call_function_interrupt(); | ||
255 | return IRQ_HANDLED; | ||
256 | } | ||
257 | |||
258 | static struct irqaction irq_resched = { | ||
259 | .handler = ipi_resched_interrupt, | ||
260 | .flags = IRQF_PERCPU, | ||
261 | .name = "IPI_resched" | ||
262 | }; | ||
263 | |||
264 | static struct irqaction irq_call = { | ||
265 | .handler = ipi_call_interrupt, | ||
266 | .flags = IRQF_PERCPU, | ||
267 | .name = "IPI_call" | ||
268 | }; | ||
269 | #endif | ||
270 | |||
222 | asmlinkage void plat_irq_dispatch(void) | 271 | asmlinkage void plat_irq_dispatch(void) |
223 | { | 272 | { |
224 | unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; | 273 | unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; |
@@ -312,6 +361,17 @@ void __init arch_init_irq(void) | |||
312 | irq_set_chip_and_handler(i, <q_irq_type, | 361 | irq_set_chip_and_handler(i, <q_irq_type, |
313 | handle_level_irq); | 362 | handle_level_irq); |
314 | 363 | ||
364 | #if defined(CONFIG_MIPS_MT_SMP) | ||
365 | if (cpu_has_vint) { | ||
366 | pr_info("Setting up IPI vectored interrupts\n"); | ||
367 | set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch); | ||
368 | set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch); | ||
369 | } | ||
370 | arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ, | ||
371 | &irq_resched); | ||
372 | arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call); | ||
373 | #endif | ||
374 | |||
315 | #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) | 375 | #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) |
316 | set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | | 376 | set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | |
317 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); | 377 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); |
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index e34fcfd0d5ca..664b7b722248 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c | |||
@@ -68,4 +68,9 @@ void __init prom_init(void) | |||
68 | soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0'; | 68 | soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0'; |
69 | pr_info("SoC: %s\n", soc_info.sys_type); | 69 | pr_info("SoC: %s\n", soc_info.sys_type); |
70 | prom_init_cmdline(); | 70 | prom_init_cmdline(); |
71 | |||
72 | #if defined(CONFIG_MIPS_MT_SMP) | ||
73 | if (register_vsmp_smp_ops()) | ||
74 | panic("failed to register_vsmp_smp_ops()"); | ||
75 | #endif | ||
71 | } | 76 | } |