diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2011-04-19 19:41:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-21 18:31:31 -0400 |
commit | a481b5d0cb5d1884f16460b4846755518360f1ca (patch) | |
tree | 3a6a73f0adc58e3c218b1d3e081c2d8504d94b57 /arch/sparc | |
parent | ea044ec3984472a2e8de91e17872868baac62a50 (diff) |
sparc32, leon: code cleanup of timer/IRQ controller initialization
Cleaned up leon_init_timers() by removing unnecessary double checking
and one indentation level. Changed LEON_IMASK to LEON_IMASK(cpu).
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')
-rw-r--r-- | arch/sparc/kernel/leon_kernel.c | 156 |
1 files changed, 72 insertions, 84 deletions
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 5d7e41c19362..d8fafeacb496 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -37,7 +37,7 @@ unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ | |||
37 | 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 */ | 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(cpu) (&leon3_irqctrl_regs->mask[cpu]) |
41 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) | 41 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) |
42 | #define LEON_DO_ACK_HW 1 | 42 | #define LEON_DO_ACK_HW 1 |
43 | 43 | ||
@@ -79,8 +79,8 @@ void leon_eirq_setup(unsigned int eirq) | |||
79 | */ | 79 | */ |
80 | irq_link(veirq); | 80 | irq_link(veirq); |
81 | mask = 1 << eirq; | 81 | mask = 1 << eirq; |
82 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK); | 82 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); |
83 | LEON3_BYPASS_STORE_PA(LEON_IMASK, (oldmask | mask)); | 83 | LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask)); |
84 | sparc_leon_eirq = eirq; | 84 | sparc_leon_eirq = eirq; |
85 | } | 85 | } |
86 | 86 | ||
@@ -101,23 +101,23 @@ static inline unsigned long get_irqmask(unsigned int irq) | |||
101 | 101 | ||
102 | static void leon_unmask_irq(struct irq_data *data) | 102 | static void leon_unmask_irq(struct irq_data *data) |
103 | { | 103 | { |
104 | unsigned long mask, flags; | 104 | unsigned long mask, oldmask, flags; |
105 | 105 | ||
106 | mask = (unsigned long)data->chip_data; | 106 | mask = (unsigned long)data->chip_data; |
107 | spin_lock_irqsave(&leon_irq_lock, flags); | 107 | spin_lock_irqsave(&leon_irq_lock, flags); |
108 | LEON3_BYPASS_STORE_PA(LEON_IMASK, | 108 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); |
109 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask))); | 109 | LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask)); |
110 | spin_unlock_irqrestore(&leon_irq_lock, flags); | 110 | spin_unlock_irqrestore(&leon_irq_lock, flags); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void leon_mask_irq(struct irq_data *data) | 113 | static void leon_mask_irq(struct irq_data *data) |
114 | { | 114 | { |
115 | unsigned long mask, flags; | 115 | unsigned long mask, oldmask, flags; |
116 | 116 | ||
117 | mask = (unsigned long)data->chip_data; | 117 | mask = (unsigned long)data->chip_data; |
118 | spin_lock_irqsave(&leon_irq_lock, flags); | 118 | spin_lock_irqsave(&leon_irq_lock, flags); |
119 | LEON3_BYPASS_STORE_PA(LEON_IMASK, | 119 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); |
120 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask))); | 120 | LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask & ~mask)); |
121 | spin_unlock_irqrestore(&leon_irq_lock, flags); | 121 | spin_unlock_irqrestore(&leon_irq_lock, flags); |
122 | } | 122 | } |
123 | 123 | ||
@@ -261,92 +261,83 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
261 | leon3_gptimer_irq = *(unsigned int *)pp->value; | 261 | leon3_gptimer_irq = *(unsigned int *)pp->value; |
262 | } while (0); | 262 | } while (0); |
263 | 263 | ||
264 | if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { | 264 | if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq)) |
265 | LEON3_BYPASS_STORE_PA( | 265 | goto bad; |
266 | &leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); | 266 | |
267 | LEON3_BYPASS_STORE_PA( | 267 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); |
268 | &leon3_gptimer_regs->e[leon3_gptimer_idx].rld, | 268 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld, |
269 | (((1000000 / HZ) - 1))); | 269 | (((1000000 / HZ) - 1))); |
270 | LEON3_BYPASS_STORE_PA( | 270 | LEON3_BYPASS_STORE_PA( |
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 | leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx; | 274 | leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx; |
275 | |||
276 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & | ||
277 | (1<<LEON3_GPTIMER_SEPIRQ))) { | ||
278 | prom_printf("irq timer not configured with separate irqs\n"); | ||
279 | BUG(); | ||
280 | } | ||
281 | 275 | ||
282 | LEON3_BYPASS_STORE_PA( | 276 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & |
283 | &leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0); | 277 | (1<<LEON3_GPTIMER_SEPIRQ))) { |
284 | LEON3_BYPASS_STORE_PA( | 278 | printk(KERN_ERR "timer not configured with separate irqs\n"); |
285 | &leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, | 279 | BUG(); |
286 | (((1000000/HZ) - 1))); | ||
287 | LEON3_BYPASS_STORE_PA( | ||
288 | &leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); | ||
289 | # endif | ||
290 | |||
291 | /* | ||
292 | * The IRQ controller may (if implemented) consist of multiple | ||
293 | * IRQ controllers, each mapped on a 4Kb boundary. | ||
294 | * Each CPU may be routed to different IRQCTRLs, however | ||
295 | * we assume that all CPUs (in SMP system) is routed to the | ||
296 | * same IRQ Controller, and for non-SMP only one IRQCTRL is | ||
297 | * accessed anyway. | ||
298 | * In AMP systems, Linux must run on CPU0 for the time being. | ||
299 | */ | ||
300 | cpu = sparc_leon3_cpuid(); | ||
301 | icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); | ||
302 | icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; | ||
303 | leon3_irqctrl_regs += icsel; | ||
304 | |||
305 | /* Probe extended IRQ controller */ | ||
306 | eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) | ||
307 | >> 16) & 0xf; | ||
308 | if (eirq != 0) | ||
309 | leon_eirq_setup(eirq); | ||
310 | } else { | ||
311 | goto bad; | ||
312 | } | 280 | } |
313 | 281 | ||
282 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, | ||
283 | 0); | ||
284 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, | ||
285 | (((1000000/HZ) - 1))); | ||
286 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | ||
287 | 0); | ||
288 | #endif | ||
289 | |||
290 | /* | ||
291 | * The IRQ controller may (if implemented) consist of multiple | ||
292 | * IRQ controllers, each mapped on a 4Kb boundary. | ||
293 | * Each CPU may be routed to different IRQCTRLs, however | ||
294 | * we assume that all CPUs (in SMP system) is routed to the | ||
295 | * same IRQ Controller, and for non-SMP only one IRQCTRL is | ||
296 | * accessed anyway. | ||
297 | * In AMP systems, Linux must run on CPU0 for the time being. | ||
298 | */ | ||
299 | cpu = sparc_leon3_cpuid(); | ||
300 | icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); | ||
301 | icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; | ||
302 | leon3_irqctrl_regs += icsel; | ||
303 | |||
304 | /* Probe extended IRQ controller */ | ||
305 | eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) | ||
306 | >> 16) & 0xf; | ||
307 | if (eirq != 0) | ||
308 | leon_eirq_setup(eirq); | ||
309 | |||
314 | irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx); | 310 | irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx); |
315 | err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); | 311 | err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); |
316 | |||
317 | if (err) { | 312 | if (err) { |
318 | printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n", | 313 | printk(KERN_ERR "unable to attach timer IRQ%d\n", irq); |
319 | irq); | ||
320 | prom_halt(); | 314 | prom_halt(); |
321 | } | 315 | } |
322 | 316 | ||
323 | if (leon3_gptimer_regs) { | 317 | 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, | 318 | LEON3_GPTIMER_EN | |
325 | LEON3_GPTIMER_EN | | 319 | LEON3_GPTIMER_RL | |
326 | LEON3_GPTIMER_RL | | 320 | LEON3_GPTIMER_LD | |
327 | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); | 321 | LEON3_GPTIMER_IRQEN); |
328 | 322 | ||
329 | #ifdef CONFIG_SMP | 323 | #ifdef CONFIG_SMP |
330 | /* Install per-cpu IRQ handler for broadcasted ticker */ | 324 | /* Install per-cpu IRQ handler for broadcasted ticker */ |
331 | irq = leon_build_device_irq(leon3_ticker_irq, | 325 | irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq, |
332 | handle_percpu_irq, "per-cpu", | 326 | "per-cpu", 0); |
333 | 0); | 327 | err = request_irq(irq, leon_percpu_timer_interrupt, |
334 | err = request_irq(irq, leon_percpu_timer_interrupt, | 328 | IRQF_PERCPU | IRQF_TIMER, "ticker", |
335 | IRQF_PERCPU | IRQF_TIMER, "ticker", | 329 | NULL); |
336 | NULL); | 330 | if (err) { |
337 | if (err) { | 331 | printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq); |
338 | printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq); | 332 | prom_halt(); |
339 | prom_halt(); | 333 | } |
340 | } | ||
341 | 334 | ||
342 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | 335 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, |
343 | LEON3_GPTIMER_EN | | 336 | LEON3_GPTIMER_EN | |
344 | LEON3_GPTIMER_RL | | 337 | LEON3_GPTIMER_RL | |
345 | LEON3_GPTIMER_LD | | 338 | LEON3_GPTIMER_LD | |
346 | LEON3_GPTIMER_IRQEN); | 339 | LEON3_GPTIMER_IRQEN); |
347 | #endif | 340 | #endif |
348 | |||
349 | } | ||
350 | return; | 341 | return; |
351 | bad: | 342 | bad: |
352 | printk(KERN_ERR "No Timer/irqctrl found\n"); | 343 | printk(KERN_ERR "No Timer/irqctrl found\n"); |
@@ -363,9 +354,6 @@ void leon_load_profile_irq(int cpu, unsigned int limit) | |||
363 | BUG(); | 354 | BUG(); |
364 | } | 355 | } |
365 | 356 | ||
366 | |||
367 | |||
368 | |||
369 | void __init leon_trans_init(struct device_node *dp) | 357 | void __init leon_trans_init(struct device_node *dp) |
370 | { | 358 | { |
371 | if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) { | 359 | if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) { |
@@ -420,8 +408,8 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) | |||
420 | unsigned long mask, flags, *addr; | 408 | unsigned long mask, flags, *addr; |
421 | mask = get_irqmask(irq_nr); | 409 | mask = get_irqmask(irq_nr); |
422 | spin_lock_irqsave(&leon_irq_lock, flags); | 410 | spin_lock_irqsave(&leon_irq_lock, flags); |
423 | addr = (unsigned long *)&(leon3_irqctrl_regs->mask[cpu]); | 411 | addr = (unsigned long *)LEON_IMASK(cpu); |
424 | LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | (mask))); | 412 | LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask)); |
425 | spin_unlock_irqrestore(&leon_irq_lock, flags); | 413 | spin_unlock_irqrestore(&leon_irq_lock, flags); |
426 | } | 414 | } |
427 | 415 | ||