aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2012-01-19 08:53:50 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2012-04-27 08:35:34 -0400
commit0075242b3a2f78901172aaadf73beed762a1f02f (patch)
tree18a33963355c7dcbba0d6420c2fbefe430ef7907 /arch/arm
parent3f61c80eb7dff0fb35beb8068852d3fc902315a6 (diff)
ARM: architected timers: add DT support
Add runtime DT support and documentation for the Cortex A7/A15 architected timers. Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/include/asm/arch_timer.h6
-rw-r--r--arch/arm/kernel/arch_timer.c53
2 files changed, 52 insertions, 7 deletions
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index dc008c696b5a..935897f120b6 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -10,12 +10,18 @@ struct arch_timer {
10#ifdef CONFIG_ARM_ARCH_TIMER 10#ifdef CONFIG_ARM_ARCH_TIMER
11int arch_timer_register(struct arch_timer *); 11int arch_timer_register(struct arch_timer *);
12int arch_timer_sched_clock_init(void); 12int arch_timer_sched_clock_init(void);
13int arch_timer_of_register(void);
13#else 14#else
14static inline int arch_timer_register(struct arch_timer *at) 15static inline int arch_timer_register(struct arch_timer *at)
15{ 16{
16 return -ENXIO; 17 return -ENXIO;
17} 18}
18 19
20static inline int arch_timer_of_register(void)
21{
22 return -ENXIO;
23}
24
19static inline int arch_timer_sched_clock_init(void) 25static inline int arch_timer_sched_clock_init(void)
20{ 26{
21 return -ENXIO; 27 return -ENXIO;
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index dd907048f571..1a34eeebc26e 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -17,6 +17,7 @@
17#include <linux/jiffies.h> 17#include <linux/jiffies.h>
18#include <linux/clockchips.h> 18#include <linux/clockchips.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/of_irq.h>
20#include <linux/io.h> 21#include <linux/io.h>
21 22
22#include <asm/cputype.h> 23#include <asm/cputype.h>
@@ -245,13 +246,10 @@ static struct local_timer_ops arch_timer_ops __cpuinitdata = {
245 .stop = arch_timer_stop, 246 .stop = arch_timer_stop,
246}; 247};
247 248
248int __init arch_timer_register(struct arch_timer *at) 249static int __init arch_timer_common_register(void)
249{ 250{
250 int err; 251 int err;
251 252
252 if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ))
253 return -EINVAL;
254
255 err = arch_timer_available(); 253 err = arch_timer_available();
256 if (err) 254 if (err)
257 return err; 255 return err;
@@ -262,7 +260,6 @@ int __init arch_timer_register(struct arch_timer *at)
262 260
263 clocksource_register_hz(&clocksource_counter, arch_timer_rate); 261 clocksource_register_hz(&clocksource_counter, arch_timer_rate);
264 262
265 arch_timer_ppi = at->res[0].start;
266 err = request_percpu_irq(arch_timer_ppi, arch_timer_handler, 263 err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
267 "arch_timer", arch_timer_evt); 264 "arch_timer", arch_timer_evt);
268 if (err) { 265 if (err) {
@@ -271,8 +268,7 @@ int __init arch_timer_register(struct arch_timer *at)
271 goto out_free; 268 goto out_free;
272 } 269 }
273 270
274 if (at->res[1].start > 0 || (at->res[1].flags & IORESOURCE_IRQ)) { 271 if (arch_timer_ppi2) {
275 arch_timer_ppi2 = at->res[1].start;
276 err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler, 272 err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,
277 "arch_timer", arch_timer_evt); 273 "arch_timer", arch_timer_evt);
278 if (err) { 274 if (err) {
@@ -300,6 +296,49 @@ out_free:
300 return err; 296 return err;
301} 297}
302 298
299int __init arch_timer_register(struct arch_timer *at)
300{
301 if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ))
302 return -EINVAL;
303
304 arch_timer_ppi = at->res[0].start;
305
306 if (at->res[1].start > 0 || (at->res[1].flags & IORESOURCE_IRQ))
307 arch_timer_ppi2 = at->res[1].start;
308
309 return arch_timer_common_register();
310}
311
312#ifdef CONFIG_OF
313static const struct of_device_id arch_timer_of_match[] __initconst = {
314 { .compatible = "arm,armv7-timer", },
315 {},
316};
317
318int __init arch_timer_of_register(void)
319{
320 struct device_node *np;
321 u32 freq;
322
323 np = of_find_matching_node(NULL, arch_timer_of_match);
324 if (!np) {
325 pr_err("arch_timer: can't find DT node\n");
326 return -ENODEV;
327 }
328
329 /* Try to determine the frequency from the device tree or CNTFRQ */
330 if (!of_property_read_u32(np, "clock-frequency", &freq))
331 arch_timer_rate = freq;
332
333 arch_timer_ppi = irq_of_parse_and_map(np, 0);
334 arch_timer_ppi2 = irq_of_parse_and_map(np, 1);
335 pr_info("arch_timer: found %s irqs %d %d\n",
336 np->name, arch_timer_ppi, arch_timer_ppi2);
337
338 return arch_timer_common_register();
339}
340#endif
341
303int __init arch_timer_sched_clock_init(void) 342int __init arch_timer_sched_clock_init(void)
304{ 343{
305 int err; 344 int err;