All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCHv2 00/20] A15 architected timer support
@ 2011-03-15 15:12 Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 01/20] ARM: architected timers: move local timer support to percpu_timer.c Marc Zyngier
                   ` (19 more replies)
  0 siblings, 20 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 01/20] ARM: architected timers: move local timer support to percpu_timer.c
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 02/20] ARM: omap2: remove stubbed twd_timer_setup call Marc Zyngier
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 93d595a..b7e504b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index ec0bbf7..589d4ef 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -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
 
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
index 080d74f..8988c50 100644
--- a/arch/arm/include/asm/localtimer.h
+++ b/arch/arm/include/asm/localtimer.h
@@ -10,7 +10,9 @@
 #ifndef __ASM_ARM_LOCALTIMER_H
 #define __ASM_ARM_LOCALTIMER_H
 
-struct clock_event_device;
+#include <linux/clockchips.h>
+
+struct seq_file;
 
 /*
  * Setup a per-cpu timer, whether it be a local timer or dummy broadcast
@@ -18,40 +20,58 @@ struct clock_event_device;
 void percpu_timer_setup(void);
 
 /*
- * Called from assembly, this is the local timer IRQ handler
+ * Call a per-cpu timer handler
  */
-asmlinkage void do_local_timer(struct pt_regs *);
-
-
-#ifdef CONFIG_LOCAL_TIMERS
-
-#ifdef CONFIG_HAVE_ARM_TWD
+void percpu_timer_run(void);
 
-#include "smp_twd.h"
-
-#define local_timer_ack()	twd_timer_ack()
-
-#else
+/*
+ * Stop a per-cpu timer
+ */
+void percpu_timer_stop(void);
 
 /*
- * Platform provides this to acknowledge a local timer IRQ.
- * Returns true if the local timer IRQ is to be processed.
+ * Called from assembly, this is the local timer IRQ handler
  */
-int local_timer_ack(void);
+asmlinkage void do_local_timer(struct pt_regs *);
 
-#endif
+struct local_timer_ops {
+	void	(*const pre_setup)(struct clock_event_device *clk);
+	int	(*plat_setup)(struct clock_event_device *clk);
+	void	(*const setup)(struct clock_event_device *clk);
+	int	(*const ack)(void);
+};
 
+#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 *);
 #else
-
-static inline int local_timer_setup(struct clock_event_device *evt)
+static inline void percpu_timer_register(void *dummy)
 {
-	return -ENXIO;
 }
 #endif
 
+static inline int percpu_timer_register_setup(struct local_timer_ops *ops,
+					      int (*plat_setup)(struct clock_event_device *))
+{
+	if (ops) {
+		ops->plat_setup = plat_setup;
+		percpu_timer_register(ops);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+/*
+ * show local interrupt info
+ */
+extern void show_local_irqs(struct seq_file *, int);
+
 #endif
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 96ed521..2e31e8d 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -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 */
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index fed9981..4096736 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -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
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 74554f1..277f6ff 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -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
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 3535d37..97154bc 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -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>
diff --git a/arch/arm/kernel/percpu_timer.c b/arch/arm/kernel/percpu_timer.c
new file mode 100644
index 0000000..5992fae
--- /dev/null
+++ b/arch/arm/kernel/percpu_timer.c
@@ -0,0 +1,164 @@
+/*
+ *  linux/arch/arm/kernel/percpu_timer.c
+ *
+ *  Copyright (C) 2011 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+
+#include <asm/localtimer.h>
+#include <asm/hardware/gic.h>
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+static void broadcast_timer_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+}
+#else
+#define broadcast_timer_set_mode	NULL
+#define smp_timer_broadcast		NULL
+#endif
+
+static void broadcast_timer_setup(struct clock_event_device *evt)
+{
+	/* check that no-one has registered the timer in plat_setup */
+	if (evt->name)
+		return;
+
+	evt->name	= "dummy_timer";
+	evt->features	= CLOCK_EVT_FEAT_ONESHOT |
+			  CLOCK_EVT_FEAT_PERIODIC |
+			  CLOCK_EVT_FEAT_DUMMY;
+	evt->rating	= 400;
+	evt->mult	= 1;
+	evt->set_mode	= broadcast_timer_set_mode;
+	evt->broadcast	= smp_timer_broadcast;
+
+	clockevents_register_device(evt);
+}
+
+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;
+}
+
+void percpu_timer_register(struct local_timer_ops *ops)
+{
+	timer_ops = ops;
+}
+
+/*
+ * local_timer_ack: checks for a local timer interrupt.
+ *
+ * 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()) {
+		__inc_irq_stat(cpu, local_timer_irqs);
+		percpu_timer_run();
+	}
+
+	set_irq_regs(old_regs);
+}
+
+void show_local_irqs(struct seq_file *p, int prec)
+{
+	unsigned int cpu;
+
+	seq_printf(p, "%*s: ", prec, "LOC");
+
+	for_each_present_cpu(cpu)
+		seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
+
+	seq_printf(p, " Local timer interrupts\n");
+}
+
+/*
+ * Timer (local or broadcast) support
+ */
+static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
+
+void percpu_timer_run(void)
+{
+	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
+	irq_enter();
+	evt->event_handler(evt);
+	irq_exit();
+}
+
+void __cpuinit percpu_timer_setup(void)
+{
+	int ret = 0;
+	unsigned int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
+
+	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)
+		timer_ops->pre_setup(evt);
+	if (timer_ops->plat_setup)
+		ret = timer_ops->plat_setup(evt);
+	if (ret)	/* Fallback to broadcast */
+		timer_ops = &broadcast_timer_ops;
+	if (timer_ops->setup)
+		timer_ops->setup(evt);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * The generic clock events code purposely does not stop the local timer
+ * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
+ * manually here.
+ */
+void percpu_timer_stop(void)
+{
+	unsigned int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
+
+	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+}
+#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8fe05ad..b94b19c 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -153,8 +153,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static void percpu_timer_stop(void);
-
 /*
  * __cpu_disable runs on the processor to be shutdown.
  */
@@ -426,97 +424,13 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
 }
 
 /*
- * Timer (local or broadcast) support
+ * Broadcast timer support
  */
-static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
-
-static void ipi_timer(void)
-{
-	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
-	irq_enter();
-	evt->event_handler(evt);
-	irq_exit();
-}
-
-#ifdef CONFIG_LOCAL_TIMERS
-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()) {
-		__inc_irq_stat(cpu, local_timer_irqs);
-		ipi_timer();
-	}
-
-	set_irq_regs(old_regs);
-}
-
-void show_local_irqs(struct seq_file *p, int prec)
-{
-	unsigned int cpu;
-
-	seq_printf(p, "%*s: ", prec, "LOC");
-
-	for_each_present_cpu(cpu)
-		seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
-
-	seq_printf(p, " Local timer interrupts\n");
-}
-#endif
-
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-static void smp_timer_broadcast(const struct cpumask *mask)
+void smp_timer_broadcast(const struct cpumask *mask)
 {
 	smp_cross_call(mask, IPI_TIMER);
 }
-#else
-#define smp_timer_broadcast	NULL
-#endif
-
-static void broadcast_timer_set_mode(enum clock_event_mode mode,
-	struct clock_event_device *evt)
-{
-}
-
-static void broadcast_timer_setup(struct clock_event_device *evt)
-{
-	evt->name	= "dummy_timer";
-	evt->features	= CLOCK_EVT_FEAT_ONESHOT |
-			  CLOCK_EVT_FEAT_PERIODIC |
-			  CLOCK_EVT_FEAT_DUMMY;
-	evt->rating	= 400;
-	evt->mult	= 1;
-	evt->set_mode	= broadcast_timer_set_mode;
-
-	clockevents_register_device(evt);
-}
-
-void __cpuinit percpu_timer_setup(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-
-	evt->cpumask = cpumask_of(cpu);
-	evt->broadcast = smp_timer_broadcast;
-
-	if (local_timer_setup(evt))
-		broadcast_timer_setup(evt);
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * The generic clock events code purposely does not stop the local timer
- * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
- * manually here.
- */
-static void percpu_timer_stop(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-
-	evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
-}
 #endif
 
 static DEFINE_SPINLOCK(stop_lock);
@@ -556,7 +470,7 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 
 	switch (ipinr) {
 	case IPI_TIMER:
-		ipi_timer();
+		percpu_timer_run();
 		break;
 
 	case IPI_RESCHEDULE:
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 60636f4..4fdfb85 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -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;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 02/20] ARM: omap2: remove stubbed twd_timer_setup call
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 01/20] ARM: architected timers: move local timer support to percpu_timer.c Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 03/20] ARM: exynos4: " Marc Zyngier
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-omap2/timer-mpu.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c
index 31c0ac4..02feaff 100644
--- a/arch/arm/mach-omap2/timer-mpu.c
+++ b/arch/arm/mach-omap2/timer-mpu.c
@@ -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;
 }
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 03/20] ARM: exynos4: remove stubbed twd_timer_setup call
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 01/20] ARM: architected timers: move local timer support to percpu_timer.c Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 02/20] ARM: omap2: remove stubbed twd_timer_setup call Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 04/20] ARM: shmobile: " Marc Zyngier
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-exynos4/localtimer.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-exynos4/localtimer.c b/arch/arm/mach-exynos4/localtimer.c
index 6bf3d0a..9d9be20 100644
--- a/arch/arm/mach-exynos4/localtimer.c
+++ b/arch/arm/mach-exynos4/localtimer.c
@@ -21,6 +21,5 @@
 int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
 	evt->irq = IRQ_LOCALTIMER;
-	twd_timer_setup(evt);
 	return 0;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 04/20] ARM: shmobile: remove stubbed twd_timer_setup call
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (2 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 03/20] ARM: exynos4: " Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 05/20] ARM: tegra: " Marc Zyngier
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-shmobile/localtimer.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-shmobile/localtimer.c b/arch/arm/mach-shmobile/localtimer.c
index ad9ccc9..a4c4e8b 100644
--- a/arch/arm/mach-shmobile/localtimer.c
+++ b/arch/arm/mach-shmobile/localtimer.c
@@ -21,6 +21,5 @@
 int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
 	evt->irq = 29;
-	twd_timer_setup(evt);
 	return 0;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 05/20] ARM: tegra: remove stubbed twd_timer_setup call
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (3 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 04/20] ARM: shmobile: " Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 06/20] ARM: ux500: " Marc Zyngier
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Colin Cross <ccross@android.com>
Cc: Erik Gilling <konkers@android.com>
Cc: Olof Johansson <olof@lixom.net>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-tegra/localtimer.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c
index e91d681..aaabad8 100644
--- a/arch/arm/mach-tegra/localtimer.c
+++ b/arch/arm/mach-tegra/localtimer.c
@@ -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;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 06/20] ARM: ux500: remove stubbed twd_timer_setup call
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (4 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 05/20] ARM: tegra: " Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 07/20] ARM: versatile: " Marc Zyngier
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-ux500/localtimer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-ux500/localtimer.c b/arch/arm/mach-ux500/localtimer.c
index 5ba1133..c648725 100644
--- a/arch/arm/mach-ux500/localtimer.c
+++ b/arch/arm/mach-ux500/localtimer.c
@@ -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;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 07/20] ARM: versatile: remove stubbed twd_timer_setup call
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (5 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 06/20] ARM: ux500: " Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 08/20] ARM: remove unused twd_timer_setup stub Marc Zyngier
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/plat-versatile/localtimer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/arm/plat-versatile/localtimer.c b/arch/arm/plat-versatile/localtimer.c
index 0fb3961..93ea3e3 100644
--- a/arch/arm/plat-versatile/localtimer.c
+++ b/arch/arm/plat-versatile/localtimer.c
@@ -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;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 08/20] ARM: remove unused twd_timer_setup stub
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (6 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 07/20] ARM: versatile: " Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 09/20] ARM: architected timers: add A15 architected timers Marc Zyngier
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Now that there is no in-tree users of twd_timer_setup() anymore,
remove it completely.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/smp_twd.h |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index 4096736..d2abe52 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -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
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 09/20] ARM: architected timers: add A15 architected timers
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (7 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 08/20] ARM: remove unused twd_timer_setup stub Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-04-09  2:47   ` Stephen Boyd
  2011-03-15 15:12 ` [RFC PATCHv2 10/20] ARM: Platform dependent sched_clock() override Marc Zyngier
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Acked-by: Will Deacon <will.deacon@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b7e504b..38ee56e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
new file mode 100644
index 0000000..f98263c
--- /dev/null
+++ b/arch/arm/include/asm/arch_timer.h
@@ -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
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
index c115b82..b362a1e 100644
--- a/arch/arm/include/asm/hardware/entry-macro-gic.S
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -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
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 277f6ff..add5e77 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -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
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
new file mode 100644
index 0000000..bc05604
--- /dev/null
+++ b/arch/arm/kernel/arch_timer.c
@@ -0,0 +1,223 @@
+/*
+ *  linux/arch/arm/kernel/arch_timer.c
+ *
+ *  Copyright (C) 2011 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/jiffies.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/localtimer.h>
+#include <asm/hardware/gic.h>
+
+static unsigned long arch_timer_rate;
+
+/*
+ * Architected system timer support.
+ */
+
+#define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
+#define ARCH_TIMER_CTRL_IT_MASK		(1 << 1)
+
+#define ARCH_TIMER_REG_CTRL		0
+#define ARCH_TIMER_REG_FREQ		1
+#define ARCH_TIMER_REG_TVAL		2
+
+static void arch_timer_reg_write(int reg, u32 val)
+{
+	switch (reg) {
+	case ARCH_TIMER_REG_CTRL:
+		asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
+		break;
+	case ARCH_TIMER_REG_TVAL:
+		asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
+		break;
+	}
+
+	isb();
+}
+
+static u32 arch_timer_reg_read(int reg)
+{
+	u32 val;
+
+	switch (reg) {
+	case ARCH_TIMER_REG_CTRL:
+		asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
+		break;
+	case ARCH_TIMER_REG_FREQ:
+		asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
+		break;
+	case ARCH_TIMER_REG_TVAL:
+		asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
+		break;
+	default:
+		BUG();
+	}
+
+	return val;
+}
+
+static int arch_timer_ack(void)
+{
+	unsigned long ctrl;
+
+	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	if (ctrl & 0x4) {
+		ctrl |= ARCH_TIMER_CTRL_IT_MASK;
+		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+		return 1;
+	}
+
+	return 0;
+}
+
+static void arch_set_mode(enum clock_event_mode mode,
+			  struct clock_event_device *clk)
+{
+}
+
+static int arch_set_next_event(unsigned long evt,
+			       struct clock_event_device *unused)
+{
+	unsigned long ctrl;
+
+	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	ctrl |= ARCH_TIMER_CTRL_ENABLE;
+	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
+
+	arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
+	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+
+	return 0;
+}
+
+static void __cpuinit arch_timer_pre_setup(struct clock_event_device *clk)
+{
+	unsigned long ctrl;
+
+	/* Let's make sure the timer is off before doing anything else */
+	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
+	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+}
+
+static void __cpuinit arch_timer_setup(struct clock_event_device *clk)
+{
+	clk->features = CLOCK_EVT_FEAT_ONESHOT;
+	clk->name = "arch_sys_timer";
+	clk->rating = 350;
+	clockevents_calc_mult_shift(clk, arch_timer_rate, 4);
+
+	clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
+	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
+	clk->set_mode = arch_set_mode;
+	clk->set_next_event = arch_set_next_event;
+
+	/* Make sure our local interrupt controller has this enabled */
+	gic_enable_ppi(clk->irq);
+
+	clockevents_register_device(clk);
+}
+
+static struct local_timer_ops arch_timer_ops = {
+	.pre_setup	= arch_timer_pre_setup,
+	.setup		= arch_timer_setup,
+	.ack		= arch_timer_ack,
+};
+
+/* Is the optional system timer available? */
+static int local_timer_is_architected(void)
+{
+	return (cpu_architecture() >= CPU_ARCH_ARMv7) &&
+	       ((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
+}
+
+static int arch_timer_available(void)
+{
+	unsigned long freq;
+
+	if (!local_timer_is_architected())
+		return 0;
+
+	if (arch_timer_rate == 0) {
+		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0);
+		freq = arch_timer_reg_read(ARCH_TIMER_REG_FREQ);
+
+		/* Check the timer frequency. */
+		if (freq == 0) {
+			pr_warn("Architected timer frequency not available\n");
+			return 0;
+		}
+
+		arch_timer_rate = freq;
+		pr_info("Architected local timer running at %lu.%02luMHz.\n",
+			arch_timer_rate / 1000000, (arch_timer_rate / 100000) % 100);
+	}
+
+	return 1;
+}
+
+static inline cycle_t arch_counter_get_cntpct(void)
+{
+	u32 cvall, cvalh;
+
+	asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+
+	return ((u64) cvalh << 32) | cvall;
+}
+
+static inline cycle_t arch_counter_get_cntvct(void)
+{
+	u32 cvall, cvalh;
+
+	asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+
+	return ((u64) cvalh << 32) | cvall;
+}
+
+static cycle_t arch_counter_read(struct clocksource *cs)
+{
+	return arch_counter_get_cntpct();
+}
+
+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),
+};
+
+static int __init arch_timer_clocksource_init(void)
+{
+	struct clocksource *cs = &clocksource_counter;
+
+	percpu_timer_setup();
+
+	clocksource_register_hz(cs, arch_timer_rate);
+
+	return 0;
+}
+
+int __init arch_timer_register_setup(void (*setup)(struct clock_event_device *))
+{
+	if (!arch_timer_available())
+		return -ENODEV;
+
+	percpu_timer_register_setup(&arch_timer_ops, setup);
+	arch_timer_clocksource_init();
+	return 0;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 10/20] ARM: Platform dependent sched_clock() override
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (8 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 09/20] ARM: architected timers: add A15 architected timers Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 11/20] ARM: architected timers: Add A15 specific sched_clock implementation Marc Zyngier
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 38ee56e..08b3ff2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h
index c8e6ddf..27ef05e 100644
--- a/arch/arm/include/asm/sched_clock.h
+++ b/arch/arm/include/asm/sched_clock.h
@@ -21,6 +21,17 @@ struct clock_data {
 
 #define DEFINE_CLOCK_DATA(name)	struct clock_data name
 
+#ifdef CONFIG_ARCH_SCHED_CLOCK
+#define __DEFINE_SCHED_CLOCK_ALIAS(name)
+#else
+#define __DEFINE_SCHED_CLOCK_ALIAS(name) \
+	unsigned long long sched_clock(void) __attribute__ ((alias (#name)));
+#endif
+
+#define DEFINE_SCHED_CLOCK_FUNC(name) \
+	__DEFINE_SCHED_CLOCK_ALIAS(name)	\
+	static unsigned long long notrace name(void)
+
 static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
 {
 	return (cyc * mult) >> shift;
@@ -94,20 +105,35 @@ static inline unsigned long long cyc_to_sched_clock(struct clock_data *cd,
  * and shift.  Also setup a timer to ensure that the epoch is refreshed
  * at the appropriate time interval, which will call your update
  * handler.
+ *
+ * Use the _arch_ version if you want your sched_clock function to be
+ * selected at run time (if CONFIG_ARCH_SCHED_CLOCK is enabled).
  */
-void init_sched_clock(struct clock_data *, void (*)(void),
+void init_arch_sched_clock(struct clock_data *, void (*)(void),
+	unsigned long long (*)(void),
 	unsigned int, unsigned long);
 
+static inline void init_sched_clock(struct clock_data *cd,
+				    void (*update)(void),
+				    unsigned int bits, unsigned long rate)
+{
+	init_arch_sched_clock(cd, update, NULL, bits, rate);
+}
+
 /*
  * Use this initialization function rather than init_sched_clock() if
  * you're using cyc_to_fixed_sched_clock, which will warn if your
  * constants are incorrect.
+ *
+ * Use the _arch_ version if you want your sched_clock function to be
+ * selected at run time (if CONFIG_ARCH_SCHED_CLOCK is enabled).
  */
-static inline void init_fixed_sched_clock(struct clock_data *cd,
-	void (*update)(void), unsigned int bits, unsigned long rate,
+static inline void init_fixed_arch_sched_clock(struct clock_data *cd,
+	void (*update)(void), unsigned long long (*sched_clock_fn)(void),
+	unsigned int bits, unsigned long rate,
 	u32 mult, u32 shift)
 {
-	init_sched_clock(cd, update, bits, rate);
+	init_arch_sched_clock(cd, update, sched_clock_fn, bits, rate);
 	if (cd->mult != mult || cd->shift != shift) {
 		pr_crit("sched_clock: wrong multiply/shift: %u>>%u vs calculated %u>>%u\n"
 			"sched_clock: fix multiply/shift to avoid scheduler hiccups\n",
@@ -115,6 +141,13 @@ static inline void init_fixed_sched_clock(struct clock_data *cd,
 	}
 }
 
+static inline void init_fixed_sched_clock(struct clock_data *cd,
+	void (*update)(void), unsigned int bits, unsigned long rate,
+	u32 mult, u32 shift)
+{
+	init_fixed_arch_sched_clock(cd, update, NULL, bits, rate, mult, shift);
+}
+
 extern void sched_clock_postinit(void);
 
 #endif
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
index 9a46370..3c1d08b 100644
--- a/arch/arm/kernel/sched_clock.c
+++ b/arch/arm/kernel/sched_clock.c
@@ -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);
 
diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c
index 3d6a4c2..d6ebd0f 100644
--- a/arch/arm/plat-versatile/sched-clock.c
+++ b/arch/arm/plat-versatile/sched-clock.c
@@ -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);
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 11/20] ARM: architected timers: Add A15 specific sched_clock implementation
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (9 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 10/20] ARM: Platform dependent sched_clock() override Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 12/20] ARM: versatile/vexpress: rework timer support Marc Zyngier
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Provide an A15 sched_clock implementation using the virtual counter,
which is thought to be more useful than the physical one in a
virtualised environment, as it can offset the time spent in another
VM or the hypervisor.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/arch_timer.h |    4 ++--
 arch/arm/kernel/arch_timer.c      |   32 +++++++++++++++++++++++++++++++-
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index f98263c..9fa0556 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -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;
 }
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index bc05604..fe55919 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -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;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 12/20] ARM: versatile/vexpress: rework timer support
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (10 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 11/20] ARM: architected timers: Add A15 specific sched_clock implementation Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 13/20] ARM: msm: dynamically register local timer setup function Marc Zyngier
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Dynamically register the TWD setup function.

For vexpress, give preference to architected timers over SP804 timers
and versatile sched_clock implementation, if available.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 2ecc1d9..3a0900f 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -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
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index b2985fc..76da67d 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -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);
 }
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 92ace2c..280befd 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -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);
 }
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index ba46e8e..9fa5ad6 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -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;
diff --git a/arch/arm/plat-versatile/include/plat/localtimer.h b/arch/arm/plat-versatile/include/plat/localtimer.h
new file mode 100644
index 0000000..c6cdf72
--- /dev/null
+++ b/arch/arm/plat-versatile/include/plat/localtimer.h
@@ -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
diff --git a/arch/arm/plat-versatile/localtimer.c b/arch/arm/plat-versatile/localtimer.c
index 93ea3e3..01025ea 100644
--- a/arch/arm/plat-versatile/localtimer.c
+++ b/arch/arm/plat-versatile/localtimer.c
@@ -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);
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 13/20] ARM: msm: dynamically register local timer setup function
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (11 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 12/20] ARM: versatile/vexpress: rework timer support Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 14/20] ARM: omap4: " Marc Zyngier
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: David Brown <davidb@codeaurora.org>
Cc: Daniel Walker <dwalker@fifo99.com>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-msm/timer.c |   22 +++++++++++++++++++---
 1 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 56f920c..f4b6d54 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -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;
 }
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timer setup function
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (12 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 13/20] ARM: msm: dynamically register local timer setup function Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-16  5:55   ` [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup function Santosh Shilimkar
  2011-03-15 15:12 ` [RFC PATCHv2 15/20] ARM: exynos4: dynamically register local timer setup function Marc Zyngier
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index a45cd64..41f8b67 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -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
 
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 3b9cf85..98d03c5 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -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();
diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c
deleted file mode 100644
index 02feaff..0000000
--- a/arch/arm/mach-omap2/timer-mpu.c
+++ /dev/null
@@ -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 <santosh.shilimkar@ti.com>
- *
- * 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;
-}
-
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 15/20] ARM: exynos4: dynamically register local timer setup function
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (13 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 14/20] ARM: omap4: " Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:12 ` [RFC PATCHv2 16/20] ARM: shmobile: " Marc Zyngier
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Also convert MCT to the new local timers API.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index 9473adb..f6f3075 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -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
diff --git a/arch/arm/mach-exynos4/localtimer.c b/arch/arm/mach-exynos4/localtimer.c
deleted file mode 100644
index 9d9be20..0000000
--- a/arch/arm/mach-exynos4/localtimer.c
+++ /dev/null
@@ -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;
-}
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index af82a8f..4d67123 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -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 = {
diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c
index 86b9fa0..ce08297 100644
--- a/arch/arm/mach-exynos4/time.c
+++ b/arch/arm/mach-exynos4/time.c
@@ -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();
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 16/20] ARM: shmobile: dynamically register local timer setup function
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (14 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 15/20] ARM: exynos4: dynamically register local timer setup function Marc Zyngier
@ 2011-03-15 15:12 ` Marc Zyngier
  2011-03-15 15:13 ` [RFC PATCHv2 17/20] ARM: tegra: " Marc Zyngier
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index e2507f6..290a232 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -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
diff --git a/arch/arm/mach-shmobile/localtimer.c b/arch/arm/mach-shmobile/localtimer.c
deleted file mode 100644
index a4c4e8b..0000000
--- a/arch/arm/mach-shmobile/localtimer.c
+++ /dev/null
@@ -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;
-}
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index 895794b..30a75c0 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -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;
 }
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 17/20] ARM: tegra: dynamically register local timer setup function
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (15 preceding siblings ...)
  2011-03-15 15:12 ` [RFC PATCHv2 16/20] ARM: shmobile: " Marc Zyngier
@ 2011-03-15 15:13 ` Marc Zyngier
  2011-03-15 15:13 ` [RFC PATCHv2 18/20] ARM: ux500: " Marc Zyngier
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Colin Cross <ccross@android.com>
Cc: Erik Gilling <konkers@android.com>
Cc: Olof Johansson <olof@lixom.net>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 9f7a7e1..5f4d7f1 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -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
diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c
deleted file mode 100644
index aaabad8..0000000
--- a/arch/arm/mach-tegra/localtimer.c
+++ /dev/null
@@ -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;
-}
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 0fcb1eb..5c756f3 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -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) {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 18/20] ARM: ux500: dynamically register local timer setup function
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (16 preceding siblings ...)
  2011-03-15 15:13 ` [RFC PATCHv2 17/20] ARM: tegra: " Marc Zyngier
