diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2011-04-19 19:41:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-21 18:31:30 -0400 |
commit | 2cf9530420e446bb61f665d02afeb81070106900 (patch) | |
tree | 157ee818554017ed8495a0556d30d38e662d2be9 /arch/sparc/kernel/leon_kernel.c | |
parent | 4c6773c3954cb1192f70a63e2dc61adc55bb0948 (diff) |
sparc32,leon: per-cpu ticker use genirq per-cpu handler
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/leon_kernel.c')
-rw-r--r-- | arch/sparc/kernel/leon_kernel.c | 39 |
1 files changed, 14 insertions, 25 deletions
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 210f4a0a8457..d867543edfe1 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ | 27 | struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ |
28 | struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ | 28 | struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ |
29 | struct amba_apb_device leon_percpu_timer_dev[16]; | ||
30 | 29 | ||
31 | int leondebug_irq_disable; | 30 | int leondebug_irq_disable; |
32 | int leon_debug_irqout; | 31 | int leon_debug_irqout; |
@@ -36,6 +35,7 @@ static DEFINE_SPINLOCK(leon_irq_lock); | |||
36 | 35 | ||
37 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ | 36 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ |
38 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ | 37 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ |
38 | int leon3_ticker_irq; /* Timer ticker IRQ */ | ||
39 | unsigned int sparc_leon_eirq; | 39 | unsigned int sparc_leon_eirq; |
40 | #define LEON_IMASK (&leon3_irqctrl_regs->mask[0]) | 40 | #define LEON_IMASK (&leon3_irqctrl_regs->mask[0]) |
41 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) | 41 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) |
@@ -271,9 +271,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
271 | &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); | 271 | &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); |
272 | 272 | ||
273 | #ifdef CONFIG_SMP | 273 | #ifdef CONFIG_SMP |
274 | leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; | 274 | leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx; |
275 | leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 + | ||
276 | leon3_gptimer_idx; | ||
277 | 275 | ||
278 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & | 276 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & |
279 | (1<<LEON3_GPTIMER_SEPIRQ))) { | 277 | (1<<LEON3_GPTIMER_SEPIRQ))) { |
@@ -322,27 +320,6 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
322 | prom_halt(); | 320 | prom_halt(); |
323 | } | 321 | } |
324 | 322 | ||
325 | # ifdef CONFIG_SMP | ||
326 | { | ||
327 | unsigned long flags; | ||
328 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)]; | ||
329 | |||
330 | /* For SMP we use the level 14 ticker, however the bootup code | ||
331 | * has copied the firmwares level 14 vector into boot cpu's | ||
332 | * trap table, we must fix this now or we get squashed. | ||
333 | */ | ||
334 | local_irq_save(flags); | ||
335 | |||
336 | patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ | ||
337 | |||
338 | /* Adjust so that we jump directly to smpleon_ticker */ | ||
339 | trap_table->inst_three += smpleon_ticker - real_irq_entry; | ||
340 | |||
341 | local_flush_cache_all(); | ||
342 | local_irq_restore(flags); | ||
343 | } | ||
344 | # endif | ||
345 | |||
346 | if (leon3_gptimer_regs) { | 323 | if (leon3_gptimer_regs) { |
347 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, | 324 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, |
348 | LEON3_GPTIMER_EN | | 325 | LEON3_GPTIMER_EN | |
@@ -350,6 +327,18 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
350 | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); | 327 | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); |
351 | 328 | ||
352 | #ifdef CONFIG_SMP | 329 | #ifdef CONFIG_SMP |
330 | /* Install per-cpu IRQ handler for broadcasted ticker */ | ||
331 | irq = leon_build_device_irq(leon3_ticker_irq, | ||
332 | handle_percpu_irq, "per-cpu", | ||
333 | 0); | ||
334 | err = request_irq(irq, leon_percpu_timer_interrupt, | ||
335 | IRQF_PERCPU | IRQF_TIMER, "ticker", | ||
336 | NULL); | ||
337 | if (err) { | ||
338 | printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq); | ||
339 | prom_halt(); | ||
340 | } | ||
341 | |||
353 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | 342 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, |
354 | LEON3_GPTIMER_EN | | 343 | LEON3_GPTIMER_EN | |
355 | LEON3_GPTIMER_RL | | 344 | LEON3_GPTIMER_RL | |