diff options
Diffstat (limited to 'arch/ia64/sn/kernel/sn2/timer.c')
-rw-r--r-- | arch/ia64/sn/kernel/sn2/timer.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index deb9baf4d473..56a88b6df4b4 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <asm/hw_irq.h> | 15 | #include <asm/hw_irq.h> |
16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
17 | #include <asm/timex.h> | ||
17 | 18 | ||
18 | #include <asm/sn/leds.h> | 19 | #include <asm/sn/leds.h> |
19 | #include <asm/sn/shub_mmr.h> | 20 | #include <asm/sn/shub_mmr.h> |
@@ -28,9 +29,27 @@ static struct time_interpolator sn2_interpolator = { | |||
28 | .source = TIME_SOURCE_MMIO64 | 29 | .source = TIME_SOURCE_MMIO64 |
29 | }; | 30 | }; |
30 | 31 | ||
32 | /* | ||
33 | * sn udelay uses the RTC instead of the ITC because the ITC is not | ||
34 | * synchronized across all CPUs, and the thread may migrate to another CPU | ||
35 | * if preemption is enabled. | ||
36 | */ | ||
37 | static void | ||
38 | ia64_sn_udelay (unsigned long usecs) | ||
39 | { | ||
40 | unsigned long start = rtc_time(); | ||
41 | unsigned long end = start + | ||
42 | usecs * sn_rtc_cycles_per_second / 1000000; | ||
43 | |||
44 | while (time_before((unsigned long)rtc_time(), end)) | ||
45 | cpu_relax(); | ||
46 | } | ||
47 | |||
31 | void __init sn_timer_init(void) | 48 | void __init sn_timer_init(void) |
32 | { | 49 | { |
33 | sn2_interpolator.frequency = sn_rtc_cycles_per_second; | 50 | sn2_interpolator.frequency = sn_rtc_cycles_per_second; |
34 | sn2_interpolator.addr = RTC_COUNTER_ADDR; | 51 | sn2_interpolator.addr = RTC_COUNTER_ADDR; |
35 | register_time_interpolator(&sn2_interpolator); | 52 | register_time_interpolator(&sn2_interpolator); |
53 | |||
54 | ia64_udelay = &ia64_sn_udelay; | ||
36 | } | 55 | } |