@ 2011-03-15 15:13 ` Marc Zyngier
  2011-03-15 15:13 ` [RFC PATCHv2 19/20] ARM: simplify percpu_timer_setup Marc Zyngier
  2011-03-15 15:13 ` [RFC PATCHv2 20/20] ARM: simplify percpu_timer_ack Marc Zyngier
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

Cc: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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

diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index b549a8f..224bc74 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -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
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 5a43107..e4b1bb6 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -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);
diff --git a/arch/arm/mach-ux500/localtimer.c b/arch/arm/mach-ux500/localtimer.c
deleted file mode 100644
index c648725..0000000
--- a/arch/arm/mach-ux500/localtimer.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2008-2009 ST-Ericsson
- * Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
- *
- * 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;
-}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 19/20] ARM: simplify percpu_timer_setup
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (17 preceding siblings ...)
  2011-03-15 15:13 ` [RFC PATCHv2 18/20] ARM: ux500: " Marc Zyngier
@ 2011-03-15 15:13 ` Marc Zyngier
  2011-03-15 15:13 ` [RFC PATCHv2 20/20] ARM: simplify percpu_timer_ack Marc Zyngier
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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(-)

diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
index 8988c50..d47a0cd 100644
--- a/arch/arm/include/asm/localtimer.h
+++ b/arch/arm/include/asm/localtimer.h
@@ -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 *);
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index d2abe52..2c01220 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -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;
 }
