Root/target/linux/leon/patches/009-remove_second_timer.patch

1From 300f3ee36c3019ee36f81befd91cd1b32544cefe Mon Sep 17 00:00:00 2001
2From: Daniel Hellstrom <daniel@gaisler.com>
3Date: Wed, 22 Sep 2010 15:39:05 +0200
4Subject: [PATCH] SPARC/LEON: Removed the need for two timers, per-cpu ticker is shared with system clock timer.
5
6Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
7---
8 arch/sparc/include/asm/leon.h | 2 +-
9 arch/sparc/include/asm/leon_amba.h | 3 +-
10 arch/sparc/kernel/entry.S | 3 +-
11 arch/sparc/kernel/leon_kernel.c | 37 ++++++++---------------------------
12 arch/sparc/kernel/leon_smp.c | 8 ++++++-
13 5 files changed, 21 insertions(+), 32 deletions(-)
14
15--- a/arch/sparc/include/asm/leon.h
16+++ b/arch/sparc/include/asm/leon.h
17@@ -240,7 +240,7 @@ static inline int sparc_leon3_cpuid(void
18 
19 #ifdef CONFIG_SMP
20 # define LEON3_IRQ_RESCHEDULE 13
21-# define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq)
22+# define LEON3_IRQ_TICKER (leon3_gptimer_irq + leon3_gptimer_idx)
23 # define LEON3_IRQ_CROSS_CALL 15
24 #endif
25 
26--- a/arch/sparc/include/asm/leon_amba.h
27+++ b/arch/sparc/include/asm/leon_amba.h
28@@ -182,11 +182,12 @@ void _amba_init(struct device_node *dp,
29 
30 extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
31 extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
32-extern struct amba_apb_device leon_percpu_timer_dev[16];
33 extern int leondebug_irq_disable;
34 extern int leon_debug_irqout;
35 extern unsigned long leon3_gptimer_irq;
36+extern unsigned long leon3_gptimer_idx; /* Timer Index (starting at 0) with Timer Core */
37 extern unsigned int sparc_leon_eirq;
38+extern unsigned long leon3_cpu_idx;
39 
40 #endif /* __ASSEMBLY__ */
41 
42--- a/arch/sparc/kernel/entry.S
43+++ b/arch/sparc/kernel/entry.S
44@@ -411,8 +411,9 @@ smpleon_ticker:
45     WRITE_PAUSE
46     wr %g2, PSR_ET, %psr
47     WRITE_PAUSE
48+ mov %l7, %o0 ! irq level
49     call leon_percpu_timer_interrupt
50- add %sp, STACKFRAME_SZ, %o0
51+ add %sp, STACKFRAME_SZ, %o1 ! pt_regs
52     wr %l0, PSR_ET, %psr
53     WRITE_PAUSE
54     RESTORE_ALL
55--- a/arch/sparc/kernel/leon_kernel.c
56+++ b/arch/sparc/kernel/leon_kernel.c
57@@ -25,7 +25,6 @@
58 
59 struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */
60 struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */
61-struct amba_apb_device leon_percpu_timer_dev[16];
62 
63 int leondebug_irq_disable;
64 int leon_debug_irqout;
65@@ -34,6 +33,7 @@ static int dummy_master_l10_counter;
66 unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */
67 unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */
68 unsigned int sparc_leon_eirq;
69+unsigned long leon3_cpu_idx = 0; /* Boot CPU Index */
70 #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
71 
72 /* Return the IRQ of the pending IRQ on the extended IRQ controller */
73@@ -109,13 +109,14 @@ void __init leon_init_timers(irq_handler
74     struct device_node *rootnp, *np;
75     struct property *pp;
76     int len;
77- int cpu, icsel;
78+ int icsel;
79     int ampopts;
80 
81     leondebug_irq_disable = 0;
82     leon_debug_irqout = 0;
83     master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
84     dummy_master_l10_counter = 0;
85+ leon3_cpu_idx = sparc_leon3_cpuid();
86 
87     /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */
88     rootnp = of_find_node_by_path("/ambapp0");
89@@ -152,21 +153,11 @@ void __init leon_init_timers(irq_handler
90                       (((1000000 / HZ) - 1)));
91         LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
92 
93-#ifdef CONFIG_SMP
94- leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
95- leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx;
96-
97         if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
98               (1<<LEON3_GPTIMER_SEPIRQ))) {
99- prom_printf("irq timer not configured with separate irqs\n");
100- BUG();
101+ prom_printf("LEON-SMP: GPTIMER use shared irqs, using other timers will fail.\n");
102         }
103 
104- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
105- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1)));
106- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
107-# endif
108-
109         /* The IRQ controller may (if implemented) consist of multiple
110          * IRQ controllers, each mapped on a 4Kb boundary.
111          * Each CPU may be routed to different IRQCTRLs, however
112@@ -175,9 +166,8 @@ void __init leon_init_timers(irq_handler
113          * accessed anyway.
114          * In AMP systems, Linux may not be run on CPU0.
115          */
116- cpu = sparc_leon3_cpuid();
117- icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
118- icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
119+ icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[leon3_cpu_idx/8]);
120+ icsel = (icsel >> ((7 - (leon3_cpu_idx & 0x7)) * 4)) & 0xf;
121         leon3_irqctrl_regs += icsel;
122 
123         LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0);
124@@ -204,7 +194,8 @@ void __init leon_init_timers(irq_handler
125 # ifdef CONFIG_SMP
126     {
127         unsigned long flags;
128- struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)];
129+ struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 +
130+ (leon3_gptimer_irq + leon3_gptimer_idx - 1)];
131 
132         /* For SMP we use the level 14 ticker, however the bootup code
133          * has copied the firmwares level 14 vector into boot cpu's
134@@ -222,21 +213,11 @@ void __init leon_init_timers(irq_handler
135     }
136 # endif
137 
138- if (leon3_gptimer_regs) {
139- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
140+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
141                       LEON3_GPTIMER_EN |
142                       LEON3_GPTIMER_RL |
143                       LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
144 
145-#ifdef CONFIG_SMP
146- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
147- LEON3_GPTIMER_EN |
148- LEON3_GPTIMER_RL |
149- LEON3_GPTIMER_LD |
150- LEON3_GPTIMER_IRQEN);
151-#endif
152-
153- }
154 }
155 
156 void leon_clear_clock_irq(void)
157--- a/arch/sparc/kernel/leon_smp.c
158+++ b/arch/sparc/kernel/leon_smp.c
159@@ -52,6 +52,7 @@ extern volatile unsigned long cpu_callin
160 extern unsigned char boot_cpu_id;
161 extern cpumask_t smp_commenced_mask;
162 void __init leon_configure_cache_smp(void);
163+extern void handler_irq(int irq, struct pt_regs * regs);
164 
165 static inline unsigned long do_swap(volatile unsigned long *ptr,
166                     unsigned long val)
167@@ -385,7 +386,7 @@ void leon_cross_call_irq(void)
168     ccall_info.processors_out[i] = 1;
169 }
170 
171-void leon_percpu_timer_interrupt(struct pt_regs *regs)
172+void leon_percpu_timer_interrupt(int irq, struct pt_regs *regs)
173 {
174     struct pt_regs *old_regs;
175     int cpu = smp_processor_id();
176@@ -406,6 +407,11 @@ void leon_percpu_timer_interrupt(struct
177         prof_counter(cpu) = prof_multiplier(cpu);
178     }
179     set_irq_regs(old_regs);
180+
181+ if ( cpu == leon3_cpu_idx ) {
182+ /* Ticker Clock is shared with the System Clock */
183+ handler_irq(irq, regs);
184+ }
185 }
186 
187 static void __init smp_setup_percpu_timer(void)
188

Archive Download this file



interactive