aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-01-03 20:41:32 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-04 14:16:37 -0500
commit2791c1a4390085789e37347fc49f7d189fedae88 (patch)
tree4d5f22601d8a764c377f4378c7e3e8fb5884d343 /arch/sparc
parent9742e72cd1e24ede007daa8f3eb1cece66f0fd0f (diff)
SPARC/LEON: added support for selecting Timer Core and Timer within core
The ability to select Timer Core and Timer instance for system clock makes it possible for multiple AMP systems to coexist. Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/kernel/leon_kernel.c80
1 files changed, 54 insertions, 26 deletions
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 88ade07f976c..fdab7f854f80 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -32,6 +32,7 @@ int leon_debug_irqout;
32static int dummy_master_l10_counter; 32static int dummy_master_l10_counter;
33 33
34unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ 34unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
35unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
35unsigned int sparc_leon_eirq; 36unsigned int sparc_leon_eirq;
36#define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) 37#define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
37 38
@@ -105,10 +106,11 @@ static void leon_disable_irq(unsigned int irq_nr)
105void __init leon_init_timers(irq_handler_t counter_fn) 106void __init leon_init_timers(irq_handler_t counter_fn)
106{ 107{
107 int irq; 108 int irq;
108 struct device_node *rootnp, *np; 109 struct device_node *rootnp, *np, *nnp;
109 struct property *pp; 110 struct property *pp;
110 int len; 111 int len;
111 int cpu, icsel; 112 int cpu, icsel;
113 int ampopts;
112 114
113 leondebug_irq_disable = 0; 115 leondebug_irq_disable = 0;
114 leon_debug_irqout = 0; 116 leon_debug_irqout = 0;
@@ -131,30 +133,52 @@ void __init leon_init_timers(irq_handler_t counter_fn)
131 leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; 133 leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
132 134
133 /* Find GPTIMER Timer Registers base address otherwise bail out. */ 135 /* Find GPTIMER Timer Registers base address otherwise bail out. */
134 np = of_find_node_by_name(rootnp, "GAISLER_GPTIMER"); 136 nnp = rootnp;
135 if (!np) { 137 do {
136 np = of_find_node_by_name(np, "01_011"); 138 np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
137 if (!np) 139 if (!np) {
138 goto bad; 140 np = of_find_node_by_name(nnp, "01_011");
139 } 141 if (!np)
140 pp = of_find_property(np, "reg", &len); 142 goto bad;
141 if (!pp) 143 }
142 goto bad; 144
143 leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; 145 ampopts = 0;
144 pp = of_find_property(np, "interrupts", &len); 146 pp = of_find_property(np, "ampopts", &len);
145 if (!pp) 147 if (pp) {
146 goto bad; 148 ampopts = *(int *)pp->value;
147 leon3_gptimer_irq = *(unsigned int *)pp->value; 149 if (ampopts == 0) {
150 /* Skip this instance, resource already
151 * allocated by other OS */
152 nnp = np;
153 continue;
154 }
155 }
156
157 /* Select Timer-Instance on Timer Core. Default is zero */
158 leon3_gptimer_idx = ampopts & 0x7;
159
160 pp = of_find_property(np, "reg", &len);
161 if (pp)
162 leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
163 pp->value;
164 pp = of_find_property(np, "interrupts", &len);
165 if (pp)
166 leon3_gptimer_irq = *(unsigned int *)pp->value;
167 } while (0);
148 168
149 if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { 169 if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) {
150 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); 170 LEON3_BYPASS_STORE_PA(
151 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, 171 &leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0);
152 (((1000000 / HZ) - 1))); 172 LEON3_BYPASS_STORE_PA(
153 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); 173 &leon3_gptimer_regs->e[leon3_gptimer_idx].rld,
174 (((1000000 / HZ) - 1)));
175 LEON3_BYPASS_STORE_PA(
176 &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
154 177
155#ifdef CONFIG_SMP 178#ifdef CONFIG_SMP
156 leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; 179 leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
157 leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; 180 leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 +
181 leon3_gptimer_idx;
158 182
159 if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & 183 if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
160 (1<<LEON3_GPTIMER_SEPIRQ))) { 184 (1<<LEON3_GPTIMER_SEPIRQ))) {
@@ -162,9 +186,13 @@ void __init leon_init_timers(irq_handler_t counter_fn)
162 BUG(); 186 BUG();
163 } 187 }
164 188
165 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0); 189 LEON3_BYPASS_STORE_PA(
166 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); 190 &leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
167 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); 191 LEON3_BYPASS_STORE_PA(
192 &leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld,
193 (((1000000/HZ) - 1)));
194 LEON3_BYPASS_STORE_PA(
195 &leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
168# endif 196# endif
169 197
170 /* 198 /*
@@ -184,7 +212,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
184 goto bad; 212 goto bad;
185 } 213 }
186 214
187 irq = request_irq(leon3_gptimer_irq, 215 irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx,
188 counter_fn, 216 counter_fn,
189 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); 217 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
190 218
@@ -216,13 +244,13 @@ void __init leon_init_timers(irq_handler_t counter_fn)
216# endif 244# endif
217 245
218 if (leon3_gptimer_regs) { 246 if (leon3_gptimer_regs) {
219 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 247 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
220 LEON3_GPTIMER_EN | 248 LEON3_GPTIMER_EN |
221 LEON3_GPTIMER_RL | 249 LEON3_GPTIMER_RL |
222 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); 250 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
223 251
224#ifdef CONFIG_SMP 252#ifdef CONFIG_SMP
225 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 253 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
226 LEON3_GPTIMER_EN | 254 LEON3_GPTIMER_EN |
227 LEON3_GPTIMER_RL | 255 LEON3_GPTIMER_RL |
228 LEON3_GPTIMER_LD | 256 LEON3_GPTIMER_LD |