Skip to contentSkip to conversation

A15 architected timer support

RFC PATCH New Marc Zyngier 3 participants 26 messages Mar 15, 2011 – Apr 11, 2011

Subsystems (9)
lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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
index 93d595a..b7e504b 100644
@@ -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
index ec0bbf7..589d4ef 100644
@@ -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
index 96ed521..2e31e8d 100644
@@ -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
index fed9981..4096736 100644
@@ -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
index 74554f1..277f6ff 100644
@@ -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
index 3535d37..97154bc 100644
@@ -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
index 60636f4..4fdfb85 100644
@@ -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
#2 lore raw

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
index 31c0ac4..02feaff 100644
@@ -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
#3 lore raw

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
index 6bf3d0a..9d9be20 100644
@@ -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
#4 lore raw

RFC PATCH v2 4/20 ARM: shmobile: remove stubbed twd_timer_setup call

In reply to Marc Zyngier
Cc Paul Mundt <[email protected]>
Cc Magnus Damm <[email protected]>
---
 arch/arm/mach-shmobile/localtimer.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-shmobile/localtimer.c +0 -1
index ad9ccc9..a4c4e8b 100644
@@ -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
#5 lore raw

RFC PATCH v2 5/20 ARM: tegra: remove stubbed twd_timer_setup call

In reply to Marc Zyngier
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
---
 arch/arm/mach-tegra/localtimer.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/localtimer.c +1 -3
index e91d681..aaabad8 100644
@@ -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
#6 lore raw

RFC PATCH v2 6/20 ARM: ux500: remove stubbed twd_timer_setup call

In reply to Marc Zyngier
Cc Srinidhi Kasagar <[email protected]>
Cc Linus Walleij <[email protected]>
---
 arch/arm/mach-ux500/localtimer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)
arch/arm/mach-ux500/localtimer.c +0 -3
index 5ba1133..c648725 100644
@@ -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
#7 lore raw

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
index 0fb3961..93ea3e3 100644
@@ -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
#8 lore raw

RFC PATCH v2 8/20 ARM: remove unused twd_timer_setup stub

In reply to Marc Zyngier

Now 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
index 4096736..d2abe52 100644
@@ -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
#9 lore raw

RFC PATCH v2 9/20 ARM: architected timers: add A15 architected timers

In reply to Marc Zyngier

The 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
index b7e504b..38ee56e 100644
@@ -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
new file mode 100644
index 0000000..f98263c
@@ -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
index c115b82..b362a1e 100644
@@ -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
index 277f6ff..add5e77 100644
@@ -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
#10 lore raw

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
index b7e504b..38ee56e 100644
@@ -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.
#11 lore raw

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
index b7e504b..38ee56e 100644
@@ -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_ONESHOT

I don't think you need to select TICK_ONESHOT. The user should be selecting NO_HZ or HIGH_RES_TIMERS instead, 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_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/

You're probably right here. Will fix.

Thanks for reviewing.

	M.
Signature · 1 line
Reality is an implementation detail.
#12 lore raw

RFC PATCH v2 10/20 ARM: Platform dependent sched_clock() override

In reply to Marc Zyngier

sched_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
index 38ee56e..08b3ff2 100644
@@ -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
index 9a46370..3c1d08b 100644
@@ -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
index 3d6a4c2..d6ebd0f 100644
@@ -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
#13 lore raw

RFC PATCH v2 11/20 ARM: architected timers: Add A15 specific sched_clock implementation

In reply to Marc Zyngier

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.

---
 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
index f98263c..9fa0556 100644
@@ -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
index bc05604..fe55919 100644
@@ -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
#14 lore raw

RFC PATCH v2 12/20 ARM: versatile/vexpress: rework timer support

In reply to Marc Zyngier

Dynamically 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
index 2ecc1d9..3a0900f 100644
@@ -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
index b2985fc..76da67d 100644
@@ -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
index 92ace2c..280befd 100644
@@ -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
index ba46e8e..9fa5ad6 100644
@@ -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
new file mode 100644
index 0000000..c6cdf72
@@ -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
index 93ea3e3..01025ea 100644
@@ -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
#15 lore raw

