A7/A15 architected timer support
Subsystems (3)
v2 cover A7/A15 architected timer support
This patch series adds support for the architected timers found in Cortex-A7 and Cortex-A15. It adds local timer support, sched_clock, global timer and DT support.
Tested on Cortex A15, based on Russell's for-armsoc branch plus my local timer series.
Branch also available at:git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git arch_timers-for-rmk
* From the initial revision:
- Fixed global timer registration when an SMP kernel is running on UP with LOCAL_TIMERS enabled.
Marc Zyngier (4):
ARM: local timers: Add A15 architected timer support
ARM: architected timers: Add A15 specific sched_clock implementation
ARM: architected timers: add DT support
ARM: architected timers: add support for UP timer
.../devicetree/bindings/arm/arch_timer.txt | 23 ++ arch/arm/Kconfig | 7 + arch/arm/include/asm/arch_timer.h | 13 + arch/arm/kernel/Makefile | 1 + arch/arm/kernel/arch_timer.c | 363 ++++++++++++++++++++ 5 files changed, 407 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/arch_timer.txt create mode 100644 arch/arm/include/asm/arch_timer.h create mode 100644 arch/arm/kernel/arch_timer.c
Signature · 1 line
1.7.7.1
PATCH v2 1/4 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.
--- arch/arm/Kconfig | 7 + arch/arm/include/asm/arch_timer.h | 12 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/arch_timer.c | 286 +++++++++++++++++++++++++++++++++++++ 4 files changed, 306 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch_timer.h create mode 100644 arch/arm/kernel/arch_timer.c
arch/arm/Kconfig +7 -0
@@ -1522,6 +1522,13 @@ config HAVE_ARM_SCU help This option enables support for the ARM system coherency unit +config ARM_ARCH_TIMER + bool "Architected timer support" + depends on CPU_V7 + select TICK_ONESHOT + help + This option enables support for the ARM architected timer + config HAVE_ARM_TWD bool depends on SMP
arch/arm/include/asm/arch_timer.h new file +12 -0
@@ -0,0 +1,12 @@ +#ifndef __ASMARM_ARCH_TIMER_H +#define __ASMARM_ARCH_TIMER_H + +#include <linux/ioport.h> + +struct arch_timer { +struct resource res[2 ]; +}; + +int arch_timer_register (struct arch_timer *); + +#endif
arch/arm/kernel/Makefile +1 -0
@@ -34,6 +34,7 @@ obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_SMP) += smp.o smp_tlb.o obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o +obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
arch/arm/kernel/arch_timer.c new file +286 -0
286 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 1/4 ARM: local timers: Add A15 architected timer support
Hi Marc,
Quoted 4 lines · Marc Zyngier
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.
[snip]
Quoted 47 lines
arch/arm/kernel/arch_timer.c new file +41
-0@@ -0,0 +1,286 @@ +/* +* linux/arch/arm/kernel/arch_timer.c +* +* Copyright (C) 2011 ARM Ltd. +* All Rights Reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/smp.h> +#include <linux/cpu.h> +#include <linux/jiffies.h> +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/io.h> + +#include <asm/cputype.h> +#include <asm/localtimer.h> +#include <asm/arch_timer.h> + +static unsigned long arch_timer_rate; +static int arch_timer_ppi; +static int arch_timer_ppi2; + +static struct clock_event_device __percpu **arch_timer_evt; + +/* +* Architected system timer support. +*/ + +#define ARCH_TIMER_CTRL_ENABLE (1 << 0) +#define ARCH_TIMER_CTRL_IT_MASK (1 << 1) + +#define ARCH_TIMER_REG_CTRL 0 +#define ARCH_TIMER_REG_FREQ 1 +#define ARCH_TIMER_REG_TVAL 2
[snip]
arch/arm/kernel/arch_timer.c line 84
Quoted 7 lines
arch/arm/kernel/arch_timer.c new file +7
-0+static irqreturn_t arch_timer_handler (int irq,void *dev_id) +{ +struct clock_event_device *evt = *(struct clock_event_device **)dev_id; +unsigned long ctrl; + + ctrl =arch_timer_reg_read (ARCH_TIMER_REG_CTRL ); +if (ctrl &0x4 ) {
Perhaps this bit could be given a name like the others.
[snip]
arch/arm/kernel/arch_timer.c line 193
Quoted 7 lines
arch/arm/kernel/arch_timer.c new file +7
-0+static inline cycle_t arch_counter_get_cntpct (void ) +{ +u32 cvall, cvalh; + + asmvolatile ("mrrc p15, 0, %0, %1, c14" :"=r" (cvall),"=r" (cvalh)); + +return ((u64 ) cvalh <<32 ) | cvall;
Would it not be better to cast to cycle_t?
arch/arm/kernel/arch_timer.c line 202
Quoted 9 lines
arch/arm/kernel/arch_timer.c new file +9
-0+} + +static inline cycle_t arch_counter_get_cntvct (void ) +{ +u32 cvall, cvalh; + + asmvolatile ("mrrc p15, 1, %0, %1, c14" :"=r" (cvall),"=r" (cvalh)); + +return ((u64 ) cvalh <<32 ) | cvall;
Ditto.
Quoted 1 line
+}
[snip]
arch/arm/kernel/arch_timer.c line 281
Quoted 5 lines
arch/arm/kernel/arch_timer.c new file +5
-0+out_free_irq: +free_percpu_irq (arch_timer_ppi, arch_timer_evt); +if (arch_timer_ppi2) +free_percpu_irq (arch_timer_ppi2, arch_timer_evt); +
Trailing whitespace.
arch/arm/kernel/arch_timer.c line 286
Quoted 5 lines
arch/arm/kernel/arch_timer.c new file +5
-0+out_free: +free_percpu (arch_timer_evt); + +return err; +}
Regards,
Christopher
Signature · 2 lines
Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
PATCH v2 2/4 ARM: architected timers: Add A15 specific sched_clock implementation
In reply to Marc ZyngierProvide 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.
--- arch/arm/include/asm/arch_timer.h | 1 + arch/arm/kernel/arch_timer.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 0 deletions(-)
arch/arm/include/asm/arch_timer.h +1 -0
@@ -8,5 +8,6 @@ struct arch_timer { };int arch_timer_register (struct arch_timer *); +int arch_timer_sched_clock_init (void );#endif
arch/arm/kernel/arch_timer.c +25 -0
@@ -22,6 +22,7 @@#include <asm/cputype.h> #include <asm/localtimer.h> #include <asm/arch_timer.h> +#include <asm/sched_clock.h> static unsigned long arch_timer_rate;static int arch_timer_ppi;
@@ -202,6 +203,18 @@ static inline cycle_t arch_counter_get_cntvct(void)return ((u64 ) 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@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 ();
@@ -284,3 +297,15 @@ out_free:return err; } + +int 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 ; +}
Signature · 1 line
1.7.7.1
PATCH v2 3/4 ARM: architected timers: add DT support
In reply to Marc ZyngierAdd runtime DT support and documentation for the Cortex A7/A15 architected timers.
--- .../devicetree/bindings/arm/arch_timer.txt | 23 +++++++++ arch/arm/kernel/arch_timer.c | 53 +++++++++++++++++--- 2 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/arch_timer.txt
Documentation/devicetree/bindings/arm/arch_timer.txt new file +23 -0
@@ -0,0 +1,23 @@ +* ARM architected timer + +ARM Cortex-A7 and Cortex-A15 have a per-core architected timer, which +provides a per-cpu local timer. + +The timer is attached to a GIC to deliver its two per-processor +interrupts (one for the secure mode, one for the non-secure mode). + +** Timer node properties: + +- compatible : Should be "arm,armv7-timer" + +- interrupts : One or two interrupts for secure and non-secure mode + +- clock-frequency : The frequency of the main counter, in Hz. Optionnal. + +Example: + + timer { + compatible = "arm,armv7-timer""; + interrupts = <1 13 0xf08 1 14 0xf08>; + clock-frequency = <100000000>; + };
arch/arm/kernel/arch_timer.c +46 -7
86 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 3/4 ARM: architected timers: add DT support
Hi Marc,
Quoted 22 lines · Marc Zyngier
Add runtime DT support and documentation for the Cortex A7/A15 architected timers.
Signed-off-by Will Deacon <[email protected]>Signed-off-by Marc Zyngier <[email protected]>--- .../devicetree/bindings/arm/arch_timer.txt | 23 +++++++++ arch/arm/kernel/arch_timer.c | 53 +++++++++++++++++--- 2 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/arch_timer.txtDocumentation/devicetree/bindings/arm/arch_timer.txt new file +5
-0@@ -0,0 +1,23 @@ +* ARM architected timer + +ARM Cortex-A7 and Cortex-A15 have a per-core architected timer, which +provides a per-cpu local timer. +
Documentation/devicetree/bindings/arm/arch_timer.txt line 15
Quoted 10 lines
Documentation/devicetree/bindings/arm/arch_timer.txt new file +10
-0+The timer is attached to a GIC to deliver its two per-processor +interrupts (one for the secure mode, one for the non-secure mode). + +** Timer node properties: + +- compatible : Should be "arm,armv7-timer" + +- interrupts : One or two interrupts for secure and non-secure mode + +- clock-frequency : The frequency of the main counter, in Hz. Optionnal.
Spelling.
[snip]
Regards,
Christopher
Signature · 2 lines
Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
PATCH v2 4/4 ARM: architected timers: add support for UP timer
In reply to Marc ZyngierIf CONFIG_LOCAL_TIMERS is not defined, let the architected timer driver register a single clock_event_device that is used as a global timer.
--- arch/arm/kernel/arch_timer.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-)
arch/arm/kernel/arch_timer.c +14 -1
@@ -229,6 +229,7 @@ static struct clocksource clocksource_counter = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +#ifdef CONFIG_LOCAL_TIMERS static void __cpuinit arch_timer_stop (struct clock_event_device *clk) { pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
@@ -243,6 +244,9 @@ static struct local_timer_ops arch_timer_ops __cpuinitdata = { .setup = arch_timer_setup, .stop = arch_timer_stop, }; +#else +static struct clock_event_device arch_timer_global_evt; +#endif static int __init arch_timer_common_register (void ) {
@@ -277,7 +281,16 @@ static int __init arch_timer_common_register(void) } } - err =local_timer_register (&arch_timer_ops); +#ifdef CONFIG_LOCAL_TIMERS +if (is_smp ()) + err =local_timer_register (&arch_timer_ops); + else +#endif + { + arch_timer_global_evt.cpumask =cpumask_of (0 ); + err =arch_timer_setup (&arch_timer_global_evt); + } +if (err) goto out_free_irq;
Signature · 1 line
1.7.7.1
PATCH v2 4/4 ARM: architected timers: add support for UP timer
Hi Marc,
Quoted 3 lines · Marc Zyngier
If
CONFIG_LOCAL_TIMERSis not defined, let the architected timer driver register a singleclock_event_devicethat is used as a global timer.
[snip]
Quoted 10 lines
static int
__initarch_timer_common_register(void){arch/arm/kernel/arch_timer.c +3
-1@@ -277,7 +281,16 @@ static int __init arch_timer_common_register(void) } } - err =local_timer_register (&arch_timer_ops); +#ifdef CONFIG_LOCAL_TIMERS +if (is_smp ()) + err =local_timer_register (&arch_timer_ops);
arch/arm/kernel/arch_timer.c static int __init arch_timer_common_register(void) · line 296
Quoted 10 lines
arch/arm/kernel/arch_timer.c +7
-0+ else +#endif + { + arch_timer_global_evt.cpumask =cpumask_of (0 ); + err =arch_timer_setup (&arch_timer_global_evt); + } +if (err) goto out_free_irq;
The logic here seems unnecessarily split between the preprocessor and compiler. Certainly this can be revised to a more elegant form that better keeps with the guidelines on ifdef usage [1].
1. http://www.linuxjournal.com/article/5780?page=0,3
Regards,
Christopher
Signature · 2 lines
Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
PATCH v2 4/4 ARM: architected timers: add support for UP timer
Hi Christopher,
Quoted 32 lines · Christopher Covington
Quoted 3 lines · Marc Zyngier
If
CONFIG_LOCAL_TIMERSis not defined, let the architected timer driver register a singleclock_event_devicethat is used as a global timer.[snip]
Quoted 10 lines
static int
__initarch_timer_common_register(void){arch/arm/kernel/arch_timer.c +3
-1@@ -277,7 +281,16 @@ static int __init arch_timer_common_register(void) } } - err =local_timer_register (&arch_timer_ops); +#ifdef CONFIG_LOCAL_TIMERS +if (is_smp ()) + err =local_timer_register (&arch_timer_ops);arch/arm/kernel/arch_timer.c static int __init arch_timer_common_register(void) · line 296
Quoted 10 lines
arch/arm/kernel/arch_timer.c +7
-0+ else +#endif + { + arch_timer_global_evt.cpumask =cpumask_of (0 ); + err =arch_timer_setup (&arch_timer_global_evt); + } +if (err) goto out_free_irq;The logic here seems unnecessarily split between the preprocessor and compiler. Certainly this can be revised to a more elegant form that better keeps with the guidelines on ifdef usage [1].
Quoted 1 line
This would require a small change in the local timer code (basically refusing to register a local timer if not on an SMP platform). But this is just moving code from one #ifdef section to another...
Thanks for reviewing.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...