aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-04-19 19:41:25 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-21 18:31:31 -0400
commita481b5d0cb5d1884f16460b4846755518360f1ca (patch)
tree3a6a73f0adc58e3c218b1d3e081c2d8504d94b57 /arch/sparc
parentea044ec3984472a2e8de91e17872868baac62a50 (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.c156
1 files changed, 72 insertions, 84 deletions
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 5d7e41c1936..d8fafeacb49 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 */
37unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ 37unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
38int leon3_ticker_irq; /* Timer ticker IRQ */ 38int leon3_ticker_irq; /* Timer ticker IRQ */
39unsigned int sparc_leon_eirq; 39unsigned 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
102static void leon_unmask_irq(struct irq_data *data) 102static 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
113static void leon_mask_irq(struct irq_data *data) 113static 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;
351bad: 342bad:
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
369void __init leon_trans_init(struct device_node *dp) 357void __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