diff --git a/arch/arm/kernel/percpu_timer.c b/arch/arm/kernel/percpu_timer.c
index 5992fae..85af863 100644
--- a/arch/arm/kernel/percpu_timer.c
+++ b/arch/arm/kernel/percpu_timer.c
@@ -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)
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 4fdfb85..e0bb094 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -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;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 20/20] ARM: simplify percpu_timer_ack
  2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
                   ` (18 preceding siblings ...)
  2011-03-15 15:13 ` [RFC PATCHv2 19/20] ARM: simplify percpu_timer_setup Marc Zyngier
@ 2011-03-15 15:13 ` Marc Zyngier
  19 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-03-15 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kernel/percpu_timer.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/arch/arm/kernel/percpu_timer.c b/arch/arm/kernel/percpu_timer.c
index 85af863..6e1942b 100644
--- a/arch/arm/kernel/percpu_timer.c
+++ b/arch/arm/kernel/percpu_timer.c
@@ -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();
 	}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup function
  2011-03-15 15:12 ` [RFC PATCHv2 14/20] ARM: omap4: " Marc Zyngier
@ 2011-03-16  5:55   ` Santosh Shilimkar
  2011-03-16 10:03     ` Marc Zyngier
  0 siblings, 1 reply; 26+ messages in thread
