aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/smp_twd.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/smp_twd.c')
-rw-r--r--arch/arm/kernel/smp_twd.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index f0575610b17e..a9783947c086 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -10,8 +10,10 @@
10 */ 10 */
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/clk.h>
13#include <linux/delay.h> 14#include <linux/delay.h>
14#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/err.h>
15#include <linux/smp.h> 17#include <linux/smp.h>
16#include <linux/jiffies.h> 18#include <linux/jiffies.h>
17#include <linux/clockchips.h> 19#include <linux/clockchips.h>
@@ -25,6 +27,7 @@
25/* set up by the platform code */ 27/* set up by the platform code */
26void __iomem *twd_base; 28void __iomem *twd_base;
27 29
30static struct clk *twd_clk;
28static unsigned long twd_timer_rate; 31static unsigned long twd_timer_rate;
29 32
30static struct clock_event_device __percpu **twd_evt; 33static struct clock_event_device __percpu **twd_evt;
@@ -140,6 +143,35 @@ static irqreturn_t twd_handler(int irq, void *dev_id)
140 return IRQ_NONE; 143 return IRQ_NONE;
141} 144}
142 145
146static struct clk *twd_get_clock(void)
147{
148 struct clk *clk;
149 int err;
150
151 clk = clk_get_sys("smp_twd", NULL);
152 if (IS_ERR(clk)) {
153 pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk));
154 return clk;
155 }
156
157 err = clk_prepare(clk);
158 if (err) {
159 pr_err("smp_twd: clock failed to prepare: %d\n", err);
160 clk_put(clk);
161 return ERR_PTR(err);
162 }
163
164 err = clk_enable(clk);
165 if (err) {
166 pr_err("smp_twd: clock failed to enable: %d\n", err);
167 clk_unprepare(clk);
168 clk_put(clk);
169 return ERR_PTR(err);
170 }
171
172 return clk;
173}
174
143/* 175/*
144 * Setup the local clock events for a CPU. 176 * Setup the local clock events for a CPU.
145 */ 177 */
@@ -165,7 +197,13 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
165 } 197 }
166 } 198 }
167 199
168 twd_calibrate_rate(); 200 if (!twd_clk)
201 twd_clk = twd_get_clock();
202
203 if (!IS_ERR_OR_NULL(twd_clk))
204 twd_timer_rate = clk_get_rate(twd_clk);
205 else
206 twd_calibrate_rate();
169 207
170 clk->name = "local_timer"; 208 clk->name = "local_timer";
171 clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | 209 clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |