diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/kernel/leon_kernel.c | 80 |
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; | |||
32 | static int dummy_master_l10_counter; | 32 | static int dummy_master_l10_counter; |
33 | 33 | ||
34 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ | 34 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ |
35 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ | ||
35 | unsigned int sparc_leon_eirq; | 36 | unsigned 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) | |||
105 | void __init leon_init_timers(irq_handler_t counter_fn) | 106 | void __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 | |