From: Santosh Shilimkar @ 2011-03-16  5:55 UTC (permalink / raw)
  To: linux-arm-kernel

Marc,
> -----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
>
> Cc: Tony Lindgren <tony@atomide.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  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
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-
> omap2/Makefile
> index a45cd64..41f8b67 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -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
>
> diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-
> omap2/timer-gp.c
> index 3b9cf85..98d03c5 100644
> --- a/arch/arm/mach-omap2/timer-gp.c
> +++ b/arch/arm/mach-omap2/timer-gp.c
> @@ -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)

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup function
  2011-03-16  5:55   ` [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup function Santosh Shilimkar
@ 2011-03-16 10:03     ` Marc Zyngier
  2011-03-17 10:12       ` Santosh Shilimkar
  0 siblings, 1 reply; 26+ messages in thread
From: Marc Zyngier @ 2011-03-16 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Santosh,

On Wed, 2011-03-16 at 11:25 +0530, Santosh Shilimkar wrote:
> Marc,
> > -----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
> >
> > Cc: Tony Lindgren <tony@atomide.com>
> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> > ---
> >  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
> >
> > diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-
> > omap2/Makefile
> > index a45cd64..41f8b67 100644
> > --- a/arch/arm/mach-omap2/Makefile
> > +++ b/arch/arm/mach-omap2/Makefile
> > @@ -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
> >
> > diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-
> > omap2/timer-gp.c
> > index 3b9cf85..98d03c5 100644
> > --- a/arch/arm/mach-omap2/timer-gp.c
> > +++ b/arch/arm/mach-omap2/timer-gp.c
> > @@ -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)
> 
> 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.

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.
-- 
Reality is an implementation detail.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup function
  2011-03-16 10:03     ` Marc Zyngier
