diff options
Diffstat (limited to 'arch/arm/lib/delay.c')
-rw-r--r-- | arch/arm/lib/delay.c | 34 |
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 | 37 | static const struct delay_timer *delay_timer; |
38 | static bool delay_calibrated; | ||
39 | |||
40 | int 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 | |||
38 | static void __timer_delay(unsigned long cycles) | 49 | static 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 | ||
58 | void __init init_current_timer_delay(unsigned long freq) | 69 | void __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 | ||
67 | unsigned long __cpuinit calibrate_delay_is_known(void) | 85 | unsigned 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 | ||