From 022c03a2d650c641fa0f94dbc9d9ff77f8057678 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 11 Jan 2012 17:25:17 +0000 Subject: ARM: local timers: Add A15 architected timer support Add support for the A15 generic timer and clocksource. As the timer generates interrupts on a different PPI depending on the execution mode (normal or secure), it is possible to register two different PPIs. Signed-off-by: Marc Zyngier --- arch/arm/include/asm/arch_timer.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 arch/arm/include/asm/arch_timer.h (limited to 'arch/arm/include/asm/arch_timer.h') diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h new file mode 100644 index 00000000000..827305d77b3 --- /dev/null +++ b/arch/arm/include/asm/arch_timer.h @@ -0,0 +1,19 @@ +#ifndef __ASMARM_ARCH_TIMER_H +#define __ASMARM_ARCH_TIMER_H + +#include + +struct arch_timer { + struct resource res[2]; +}; + +#ifdef CONFIG_ARM_ARCH_TIMER +int arch_timer_register(struct arch_timer *); +#else +static inline int arch_timer_register(struct arch_timer *at) +{ + return -ENXIO; +} +#endif + +#endif -- cgit v1.2.3-70-g09d2 From 3f61c80eb7dff0fb35beb8068852d3fc902315a6 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 14 Jan 2011 15:32:36 +0000 Subject: ARM: architected timers: Add A15 specific sched_clock implementation Provide an A15 sched_clock implementation using the virtual counter, which is thought to be more useful than the physical one in a virtualised environment, as it can offset the time spent in another VM or the hypervisor. Acked-by: Catalin Marinas Signed-off-by: Marc Zyngier --- arch/arm/include/asm/arch_timer.h | 6 ++++++ arch/arm/kernel/arch_timer.c | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'arch/arm/include/asm/arch_timer.h') diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 827305d77b3..dc008c696b5 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -9,11 +9,17 @@ struct arch_timer { #ifdef CONFIG_ARM_ARCH_TIMER int arch_timer_register(struct arch_timer *); +int arch_timer_sched_clock_init(void); #else static inline int arch_timer_register(struct arch_timer *at) { return -ENXIO; } + +static inline int arch_timer_sched_clock_init(void) +{ + return -ENXIO; +} #endif #endif diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index bb9a8b45bff..dd907048f57 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -23,6 +23,7 @@ #include #include #include +#include static unsigned long arch_timer_rate; static int arch_timer_ppi; @@ -204,6 +205,18 @@ static inline cycle_t arch_counter_get_cntvct(void) return ((cycle_t) cvalh << 32) | cvall; } +static u32 notrace arch_counter_get_cntvct32(void) +{ + cycle_t cntvct = arch_counter_get_cntvct(); + + /* + * The sched_clock infrastructure only knows about counters + * with at most 32bits. Forget about the upper 24 bits for the + * time being... + */ + return (u32)(cntvct & (u32)~0); +} + static cycle_t arch_counter_read(struct clocksource *cs) { return arch_counter_get_cntpct(); @@ -286,3 +299,15 @@ out_free: return err; } + +int __init arch_timer_sched_clock_init(void) +{ + int err; + + err = arch_timer_available(); + if (err) + return err; + + setup_sched_clock(arch_counter_get_cntvct32, 32, arch_timer_rate); + return 0; +} -- cgit v1.2.3-70-g09d2 From 0075242b3a2f78901172aaadf73beed762a1f02f Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 19 Jan 2012 13:53:50 +0000 Subject: ARM: architected timers: add DT support Add runtime DT support and documentation for the Cortex A7/A15 architected timers. Signed-off-by: Will Deacon Signed-off-by: Marc Zyngier --- .../devicetree/bindings/arm/arch_timer.txt | 27 +++++++++++ arch/arm/include/asm/arch_timer.h | 6 +++ arch/arm/kernel/arch_timer.c | 53 +++++++++++++++++++--- 3 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/arch_timer.txt (limited to 'arch/arm/include/asm/arch_timer.h') diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt new file mode 100644 index 00000000000..52478c83d0c --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt @@ -0,0 +1,27 @@ +* ARM architected timer + +ARM Cortex-A7 and Cortex-A15 have a per-core architected timer, which +provides per-cpu timers. + +The timer is attached to a GIC to deliver its per-processor interrupts. + +** Timer node properties: + +- compatible : Should at least contain "arm,armv7-timer". + +- interrupts : Interrupt list for secure, non-secure, virtual and + hypervisor timers, in that order. + +- clock-frequency : The frequency of the main counter, in Hz. Optional. + +Example: + + timer { + compatible = "arm,cortex-a15-timer", + "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + clock-frequency = <100000000>; + }; diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index dc008c696b5..935897f120b 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -10,12 +10,18 @@ struct arch_timer { #ifdef CONFIG_ARM_ARCH_TIMER int arch_timer_register(struct arch_timer *); int arch_timer_sched_clock_init(void); +int arch_timer_of_register(void); #else static inline int arch_timer_register(struct arch_timer *at) { return -ENXIO; } +static inline int arch_timer_of_register(void) +{ + return -ENXIO; +} + static inline int arch_timer_sched_clock_init(void) { return -ENXIO; diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index dd907048f57..1a34eeebc26 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -245,13 +246,10 @@ static struct local_timer_ops arch_timer_ops __cpuinitdata = { .stop = arch_timer_stop, }; -int __init arch_timer_register(struct arch_timer *at) +static int __init arch_timer_common_register(void) { int err; - if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ)) - return -EINVAL; - err = arch_timer_available(); if (err) return err; @@ -262,7 +260,6 @@ int __init arch_timer_register(struct arch_timer *at) clocksource_register_hz(&clocksource_counter, arch_timer_rate); - arch_timer_ppi = at->res[0].start; err = request_percpu_irq(arch_timer_ppi, arch_timer_handler, "arch_timer", arch_timer_evt); if (err) { @@ -271,8 +268,7 @@ int __init arch_timer_register(struct arch_timer *at) goto out_free; } - if (at->res[1].start > 0 || (at->res[1].flags & IORESOURCE_IRQ)) { - arch_timer_ppi2 = at->res[1].start; + if (arch_timer_ppi2) { err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler, "arch_timer", arch_timer_evt); if (err) { @@ -300,6 +296,49 @@ out_free: return err; } +int __init arch_timer_register(struct arch_timer *at) +{ + if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ)) + return -EINVAL; + + arch_timer_ppi = at->res[0].start; + + if (at->res[1].start > 0 || (at->res[1].flags & IORESOURCE_IRQ)) + arch_timer_ppi2 = at->res[1].start; + + return arch_timer_common_register(); +} + +#ifdef CONFIG_OF +static const struct of_device_id arch_timer_of_match[] __initconst = { + { .compatible = "arm,armv7-timer", }, + {}, +}; + +int __init arch_timer_of_register(void) +{ + struct device_node *np; + u32 freq; + + np = of_find_matching_node(NULL, arch_timer_of_match); + if (!np) { + pr_err("arch_timer: can't find DT node\n"); + return -ENODEV; + } + + /* Try to determine the frequency from the device tree or CNTFRQ */ + if (!of_property_read_u32(np, "clock-frequency", &freq)) + arch_timer_rate = freq; + + arch_timer_ppi = irq_of_parse_and_map(np, 0); + arch_timer_ppi2 = irq_of_parse_and_map(np, 1); + pr_info("arch_timer: found %s irqs %d %d\n", + np->name, arch_timer_ppi, arch_timer_ppi2); + + return arch_timer_common_register(); +} +#endif + int __init arch_timer_sched_clock_init(void) { int err; -- cgit v1.2.3-70-g09d2 From fb8a99f9f6bdc908cbbd2284cee80c709d9f7c03 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Apr 2012 13:18:42 +0100 Subject: ARM: architected timers: remove support for non DT platforms All mainline platforms using the ARM architected timers are DT only. As such, remove the ad-hoc support that is not longer needed anymore. Signed-off-by: Marc Zyngier --- arch/arm/include/asm/arch_timer.h | 14 +------------- arch/arm/kernel/arch_timer.c | 19 ++----------------- 2 files changed, 3 insertions(+), 30 deletions(-) (limited to 'arch/arm/include/asm/arch_timer.h') diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 935897f120b..ed2e95d46e2 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -1,22 +1,10 @@ #ifndef __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H -#include - -struct arch_timer { - struct resource res[2]; -}; - #ifdef CONFIG_ARM_ARCH_TIMER -int arch_timer_register(struct arch_timer *); -int arch_timer_sched_clock_init(void); int arch_timer_of_register(void); +int arch_timer_sched_clock_init(void); #else -static inline int arch_timer_register(struct arch_timer *at) -{ - return -ENXIO; -} - static inline int arch_timer_of_register(void) { return -ENXIO; diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index 154f0a1756b..dd58035621f 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -248,7 +248,7 @@ static struct local_timer_ops arch_timer_ops __cpuinitdata = { static struct clock_event_device arch_timer_global_evt; -static int __init arch_timer_common_register(void) +static int __init arch_timer_register(void) { int err; @@ -309,20 +309,6 @@ out_free: return err; } -int __init arch_timer_register(struct arch_timer *at) -{ - if (at->res[0].start <= 0 || !(at->res[0].flags & IORESOURCE_IRQ)) - return -EINVAL; - - arch_timer_ppi = at->res[0].start; - - if (at->res[1].start > 0 || (at->res[1].flags & IORESOURCE_IRQ)) - arch_timer_ppi2 = at->res[1].start; - - return arch_timer_common_register(); -} - -#ifdef CONFIG_OF static const struct of_device_id arch_timer_of_match[] __initconst = { { .compatible = "arm,armv7-timer", }, {}, @@ -348,9 +334,8 @@ int __init arch_timer_of_register(void) pr_info("arch_timer: found %s irqs %d %d\n", np->name, arch_timer_ppi, arch_timer_ppi2); - return arch_timer_common_register(); + return arch_timer_register(); } -#endif int __init arch_timer_sched_clock_init(void) { -- cgit v1.2.3-70-g09d2