diff options
Diffstat (limited to 'arch/microblaze/kernel/timer.c')
-rw-r--r-- | arch/microblaze/kernel/timer.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 3e39b1082fdf..fb0c61443f19 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c | |||
@@ -12,12 +12,12 @@ | |||
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/sched_clock.h> | ||
15 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
16 | #include <linux/clockchips.h> | 17 | #include <linux/clockchips.h> |
17 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
18 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
19 | #include <asm/cpuinfo.h> | 20 | #include <asm/cpuinfo.h> |
20 | #include <linux/cnt32_to_63.h> | ||
21 | 21 | ||
22 | static void __iomem *timer_baseaddr; | 22 | static void __iomem *timer_baseaddr; |
23 | 23 | ||
@@ -167,10 +167,15 @@ static __init void xilinx_clockevent_init(void) | |||
167 | clockevents_register_device(&clockevent_xilinx_timer); | 167 | clockevents_register_device(&clockevent_xilinx_timer); |
168 | } | 168 | } |
169 | 169 | ||
170 | static u64 xilinx_clock_read(void) | ||
171 | { | ||
172 | return in_be32(timer_baseaddr + TCR1); | ||
173 | } | ||
174 | |||
170 | static cycle_t xilinx_read(struct clocksource *cs) | 175 | static cycle_t xilinx_read(struct clocksource *cs) |
171 | { | 176 | { |
172 | /* reading actual value of timer 1 */ | 177 | /* reading actual value of timer 1 */ |
173 | return (cycle_t) (in_be32(timer_baseaddr + TCR1)); | 178 | return (cycle_t)xilinx_clock_read(); |
174 | } | 179 | } |
175 | 180 | ||
176 | static struct timecounter xilinx_tc = { | 181 | static struct timecounter xilinx_tc = { |
@@ -222,17 +227,17 @@ static int __init xilinx_clocksource_init(void) | |||
222 | return 0; | 227 | return 0; |
223 | } | 228 | } |
224 | 229 | ||
225 | /* | ||
226 | * We have to protect accesses before timer initialization | ||
227 | * and return 0 for sched_clock function below. | ||
228 | */ | ||
229 | static int timer_initialized; | ||
230 | |||
231 | static void __init xilinx_timer_init(struct device_node *timer) | 230 | static void __init xilinx_timer_init(struct device_node *timer) |
232 | { | 231 | { |
232 | struct clk *clk; | ||
233 | static int initialized; | ||
233 | u32 irq; | 234 | u32 irq; |
234 | u32 timer_num = 1; | 235 | u32 timer_num = 1; |
235 | int ret; | 236 | |
237 | if (initialized) | ||
238 | return; | ||
239 | |||
240 | initialized = 1; | ||
236 | 241 | ||
237 | timer_baseaddr = of_iomap(timer, 0); | 242 | timer_baseaddr = of_iomap(timer, 0); |
238 | if (!timer_baseaddr) { | 243 | if (!timer_baseaddr) { |
@@ -250,10 +255,20 @@ static void __init xilinx_timer_init(struct device_node *timer) | |||
250 | 255 | ||
251 | pr_info("%s: irq=%d\n", timer->full_name, irq); | 256 | pr_info("%s: irq=%d\n", timer->full_name, irq); |
252 | 257 | ||
253 | /* If there is clock-frequency property than use it */ | 258 | clk = of_clk_get(timer, 0); |
254 | ret = of_property_read_u32(timer, "clock-frequency", &timer_clock_freq); | 259 | if (IS_ERR(clk)) { |
255 | if (ret < 0) | 260 | pr_err("ERROR: timer CCF input clock not found\n"); |
261 | /* If there is clock-frequency property than use it */ | ||
262 | of_property_read_u32(timer, "clock-frequency", | ||
263 | &timer_clock_freq); | ||
264 | } else { | ||
265 | timer_clock_freq = clk_get_rate(clk); | ||
266 | } | ||
267 | |||
268 | if (!timer_clock_freq) { | ||
269 | pr_err("ERROR: Using CPU clock frequency\n"); | ||
256 | timer_clock_freq = cpuinfo.cpu_clock_freq; | 270 | timer_clock_freq = cpuinfo.cpu_clock_freq; |
271 | } | ||
257 | 272 | ||
258 | freq_div_hz = timer_clock_freq / HZ; | 273 | freq_div_hz = timer_clock_freq / HZ; |
259 | 274 | ||
@@ -263,18 +278,8 @@ static void __init xilinx_timer_init(struct device_node *timer) | |||
263 | #endif | 278 | #endif |
264 | xilinx_clocksource_init(); | 279 | xilinx_clocksource_init(); |
265 | xilinx_clockevent_init(); | 280 | xilinx_clockevent_init(); |
266 | timer_initialized = 1; | ||
267 | } | ||
268 | 281 | ||
269 | unsigned long long notrace sched_clock(void) | 282 | sched_clock_register(xilinx_clock_read, 32, timer_clock_freq); |
270 | { | ||
271 | if (timer_initialized) { | ||
272 | struct clocksource *cs = &clocksource_microblaze; | ||
273 | |||
274 | cycle_t cyc = cnt32_to_63(cs->read(NULL)) & LLONG_MAX; | ||
275 | return clocksource_cyc2ns(cyc, cs->mult, cs->shift); | ||
276 | } | ||
277 | return 0; | ||
278 | } | 283 | } |
279 | 284 | ||
280 | CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a", | 285 | CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a", |