aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/lib/delay.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lib/delay.c')
-rw-r--r--arch/arm/lib/delay.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c
index d6dacc69254e..9d0a30032d7f 100644
--- a/arch/arm/lib/delay.c
+++ b/arch/arm/lib/delay.c
@@ -34,7 +34,18 @@ struct arm_delay_ops arm_delay_ops = {
34 .udelay = __loop_udelay, 34 .udelay = __loop_udelay,
35}; 35};
36 36
37#ifdef ARCH_HAS_READ_CURRENT_TIMER 37static const struct delay_timer *delay_timer;
38static bool delay_calibrated;
39
40int read_current_timer(unsigned long *timer_val)
41{
42 if (!delay_timer)
43 return -ENXIO;
44
45 *timer_val = delay_timer->read_current_timer();
46 return 0;
47}
48
38static void __timer_delay(unsigned long cycles) 49static void __timer_delay(unsigned long cycles)
39{ 50{
40 cycles_t start = get_cycles(); 51 cycles_t start = get_cycles();
@@ -55,17 +66,24 @@ static void __timer_udelay(unsigned long usecs)
55 __timer_const_udelay(usecs * UDELAY_MULT); 66 __timer_const_udelay(usecs * UDELAY_MULT);
56} 67}
57 68
58void __init init_current_timer_delay(unsigned long freq) 69void __init register_current_timer_delay(const struct delay_timer *timer)
59{ 70{
60 pr_info("Switching to timer-based delay loop\n"); 71 if (!delay_calibrated) {
61 lpj_fine = freq / HZ; 72 pr_info("Switching to timer-based delay loop\n");
62 arm_delay_ops.delay = __timer_delay; 73 delay_timer = timer;
63 arm_delay_ops.const_udelay = __timer_const_udelay; 74 lpj_fine = timer->freq / HZ;
64 arm_delay_ops.udelay = __timer_udelay; 75 loops_per_jiffy = lpj_fine;
76 arm_delay_ops.delay = __timer_delay;
77 arm_delay_ops.const_udelay = __timer_const_udelay;
78 arm_delay_ops.udelay = __timer_udelay;
79 delay_calibrated = true;
80 } else {
81 pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
82 }
65} 83}
66 84
67unsigned long __cpuinit calibrate_delay_is_known(void) 85unsigned long __cpuinit calibrate_delay_is_known(void)
68{ 86{
87 delay_calibrated = true;
69 return lpj_fine; 88 return lpj_fine;
70} 89}
71#endif