A15 architected timer support
Subsystems (9)
v2 cover A15 architected timer support
This patch set adds support for the architected (or generic) timers that appear in the Cortex A15. The specification is part of the ARMv7-AR LPA Virtualization Extensions, available from (free registration required):
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0406b_virtualization_extns/index.html
They provide physical and virtual timers/counters (the later being under control of the hypervisor). The code provides a clock source (using the physical counter) and a sched_clock implementation (using the virtual counter, so the local scheduling is not affected by having multiple VMs scheduled in and out of the CPU by the hypervisor).
Modifications are relatively invasive:
- The timer interrupt is on IRQ 29 or 30, depending on whether the kernel is running in secure or normal mode. As it is not possible to distinguish between the two modes in a reliable way, we have to check if we're running on an A15 or not (the feature register may be virtualized, and thus potentially expensive to access).
- Local timer is also used in an UP configuration, so the local timer code is isolated from SMP support.
- A registration interface is introduced to allow a platform to pick its preferred implementation (architected timers, twd, msm local timers...). This causes some code churn in the platform specific code as the registration mechanism takes place at runtime instead of having a link time selection (local_timer_setup).
- Broadcast timers become the fallback in case no local timers are available.
- Allow the kernel to have multiple sched_clock() implementations compiled in, and extend the existing API to register one at runtime.
On the (emulated) Versatile Express platform, the A15 is running without the SP804 that is usually used across the whole Versatile range. The same binary kernel also runs on the Cortex A5 tile using TWD and SP804 (both patch sets to be posted shortly).
Patches #1, 9, 10 and 11 carry the core modifications. All the others are platform support changes and various cleanups. This patch set depends on Will Deacon's multi-tile patch. Tested on next-20110314.
Any comments are welcome.
Changelog:
* From v1:
- Fix typo in the msm platform code (noticed by David Brown)
- Fix a few TWD setup function signatures
- Convert Samsung MCT (exynos4) to the new local timer API
Marc Zyngier (20):
ARM: architected timers: move local timer support to percpu_timer.c
ARM: omap2: remove stubbed twd_timer_setup call
ARM: exynos4: remove stubbed twd_timer_setup call
ARM: shmobile: remove stubbed twd_timer_setup call
ARM: tegra: remove stubbed twd_timer_setup call
ARM: ux500: remove stubbed twd_timer_setup call
ARM: versatile: remove stubbed twd_timer_setup call
ARM: remove unused twd_timer_setup stub
ARM: architected timers: add A15 architected timers
ARM: Platform dependent sched_clock() override
ARM: architected timers: Add A15 specific sched_clock implementation
ARM: versatile/vexpress: rework timer support
ARM: msm: dynamically register local timer setup function
ARM: omap4: dynamically register local timer setup function
ARM: exynos4: dynamically register local timer setup function
ARM: shmobile: dynamically register local timer setup function
ARM: tegra: dynamically register local timer setup function
ARM: ux500: dynamically register local timer setup function
ARM: simplify percpu_timer_setup
ARM: simplify percpu_timer_ack
arch/arm/Kconfig | 20 ++- arch/arm/include/asm/arch_timer.h | 13 + arch/arm/include/asm/entry-macro-multi.S | 2 +- arch/arm/include/asm/hardware/entry-macro-gic.S | 18 ++ arch/arm/include/asm/localtimer.h | 61 +++-- arch/arm/include/asm/sched_clock.h | 41 +++- arch/arm/include/asm/smp.h | 7 +- arch/arm/include/asm/smp_twd.h | 14 +- arch/arm/kernel/Makefile | 2 + arch/arm/kernel/arch_timer.c | 253 +++++++++++++++++++++ arch/arm/kernel/irq.c | 1 + arch/arm/kernel/percpu_timer.c | 141 ++++++++++++ arch/arm/kernel/sched_clock.c | 23 ++- arch/arm/kernel/smp.c | 92 +------- arch/arm/kernel/smp_twd.c | 21 ++- arch/arm/mach-exynos4/Makefile | 1 - arch/arm/mach-exynos4/localtimer.c | 26 -- arch/arm/mach-exynos4/mct.c | 22 ++- arch/arm/mach-exynos4/time.c | 10 + arch/arm/mach-msm/timer.c | 22 ++- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/timer-gp.c | 13 +- arch/arm/mach-omap2/timer-mpu.c | 39 ---- arch/arm/mach-realview/realview_eb.c | 4 +- arch/arm/mach-realview/realview_pb11mp.c | 4 +- arch/arm/mach-realview/realview_pbx.c | 5 +- arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/localtimer.c | 26 -- arch/arm/mach-shmobile/timer.c | 13 + arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/localtimer.c | 26 -- arch/arm/mach-tegra/timer.c | 11 + arch/arm/mach-ux500/Makefile | 1 - arch/arm/mach-ux500/cpu.c | 13 + arch/arm/mach-ux500/localtimer.c | 29 --- arch/arm/mach-vexpress/v2m.c | 29 +++- arch/arm/plat-versatile/include/plat/localtimer.h | 9 + arch/arm/plat-versatile/localtimer.c | 11 +- arch/arm/plat-versatile/sched-clock.c | 7 +- 39 files changed, 730 insertions(+), 304 deletions(-) create mode 100644 arch/arm/include/asm/arch_timer.h create mode 100644 arch/arm/kernel/arch_timer.c create mode 100644 arch/arm/kernel/percpu_timer.c delete mode 100644 arch/arm/mach-exynos4/localtimer.c delete mode 100644 arch/arm/mach-omap2/timer-mpu.c delete mode 100644 arch/arm/mach-shmobile/localtimer.c delete mode 100644 arch/arm/mach-tegra/localtimer.c delete mode 100644 arch/arm/mach-ux500/localtimer.c create mode 100644 arch/arm/plat-versatile/include/plat/localtimer.h
RFC PATCH v2 1/20 ARM: architected timers: move local timer support to percpu_timer.c
To introduce the A15 architected timers without causing too much disruption on the rest of the kernel, introduce percpu_timer.c to act as a registration interface that the platform can call at runtime.
Timer functions are moved out of smp.c (as the A15 can use the local timer in UP configuration) and smp_twd.c now returns a set of operations that percpu_timer.c can call.
--- arch/arm/Kconfig | 6 +- arch/arm/include/asm/entry-macro-multi.S | 2 +- arch/arm/include/asm/localtimer.h | 60 +++++++---- arch/arm/include/asm/smp.h | 7 +- arch/arm/include/asm/smp_twd.h | 27 ++++- arch/arm/kernel/Makefile | 1 + arch/arm/kernel/irq.c | 1 + arch/arm/kernel/percpu_timer.c | 164 ++++++++++++++++++++++++++++++ arch/arm/kernel/smp.c | 92 +---------------- arch/arm/kernel/smp_twd.c | 29 +++++- 10 files changed, 266 insertions(+), 123 deletions(-) create mode 100644 arch/arm/kernel/percpu_timer.c
arch/arm/Kconfig +3 -3
@@ -1326,6 +1326,7 @@ config SMP ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE select USE_GENERIC_SMP_HELPERS select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP + select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT) help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If
@@ -1407,10 +1408,9 @@ config HOTPLUG_CPU can be controlled through /sys/devices/system/cpu. config LOCAL_TIMERS - bool "Use local timer interrupts" - depends on SMP + bool + depends on SMP || ARCH_MSM_SCORPIONMP default y - select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT) help Enable support for local timers on SMP platforms, rather then the legacy IPI broadcast method. Local timers allows the system
arch/arm/include/asm/entry-macro-multi.S +1 -1
@@ -23,6 +23,7 @@ movne r1, sp adrne lr, BSYM(1b) bne do_IPI +#endif #ifdef CONFIG_LOCAL_TIMERS test_for_ltirq r0, r6, r5, lr
@@ -30,7 +31,6 @@ adrne lr, BSYM(1b) bne do_local_timer #endif -#endif 9997: .endm
arch/arm/include/asm/localtimer.h +40 -20
87 lines not on this page · raw message
arch/arm/include/asm/smp.h +3 -4
@@ -95,9 +95,8 @@ extern void platform_cpu_enable(unsigned int cpu);extern void arch_send_call_function_single_ipi (int cpu);extern void arch_send_call_function_ipi_mask (const struct cpumask *mask); -/* -* show local interrupt info -*/ -extern void show_local_irqs (struct seq_file *,int ); +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST +void smp_timer_broadcast (const struct cpumask *mask); +#endif #endif /* ifndef __ASM_ARM_SMP_H */
arch/arm/include/asm/smp_twd.h +23 -4
@@ -1,6 +1,8 @@#ifndef __ASMARM_SMP_TWD_H#define __ASMARM_SMP_TWD_H +#include <linux/clockchips.h> +#define TWD_TIMER_LOAD 0x00#define TWD_TIMER_COUNTER 0x04#define TWD_TIMER_CONTROL 0x08
@@ -18,11 +20,28 @@#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) -struct clock_event_device ; -extern void __iomem *twd_base; -int twd_timer_ack (void ); -void twd_timer_setup (struct clock_event_device *); +#ifdef CONFIG_HAVE_ARM_TWD +struct local_timer_ops *local_timer_get_twd_ops (void ); +int twd_timer_register_setup (int (*setup)(struct clock_event_device *)); +#else +static inline struct local_timer_ops *local_timer_get_twd_ops (void ) +{ +return NULL ; +} + +static inline int twd_timer_register_setup (int (*setup)(struct clock_event_device *)) +{ +return -ENODEV ; +} +#endif + +/* +* Dummy function, to be removed once there is no in-tree user anymore. +*/ +static inline void twd_timer_setup (void *dummy) +{ +}#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_LOCAL_TIMERS) += percpu_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/irq.c +1 -0
@@ -38,6 +38,7 @@#include <linux/ftrace.h> #include <asm/system.h> +#include <asm/localtimer.h> #include <asm/mach/arch.h> #include <asm/mach/irq.h> #include <asm/mach/time.h>
arch/arm/kernel/percpu_timer.c new file +164 -0
164 lines not on this page · raw message
arch/arm/kernel/smp.c +3 -89
115 lines not on this page · raw message
arch/arm/kernel/smp_twd.c +27 -2
@@ -18,6 +18,7 @@#include <linux/irq.h> #include <linux/io.h> +#include <asm/localtimer.h> #include <asm/smp_twd.h> #include <asm/hardware/gic.h>
@@ -70,7 +71,7 @@ static int twd_set_next_event(unsigned long evt,* If a local timer interrupt has occurred, acknowledge and return 1. * Otherwise, return 0. */ -int twd_timer_ack (void ) +static int twd_timer_ack (void ) {if (__raw_readl (twd_base +TWD_TIMER_INTSTAT )) {__raw_writel (1 , twd_base +TWD_TIMER_INTSTAT );
@@ -122,7 +123,7 @@ static void __cpuinit twd_calibrate_rate(void)/* * Setup the local clock events for a CPU. */ -void __cpuinit twd_timer_setup (struct clock_event_device *clk) +static void __cpuinit twd_setup (struct clock_event_device *clk) {twd_calibrate_rate ();
@@ -142,3 +143,27 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)clockevents_register_device (clk); } + +static struct local_timer_ops twd_timer_ops = { + .setup = twd_setup, + .ack = twd_timer_ack, +}; + +struct local_timer_ops *local_timer_get_twd_ops (void ) +{ +if (!twd_base) { +pr_warn ("TWD base address not set\n" ); +return NULL ; + } + +return &twd_timer_ops; +} + +int __init twd_timer_register_setup (int (*setup)(struct clock_event_device *)) +{ +if (!twd_base) +return -ENODEV ; + +percpu_timer_register_setup (&twd_timer_ops, setup); +return 0 ; +}
Signature · 1 line
1.7.0.4
RFC PATCH v2 2/20 ARM: omap2: remove stubbed twd_timer_setup call
In reply to Marc Zyngier--- arch/arm/mach-omap2/timer-mpu.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/timer-mpu.c +0 -3
@@ -17,10 +17,8 @@* published by the Free Software Foundation. */ #include <linux/init.h> -#include <linux/smp.h> #include <linux/clockchips.h> #include <asm/irq.h> -#include <asm/smp_twd.h> #include <asm/localtimer.h> /*
@@ -33,7 +31,6 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)return -ENXIO ; evt->irq =OMAP44XX_IRQ_LOCALTIMER ; -twd_timer_setup (evt);return 0 ; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 3/20 ARM: exynos4: remove stubbed twd_timer_setup call
In reply to Marc Zyngier--- arch/arm/mach-exynos4/localtimer.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-exynos4/localtimer.c +0 -1
@@ -21,6 +21,5 @@int __cpuinit local_timer_setup (struct clock_event_device *evt) { evt->irq =IRQ_LOCALTIMER ; -twd_timer_setup (evt);return 0 ; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 4/20 ARM: shmobile: remove stubbed twd_timer_setup call
In reply to Marc Zyngier--- arch/arm/mach-shmobile/localtimer.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-shmobile/localtimer.c +0 -1
@@ -21,6 +21,5 @@int __cpuinit local_timer_setup (struct clock_event_device *evt) { evt->irq =29 ; -twd_timer_setup (evt);return 0 ; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 5/20 ARM: tegra: remove stubbed twd_timer_setup call
In reply to Marc Zyngier--- arch/arm/mach-tegra/localtimer.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/localtimer.c +1 -3
@@ -9,10 +9,9 @@* published by the Free Software Foundation. */ #include <linux/init.h> -#include <linux/smp.h> #include <linux/clockchips.h> +#include <asm/irq.h> -#include <asm/smp_twd.h> #include <asm/localtimer.h> /*
@@ -21,6 +20,5 @@int __cpuinit local_timer_setup (struct clock_event_device *evt) { evt->irq =IRQ_LOCALTIMER ; -twd_timer_setup (evt);return 0 ; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 6/20 ARM: ux500: remove stubbed twd_timer_setup call
In reply to Marc Zyngier--- arch/arm/mach-ux500/localtimer.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
arch/arm/mach-ux500/localtimer.c +0 -3
@@ -11,11 +11,9 @@* published by the Free Software Foundation. */ #include <linux/init.h> -#include <linux/smp.h> #include <linux/clockchips.h> #include <asm/irq.h> -#include <asm/smp_twd.h> #include <asm/localtimer.h> /*
@@ -24,6 +22,5 @@int __cpuinit local_timer_setup (struct clock_event_device *evt) { evt->irq =IRQ_LOCALTIMER ; -twd_timer_setup (evt);return 0 ; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 7/20 ARM: versatile: remove stubbed twd_timer_setup call
In reply to Marc Zyngier--- arch/arm/plat-versatile/localtimer.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
arch/arm/plat-versatile/localtimer.c +0 -3
@@ -9,10 +9,8 @@* published by the Free Software Foundation. */ #include <linux/init.h> -#include <linux/smp.h> #include <linux/clockchips.h> -#include <asm/smp_twd.h> #include <asm/localtimer.h> #include <mach/irqs.h>
@@ -22,6 +20,5 @@int __cpuinit local_timer_setup (struct clock_event_device *evt) { evt->irq =IRQ_LOCALTIMER ; -twd_timer_setup (evt);return 0 ; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 8/20 ARM: remove unused twd_timer_setup stub
In reply to Marc ZyngierNow that there is no in-tree users of twd_timer_setup() anymore, remove it completely.
--- arch/arm/include/asm/smp_twd.h | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-)
arch/arm/include/asm/smp_twd.h +0 -7
@@ -37,11 +37,4 @@ static inline int twd_timer_register_setup(int (*setup)(struct clock_event_devic }#endif -/* -* Dummy function, to be removed once there is no in-tree user anymore. -*/ -static inline void twd_timer_setup (void *dummy) -{ -} -#endif
Signature · 1 line
1.7.0.4
RFC PATCH v2 9/20 ARM: architected timers: add A15 architected timers
In reply to Marc ZyngierThe ARM architecture provides a set of optional system timers that can be used as clocksources for local timer events.
This patch adds support for these timers, giving them priority over any private timers if they are detected at runtime.
A global counter is also used to implement a clock source.
--- arch/arm/Kconfig | 7 +- arch/arm/include/asm/arch_timer.h | 13 ++ arch/arm/include/asm/hardware/entry-macro-gic.S | 18 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/arch_timer.c | 223 +++++++++++++++++++++++ 5 files changed, 261 insertions(+), 1 deletions(-) create mode 100644 arch/arm/include/asm/arch_timer.h create mode 100644 arch/arm/kernel/arch_timer.c
arch/arm/Kconfig +6 -1
@@ -1407,9 +1407,14 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. +config HAVE_ARCH_TIMERS + bool + depends on CPU_V7 + select TICK_ONESHOT + config LOCAL_TIMERS bool - depends on SMP || ARCH_MSM_SCORPIONMP + depends on SMP || HAVE_ARCH_TIMERS || ARCH_MSM_SCORPIONMP default y help Enable support for local timers on SMP platforms, rather then the
arch/arm/include/asm/arch_timer.h new file +13 -0
@@ -0,0 +1,13 @@ +#ifndef __ASMARM_ARCH_TIMER_H +#define __ASMARM_ARCH_TIMER_H + +#ifdef CONFIG_HAVE_ARCH_TIMERS +int arch_timer_register_setup (void (*setup)(struct clock_event_device *)); +#else +static inline int arch_timer_register_setup (void (*setup)(struct clock_event_device *)) +{ +return -ENODEV ; +} +#endif + +#endif
arch/arm/include/asm/hardware/entry-macro-gic.S +18 -0
@@ -67,8 +67,26 @@ .macro test_for_ltirq, irqnr, irqstat, base, tmp bic \irqnr, \irqstat, #0x1c00 +#ifdef CONFIG_HAVE_ARCH_TIMERS + /* + * We need to check for both PPI 29 and 30, as we have no way + * to know whether we're running in normal or secure mode. + * We cannot check for the architected timers being available, + * as the feature register may be virtualised (slow access). + * Check for an A15 instead. + * If this matches, check for PPI 30. Otherwise, fallback + * to the the usual 29. + */ + mrc p15, 0, \tmp, c0, c0, 0 + and \tmp, \tmp, #0xff0 + teq \tmp, #0x0f0 + cmpeq \irqnr, #30 + movne \tmp, #0 + cmpne \irqnr, #29 +#else mov \tmp, #0 cmp \irqnr, #29 +#endif moveq \tmp, #1 streq \irqstat, [\base, #GIC_CPU_EOI] cmp \tmp, #0
arch/arm/kernel/Makefile +1 -0
@@ -33,6 +33,7 @@ obj-$(CONFIG_PM) += sleep.o 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_ARCH_TIMERS) += arch_timer.o obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o obj-$(CONFIG_LOCAL_TIMERS) += percpu_timer.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
arch/arm/kernel/arch_timer.c new file +223 -0
223 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC PATCH v2 9/20 ARM: architected timers: add A15 architected timers
arch/arm/Kconfig config HOTPLUG_CPU · line 1413
Quoted 13 lines · Marc Zyngier
arch/arm/Kconfig +4
-0@@ -1407,9 +1407,14 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. +config HAVE_ARCH_TIMERS + bool + depends on CPU_V7 + select TICK_ONESHOT
I don't think you need to select TICK_ONESHOT. The user should be selecting NO_HZ or HIGH_RES_TIMERS instead, right?
arch/arm/Kconfig config HOTPLUG_CPU · line 1420
Quoted 7 lines
arch/arm/Kconfig +7
-0+ +static struct clocksource clocksource_counter = { + .name = "arch_sys_counter", + .rating = 400, + .read = arch_counter_read, + .mask = CLOCKSOURCE_MASK(56), + .flags = (CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES),
I'm fairly certain that CLOCK_SOURCE_VALID_FOR_HRES is a private flag not to be used by clocksource drivers. At least grepping the kernel for it shows no results outside of kernel/time/
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.
RFC PATCH v2 9/20 ARM: architected timers: add A15 architected timers
On Fri, 2011-04-08 at 19:47 -0700, Stephen Boyd wrote:
Hi Stephen,
Quoted 10 lines · Marc Zyngier
Quoted 9 lines
arch/arm/Kconfig +0
-0@@ -1407,9 +1407,14 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu.
Quoted 7 lines
arch/arm/Kconfig config HOTPLUG_CPU · line 1413
Quoted 4 lines
arch/arm/Kconfig +4
-0+config HAVE_ARCH_TIMERS + bool + depends on CPU_V7 + select TICK_ONESHOTI don't think you need to select
TICK_ONESHOT. The user should be selectingNO_HZorHIGH_RES_TIMERSinstead, right?
The A15 timer only has the one-shot feature (ie no auto-relead). Not having TICK_ONESHOT would render the timer completely unusable if neither NO_HZ nor HIGH_RES_TIMERS are selected. For that reason, I believe selecting TICK_ONESHOT is necessary.
Quoted 11 lines
arch/arm/Kconfig config HOTPLUG_CPU · line 1420
Quoted 7 lines
arch/arm/Kconfig +7
-0+ +static struct clocksource clocksource_counter = { + .name = "arch_sys_counter", + .rating = 400, + .read = arch_counter_read, + .mask = CLOCKSOURCE_MASK(56), + .flags = (CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES),I'm fairly certain that
CLOCK_SOURCE_VALID_FOR_HRESis a private flag not to be used by clocksource drivers. At least grepping the kernel for it shows no results outside ofkernel/time/
You're probably right here. Will fix.
Thanks for reviewing.
M.
Signature · 1 line
Reality is an implementation detail.
RFC PATCH v2 10/20 ARM: Platform dependent sched_clock() override
In reply to Marc Zyngiersched_clock being a (weak) global symbol, there can only be a single implementation in the kernel, which may cause problems on the rocky road towards supporting multiple architectures in a single kernel image.
This patch adds a way of overriding the default sched_clock() by extending the ARM sched_clock framework. The sched_clock() call also becomes slightly more expensive (indirect function call).
VExpress support is updated to use that functionnality.
--- arch/arm/Kconfig | 9 +++++++ arch/arm/include/asm/sched_clock.h | 41 +++++++++++++++++++++++++++++--- arch/arm/kernel/sched_clock.c | 23 +++++++++++++++++- arch/arm/plat-versatile/sched-clock.c | 7 +++-- 4 files changed, 72 insertions(+), 8 deletions(-)
arch/arm/Kconfig +9 -0
@@ -48,6 +48,14 @@ config SYS_SUPPORTS_APM_EMULATION config HAVE_SCHED_CLOCK bool +config ARCH_SCHED_CLOCK + bool + help + Allow the default sched_clock() to be overloaded at runtime. + Use this option if you build a kernel for a platform with + multiplee sched_clock sources, one of which will be selected + at runtime. + config GENERIC_GPIO bool
@@ -275,6 +283,7 @@ config ARCH_VEXPRESS select ARM_TIMER_SP804 select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS + select ARCH_SCHED_CLOCK select HAVE_CLK select HAVE_PATA_PLATFORM select ICST
arch/arm/include/asm/sched_clock.h +37 -4
69 lines not on this page · raw message
arch/arm/kernel/sched_clock.c +22 -1
@@ -18,13 +18,29 @@ static void sched_clock_poll(unsigned long wrap_ticks); static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);static void (*sched_clock_update_fn)(void ); +#ifdef CONFIG_ARCH_SCHED_CLOCK +static unsigned long long notrace default_sched_clock (void ) +{ +return (unsigned long long )(jiffies -INITIAL_JIFFIES ) + * (NSEC_PER_SEC /HZ ); +} + +static unsigned long long __read_mostly (*sched_clock_fn)(void ) = default_sched_clock; + +unsigned long long notrace sched_clock (void ) +{ +return sched_clock_fn (); +} +#endif +static void sched_clock_poll (unsigned long wrap_ticks) {mod_timer (&sched_clock_timer,round_jiffies (jiffies + wrap_ticks));sched_clock_update_fn (); } -void __init init_sched_clock (struct clock_data *cd,void (*update)(void ), +void __init init_arch_sched_clock (struct clock_data *cd,void (*update)(void ), +unsigned long long (*arch_sched_clock_fn)(void ),unsigned int clock_bits,unsigned long rate) {unsigned long r, w;
@@ -33,6 +49,11 @@ void __init init_sched_clock(struct clock_data *cd, void (*update)(void), sched_clock_update_fn = update; +#ifdef CONFIG_ARCH_SCHED_CLOCK +if (arch_sched_clock_fn) + sched_clock_fn = arch_sched_clock_fn; +#endif +/* calculate the mult/shift to convert counter ticks to ns. */ clocks_calc_mult_shift (&cd->mult, &cd->shift, rate,NSEC_PER_SEC ,0 );
arch/arm/plat-versatile/sched-clock.c +4 -3
@@ -34,7 +34,7 @@ static void __iomem *ctr;#define SC_MULT 2796202667u#define SC_SHIFT 26 -unsigned long long notrace sched_clock (void ) +DEFINE_SCHED_CLOCK_FUNC (versatile_sched_clock) {if (ctr) {u32 cyc =readl (ctr);
@@ -53,6 +53,7 @@ static void notrace versatile_update_sched_clock(void)void __init versatile_sched_clock_init (void __iomem *reg,unsigned long rate) { ctr = reg; -init_fixed_sched_clock (&cd, versatile_update_sched_clock, -32 , rate,SC_MULT ,SC_SHIFT ); +init_fixed_arch_sched_clock (&cd, versatile_update_sched_clock, + versatile_sched_clock, +32 , rate,SC_MULT ,SC_SHIFT ); }
Signature · 1 line
1.7.0.4
RFC PATCH v2 11/20 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 | 4 ++-- arch/arm/kernel/arch_timer.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-)
arch/arm/include/asm/arch_timer.h +2 -2
@@ -2,9 +2,9 @@#define __ASMARM_ARCH_TIMER_H#ifdef CONFIG_HAVE_ARCH_TIMERS -int arch_timer_register_setup (void (*setup)(struct clock_event_device *)); +int arch_timer_register_setup (int (*setup)(struct clock_event_device *));#else -static inline int arch_timer_register_setup (void (*setup)(struct clock_event_device *)) +static inline int arch_timer_register_setup (int (*setup)(struct clock_event_device *)) {return -ENODEV ; }
arch/arm/kernel/arch_timer.c +31 -1
@@ -20,10 +20,13 @@#include <asm/cputype.h> #include <asm/localtimer.h> +#include <asm/sched_clock.h> #include <asm/hardware/gic.h> static unsigned long arch_timer_rate; +static DEFINE_CLOCK_DATA (cd); +/* * Architected system timer support. */
@@ -201,6 +204,30 @@ static struct clocksource clocksource_counter = { .flags = (CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES), }; +static u32 arch_counter_get_cntvct32 (void ) +{ +cycle_t cntvct; + + 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 ); +} + +DEFINE_SCHED_CLOCK_FUNC (arch_timer_sched_clock) +{ +return cyc_to_sched_clock (&cd,arch_counter_get_cntvct32 (), (u32 )~0 ); +} + +static void notrace arch_timer_update_sched_clock(void) +{ +update_sched_clock (&cd,arch_counter_get_cntvct32 (), (u32 )~0 ); +} +static int __init arch_timer_clocksource_init (void ) {struct clocksource *cs = &clocksource_counter;
@@ -209,10 +236,13 @@ static int __init arch_timer_clocksource_init(void)clocksource_register_hz (cs, arch_timer_rate); +init_arch_sched_clock (&cd, arch_timer_update_sched_clock, + arch_timer_sched_clock,32 , arch_timer_rate); +return 0 ; } -int __init arch_timer_register_setup (void (*setup)(struct clock_event_device *)) +int __init arch_timer_register_setup (int (*setup)(struct clock_event_device *)) {if (!arch_timer_available ())return -ENODEV ;
Signature · 1 line
1.7.0.4
RFC PATCH v2 12/20 ARM: versatile/vexpress: rework timer support
In reply to Marc ZyngierDynamically register the TWD setup function.
For vexpress, give preference to architected timers over SP804 timers and versatile sched_clock implementation, if available.
--- arch/arm/mach-realview/realview_eb.c | 4 ++- arch/arm/mach-realview/realview_pb11mp.c | 4 ++- arch/arm/mach-realview/realview_pbx.c | 5 ++- arch/arm/mach-vexpress/v2m.c | 29 ++++++++++++++++++++- arch/arm/plat-versatile/include/plat/localtimer.h | 9 ++++++ arch/arm/plat-versatile/localtimer.c | 10 ++++++- 6 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 arch/arm/plat-versatile/include/plat/localtimer.h
arch/arm/mach-realview/realview_eb.c +3 -1
@@ -45,6 +45,8 @@#include <mach/board-eb.h> #include <mach/irqs.h> +#include <plat/localtimer.h> +#include "core.h" static struct map_desc realview_eb_io_desc[]__initdata = {
@@ -402,7 +404,7 @@ static void __init realview_eb_timer_init(void)if (core_tile_eb11mp () ||core_tile_a9mp ()) {#ifdef CONFIG_LOCAL_TIMERS - twd_base =__io_address (REALVIEW_EB11MP_TWD_BASE ); +versatile_local_timer_init (__io_address (REALVIEW_EB11MP_TWD_BASE ));#endif timer_irq =IRQ_EB11MP_TIMER0_1 ; }else
arch/arm/mach-realview/realview_pb11mp.c +3 -1
@@ -46,6 +46,8 @@#include <mach/board-pb11mp.h> #include <mach/irqs.h> +#include <plat/localtimer.h> +#include "core.h" static struct map_desc realview_pb11mp_io_desc[]__initdata = {
@@ -306,7 +308,7 @@ static void __init realview_pb11mp_timer_init(void) timer3_va_base =__io_address (REALVIEW_PB11MP_TIMER2_3_BASE ) +0x20 ;#ifdef CONFIG_LOCAL_TIMERS - twd_base =__io_address (REALVIEW_TC11MP_TWD_BASE ); +versatile_local_timer_init (__io_address (REALVIEW_TC11MP_TWD_BASE ));#endif realview_timer_init (IRQ_TC11MP_TIMER0_1 ); }
arch/arm/mach-realview/realview_pbx.c +3 -2
@@ -31,7 +31,6 @@#include <asm/leds.h> #include <asm/mach-types.h> #include <asm/pmu.h> -#include <asm/smp_twd.h> #include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h>
@@ -44,6 +43,8 @@#include <mach/board-pbx.h> #include <mach/irqs.h> +#include <plat/localtimer.h> +#include "core.h" static struct map_desc realview_pbx_io_desc[]__initdata = {
@@ -310,7 +311,7 @@ static void __init realview_pbx_timer_init(void)#ifdef CONFIG_LOCAL_TIMERS if (core_tile_pbx11mp () ||core_tile_pbxa9mp ()) - twd_base =__io_address (REALVIEW_PBX_TILE_TWD_BASE ); +versatile_local_timer_init (__io_address (REALVIEW_PBX_TILE_TWD_BASE ));#endif realview_timer_init (IRQ_PBX_TIMER0_1 ); }
arch/arm/mach-vexpress/v2m.c +28 -1
@@ -16,6 +16,8 @@#include <asm/mach-types.h> #include <asm/sizes.h> +#include <asm/localtimer.h> +#include <asm/arch_timer.h> #include <asm/mach/arch.h> #include <asm/mach/flash.h> #include <asm/mach/map.h>
@@ -28,6 +30,7 @@#include <mach/motherboard.h> #include <plat/sched_clock.h> +#include <plat/localtimer.h> #include "core.h"
@@ -49,13 +52,37 @@ static struct map_desc v2m_io_desc[] __initdata = {static void __init v2m_init_early (void ) { ct_desc->init_early (); -versatile_sched_clock_init (MMIO_P2V (V2M_SYS_24MHZ ),24000000 ); +} + +static int __cpuinit v2m_arch_timer_setup (struct clock_event_device *evt) +{ +versatile_local_timer_setup (evt); + +/* +* Enable PPI 30 in case we're running in normal mode instead +* of secure mode. The timer has been stopped in the pre_setup() +* phase, so it is safe to enable the interrupt here. +*/ +gic_enable_ppi (30 ); + +return 0 ; }static void __init v2m_timer_init (void ) {u32 scctrl; +/* +* Try architected timers first. If they are not available, +* fallback to TWD and versatile sched_clock. +*/ +if (!arch_timer_register_setup (v2m_arch_timer_setup)) +return ; + +versatile_local_timer_init (NULL ); + +versatile_sched_clock_init (MMIO_P2V (V2M_SYS_24MHZ ),24000000 ); +/* Select 1MHz TIMCLK as the reference clock for SP804 timers */ scctrl =readl (MMIO_P2V (V2M_SYSCTL +SCCTRL )); scctrl |=SCCTRL_TIMEREN0SEL_TIMCLK ;
arch/arm/plat-versatile/include/plat/localtimer.h new file +9 -0
@@ -0,0 +1,9 @@ +#ifndef ARM_PLAT_LOCALTIMER_H +#define ARM_PLAT_LOCALTIMER_H + +#include <linux/clockchips.h> + +void versatile_local_timer_setup (struct clock_event_device *evt); +void versatile_local_timer_init (void __iomem *base); + +#endif
arch/arm/plat-versatile/localtimer.c +9 -1
@@ -11,14 +11,22 @@#include <linux/init.h> #include <linux/clockchips.h> +#include <asm/smp_twd.h> #include <asm/localtimer.h> #include <mach/irqs.h> /* * Setup the local clock events for a CPU. */ -int __cpuinit local_timer_setup (struct clock_event_device *evt) +int __cpuinit versatile_local_timer_setup (struct clock_event_device *evt) { evt->irq =IRQ_LOCALTIMER ;return 0 ; } + +void __init versatile_local_timer_init (void __iomem *base) +{ +if (base) + twd_base = base; +twd_timer_register_setup (versatile_local_timer_setup); +}
Signature · 1 line
1.7.0.4
RFC PATCH v2 13/20 ARM: msm: dynamically register local timer setup function
In reply to Marc Zyngier--- arch/arm/mach-msm/timer.c | 22 +++++++++++++++++++--- 1 files changed, 19 insertions(+), 3 deletions(-)
arch/arm/mach-msm/timer.c +19 -3
@@ -22,8 +22,10 @@#include <linux/delay.h> #include <linux/io.h> +#include <asm/localtimer.h> #include <asm/mach/time.h> #include <mach/msm_iomap.h> +#include <mach/cpu.h> #define TIMER_MATCH_VAL 0x0000
@@ -200,6 +202,19 @@ static struct msm_clock msm_clocks[] = { } }; +#ifdef CONFIG_SMP +static void __cpuinit msm_local_timer_setup (struct clock_event_device *evt); +static int msm_local_timer_ack (void ); + +static struct local_timer_ops msm_timer_ops = { + .setup = msm_local_timer_setup, + .ack = msm_local_timer_ack, +}; +#define msm_timer_ops_ptr (&msm_timer_ops) +#else +#define msm_timer_ops_ptr NULL +#endif +static void __init msm_timer_init (void ) {int i;
@@ -228,6 +243,8 @@ static void __init msm_timer_init(void)writel (DGT_CLK_CTL_DIV_4 ,MSM_TMR_BASE +DGT_CLK_CTL );#endif +percpu_timer_register (msm_timer_ops_ptr); +for (i =0 ; i <ARRAY_SIZE (msm_clocks); i++) {struct msm_clock *clock = &msm_clocks[i];struct clock_event_device *ce = &clock->clockevent;
@@ -263,7 +280,7 @@ static void __init msm_timer_init(void) }#ifdef CONFIG_SMP -int __cpuinit local_timer_setup (struct clock_event_device *evt) +static void __cpuinit msm_local_timer_setup (struct clock_event_device *evt) {struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER ];
@@ -295,10 +312,9 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)gic_enable_ppi (clock->irq.irq);clockevents_register_device (evt); -return 0 ; } -inline int local_timer_ack (void ) +static inline int msm_local_timer_ack (void ) {return 1 ; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 14/20 ARM: omap4: dynamically register local timer setup function
In reply to Marc Zyngier--- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/timer-gp.c | 13 ++++++++++++- arch/arm/mach-omap2/timer-mpu.c | 36 ------------------------------------ 3 files changed, 12 insertions(+), 38 deletions(-) delete mode 100644 arch/arm/mach-omap2/timer-mpu.c
arch/arm/mach-omap2/Makefile +0 -1
@@ -22,7 +22,6 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o # SMP support ONLY available for OMAP4 obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o -obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o
arch/arm/mach-omap2/timer-gp.c +12 -1
@@ -39,6 +39,7 @@#include <asm/mach/time.h> #include <plat/dmtimer.h> #include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <plat/common.h> #include <plat/omap_hwmod.h>
@@ -247,12 +248,22 @@ static void __init omap2_gp_clocksource_init(void) }#endif +#ifdef CONFIG_LOCAL_TIMERS +static int __cpuinit omap4_local_timer_setup (struct clock_event_device *evt) +{ + evt->irq =OMAP44XX_IRQ_LOCALTIMER ; +return 0 ; +} +#endif +static void __init omap2_gp_timer_init (void ) {#ifdef CONFIG_LOCAL_TIMERS -if (cpu_is_omap44xx ()) { +if (cpu_is_omap44xx () &&omap_rev () !=OMAP4430_REV_ES1_0 ) { twd_base =ioremap (OMAP44XX_LOCAL_TWD_BASE ,SZ_256 );BUG_ON (!twd_base); + +twd_timer_register_setup (omap4_local_timer_setup); }#endif omap_dm_timer_init ();
arch/arm/mach-omap2/timer-mpu.c deleted +0 -36
@@ -1,36 +0,0 @@ -/* -* The MPU local timer source file. In OMAP4, both cortex-a9 cores have -* own timer in it's MPU domain. These timers will be driving the -* linux kernel SMP tick framework when active. These timers are not -* part of the wake up domain. -* -* Copyright (C) 2009 Texas Instruments, Inc. -* -* Author: -* Santosh Shilimkar <[email protected]> -* -* This file is based on arm realview smp platform file. -* Copyright (C) 2002 ARM Ltd. -* -* 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/clockchips.h> -#include <asm/irq.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ -/* Local timers are not supprted on OMAP4430 ES1.0 */ -if (omap_rev () ==OMAP4430_REV_ES1_0 ) -return -ENXIO ; - - evt->irq =OMAP44XX_IRQ_LOCALTIMER ; -return 0 ; -} -
Signature · 1 line
1.7.0.4
RFC PATCH v2 14/20 ARM: omap4: dynamically register local timersetup function
Marc,
Quoted 54 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux- arm-kernel-bounces at lists.infradead.org] On Behalf Of Marc Zyngier
Sent: Tuesday, March 15, 2011 8:43 PM
To: linux-arm-kernel at lists.infradead.org
Cc: Tony Lindgren
Subject: [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup functionCc Tony Lindgren <[email protected]>Signed-off-by Marc Zyngier <[email protected]>--- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/timer-gp.c | 13 ++++++++++++- arch/arm/mach-omap2/timer-mpu.c | 36 ---------------------------- -------- 3 files changed, 12 insertions(+), 38 deletions(-) delete mode 100644 arch/arm/mach-omap2/timer-mpu.carch/arm/mach- renamed from arch/arm/mach-omap2/Makefile +0
-0omap2/Makefile
index a45cd64..41f8b67 100644arch/arm/mach-omap2/Makefile +0
-1@@ -22,7 +22,6 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o # SMP support ONLY available for OMAP4 obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o -obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.oarch/arm/mach- renamed from arch/arm/mach-omap2/timer-gp.c +0
-0
omap2/timer-gp.c
index 3b9cf85..98d03c5 100644arch/arm/mach-omap2/timer-gp.c +4
-0@@ -39,6 +39,7 @@#include <asm/mach/time.h> #include <plat/dmtimer.h> #include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <plat/common.h> #include <plat/omap_hwmod.h> @@ -247,12 +248,22 @@ static void __init omap2_gp_clocksource_init(void) }#endif +#ifdef CONFIG_LOCAL_TIMERS +static int __cpuinit omap4_local_timer_setup (struct clock_event_device *evt) +{
arch/arm/mach-omap2/timer-gp.c static void __init · line 264
Quoted 10 lines
arch/arm/mach-omap2/timer-gp.c +6
-1+ evt->irq =OMAP44XX_IRQ_LOCALTIMER ; + return 0; +} +#endif +static void __init omap2_gp_timer_init (void ) {#ifdef CONFIG_LOCAL_TIMERS -if (cpu_is_omap44xx ()) { +if (cpu_is_omap44xx () &&omap_rev () !=OMAP4430_REV_ES1_0 )
I see one problem here. The reason we changed the signature of local_timer_setup() is in case where the local timer isn't available on a specific SOC versions, the kernel will switch to broad-cast timers.
This way the kernel built with CONFIG_LOCAL_TIMERS can still work on SoCs where twd isn't supported.
Looks like your patch breaks that unless and until I am missing something.
Regards,
Santosh
RFC PATCH v2 14/20 ARM: omap4: dynamically register local timersetup function
Hi Santosh,
Quoted 71 lines · Santosh Shilimkar
Marc,
Quoted 54 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux- arm-kernel-bounces at lists.infradead.org] On Behalf Of Marc Zyngier
Sent: Tuesday, March 15, 2011 8:43 PM
To: linux-arm-kernel at lists.infradead.org
Cc: Tony Lindgren
Subject: [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup functionCc Tony Lindgren <[email protected]>Signed-off-by Marc Zyngier <[email protected]>--- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/timer-gp.c | 13 ++++++++++++- arch/arm/mach-omap2/timer-mpu.c | 36 ---------------------------- -------- 3 files changed, 12 insertions(+), 38 deletions(-) delete mode 100644 arch/arm/mach-omap2/timer-mpu.carch/arm/mach- renamed from arch/arm/mach-omap2/Makefile +0
-0omap2/Makefile
index a45cd64..41f8b67 100644arch/arm/mach-omap2/Makefile +0
-1@@ -22,7 +22,6 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o # SMP support ONLY available for OMAP4 obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o -obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.oarch/arm/mach- renamed from arch/arm/mach-omap2/timer-gp.c +0
-0
omap2/timer-gp.c
index 3b9cf85..98d03c5 100644arch/arm/mach-omap2/timer-gp.c +4
-0@@ -39,6 +39,7 @@#include <asm/mach/time.h> #include <plat/dmtimer.h> #include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <plat/common.h> #include <plat/omap_hwmod.h> @@ -247,12 +248,22 @@ static void __init omap2_gp_clocksource_init(void) }#endif +#ifdef CONFIG_LOCAL_TIMERS +static int __cpuinit omap4_local_timer_setup (struct clock_event_device *evt) +{arch/arm/mach-omap2/timer-gp.c static void __init · line 264
Quoted 10 lines
arch/arm/mach-omap2/timer-gp.c +6
-1+ evt->irq =OMAP44XX_IRQ_LOCALTIMER ; + return 0; +} +#endif +static void __init omap2_gp_timer_init (void ) {#ifdef CONFIG_LOCAL_TIMERS -if (cpu_is_omap44xx ()) { +if (cpu_is_omap44xx () &&omap_rev () !=OMAP4430_REV_ES1_0 )I see one problem here. The reason we changed the signature of
local_timer_setup()is in case where the local timer isn't available on a specific SOC versions, the kernel will switch to broad-cast timers.
Quoted 5 lines
This way the kernel built with
CONFIG_LOCAL_TIMERScan still work on SoCs where twd isn't supported.Looks like your patch breaks that unless and until I am missing something.
I think the bit you're missing is that when no local timer is registered, the code in percpu_timer.c::percpu_timer_setup() ensures that the broadcast timers are used as a default.
In the OMAP4 case, twd is registered unless we detect a OMAP4430_REV_ES1_0. In that case, we let the magic happen and fall back to the broadcast timers. Tested on a PandaBoard with twd artificially disabled.
M.
Signature · 1 line
Reality is an implementation detail.
RFC PATCH v2 14/20 ARM: omap4: dynamically register local timersetup function
Quoted 8 lines
-----Original Message-----
From: Marc Zyngier [mailto:Marc.Zyngier at arm.com]
Sent: Wednesday, March 16, 2011 3:34 PM
To: Santosh Shilimkar
Cc: linux-arm-kernel at lists.infradead.org; Tony Lindgren
Subject: RE: [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup function
[....]
Quoted 10 lines
Quoted 5 lines
This way the kernel built with
CONFIG_LOCAL_TIMERScan still work on SoCs where twd isn't supported.Looks like your patch breaks that unless and until I am missing something.
I think the bit you're missing is that when no local timer is registered, the code in
percpu_timer.c::percpu_timer_setup()ensures that the broadcast timers are used as a default.
Quoted 6 lines
In the OMAP4 case, twd is registered unless we detect a
OMAP4430_REV_ES1_0. In that case, we let the magic happen and fall back
to the broadcast timers. Tested on a PandaBoard with twd artificially disabled.
Cool.
Thanks for the update.
RFC PATCH v2 15/20 ARM: exynos4: dynamically register local timer setup function
In reply to Marc ZyngierAlso convert MCT to the new local timers API.
--- arch/arm/mach-exynos4/Makefile | 1 - arch/arm/mach-exynos4/localtimer.c | 25 ------------------------- arch/arm/mach-exynos4/mct.c | 22 +++++++++++++++------- arch/arm/mach-exynos4/time.c | 10 ++++++++++ 4 files changed, 25 insertions(+), 33 deletions(-) delete mode 100644 arch/arm/mach-exynos4/localtimer.c
arch/arm/mach-exynos4/Makefile +0 -1
@@ -23,7 +23,6 @@ ifeq ($(CONFIG_EXYNOS4_MCT),y) obj-y += mct.o else obj-y += time.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o endif obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
arch/arm/mach-exynos4/localtimer.c deleted +0 -25
@@ -1,25 +0,0 @@ -/* linux/arch/arm/mach-exynos4/localtimer.c -* -* Cloned from linux/arch/arm/mach-realview/localtimer.c -* -* Copyright (C) 2002 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/clockchips.h> - -#include <asm/irq.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =IRQ_LOCALTIMER ; -return 0 ; -}
arch/arm/mach-exynos4/mct.c +15 -7
@@ -348,7 +348,7 @@ static struct irqaction mct_tick1_event_irq = { .handler = exynos4_mct_tick_isr, }; -static void exynos4_mct_tick_init (struct clock_event_device *evt) +static int __cpuinit exynos4_mct_tick_init (struct clock_event_device *evt) {unsigned int cpu =smp_processor_id ();
@@ -386,19 +386,26 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)irq_set_affinity (IRQ_MCT1 ,cpumask_of (1 )); setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); } -} -/* Setup the local clock events for a CPU */ -void __cpuinit local_timer_setup (struct clock_event_device *evt) -{ -exynos4_mct_tick_init (evt); +return 0 ; } -int local_timer_ack (void ) +static int exynos4_mct_timer_ack (void ) {return 0 ; } +static struct local_timer_ops exynos4_mct_ops = { + .setup = exynos4_mct_tick_init, + .ack = exynos4_mct_timer_ack, +}; + +#define exynos4_mct_ops_ptr (&exynos4_mct_ops) + +#else + +#define exynos4_mct_ops_ptr NULL +#endif /* CONFIG_LOCAL_TIMERS */ static void __init exynos4_timer_resources (void )
@@ -414,6 +421,7 @@ static void __init exynos4_timer_init(void)exynos4_timer_resources ();exynos4_clocksource_init ();exynos4_clockevent_init (); +percpu_timer_register (exynos4_mct_ops_ptr); }struct sys_timer exynos4_timer = {
arch/arm/mach-exynos4/time.c +10 -0
@@ -19,9 +19,11 @@#include <linux/clockchips.h> #include <linux/platform_device.h> +#include <asm/localtimer.h> #include <asm/smp_twd.h> #include <mach/map.h> +#include <mach/irqs.h> #include <plat/regs-timer.h> #include <asm/mach/time.h>
@@ -283,10 +285,18 @@ static void __init exynos4_timer_resources(void)clk_enable (tin4); } +#ifdef CONFIG_LOCAL_TIMERS +static void __cpuinit exynos4_local_timer_setup (struct clock_event_device *evt) +{ + evt->irq =IRQ_LOCALTIMER ; +} +#endif +static void __init exynos4_timer_init (void ) {#ifdef CONFIG_LOCAL_TIMERS twd_base =S5P_VA_TWD ; +twd_timer_register_setup (exynos4_local_timer_setup);#endif exynos4_timer_resources ();
Signature · 1 line
1.7.0.4
RFC PATCH v2 16/20 ARM: shmobile: dynamically register local timer setup function
In reply to Marc Zyngier--- arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/localtimer.c | 25 ------------------------- arch/arm/mach-shmobile/timer.c | 13 +++++++++++++ 3 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 arch/arm/mach-shmobile/localtimer.c
arch/arm/mach-shmobile/Makefile +0 -1
@@ -14,7 +14,6 @@ obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o # SMP objects smp-y := platsmp.o headsmp.o smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o -smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o # Pinmux setup
arch/arm/mach-shmobile/localtimer.c deleted +0 -25
@@ -1,25 +0,0 @@ -/* -* SMP support for R-Mobile / SH-Mobile - local timer portion -* -* Copyright (C) 2010 Magnus Damm -* -* Based on vexpress, Copyright (C) 2002 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/smp.h> -#include <linux/clockchips.h> -#include <asm/smp_twd.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =29 ; -return 0 ; -}
arch/arm/mach-shmobile/timer.c +13 -0
@@ -19,6 +19,8 @@* */ #include <linux/platform_device.h> +#include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/mach/time.h> static void __init shmobile_late_time_init (void )
@@ -36,8 +38,19 @@ static void __init shmobile_late_time_init(void)early_platform_driver_probe ("earlytimer" ,2 ,0 ); } +#ifdef CONFIG_LOCAL_TIMERS +static int __cpuinit shmobile_local_timer_setup (struct clock_event_device *evt) +{ + evt->irq =29 ; +return 0 ; +} +#else +#define shmobile_local_timer_setup NULL +#endif +static void __init shmobile_timer_init (void ) { +twd_timer_register_setup (shmobile_local_timer_setup); late_time_init = shmobile_late_time_init; }
Signature · 1 line
1.7.0.4
RFC PATCH v2 17/20 ARM: tegra: dynamically register local timer setup function
In reply to Marc Zyngier--- arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/localtimer.c | 24 ------------------------ arch/arm/mach-tegra/timer.c | 11 +++++++++++ 3 files changed, 12 insertions(+), 25 deletions(-) delete mode 100644 arch/arm/mach-tegra/localtimer.c
arch/arm/mach-tegra/Makefile +1 -1
@@ -12,7 +12,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o -obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
arch/arm/mach-tegra/localtimer.c deleted +0 -24
@@ -1,24 +0,0 @@ -/* -* arch/arm/mach-tegra/localtimer.c -* -* Copyright (C) 2002 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/clockchips.h> - -#include <asm/irq.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =IRQ_LOCALTIMER ; -return 0 ; -}
arch/arm/mach-tegra/timer.c +11 -0
@@ -30,6 +30,7 @@#include <asm/mach/time.h> #include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <mach/iomap.h>
@@ -192,6 +193,14 @@ static struct irqaction tegra_timer_irq = { .irq = INT_TMR3, }; +#ifdef CONFIG_HAVE_ARM_TWD +static int __cpuinit tegra_local_timer_setup (struct clock_event_device *evt) +{ + evt->irq =IRQ_LOCALTIMER ; +return 0 ; +} +#endif +static void __init tegra_init_timer (void ) {struct clk *clk;
@@ -212,6 +221,8 @@ static void __init tegra_init_timer(void)#ifdef CONFIG_HAVE_ARM_TWD twd_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE +0x600 ); + +twd_timer_register_setup (tegra_local_timer_setup);#endif switch (rate) {
Signature · 1 line
1.7.0.4
RFC PATCH v2 18/20 ARM: ux500: dynamically register local timer setup function
In reply to Marc Zyngier--- arch/arm/mach-ux500/Makefile | 1 - arch/arm/mach-ux500/cpu.c | 13 +++++++++++++ arch/arm/mach-ux500/localtimer.c | 26 -------------------------- 3 files changed, 13 insertions(+), 27 deletions(-) delete mode 100644 arch/arm/mach-ux500/localtimer.c
arch/arm/mach-ux500/Makefile +0 -1
@@ -14,7 +14,6 @@ obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o
arch/arm/mach-ux500/cpu.c +13 -0
@@ -8,12 +8,15 @@#include <linux/platform_device.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/clockchips.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> #include <asm/hardware/gic.h> #include <asm/mach/map.h> +#include <asm/irq.h> #include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <plat/mtu.h> #include <mach/hardware.h>
@@ -115,6 +118,14 @@ static int ux500_l2x0_init(void)early_initcall (ux500_l2x0_init);#endif +#ifdef CONFIG_LOCAL_TIMERS +static int __cpuinit ux500_local_timer_setup (struct clock_event_device *evt) +{ + evt->irq =IRQ_LOCALTIMER ; +return 0 ; +} +#endif +static void __init ux500_timer_init (void ) {#ifdef CONFIG_LOCAL_TIMERS
@@ -125,6 +136,8 @@ static void __init ux500_timer_init(void) twd_base =__io_address (U8500_TWD_BASE ); elseux500_unknown_soc (); + +twd_timer_register_setup (ux500_local_timer_setup);#endif if (cpu_is_u5500 ()) mtu_base =__io_address (U5500_MTU0_BASE );
arch/arm/mach-ux500/localtimer.c deleted +0 -26
@@ -1,26 +0,0 @@ -/* -* Copyright (C) 2008-2009 ST-Ericsson -* Srinidhi Kasagar <[email protected]> -* -* This file is heavily based on relaview platform, almost a copy. -* -* Copyright (C) 2002 ARM Ltd. -* -* 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/clockchips.h> - -#include <asm/irq.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =IRQ_LOCALTIMER ; -return 0 ; -}
Signature · 1 line
1.7.0.4
RFC PATCH v2 19/20 ARM: simplify percpu_timer_setup
In reply to Marc ZyngierNow that all in-tree providers of local_timer_setup() are dynamically registering their timers with the per cpu timer code, remove the legacy timer selection code.
If no local timer is provided, a broadcast timer will be used as a fallback.
--- arch/arm/include/asm/localtimer.h | 5 ----- arch/arm/include/asm/smp_twd.h | 8 +------- arch/arm/kernel/percpu_timer.c | 19 +------------------ arch/arm/kernel/smp_twd.c | 12 ++---------- 4 files changed, 4 insertions(+), 40 deletions(-)
arch/arm/include/asm/localtimer.h +0 -5
@@ -43,11 +43,6 @@ struct local_timer_ops {#ifdef CONFIG_LOCAL_TIMERS /* -* Setup a local timer interrupt for a CPU. -*/ -int local_timer_setup (struct clock_event_device *); - -/* * Register a local timer. */ void percpu_timer_register (struct local_timer_ops *);
arch/arm/include/asm/smp_twd.h +1 -7
@@ -23,15 +23,9 @@extern void __iomem *twd_base;#ifdef CONFIG_HAVE_ARM_TWD -struct local_timer_ops *local_timer_get_twd_ops (void );int twd_timer_register_setup (int (*setup)(struct clock_event_device *));#else -static inline struct local_timer_ops *local_timer_get_twd_ops (void ) -{ -return NULL ; -} - -static inline int twd_timer_register_setup (int (*setup)(struct clock_event_device *)) +static inline int twd_timer_register_setup (void (*setup)(struct clock_event_device *)) {return -ENODEV ; }
arch/arm/kernel/percpu_timer.c +1 -18
@@ -48,12 +48,7 @@ static struct local_timer_ops broadcast_timer_ops = { .setup = broadcast_timer_setup, }; -static struct local_timer_ops *timer_ops; - -int __attribute__ ((weak))local_timer_setup (struct clock_event_device *evt) -{ -return -ENXIO ; -} +static struct local_timer_ops *timer_ops = &broadcast_timer_ops;void percpu_timer_register (struct local_timer_ops *ops) {
@@ -124,18 +119,6 @@ void __cpuinit percpu_timer_setup(void)if (evt->name)return ; -/* -* All this can go away once we've migrated all users to -* properly register the timer they use, and broadcast can -* become the fallback. -*/ -if (!timer_ops) - timer_ops =local_timer_get_twd_ops (); -if (!timer_ops) - timer_ops = &broadcast_timer_ops; -if (!timer_ops->plat_setup) - timer_ops->plat_setup = local_timer_setup; - evt->cpumask =cpumask_of (cpu);if (timer_ops->pre_setup)
arch/arm/kernel/smp_twd.c +2 -10
@@ -149,20 +149,12 @@ static struct local_timer_ops twd_timer_ops = { .ack = twd_timer_ack, }; -struct local_timer_ops *local_timer_get_twd_ops (void ) +int __init twd_timer_register_setup (int (*setup)(struct clock_event_device *)) {if (!twd_base) {pr_warn ("TWD base address not set\n" ); -return NULL ; - } - -return &twd_timer_ops; -} - -int __init twd_timer_register_setup (int (*setup)(struct clock_event_device *)) -{ -if (!twd_base)return -ENODEV ; + }percpu_timer_register_setup (&twd_timer_ops, setup);return 0 ;
Signature · 1 line
1.7.0.4
RFC PATCH v2 20/20 ARM: simplify percpu_timer_ack
In reply to Marc ZyngierThere is no provider of local_timer_ack anymore after the conversion of msm to the percpu_timer interface. Remove the weak local_timer_ack symbol and directly call percpu_timer_ack.
--- arch/arm/kernel/percpu_timer.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
arch/arm/kernel/percpu_timer.c +1 -7
@@ -60,24 +60,18 @@ void percpu_timer_register(struct local_timer_ops *ops)* * If a local timer interrupt has occurred, acknowledge and return 1. * Otherwise, return 0. -* -* This can be overloaded by platform code that doesn't provide its -* timer in timer_fns way (msm at the moment). Once all platforms have -* migrated, the weak alias can be removed. */ static int percpu_timer_ack (void ) {return timer_ops->ack (); } -int local_timer_ack (void ) __attribute__ ((weak,alias ("percpu_timer_ack" ))); - asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) {struct pt_regs *old_regs =set_irq_regs (regs);int cpu =smp_processor_id (); -if (local_timer_ack ()) { +if (percpu_timer_ack ()) {__inc_irq_stat (cpu, local_timer_irqs);percpu_timer_run (); }
Signature · 1 line
1.7.0.4