blob: 2455d1f656739f5388ca89fe4f5a86eafa0defde [file] [log] [blame]
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -08001/*
2 * linux/arch/arm/kernel/arch_timer.c
3 *
4 * Copyright (C) 2011 ARM Ltd.
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/delay.h>
Sathish Ambley8a309822011-11-07 14:49:08 -080014#include <linux/timex.h>
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -080015#include <linux/device.h>
16#include <linux/smp.h>
17#include <linux/cpu.h>
18#include <linux/jiffies.h>
19#include <linux/clockchips.h>
20#include <linux/interrupt.h>
Marc Zyngierf2caa512012-01-19 13:53:50 +000021#include <linux/of_irq.h>
Abhimanyu Kapur05b66442012-05-31 23:28:23 -070022#include <linux/of_address.h>
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -080023#include <linux/io.h>
Sathish Ambley8a309822011-11-07 14:49:08 -080024#include <linux/irq.h>
Jeff Ohlstein57808a62012-07-16 13:39:26 -070025#include <linux/export.h>
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -080026
27#include <asm/cputype.h>
Marc Zyngierdf590cc2012-01-11 17:25:17 +000028#include <asm/localtimer.h>
29#include <asm/arch_timer.h>
Sathish Ambley8a309822011-11-07 14:49:08 -080030#include <asm/sched_clock.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070031#include <asm/hardware/gic.h>
32#include <asm/system_info.h>
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -080033
34static unsigned long arch_timer_rate;
35static int arch_timer_ppi;
36static int arch_timer_ppi2;
Abhimanyu Kapur05b66442012-05-31 23:28:23 -070037static int is_irq_percpu;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -080038
Marc Zyngierdf590cc2012-01-11 17:25:17 +000039static struct clock_event_device __percpu **arch_timer_evt;
Abhimanyu Kapur05b66442012-05-31 23:28:23 -070040static void __iomem *timer_base;
41
42static u32 timer_reg_read_cp15(int reg);
43static void timer_reg_write_cp15(int reg, u32 val);
44static inline cycle_t counter_get_cntpct_cp15(void);
45static inline cycle_t counter_get_cntvct_cp15(void);
46
47static u32 timer_reg_read_mem(int reg);
48static void timer_reg_write_mem(int reg, u32 val);
49static inline cycle_t counter_get_cntpct_mem(void);
50static inline cycle_t counter_get_cntvct_mem(void);
51
52struct arch_timer_operations {
53 void (*reg_write)(int, u32);
54 u32 (*reg_read)(int);
55 cycle_t (*get_cntpct)(void);
56 cycle_t (*get_cntvct)(void);
57};
58
59static struct arch_timer_operations arch_timer_ops_cp15 = {
60 .reg_read = &timer_reg_read_cp15,
61 .reg_write = &timer_reg_write_cp15,
62 .get_cntpct = &counter_get_cntpct_cp15,
63 .get_cntvct = &counter_get_cntvct_cp15,
64};
65
66static struct arch_timer_operations arch_timer_ops_mem = {
67 .reg_read = &timer_reg_read_mem,
68 .reg_write = &timer_reg_write_mem,
69 .get_cntpct = &counter_get_cntpct_mem,
70 .get_cntvct = &counter_get_cntvct_mem,
71};
72
73static struct arch_timer_operations *arch_specific_timer = &arch_timer_ops_cp15;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -080074
75/*
76 * Architected system timer support.
77 */
78
79#define ARCH_TIMER_CTRL_ENABLE (1 << 0)
80#define ARCH_TIMER_CTRL_IT_MASK (1 << 1)
Marc Zyngierdf590cc2012-01-11 17:25:17 +000081#define ARCH_TIMER_CTRL_IT_STAT (1 << 2)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -080082
83#define ARCH_TIMER_REG_CTRL 0
84#define ARCH_TIMER_REG_FREQ 1
85#define ARCH_TIMER_REG_TVAL 2
86
Abhimanyu Kapur05b66442012-05-31 23:28:23 -070087/* Iomapped Register Offsets */
88#define QTIMER_CNTP_LOW_REG 0x000
89#define QTIMER_CNTP_HIGH_REG 0x004
90#define QTIMER_CNTV_LOW_REG 0x008
91#define QTIMER_CNTV_HIGH_REG 0x00C
92#define QTIMER_CTRL_REG 0x02C
93#define QTIMER_FREQ_REG 0x010
94#define QTIMER_CNTP_TVAL_REG 0x028
95#define QTIMER_CNTV_TVAL_REG 0x038
96
97static void timer_reg_write_mem(int reg, u32 val)
98{
99 switch (reg) {
100 case ARCH_TIMER_REG_CTRL:
101 __raw_writel(val, timer_base + QTIMER_CTRL_REG);
102 break;
103 case ARCH_TIMER_REG_TVAL:
104 __raw_writel(val, timer_base + QTIMER_CNTP_TVAL_REG);
105 break;
106 }
107}
108
109static void timer_reg_write_cp15(int reg, u32 val)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800110{
111 switch (reg) {
112 case ARCH_TIMER_REG_CTRL:
113 asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
114 break;
115 case ARCH_TIMER_REG_TVAL:
116 asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
117 break;
118 }
119
120 isb();
121}
122
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700123static u32 timer_reg_read_mem(int reg)
124{
125 u32 val;
126
127 switch (reg) {
128 case ARCH_TIMER_REG_CTRL:
129 val = __raw_readl(timer_base + QTIMER_CTRL_REG);
130 break;
131 case ARCH_TIMER_REG_FREQ:
132 val = __raw_readl(timer_base + QTIMER_FREQ_REG);
133 break;
134 case ARCH_TIMER_REG_TVAL:
135 val = __raw_readl(timer_base + QTIMER_CNTP_TVAL_REG);
136 break;
137 default:
138 BUG();
139 }
140
141 return val;
142}
143
144static u32 timer_reg_read_cp15(int reg)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800145{
146 u32 val;
147
148 switch (reg) {
149 case ARCH_TIMER_REG_CTRL:
150 asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
151 break;
152 case ARCH_TIMER_REG_FREQ:
153 asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
154 break;
155 case ARCH_TIMER_REG_TVAL:
156 asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
157 break;
158 default:
159 BUG();
160 }
161
162 return val;
163}
164
165static irqreturn_t arch_timer_handler(int irq, void *dev_id)
166{
Sathish Ambley8a309822011-11-07 14:49:08 -0800167 struct clock_event_device *evt;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800168 unsigned long ctrl;
169
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700170 ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000171 if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800172 ctrl |= ARCH_TIMER_CTRL_IT_MASK;
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700173 arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL,
174 ctrl);
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000175 evt = *__this_cpu_ptr(arch_timer_evt);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800176 evt->event_handler(evt);
177 return IRQ_HANDLED;
178 }
179
180 return IRQ_NONE;
181}
182
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000183static void arch_timer_disable(void)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800184{
185 unsigned long ctrl;
186
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700187 ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800188 ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700189 arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800190}
191
192static void arch_timer_set_mode(enum clock_event_mode mode,
193 struct clock_event_device *clk)
194{
Subbaraman Narayanamurthye9ec85f2012-08-27 19:53:46 -0700195 unsigned long ctrl;
196
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800197 switch (mode) {
198 case CLOCK_EVT_MODE_UNUSED:
199 case CLOCK_EVT_MODE_SHUTDOWN:
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000200 arch_timer_disable();
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800201 break;
Subbaraman Narayanamurthye9ec85f2012-08-27 19:53:46 -0700202 case CLOCK_EVT_MODE_ONESHOT:
203 ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
204 ctrl |= ARCH_TIMER_CTRL_ENABLE;
205 arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800206 default:
207 break;
208 }
209}
210
211static int arch_timer_set_next_event(unsigned long evt,
212 struct clock_event_device *unused)
213{
214 unsigned long ctrl;
215
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700216 ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
Subbaraman Narayanamurthye9ec85f2012-08-27 19:53:46 -0700217 ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700218 arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
219 arch_specific_timer->reg_write(ARCH_TIMER_REG_TVAL, evt);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800220
221 return 0;
222}
223
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000224static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800225{
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000226 /* setup clock event only once for CPU 0 */
227 if (!smp_processor_id() && clk->irq == arch_timer_ppi)
228 return 0;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800229
230 /* Be safe... */
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000231 arch_timer_disable();
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800232
233 clk->features = CLOCK_EVT_FEAT_ONESHOT;
234 clk->name = "arch_sys_timer";
235 clk->rating = 450;
236 clk->set_mode = arch_timer_set_mode;
237 clk->set_next_event = arch_timer_set_next_event;
238 clk->irq = arch_timer_ppi;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800239
240 clockevents_config_and_register(clk, arch_timer_rate,
241 0xf, 0x7fffffff);
242
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000243 *__this_cpu_ptr(arch_timer_evt) = clk;
244
245 enable_percpu_irq(clk->irq, 0);
246 if (arch_timer_ppi2)
Trilok Sonieecb28c2011-07-20 16:24:14 +0100247 enable_percpu_irq(arch_timer_ppi2, 0);
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000248
249 return 0;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800250}
251
252/* Is the optional system timer available? */
253static int local_timer_is_architected(void)
254{
255 return (cpu_architecture() >= CPU_ARCH_ARMv7) &&
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700256 ((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800257}
258
259static int arch_timer_available(void)
260{
261 unsigned long freq;
262
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800263 if (arch_timer_rate == 0) {
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700264 arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, 0);
265 freq = arch_specific_timer->reg_read(ARCH_TIMER_REG_FREQ);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800266
267 /* Check the timer frequency. */
268 if (freq == 0) {
269 pr_warn("Architected timer frequency not available\n");
270 return -EINVAL;
271 }
272
273 arch_timer_rate = freq;
274 pr_info("Architected local timer running at %lu.%02luMHz.\n",
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000275 freq / 1000000, (freq / 10000) % 100);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800276 }
277
278 return 0;
279}
280
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700281static inline cycle_t counter_get_cntpct_mem(void)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800282{
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700283 u32 cvall, cvalh, thigh;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800284
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700285 do {
286 cvalh = __raw_readl(timer_base + QTIMER_CNTP_HIGH_REG);
287 cvall = __raw_readl(timer_base + QTIMER_CNTP_LOW_REG);
288 thigh = __raw_readl(timer_base + QTIMER_CNTP_HIGH_REG);
289 } while (cvalh != thigh);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800290
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000291 return ((cycle_t) cvalh << 32) | cvall;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800292}
293
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700294static inline cycle_t counter_get_cntpct_cp15(void)
295{
296 u32 cvall, cvalh;
297
298 asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
299 return ((cycle_t) cvalh << 32) | cvall;
300}
301
302static inline cycle_t counter_get_cntvct_mem(void)
303{
304 u32 cvall, cvalh, thigh;
305
306 do {
307 cvalh = __raw_readl(timer_base + QTIMER_CNTV_HIGH_REG);
308 cvall = __raw_readl(timer_base + QTIMER_CNTV_LOW_REG);
309 thigh = __raw_readl(timer_base + QTIMER_CNTV_HIGH_REG);
310 } while (cvalh != thigh);
311
312 return ((cycle_t) cvalh << 32) | cvall;
313}
314
315static inline cycle_t counter_get_cntvct_cp15(void)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800316{
317 u32 cvall, cvalh;
318
319 asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000320 return ((cycle_t) cvalh << 32) | cvall;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800321}
322
Jeff Ohlstein57808a62012-07-16 13:39:26 -0700323cycle_t arch_counter_get_cntpct(void)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800324{
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700325 return arch_specific_timer->get_cntpct();
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800326}
Jeff Ohlstein57808a62012-07-16 13:39:26 -0700327EXPORT_SYMBOL(arch_counter_get_cntpct);
328
329static cycle_t arch_counter_read(struct clocksource *cs)
330{
331 return arch_counter_get_cntpct();
332}
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800333
Sathish Ambley8a309822011-11-07 14:49:08 -0800334#ifdef ARCH_HAS_READ_CURRENT_TIMER
335int read_current_timer(unsigned long *timer_val)
336{
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700337 *timer_val = (unsigned long)arch_specific_timer->get_cntpct();
Sathish Ambley8a309822011-11-07 14:49:08 -0800338 return 0;
339}
340#endif
341
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800342static struct clocksource clocksource_counter = {
343 .name = "arch_sys_counter",
344 .rating = 400,
345 .read = arch_counter_read,
346 .mask = CLOCKSOURCE_MASK(56),
347 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
348};
349
Marc Zyngier165a4742011-11-11 14:30:44 -0800350static u32 arch_counter_get_cntvct32(void)
351{
352 cycle_t cntvct;
353
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700354 cntvct = arch_specific_timer->get_cntvct();
Marc Zyngier165a4742011-11-11 14:30:44 -0800355
356 /*
357 * The sched_clock infrastructure only knows about counters
358 * with at most 32bits. Forget about the upper 24 bits for the
359 * time being...
360 */
361 return (u32)(cntvct & (u32)~0);
362}
363
Steve Mucklef132c6c2012-06-06 18:30:57 -0700364static u32 notrace arch_timer_update_sched_clock(void)
Marc Zyngier165a4742011-11-11 14:30:44 -0800365{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700366 return arch_counter_get_cntvct32();
Marc Zyngier165a4742011-11-11 14:30:44 -0800367}
368
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000369static void __cpuinit arch_timer_stop(struct clock_event_device *clk)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800370{
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800371 pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
372 clk->irq, smp_processor_id());
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000373 disable_percpu_irq(clk->irq);
374 if (arch_timer_ppi2)
Trilok Sonieecb28c2011-07-20 16:24:14 +0100375 disable_percpu_irq(arch_timer_ppi2);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800376 arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
377}
378
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000379static struct local_timer_ops arch_timer_ops __cpuinitdata = {
380 .setup = arch_timer_setup,
381 .stop = arch_timer_stop,
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800382};
383
Marc Zyngierf2caa512012-01-19 13:53:50 +0000384static int __init arch_timer_common_register(void)
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800385{
386 int err;
387
Rohit Vaswani67770332012-06-18 13:27:45 -0700388 if (timer_base)
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700389 arch_specific_timer = &arch_timer_ops_mem;
Rohit Vaswani67770332012-06-18 13:27:45 -0700390 else if (!local_timer_is_architected())
391 return -ENXIO;
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700392
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800393 err = arch_timer_available();
394 if (err)
395 return err;
396
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000397 arch_timer_evt = alloc_percpu(struct clock_event_device *);
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800398 if (!arch_timer_evt)
399 return -ENOMEM;
400
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800401 clocksource_register_hz(&clocksource_counter, arch_timer_rate);
402
Steve Mucklef132c6c2012-06-06 18:30:57 -0700403 setup_sched_clock(arch_timer_update_sched_clock, 32, arch_timer_rate);
Sathish Ambley8a309822011-11-07 14:49:08 -0800404
405#ifdef ARCH_HAS_READ_CURRENT_TIMER
406 set_delay_fn(read_current_timer_delay_loop);
407#endif
408
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700409 if (is_irq_percpu)
410 err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000411 "arch_timer", arch_timer_evt);
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700412 else
413 err = request_irq(arch_timer_ppi, arch_timer_handler, 0,
414 "arch_timer", arch_timer_evt);
Sathish Ambley8a309822011-11-07 14:49:08 -0800415 if (err) {
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000416 pr_err("arch_timer: can't register interrupt %d (%d)\n",
417 arch_timer_ppi, err);
418 goto out_free;
Sathish Ambley8a309822011-11-07 14:49:08 -0800419 }
420
Marc Zyngierf2caa512012-01-19 13:53:50 +0000421 if (arch_timer_ppi2) {
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700422 if (is_irq_percpu)
423 err = request_percpu_irq(arch_timer_ppi2,
424 arch_timer_handler, "arch_timer",
425 arch_timer_evt);
426 else
427 err = request_irq(arch_timer_ppi2, arch_timer_handler,
428 0, "arch_timer", arch_timer_evt);
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000429 if (err) {
430 pr_err("arch_timer: can't register interrupt %d (%d)\n",
431 arch_timer_ppi2, err);
432 arch_timer_ppi2 = 0;
433 goto out_free_irq;
434 }
Sathish Ambley8a309822011-11-07 14:49:08 -0800435 }
Marc Zyngier165a4742011-11-11 14:30:44 -0800436
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000437 err = local_timer_register(&arch_timer_ops);
438 if (err)
439 goto out_free_irq;
440 percpu_timer_setup();
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800441
442 return 0;
Marc Zyngierdf590cc2012-01-11 17:25:17 +0000443
444out_free_irq:
445 free_percpu_irq(arch_timer_ppi, arch_timer_evt);
446 if (arch_timer_ppi2)
447 free_percpu_irq(arch_timer_ppi2, arch_timer_evt);
448
449out_free:
450 free_percpu(arch_timer_evt);
451
452 return err;
Marc Zyngierf5b3b2b2011-11-07 14:28:33 -0800453}
Marc Zyngierf2caa512012-01-19 13:53:50 +0000454
455int __init arch_timer_register(struct arch_timer *at)
456{
457 if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ))
458 return -EINVAL;
459
460 arch_timer_ppi = at->res[0].start;
461
462 if (at->res[1].start > 0 && (at->res[1].flags & IORESOURCE_IRQ))
463 arch_timer_ppi2 = at->res[1].start;
464
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700465 if (at->res[2].start > 0 && at->res[2].end > 0 &&
466 (at->res[2].flags & IORESOURCE_MEM))
467 timer_base = ioremap(at->res[2].start,
468 resource_size(&at->res[2]));
469
470 if (!timer_base) {
471 pr_err("arch_timer: cant map timer base\n");
472 return -ENOMEM;
473 }
474
Marc Zyngierf2caa512012-01-19 13:53:50 +0000475 return arch_timer_common_register();
476}
477
478#ifdef CONFIG_OF
479static const struct of_device_id arch_timer_of_match[] __initconst = {
480 { .compatible = "arm,armv7-timer", },
481 {},
482};
483
484int __init arch_timer_of_register(void)
485{
486 struct device_node *np;
487 u32 freq;
488 int ret;
489
490 np = of_find_matching_node(NULL, arch_timer_of_match);
491 if (!np) {
492 pr_err("arch_timer: can't find DT node\n");
493 return -ENODEV;
494 }
495
496 /* Try to determine the frequency from the device tree or CNTFRQ */
497 if (!of_property_read_u32(np, "clock-frequency", &freq))
498 arch_timer_rate = freq;
499
500 ret = irq_of_parse_and_map(np, 0);
501 if (ret <= 0) {
502 pr_err("arch_timer: interrupt not specified in timer node\n");
503 return -ENODEV;
504 }
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700505
Rohit Vaswani67770332012-06-18 13:27:45 -0700506 if (of_get_address(np, 0, NULL, NULL)) {
507 timer_base = of_iomap(np, 0);
508 if (!timer_base) {
509 pr_err("arch_timer: cant map timer base\n");
510 return -ENOMEM;
511 }
Abhimanyu Kapur05b66442012-05-31 23:28:23 -0700512 }
513
514 if (of_get_property(np, "irq-is-not-percpu", NULL))
515 is_irq_percpu = 0;
516 else
517 is_irq_percpu = 1;
518
Marc Zyngierf2caa512012-01-19 13:53:50 +0000519 arch_timer_ppi = ret;
520 ret = irq_of_parse_and_map(np, 1);
521 if (ret > 0)
522 arch_timer_ppi2 = ret;
523 pr_info("arch_timer: found %s irqs %d %d\n",
524 np->name, arch_timer_ppi, arch_timer_ppi2);
525
526 return arch_timer_common_register();
527}
528#endif