aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-10-16 18:20:48 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-10-17 13:28:47 -0400
commitb0d4056dd6f16eca63114d0c252b214449a13cca (patch)
tree50c55bdd330574fcdb718e4192d02b91f2aaa551 /arch/mips
parent60b0d65541b581955279221e060f8a0a221151b4 (diff)
[MIPS] Probe for usability of cp0 compare interrupt.
Some processors offer the option of using the interrupt on which normally the count / compare interrupt would be signaled as a normal interupt pin. Previously this required some ugly hackery for each system which is much easier done by a quick and simple probe. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/time.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 05b365167a09..e4b5e647b142 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -391,6 +391,50 @@ static void mips_event_handler(struct clock_event_device *dev)
391{ 391{
392} 392}
393 393
394/*
395 * FIXME: This doesn't hold for the relocated E9000 compare interrupt.
396 */
397static int c0_compare_int_pending(void)
398{
399 return (read_c0_cause() >> cp0_compare_irq) & 0x100;
400}
401
402static int c0_compare_int_usable(void)
403{
404 const unsigned int delta = 0x300000;
405 unsigned int cnt;
406
407 /*
408 * IP7 already pending? Try to clear it by acking the timer.
409 */
410 if (c0_compare_int_pending()) {
411 write_c0_compare(read_c0_compare());
412 irq_disable_hazard();
413 if (c0_compare_int_pending())
414 return 0;
415 }
416
417 cnt = read_c0_count();
418 cnt += delta;
419 write_c0_compare(cnt);
420
421 while ((long)(read_c0_count() - cnt) <= 0)
422 ; /* Wait for expiry */
423
424 if (!c0_compare_int_pending())
425 return 0;
426
427 write_c0_compare(read_c0_compare());
428 irq_disable_hazard();
429 if (c0_compare_int_pending())
430 return 0;
431
432 /*
433 * Feels like a real count / compare timer.
434 */
435 return 1;
436}
437
394void __cpuinit mips_clockevent_init(void) 438void __cpuinit mips_clockevent_init(void)
395{ 439{
396 uint64_t mips_freq = mips_hpt_frequency; 440 uint64_t mips_freq = mips_hpt_frequency;
@@ -412,6 +456,9 @@ void __cpuinit mips_clockevent_init(void)
412 return; 456 return;
413#endif 457#endif
414 458
459 if (!c0_compare_int_usable())
460 return;
461
415 cd = &per_cpu(mips_clockevent_device, cpu); 462 cd = &per_cpu(mips_clockevent_device, cpu);
416 463
417 cd->name = "MIPS"; 464 cd->name = "MIPS";