RFC PATCH v2 13/20 ARM: msm: dynamically register local timer setup function

In reply to Marc Zyngier
Cc David Brown <[email protected]>
Cc Daniel Walker <[email protected]>
Cc Bryan Huntsman <[email protected]>
---
 arch/arm/mach-msm/timer.c |   22 +++++++++++++++++++---
 1 files changed, 19 insertions(+), 3 deletions(-)
arch/arm/mach-msm/timer.c +19 -3
index 56f920c..f4b6d54 100644
@@ -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
#16 lore raw

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
index a45cd64..41f8b67 100644
@@ -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
index 3b9cf85..98d03c5 100644
@@ -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
deleted file mode 100644
index 02feaff..0000000
@@ -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
#17 lore raw

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 function

---
 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- renamed from arch/arm/mach-omap2/Makefile +0 -0

omap2/Makefile
index a45cd64..41f8b67 100644

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- renamed from arch/arm/mach-omap2/timer-gp.c +0 -0

omap2/timer-gp.c
index 3b9cf85..98d03c5 100644

arch/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

#18 lore raw

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 function

---
 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- renamed from arch/arm/mach-omap2/Makefile +0 -0

omap2/Makefile
index a45cd64..41f8b67 100644

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- renamed from arch/arm/mach-omap2/timer-gp.c +0 -0

omap2/timer-gp.c
index 3b9cf85..98d03c5 100644

arch/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_TIMERS can 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.
#19 lore raw

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_TIMERS can 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.

#20 lore raw

RFC PATCH v2 15/20 ARM: exynos4: dynamically register local timer setup function

In reply to Marc Zyngier

Also convert MCT to the new local timers API.

Cc Kukjin Kim <[email protected]>
Cc Changhwan Youn <[email protected]>
---
 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
index 9473adb..f6f3075 100644
@@ -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
deleted file mode 100644
index 9d9be20..0000000
@@ -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
index af82a8f..4d67123 100644
@@ -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
index 86b9fa0..ce08297 100644
@@ -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
#21 lore raw

RFC PATCH v2 16/20 ARM: shmobile: dynamically register local timer setup function

In reply to Marc Zyngier
Cc Paul Mundt <[email protected]>
Cc Magnus Damm <[email protected]>
---
 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
index e2507f6..290a232 100644
@@ -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
deleted file mode 100644
index a4c4e8b..0000000
@@ -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
index 895794b..30a75c0 100644
@@ -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
#22 lore raw

RFC PATCH v2 17/20 ARM: tegra: dynamically register local timer setup function

In reply to Marc Zyngier
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
---
 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
index 9f7a7e1..5f4d7f1 100644
@@ -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
deleted file mode 100644
index aaabad8..0000000
@@ -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
index 0fcb1eb..5c756f3 100644
@@ -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
#23 lore raw

RFC PATCH v2 18/20 ARM: ux500: dynamically register local timer setup function

In reply to Marc Zyngier
Cc Srinidhi Kasagar <[email protected]>
Cc Linus Walleij <[email protected]>
---
 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
index b549a8f..224bc74 100644
@@ -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
index 5a43107..e4b1bb6 100644
@@ -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);
 	else
 		ux500_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
deleted file mode 100644
index c648725..0000000
@@ -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
#24 lore raw

RFC PATCH v2 19/20 ARM: simplify percpu_timer_setup

In reply to Marc Zyngier

Now 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
index 8988c50..d47a0cd 100644
@@ -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
index d2abe52..2c01220 100644
@@ -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
index 5992fae..85af863 100644
@@ -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
index 4fdfb85..e0bb094 100644
@@ -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
#25 lore raw

RFC PATCH v2 20/20 ARM: simplify percpu_timer_ack

In reply to Marc Zyngier

There 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
index 85af863..6e1942b 100644
@@ -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