A7/A15 architected timer support
Subsystems (5)
v3 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 v3.4-rc3. Branch also available at:git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git timers-v3.4-rc3
* From v2:
- Allow the generic code to report that local timers cannot be used.
- Plug local timers into the VExpress DT code.
* From the initial revision:
- Fixed global timer registration when an SMP kernel is running on UP with LOCAL_TIMERS enabled.
Marc Zyngier (6):
ARM: local timers: reserve local_timer_register() to SMP
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
ARM: vexpress: plug local timers into the DT code
.../devicetree/bindings/arm/arch_timer.txt | 27 ++ arch/arm/Kconfig | 7 + arch/arm/include/asm/arch_timer.h | 31 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/arch_timer.c | 364 ++++++++++++++++++++ arch/arm/kernel/smp.c | 3 + arch/arm/mach-vexpress/v2m.c | 8 +- 7 files changed, 440 insertions(+), 1 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 v3 1/6 ARM: local timers: reserve local_timer_register() to SMP
When running an SMP_ON_UP enabled kernel on UP, or with nosmp passed to the kernel, we want to be able to detect that a local timer is not going to be used (local timers are only used on SMP platforms), so we could register it as a global timer instead.
Return -ENXIO when the above case is detected.
--- arch/arm/kernel/smp.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/kernel/smp.c +3 -0
@@ -454,6 +454,9 @@ static struct local_timer_ops *lt_ops;#ifdef CONFIG_LOCAL_TIMERS int local_timer_register (struct local_timer_ops *ops) { +if (!is_smp () || !setup_max_cpus) +return -ENXIO ; +if (lt_ops)return -EBUSY ;
Signature · 1 line
1.7.7.1
PATCH v3 2/6 ARM: local timers: Add A15 architected timer support
In reply to Marc ZyngierAdd 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 | 19 +++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/arch_timer.c | 287 +++++++++++++++++++++++++++++++++++++ 4 files changed, 314 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
@@ -1543,6 +1543,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 +19 -0
@@ -0,0 +1,19 @@ +#ifndef __ASMARM_ARCH_TIMER_H +#define __ASMARM_ARCH_TIMER_H + +#include <linux/ioport.h> + +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
arch/arm/kernel/Makefile +1 -0
@@ -34,6 +34,7 @@ obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.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 insn.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
arch/arm/kernel/arch_timer.c new file +287 -0
287 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v3 2/6 ARM: local timers: Add A15 architected timer support
arch/arm/Kconfig config HAVE_ARM_SCU · line 1549
Quoted 12 lines · Marc Zyngier
arch/arm/Kconfig +4
-0@@ -1543,6 +1543,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
I believe TICK_ONESHOT is a "hidden" option that should not be selected outside the generic clockevents layer. It seems Russell and Thomas have talked about this too, see 3872c48 (tick: Document TICK_ONESHOT config option, 2012-03-31).
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
PATCH v3 2/6 ARM: local timers: Add A15 architected timer support
On 16/04/12 18:45, Stephen Boyd wrote:
Hi Stephen,
Quoted 9 lines · Marc Zyngier
Quoted 8 lines
arch/arm/Kconfig +0
-0@@ -1543,6 +1543,13 @@ config HAVE_ARM_SCU help This option enables support for the ARM system coherency unit
Quoted 9 lines
arch/arm/Kconfig config HAVE_ARM_SCU · line 1549
Quoted 4 lines
arch/arm/Kconfig +4
-0+config ARM_ARCH_TIMER + bool "Architected timer support" + depends on CPU_V7 + select TICK_ONESHOTI believe
TICK_ONESHOTis a "hidden" option that should not be selected outside the generic clockevents layer. It seems Russell and Thomas have talked about this too, see 3872c48 (tick: DocumentTICK_ONESHOTconfig option, 2012-03-31).
Ah, thanks for noticing this. I'm glad this point has been clarified. I'll push a fix.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
PATCH v3 3/6 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 | 6 ++++++ arch/arm/kernel/arch_timer.c | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 0 deletions(-)
arch/arm/include/asm/arch_timer.h +6 -0
@@ -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
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;
@@ -203,6 +204,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@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 ();
@@ -285,3 +298,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 ; +}
Signature · 1 line
1.7.7.1
PATCH v3 4/6 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 | 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
Documentation/devicetree/bindings/arm/arch_timer.txt new file +27 -0
@@ -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>; + };
arch/arm/include/asm/arch_timer.h +6 -0
@@ -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 ;
arch/arm/kernel/arch_timer.c +46 -7
86 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v3 4/6 ARM: architected timers: add DT support
Quoted 12 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 | 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
This looks good, but do we actually still need the non-DT case?
Both vexpress and exynos5 allow booting through DT and we are not planning to add any new platforms with these timers that don't.
Arnd
PATCH v3 4/6 ARM: architected timers: add DT support
Quoted 14 lines · Arnd Bergmann
Quoted 12 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 | 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
Quoted 4 lines
This looks good, but do we actually still need the non-DT case?
Both vexpress and exynos5 allow booting through DT and we are not planning to add any new platforms with these timers that don't.
Yes, the non-DT code is a leftover from dark ages we'd rather forget. I'll remove that code for the next iteration.
Thanks,
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
PATCH v3 5/6 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 | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/kernel/arch_timer.c +13 -0
@@ -245,6 +245,8 @@ static struct local_timer_ops arch_timer_ops __cpuinitdata = { .stop = arch_timer_stop, }; +static struct clock_event_device arch_timer_global_evt; +static int __init arch_timer_common_register (void ) {int err;
@@ -279,6 +281,17 @@ static int __init arch_timer_common_register(void) } err =local_timer_register (&arch_timer_ops); +if (err) { +/* +* We couldn't register as a local timer (could be +* because we're on a UP platform, or because some +* other local timer is already present...). Try as a +* global timer instead. +*/ + 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 v3 6/6 ARM: vexpress: plug local timers into the DT code
In reply to Marc Zyngier--- arch/arm/mach-vexpress/v2m.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
arch/arm/mach-vexpress/v2m.c +7 -1
@@ -19,8 +19,10 @@#include <linux/clkdev.h> #include <linux/mtd/physmap.h> +#include <asm/arch_timer.h> #include <asm/mach-types.h> #include <asm/sizes.h> +#include <asm/smp_twd.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h>
@@ -616,7 +618,6 @@ void __init v2m_dt_init_early(void) }clkdev_add_table (v2m_dt_lookups,ARRAY_SIZE (v2m_dt_lookups)); -versatile_sched_clock_init (v2m_sysreg_base +V2M_SYS_24MHZ ,24000000 ); }static struct of_device_id vexpress_irq_match[]__initdata = {
@@ -643,6 +644,11 @@ static void __init v2m_dt_timer_init(void)return ; node =of_find_node_by_path (path);v2m_sp804_init (of_iomap (node,0 ),irq_of_parse_and_map (node,0 )); +if (arch_timer_of_register ()) +twd_local_timer_of_register (); + +if (arch_timer_sched_clock_init ()) +versatile_sched_clock_init (v2m_sysreg_base +V2M_SYS_24MHZ ,24000000 ); }static struct sys_timer v2m_dt_timer = {
Signature · 1 line
1.7.7.1
PATCH v3 6/6 ARM: vexpress: plug local timers into the DT code
arch/arm/mach-vexpress/v2m.c static void __init v2m_dt_timer_init(void) · line 652
Quoted 10 lines · Marc Zyngier
arch/arm/mach-vexpress/v2m.c +5
-0@@ -643,6 +644,11 @@ static void __init v2m_dt_timer_init(void)return ; node =of_find_node_by_path (path);v2m_sp804_init (of_iomap (node,0 ),irq_of_parse_and_map (node,0 )); +if (arch_timer_of_register ()) +twd_local_timer_of_register (); + +if (arch_timer_sched_clock_init ()) +versatile_sched_clock_init (v2m_sysreg_base +V2M_SYS_24MHZ ,24000000 ); }
My personal preference would be "if (arch_timer*() != 0)" here - obviously makes no difference, but clearly states the idea, but anyway looks good to me.
Cheers!
Pawe?
PATCH v3 6/6 ARM: vexpress: plug local timers into the DT code
Quoted 15 lines · Pawel Moll
arch/arm/mach-vexpress/v2m.c static void __init v2m_dt_timer_init(void) · line 652
Quoted 10 lines · Marc Zyngier
arch/arm/mach-vexpress/v2m.c +5
-0@@ -643,6 +644,11 @@ static void __init v2m_dt_timer_init(void)return ; node =of_find_node_by_path (path);v2m_sp804_init (of_iomap (node,0 ),irq_of_parse_and_map (node,0 )); +if (arch_timer_of_register ()) +twd_local_timer_of_register (); + +if (arch_timer_sched_clock_init ()) +versatile_sched_clock_init (v2m_sysreg_base +V2M_SYS_24MHZ ,24000000 ); }My personal preference would be "if (arch_timer*() != 0)" here - obviously makes no difference, but clearly states the idea, but anyway looks good to me.
Fair enough.
Quoted 1 line
Acked-by Pawel Moll <[email protected]>
Thanks Pawe?.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...