@ 2011-03-17 10:12       ` Santosh Shilimkar
  0 siblings, 0 replies; 26+ messages in thread
From: Santosh Shilimkar @ 2011-03-17 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

> -----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
>
[....]

> > 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.
>
Cool.
Thanks for the update.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 09/20] ARM: architected timers: add A15 architected timers
  2011-03-15 15:12 ` [RFC PATCHv2 09/20] ARM: architected timers: add A15 architected timers Marc Zyngier
@ 2011-04-09  2:47   ` Stephen Boyd
  2011-04-11  8:31     ` Marc Zyngier
  0 siblings, 1 reply; 26+ messages in thread
From: Stephen Boyd @ 2011-04-09  2:47 UTC (permalink / raw)
  To: linux-arm-kernel

On 3/15/2011 8:12 AM, Marc Zyngier wrote:
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index b7e504b..38ee56e 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -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?

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

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [RFC PATCHv2 09/20] ARM: architected timers: add A15 architected timers
  2011-04-09  2:47   ` Stephen Boyd
@ 2011-04-11  8:31     ` Marc Zyngier
  0 siblings, 0 replies; 26+ messages in thread
From: Marc Zyngier @ 2011-04-11  8:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2011-04-08 at 19:47 -0700, Stephen Boyd wrote:

