diff options
Diffstat (limited to 'arch/mips/kernel/cevt-r4k.c')
-rw-r--r-- | arch/mips/kernel/cevt-r4k.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index ae2984fff580..bab935a3d74b 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c | |||
@@ -28,7 +28,7 @@ static int mips_next_event(unsigned long delta, | |||
28 | cnt = read_c0_count(); | 28 | cnt = read_c0_count(); |
29 | cnt += delta; | 29 | cnt += delta; |
30 | write_c0_compare(cnt); | 30 | write_c0_compare(cnt); |
31 | res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0; | 31 | res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; |
32 | #ifdef CONFIG_MIPS_MT_SMTC | 32 | #ifdef CONFIG_MIPS_MT_SMTC |
33 | evpe(vpflags); | 33 | evpe(vpflags); |
34 | local_irq_restore(flags); | 34 | local_irq_restore(flags); |
@@ -179,7 +179,7 @@ static int c0_compare_int_pending(void) | |||
179 | 179 | ||
180 | static int c0_compare_int_usable(void) | 180 | static int c0_compare_int_usable(void) |
181 | { | 181 | { |
182 | const unsigned int delta = 0x300000; | 182 | unsigned int delta; |
183 | unsigned int cnt; | 183 | unsigned int cnt; |
184 | 184 | ||
185 | /* | 185 | /* |
@@ -192,11 +192,17 @@ static int c0_compare_int_usable(void) | |||
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
194 | 194 | ||
195 | cnt = read_c0_count(); | 195 | for (delta = 0x10; delta <= 0x400000; delta <<= 1) { |
196 | cnt += delta; | 196 | cnt = read_c0_count(); |
197 | write_c0_compare(cnt); | 197 | cnt += delta; |
198 | write_c0_compare(cnt); | ||
199 | irq_disable_hazard(); | ||
200 | if ((int)(read_c0_count() - cnt) < 0) | ||
201 | break; | ||
202 | /* increase delta if the timer was already expired */ | ||
203 | } | ||
198 | 204 | ||
199 | while ((long)(read_c0_count() - cnt) <= 0) | 205 | while ((int)(read_c0_count() - cnt) <= 0) |
200 | ; /* Wait for expiry */ | 206 | ; /* Wait for expiry */ |
201 | 207 | ||
202 | if (!c0_compare_int_pending()) | 208 | if (!c0_compare_int_pending()) |
@@ -218,9 +224,9 @@ void __cpuinit mips_clockevent_init(void) | |||
218 | uint64_t mips_freq = mips_hpt_frequency; | 224 | uint64_t mips_freq = mips_hpt_frequency; |
219 | unsigned int cpu = smp_processor_id(); | 225 | unsigned int cpu = smp_processor_id(); |
220 | struct clock_event_device *cd; | 226 | struct clock_event_device *cd; |
221 | unsigned int irq = MIPS_CPU_IRQ_BASE + 7; | 227 | unsigned int irq; |
222 | 228 | ||
223 | if (!cpu_has_counter) | 229 | if (!cpu_has_counter || !mips_hpt_frequency) |
224 | return; | 230 | return; |
225 | 231 | ||
226 | #ifdef CONFIG_MIPS_MT_SMTC | 232 | #ifdef CONFIG_MIPS_MT_SMTC |
@@ -237,6 +243,15 @@ void __cpuinit mips_clockevent_init(void) | |||
237 | if (!c0_compare_int_usable()) | 243 | if (!c0_compare_int_usable()) |
238 | return; | 244 | return; |
239 | 245 | ||
246 | /* | ||
247 | * With vectored interrupts things are getting platform specific. | ||
248 | * get_c0_compare_int is a hook to allow a platform to return the | ||
249 | * interrupt number of it's liking. | ||
250 | */ | ||
251 | irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; | ||
252 | if (get_c0_compare_int) | ||
253 | irq = get_c0_compare_int(); | ||
254 | |||
240 | cd = &per_cpu(mips_clockevent_device, cpu); | 255 | cd = &per_cpu(mips_clockevent_device, cpu); |
241 | 256 | ||
242 | cd->name = "MIPS"; | 257 | cd->name = "MIPS"; |
@@ -261,13 +276,15 @@ void __cpuinit mips_clockevent_init(void) | |||
261 | 276 | ||
262 | clockevents_register_device(cd); | 277 | clockevents_register_device(cd); |
263 | 278 | ||
264 | if (!cp0_timer_irq_installed) { | 279 | if (!cp0_timer_irq_installed) |
280 | return; | ||
281 | |||
282 | cp0_timer_irq_installed = 1; | ||
283 | |||
265 | #ifdef CONFIG_MIPS_MT_SMTC | 284 | #ifdef CONFIG_MIPS_MT_SMTC |
266 | #define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) | 285 | #define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) |
267 | setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); | 286 | setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); |
268 | #else | 287 | #else |
269 | setup_irq(irq, &c0_compare_irqaction); | 288 | setup_irq(irq, &c0_compare_irqaction); |
270 | #endif /* CONFIG_MIPS_MT_SMTC */ | 289 | #endif |
271 | cp0_timer_irq_installed = 1; | ||
272 | } | ||
273 | } | 290 | } |