Hi Stephen,

> On 3/15/2011 8:12 AM, Marc Zyngier wrote:
> >
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index b7e504b..38ee56e 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -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?

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.

> > +
> > +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.
-- 
Reality is an implementation detail.

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2011-04-11  8:31 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-15 15:12 [RFC PATCHv2 00/20] A15 architected timer support Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 01/20] ARM: architected timers: move local timer support to percpu_timer.c Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 02/20] ARM: omap2: remove stubbed twd_timer_setup call Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 03/20] ARM: exynos4: " Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 04/20] ARM: shmobile: " Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 05/20] ARM: tegra: " Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 06/20] ARM: ux500: " Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 07/20] ARM: versatile: " Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 08/20] ARM: remove unused twd_timer_setup stub Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 09/20] ARM: architected timers: add A15 architected timers Marc Zyngier
2011-04-09  2:47   ` Stephen Boyd
2011-04-11  8:31     ` Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 10/20] ARM: Platform dependent sched_clock() override Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 11/20] ARM: architected timers: Add A15 specific sched_clock implementation Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 12/20] ARM: versatile/vexpress: rework timer support Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 13/20] ARM: msm: dynamically register local timer setup function Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 14/20] ARM: omap4: " Marc Zyngier
2011-03-16  5:55   ` [RFC PATCHv2 14/20] ARM: omap4: dynamically register local timersetup function Santosh Shilimkar
2011-03-16 10:03     ` Marc Zyngier
2011-03-17 10:12       ` Santosh Shilimkar
2011-03-15 15:12 ` [RFC PATCHv2 15/20] ARM: exynos4: dynamically register local timer setup function Marc Zyngier
2011-03-15 15:12 ` [RFC PATCHv2 16/20] ARM: shmobile: " Marc Zyngier
2011-03-15 15:13 ` [RFC PATCHv2 17/20] ARM: tegra: " Marc Zyngier
2011-03-15 15:13 ` [RFC PATCHv2 18/20] ARM: ux500: " Marc Zyngier
2011-03-15 15:13 ` [RFC PATCHv2 19/20] ARM: simplify percpu_timer_setup Marc Zyngier
2011-03-15 15:13 ` [RFC PATCHv2 20/20] ARM: simplify percpu_timer_ack Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.