* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
@ 2011-06-16 19:06 Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 01/16] ARM: local timers: early device probing hooks Marc Zyngier
` (17 more replies)
0 siblings, 18 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
The arch/arm tree contains several SMP local timer implementations
(smp_twd, Exynos4 mct, and the msm timer, with more to come), and the
word these days is that they should be moved to the driver directory.
Furthermore, the current core implementation makes it impossible to
compile a kernel with several SMP local timer implementations, as the
core code directly calls into the driver code.
This series moves these three drivers to driver/clocksource, with the
following changes:
- They are converted to platform devices, and registered as early devices.
- CPU notifiers are used to start/stop the timers on secondary cores.
Each platform registers an early platform device with the associated
resources (memory, interrupts). At the core level, an early device
probe hook is installed, and binds devices and drivers if
possible. The broadcast timer is always registered by the core code,
and is used by the kernel if no other timer is available.
Small side effect on the mpcode_wdt watchdog driver, who used to share
an include file with smp_twd, and now has a private copy of the
definition of few registers it needs.
It should be relatively easy to move other (non SMP)
timers/clocksources the same way, as it's already been done for
shmobile. Furthermore, it is now straightforward to convert these
platform devices to OF devices, and plug everything into the device
tree.
Patches against next-20110615 + my earlier GIC-PPI series. Tested on
VExpress, PB11MP, Pandaboard, Tegra Harmony and Exynos4 SMDK-v310.
Thomas and Arnd cc-ed on the whole series, as this could be
consolidation material.
As always, comments welcome.
Marc Zyngier (16):
ARM: local timers: early device probing hooks
ARM: local timers: add arm_smp_twd driver to driver/clocksource
ARM: local timers: move realview to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
ARM: local timers: move vexpress to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
ARM: local timers: remove localtimer.c from plat-versatile
ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
ARM: local timers: move OMAP4 to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
ARM: local timers: move shmobile to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
ARM: local timers: move ux500 to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
ARM: local timers: add exynos_mct driver to driver/clocksource
ARM: local timers: move exynos4 to
LOCAL_TIMER_DEVICES/EXYNOS_MCT/ARM_SMP_TWD
ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h
ARM: local timers: remove smp_twd from arch/arm
ARM: local timers: add msm_timer driver to driver/clocksource
ARM: local timers: move msm to LOCAL_TIMER_DEVICES/MSM_TIMER
ARM: local timers: remove local timer support from arch/arm
arch/arm/Kconfig | 19 +--
arch/arm/include/asm/localtimer.h | 58 -----
arch/arm/include/asm/mach/time.h | 1 +
arch/arm/include/asm/smp_twd.h | 28 ---
arch/arm/kernel/Makefile | 1 -
arch/arm/kernel/smp.c | 70 ++-----
arch/arm/kernel/smp_twd.c | 163 --------------
arch/arm/kernel/time.c | 15 ++
arch/arm/mach-exynos4/Kconfig | 2 +
arch/arm/mach-exynos4/Makefile | 1 -
arch/arm/mach-exynos4/localtimer.c | 27 ---
arch/arm/mach-exynos4/mct.c | 197 +----------------
arch/arm/mach-exynos4/time.c | 33 +++-
arch/arm/mach-msm/Kconfig | 10 +
arch/arm/mach-msm/timer.c | 290 +------------------------
arch/arm/mach-omap2/Kconfig | 3 +-
arch/arm/mach-omap2/Makefile | 1 -
arch/arm/mach-omap2/timer-gp.c | 40 +++-
arch/arm/mach-omap2/timer-mpu.c | 40 ----
arch/arm/mach-realview/Kconfig | 8 +
arch/arm/mach-realview/realview_eb.c | 31 +++-
arch/arm/mach-realview/realview_pb11mp.c | 30 +++-
arch/arm/mach-realview/realview_pbx.c | 31 +++-
arch/arm/mach-shmobile/Kconfig | 2 +
arch/arm/mach-shmobile/Makefile | 1 -
arch/arm/mach-shmobile/localtimer.c | 27 ---
arch/arm/mach-shmobile/platsmp.c | 1 -
arch/arm/mach-shmobile/setup-sh73a0.c | 21 ++
arch/arm/mach-shmobile/smp-sh73a0.c | 6 -
arch/arm/mach-shmobile/timer.c | 2 +-
arch/arm/mach-tegra/Kconfig | 2 +
arch/arm/mach-tegra/Makefile | 2 +-
arch/arm/mach-tegra/localtimer.c | 27 ---
arch/arm/mach-tegra/timer.c | 32 +++-
arch/arm/mach-ux500/Kconfig | 2 +
arch/arm/mach-ux500/Makefile | 1 -
arch/arm/mach-ux500/cpu-db5500.c | 1 -
arch/arm/mach-ux500/cpu-db8500.c | 1 -
arch/arm/mach-ux500/cpu.c | 38 +++-
arch/arm/mach-ux500/localtimer.c | 30 ---
arch/arm/mach-vexpress/Kconfig | 2 +
arch/arm/mach-vexpress/ct-ca9x4.c | 30 +++-
arch/arm/plat-s5p/s5p-time.c | 1 -
arch/arm/plat-versatile/Makefile | 1 -
arch/arm/plat-versatile/localtimer.c | 28 ---
drivers/clocksource/Kconfig | 6 +
drivers/clocksource/Makefile | 3 +
drivers/clocksource/arm_smp_twd.c | 265 +++++++++++++++++++++++
drivers/clocksource/exynos4_mct.c | 283 ++++++++++++++++++++++++
drivers/clocksource/msm_timer.c | 345 ++++++++++++++++++++++++++++++
drivers/watchdog/Kconfig | 2 +-
drivers/watchdog/mpcore_wdt.c | 7 +-
52 files changed, 1239 insertions(+), 1029 deletions(-)
delete mode 100644 arch/arm/include/asm/localtimer.h
delete mode 100644 arch/arm/include/asm/smp_twd.h
delete mode 100644 arch/arm/kernel/smp_twd.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
delete mode 100644 arch/arm/plat-versatile/localtimer.c
create mode 100644 drivers/clocksource/arm_smp_twd.c
create mode 100644 drivers/clocksource/exynos4_mct.c
create mode 100644 drivers/clocksource/msm_timer.c
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 01/16] ARM: local timers: early device probing hooks
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-17 14:56 ` Arnd Bergmann
2011-06-16 19:06 ` [RFC PATCH 02/16] ARM: local timers: add arm_smp_twd driver to driver/clocksource Marc Zyngier
` (16 subsequent siblings)
17 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Introduce hooks to probe local timers registered as early devices.
Use the late_time_init hook to perform the probing. Since shmobile
is already using this hook, add an ARM specific arm_late_time_init
hook that platforms can use instead.
This is controlled by a new config option (LOCAL_TIMER_DEVICES)
which prevents LOCAL_TIMERS from being selected, as the two
clearly conflict.
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/Kconfig | 5 ++++-
arch/arm/include/asm/mach/time.h | 1 +
arch/arm/kernel/time.c | 15 +++++++++++++++
arch/arm/mach-shmobile/timer.c | 2 +-
4 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cdc89ed..dafb20a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1415,7 +1415,7 @@ config HOTPLUG_CPU
config LOCAL_TIMERS
bool "Use local timer interrupts"
- depends on SMP
+ depends on SMP && !LOCAL_TIMER_DEVICES
default y
select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
help
@@ -1424,6 +1424,9 @@ config LOCAL_TIMERS
accounting to be spread across the timer interval, preventing a
"thundering herd" at every timer tick.
+config LOCAL_TIMER_DEVICES
+ bool
+
source kernel/Kconfig.preempt
config HZ
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index d5adaae..f46ca39 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -43,5 +43,6 @@ struct sys_timer {
};
extern void timer_tick(void);
+extern void (* __initdata arm_late_time_init)(void);
#endif
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index cb634c3..32d0df8 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -24,6 +24,7 @@
#include <linux/syscore_ops.h>
#include <linux/timer.h>
#include <linux/irq.h>
+#include <linux/platform_device.h>
#include <linux/mc146818rtc.h>
@@ -147,6 +148,19 @@ static int __init timer_init_syscore_ops(void)
device_initcall(timer_init_syscore_ops);
+void (* __initdata arm_late_time_init)(void);
+
+static void __init __arm_late_time_init(void)
+{
+ if (arm_late_time_init)
+ arm_late_time_init();
+
+#ifdef CONFIG_LOCAL_TIMER_DEVICES
+ early_platform_driver_register_all("localtimer");
+ early_platform_driver_probe("localtimer", 1, 0);
+#endif
+}
+
void __init time_init(void)
{
system_timer = machine_desc->timer;
@@ -154,5 +168,6 @@ void __init time_init(void)
#ifdef CONFIG_HAVE_SCHED_CLOCK
sched_clock_postinit();
#endif
+ late_time_init = __arm_late_time_init;
}
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index 895794b..835baa4 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -38,7 +38,7 @@ static void __init shmobile_late_time_init(void)
static void __init shmobile_timer_init(void)
{
- late_time_init = shmobile_late_time_init;
+ arm_late_time_init = shmobile_late_time_init;
}
struct sys_timer shmobile_timer = {
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 02/16] ARM: local timers: add arm_smp_twd driver to driver/clocksource
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 01/16] ARM: local timers: early device probing hooks Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 03/16] ARM: local timers: move realview to LOCAL_TIMER_DEVICES/ARM_SMP_TWD Marc Zyngier
` (15 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Add a "new" driver to driver/clocksource to support the ARM TWD
hardware. This is basically a copy of arch/arm/kernel/smp_twd.c,
turned into a platform driver, with a CPU notifier being used
to start/stop timers on secondary cores.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/clocksource/Kconfig | 3 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/arm_smp_twd.c | 265 +++++++++++++++++++++++++++++++++++++
3 files changed, 269 insertions(+), 0 deletions(-)
create mode 100644 drivers/clocksource/arm_smp_twd.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 330343b..a436dd4 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -9,3 +9,6 @@ config CLKBLD_I8253
config CLKSRC_MMIO
bool
+
+config ARM_SMP_TWD
+ bool
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 7922a0c..b7e6397 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
obj-$(CONFIG_CLKBLD_I8253) += i8253.o
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
+obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
diff --git a/drivers/clocksource/arm_smp_twd.c b/drivers/clocksource/arm_smp_twd.c
new file mode 100644
index 0000000..5e2e8cc
--- /dev/null
+++ b/drivers/clocksource/arm_smp_twd.c
@@ -0,0 +1,265 @@
+/*
+ * linux/arch/arm/kernel/smp_twd.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/kernel.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+#include <linux/jiffies.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware/gic.h>
+
+#define TWD_TIMER_LOAD 0x00
+#define TWD_TIMER_COUNTER 0x04
+#define TWD_TIMER_CONTROL 0x08
+#define TWD_TIMER_INTSTAT 0x0C
+
+#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
+#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
+#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
+#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
+
+static void __iomem *twd_base;
+static int twd_ppi;
+
+static unsigned long twd_timer_rate;
+static DEFINE_PER_CPU(bool, irq_reqd);
+static struct clock_event_device __percpu *twd_evt;
+
+static void twd_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ unsigned long ctrl;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* timer load already set up */
+ ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
+ | TWD_TIMER_CONTROL_PERIODIC;
+ __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* period set, and timer enabled in 'next_event' hook */
+ ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ ctrl = 0;
+ }
+
+ __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
+}
+
+static int twd_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+
+ ctrl |= TWD_TIMER_CONTROL_ENABLE;
+
+ __raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
+ __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
+
+ return 0;
+}
+
+static irqreturn_t twd_handler(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = dev_id;
+
+ if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
+ __raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static void __cpuinit twd_calibrate_rate(void)
+{
+ unsigned long count;
+ u64 waitjiffies;
+
+ /*
+ * If this is the first time round, we need to work out how fast
+ * the timer ticks
+ */
+ if (twd_timer_rate == 0) {
+ printk(KERN_INFO "Calibrating local timer... ");
+
+ /* Wait for a tick to start */
+ waitjiffies = get_jiffies_64() + 1;
+
+ while (get_jiffies_64() < waitjiffies)
+ udelay(10);
+
+ /* OK, now the tick has started, let's get the timer going */
+ waitjiffies += 5;
+
+ /* enable, no interrupt or reload */
+ __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
+
+ /* maximum value */
+ __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
+
+ while (get_jiffies_64() < waitjiffies)
+ udelay(10);
+
+ count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
+
+ twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
+
+ printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
+ (twd_timer_rate / 1000000) % 100);
+ }
+}
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+static void __cpuinit twd_setup(void *data)
+{
+ struct clock_event_device *clk = data;
+ int err;
+
+ twd_calibrate_rate();
+
+ clk->name = "arm_smp_twd";
+ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_C3STOP;
+ clk->rating = 450;
+ clk->set_mode = twd_set_mode;
+ clk->set_next_event = twd_set_next_event;
+ clk->shift = 20;
+ clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift);
+ clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
+ clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
+ clk->irq = gic_ppi_to_vppi(twd_ppi);
+ clk->cpumask = cpumask_of(smp_processor_id());
+
+ pr_debug("Configuring %s on cpu #%d\n", clk->name, smp_processor_id());
+
+ err = request_irq(clk->irq, twd_handler,
+ IRQF_PERCPU | IRQF_NOBALANCING | IRQF_TIMER,
+ clk->name, clk);
+ if (err) {
+ pr_err("%s: can't register interrupt %d on cpu %d (%d)\n",
+ clk->name, clk->irq, smp_processor_id(), err);
+ return;
+ }
+
+ clockevents_register_device(clk);
+}
+
+static void __cpuinit twd_teardown(void *data)
+{
+ struct clock_event_device *clk = data;
+ pr_debug("twd_teardown disable IRQ%d cpu #%d\n",
+ clk->irq, smp_processor_id());
+ disable_irq(clk->irq);
+ twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+}
+
+static void __cpuinit twd_restart(void *data)
+{
+ struct clock_event_device *clk = data;
+ pr_debug("twd_restart enable IRQ%d cpu #%d\n",
+ clk->irq, smp_processor_id());
+ enable_irq(clk->irq);
+ clockevents_register_device(clk);
+}
+
+static int __cpuinit twd_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ int cpu = (int)data;
+ struct clock_event_device *clk = per_cpu_ptr(twd_evt, cpu);
+ bool *reqd = &per_cpu(irq_reqd, cpu);
+
+ switch (action) {
+ case CPU_STARTING:
+ case CPU_STARTING_FROZEN:
+ if (!*reqd) {
+ smp_call_function_single(cpu, twd_setup, clk, 1);
+ *reqd = true;
+ } else {
+ smp_call_function_single(cpu, twd_restart, clk, 1);
+ }
+ break;
+
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ smp_call_function_single(cpu, twd_teardown, clk, 1);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata twd_cpu_nb = {
+ .notifier_call = twd_cpu_notify,
+};
+
+static int twd_probe(struct platform_device *pdev)
+{
+ struct resource *mem;
+ struct clock_event_device *clk;
+ int irq;
+
+ if (twd_base)
+ return -EBUSY;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (!mem || irq < 0)
+ return -EINVAL;
+
+ twd_base = ioremap(mem->start, resource_size(mem));
+ twd_evt = alloc_percpu(struct clock_event_device);
+ if (!twd_base || !twd_evt) {
+ iounmap(twd_base);
+ twd_base = NULL;
+ free_percpu(twd_evt);
+ return -ENOMEM;
+ }
+
+ twd_ppi = irq;
+
+ /* Immediately configure the timer on the boot CPU */
+ clk = per_cpu_ptr(twd_evt, smp_processor_id());
+ twd_setup(clk);
+
+ register_cpu_notifier(&twd_cpu_nb);
+
+ return 0;
+}
+
+static int twd_remove(struct platform_device *pdev)
+{
+ return -EBUSY;
+}
+
+static struct platform_driver twd_driver = {
+ .probe = twd_probe,
+ .remove = __devexit_p(twd_remove),
+ .driver = {
+ .name = "arm_smp_twd",
+ },
+};
+
+early_platform_init("localtimer", &twd_driver);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 03/16] ARM: local timers: move realview to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 01/16] ARM: local timers: early device probing hooks Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 02/16] ARM: local timers: add arm_smp_twd driver to driver/clocksource Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 04/16] ARM: local timers: move vexpress " Marc Zyngier
` (14 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the RealView platforms to use the new arm_smp_twd driver.
Add the platform devices and register them as early platform devices.
Tested on a PB11MP.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-realview/Kconfig | 8 +++++++
arch/arm/mach-realview/realview_eb.c | 31 ++++++++++++++++++++++++++---
arch/arm/mach-realview/realview_pb11mp.c | 30 +++++++++++++++++++++++++---
arch/arm/mach-realview/realview_pbx.c | 31 +++++++++++++++++++++++++----
4 files changed, 87 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index b9a9805..7eec270 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -12,6 +12,8 @@ config REALVIEW_EB_A9MP
bool "Support Multicore Cortex-A9 Tile"
depends on MACH_REALVIEW_EB
select CPU_V7
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
help
Enable support for the Cortex-A9MPCore tile fitted to the
Realview(R) Emulation Baseboard platform.
@@ -21,6 +23,8 @@ config REALVIEW_EB_ARM11MP
depends on MACH_REALVIEW_EB
select CPU_V6K
select ARCH_HAS_BARRIERS if SMP
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
help
Enable support for the ARM11MPCore tile fitted to the Realview(R)
Emulation Baseboard platform.
@@ -40,6 +44,8 @@ config MACH_REALVIEW_PB11MP
select ARM_GIC
select HAVE_PATA_PLATFORM
select ARCH_HAS_BARRIERS if SMP
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
help
Include support for the ARM(R) RealView(R) Platform Baseboard for
the ARM11MPCore. This platform has an on-board ARM11MPCore and has
@@ -79,6 +85,8 @@ config MACH_REALVIEW_PBX
select HAVE_PATA_PLATFORM
select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
select ZONE_DMA if SPARSEMEM
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
help
Include support for the ARM(R) RealView(R) Platform Baseboard
Explore.
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 10e75fa..fbc941c 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -36,7 +36,6 @@
#include <asm/pgtable.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
-#include <asm/localtimer.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -330,6 +329,31 @@ static struct platform_device char_lcd_device = {
.resource = char_lcd_resources,
};
+static struct resource eb_twd_resources[] = {
+ {
+ .start = REALVIEW_EB11MP_TWD_BASE,
+ .end = REALVIEW_EB11MP_TWD_BASE + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_LOCALTIMER,
+ .end = IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device eb_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = eb_twd_resources,
+ .num_resources = ARRAY_SIZE(eb_twd_resources),
+};
+
+static struct platform_device *eb_early_devices[] = {
+ &eb_twd_device,
+};
+
+
static void __init gic_init_irq(void)
{
if (core_tile_eb11mp() || core_tile_a9mp()) {
@@ -401,14 +425,13 @@ static void __init realview_eb_timer_init(void)
timer3_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE) + 0x20;
if (core_tile_eb11mp() || core_tile_a9mp()) {
-#ifdef CONFIG_LOCAL_TIMERS
- twd_base = __io_address(REALVIEW_EB11MP_TWD_BASE);
-#endif
timer_irq = IRQ_EB11MP_TIMER0_1;
} else
timer_irq = IRQ_EB_TIMER0_1;
realview_timer_init(timer_irq);
+ early_platform_add_devices(eb_early_devices,
+ ARRAY_SIZE(eb_early_devices));
}
static struct sys_timer realview_eb_timer = {
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index b2985fc..9ed17c1 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -36,7 +36,6 @@
#include <asm/pgtable.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
-#include <asm/localtimer.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
@@ -276,6 +275,30 @@ static struct platform_device pmu_device = {
.resource = pmu_resources,
};
+static struct resource realview_pb11mp_twd_resources[] = {
+ {
+ .start = REALVIEW_TC11MP_TWD_BASE,
+ .end = REALVIEW_TC11MP_TWD_BASE + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_LOCALTIMER,
+ .end = IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device realview_pb11mp_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = realview_pb11mp_twd_resources,
+ .num_resources = ARRAY_SIZE(realview_pb11mp_twd_resources),
+};
+
+static struct platform_device *realview_pb11mp_early_devices[] = {
+ &realview_pb11mp_twd_device,
+};
+
static void __init gic_init_irq(void)
{
unsigned int pldctrl;
@@ -305,10 +328,9 @@ static void __init realview_pb11mp_timer_init(void)
timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE);
timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20;
-#ifdef CONFIG_LOCAL_TIMERS
- twd_base = __io_address(REALVIEW_TC11MP_TWD_BASE);
-#endif
realview_timer_init(IRQ_TC11MP_TIMER0_1);
+ early_platform_add_devices(realview_pb11mp_early_devices,
+ ARRAY_SIZE(realview_pb11mp_early_devices));
}
static struct sys_timer realview_pb11mp_timer = {
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 92ace2c..768faec 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>
@@ -288,6 +287,30 @@ static struct platform_device pmu_device = {
.resource = pmu_resources,
};
+static struct resource realview_pbx_twd_resources[] = {
+ {
+ .start = REALVIEW_PBX_TILE_TWD_BASE,
+ .end = REALVIEW_PBX_TILE_TWD_BASE + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_LOCALTIMER,
+ .end = IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device realview_pbx_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = realview_pbx_twd_resources,
+ .num_resources = ARRAY_SIZE(realview_pbx_twd_resources),
+};
+
+static struct platform_device *realview_pbx_early_devices[] = {
+ &realview_pbx_twd_device,
+};
+
static void __init gic_init_irq(void)
{
/* ARM PBX on-board GIC */
@@ -308,11 +331,9 @@ static void __init realview_pbx_timer_init(void)
timer2_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE);
timer3_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE) + 0x20;
-#ifdef CONFIG_LOCAL_TIMERS
- if (core_tile_pbx11mp() || core_tile_pbxa9mp())
- twd_base = __io_address(REALVIEW_PBX_TILE_TWD_BASE);
-#endif
realview_timer_init(IRQ_PBX_TIMER0_1);
+ early_platform_add_devices(realview_pbx_early_devices,
+ ARRAY_SIZE(realview_pbx_early_devices));
}
static struct sys_timer realview_pbx_timer = {
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 04/16] ARM: local timers: move vexpress to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (2 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 03/16] ARM: local timers: move realview to LOCAL_TIMER_DEVICES/ARM_SMP_TWD Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 05/16] ARM: local timers: remove localtimer.c from plat-versatile Marc Zyngier
` (13 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the vexpress platform (actually the CA9x4 tile) to use
the new arm_smp_twd driver. Add the platform device and register
it as early platform device.
Tested on a VExpress.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-vexpress/Kconfig | 2 ++
arch/arm/mach-vexpress/ct-ca9x4.c | 30 ++++++++++++++++++++++++++----
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 6f59932..c26a5ec 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -28,6 +28,8 @@ config ARCH_VEXPRESS_CA9X4
depends on VEXPRESS_ORIGINAL_MEMORY_MAP
select CPU_V7
select ARM_GIC
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
select ARM_ERRATA_720789
select ARM_ERRATA_751472
select ARM_ERRATA_753970
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index b06d056..4977e09 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -15,7 +15,6 @@
#include <asm/hardware/gic.h>
#include <asm/pmu.h>
#include <asm/smp_scu.h>
-#include <asm/smp_twd.h>
#include <mach/ct-ca9x4.h>
@@ -49,11 +48,32 @@ static struct map_desc ct_ca9x4_io_desc[] __initdata = {
},
};
+static struct resource ct_ca9x4_twd_resources[] = {
+ {
+ .start = A9_MPCORE_TWD,
+ .end = A9_MPCORE_TWD + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_LOCALTIMER,
+ .end = IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ct_ca9x4_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = ct_ca9x4_twd_resources,
+ .num_resources = ARRAY_SIZE(ct_ca9x4_twd_resources),
+};
+
+static struct platform_device *ct_ca9x4_early_devices[] = {
+ &ct_ca9x4_twd_device,
+};
+
static void __init ct_ca9x4_map_io(void)
{
-#ifdef CONFIG_LOCAL_TIMERS
- twd_base = MMIO_P2V(A9_MPCORE_TWD);
-#endif
iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
}
@@ -192,6 +212,8 @@ static struct platform_device pmu_device = {
static void __init ct_ca9x4_init_early(void)
{
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+ early_platform_add_devices(ct_ca9x4_early_devices,
+ ARRAY_SIZE(ct_ca9x4_early_devices));
}
static void __init ct_ca9x4_init(void)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 05/16] ARM: local timers: remove localtimer.c from plat-versatile
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (3 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 04/16] ARM: local timers: move vexpress " Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 06/16] ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD Marc Zyngier
` (12 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
As the localtimer infrastructure is not use anymore by any of
the Versatile platforms, remove localtimer.c.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/plat-versatile/Makefile | 1 -
arch/arm/plat-versatile/localtimer.c | 28 ----------------------------
2 files changed, 0 insertions(+), 29 deletions(-)
delete mode 100644 arch/arm/plat-versatile/localtimer.c
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 69714db..a5cb194 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -1,5 +1,4 @@
obj-y := clock.o
-obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
diff --git a/arch/arm/plat-versatile/localtimer.c b/arch/arm/plat-versatile/localtimer.c
deleted file mode 100644
index a76daf4..0000000
--- a/arch/arm/plat-versatile/localtimer.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/arch/arm/plat-versatile/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/smp.h>
-#include <linux/clockchips.h>
-
-#include <asm/smp_twd.h>
-#include <asm/localtimer.h>
-#include <asm/hardware/gic.h>
-#include <mach/irqs.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
- evt->irq = gic_ppi_to_vppi(IRQ_LOCALTIMER);
- twd_timer_setup(evt);
- return 0;
-}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 06/16] ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (4 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 05/16] ARM: local timers: remove localtimer.c from plat-versatile Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 20:07 ` Stephen Warren
2011-06-16 19:06 ` [RFC PATCH 07/16] ARM: local timers: move OMAP4 " Marc Zyngier
` (11 subsequent siblings)
17 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the Tegra platforms to use the new arm_smp_twd driver.
Add the platform device and register it as early platform device.
Tested on a Harmony board.
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/Kconfig | 2 ++
arch/arm/mach-tegra/Makefile | 2 +-
arch/arm/mach-tegra/localtimer.c | 27 ---------------------------
arch/arm/mach-tegra/timer.c | 32 +++++++++++++++++++++++++++-----
4 files changed, 30 insertions(+), 33 deletions(-)
delete mode 100644 arch/arm/mach-tegra/localtimer.c
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 5ec1846..4b05f02 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -9,6 +9,8 @@ config ARCH_TEGRA_2x_SOC
bool "Tegra 2 family"
select CPU_V7
select ARM_GIC
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
select ARCH_REQUIRE_GPIOLIB
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB_SUPPORT
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 823c703..efbddfc 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 97cd0a9..0000000
--- a/arch/arm/mach-tegra/localtimer.c
+++ /dev/null
@@ -1,27 +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/smp.h>
-#include <linux/clockchips.h>
-#include <asm/irq.h>
-#include <asm/smp_twd.h>
-#include <asm/localtimer.h>
-#include <asm/hardware/gic.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
- evt->irq = gic_ppi_to_vppi(IRQ_LOCALTIMER);
- twd_timer_setup(evt);
- return 0;
-}
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 9035042..4e1ecd0 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -27,9 +27,9 @@
#include <linux/clocksource.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <asm/mach/time.h>
-#include <asm/localtimer.h>
#include <asm/sched_clock.h>
#include <mach/iomap.h>
@@ -179,6 +179,30 @@ static struct irqaction tegra_timer_irq = {
.irq = INT_TMR3,
};
+static struct resource tegra_twd_resources[] = {
+ {
+ .start = TEGRA_ARM_PERIF_BASE + 0x600,
+ .end = TEGRA_ARM_PERIF_BASE + 0x600 + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_LOCALTIMER,
+ .end = IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tegra_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = tegra_twd_resources,
+ .num_resources = ARRAY_SIZE(tegra_twd_resources),
+};
+
+static struct platform_device *tegra_early_devices[] = {
+ &tegra_twd_device,
+};
+
static void __init tegra_init_timer(void)
{
struct clk *clk;
@@ -197,10 +221,6 @@ static void __init tegra_init_timer(void)
BUG_ON(IS_ERR(clk));
clk_enable(clk);
-#ifdef CONFIG_HAVE_ARM_TWD
- twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
-#endif
-
switch (rate) {
case 12000000:
timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -241,6 +261,8 @@ static void __init tegra_init_timer(void)
tegra_clockevent.cpumask = cpu_all_mask;
tegra_clockevent.irq = tegra_timer_irq.irq;
clockevents_register_device(&tegra_clockevent);
+ early_platform_add_devices(tegra_early_devices,
+ ARRAY_SIZE(tegra_early_devices));
}
struct sys_timer tegra_timer = {
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 07/16] ARM: local timers: move OMAP4 to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (5 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 06/16] ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-17 8:16 ` Santosh Shilimkar
2011-06-16 19:06 ` [RFC PATCH 08/16] ARM: local timers: move shmobile " Marc Zyngier
` (10 subsequent siblings)
17 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the OMAP4 platforms to use the new arm_smp_twd driver.
Add the platform device and register it as early platform device.
Tested on a Pandaboard.
Cc: Tony Lindgren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-omap2/Kconfig | 3 +-
arch/arm/mach-omap2/Makefile | 1 -
arch/arm/mach-omap2/timer-gp.c | 40 ++++++++++++++++++++++++++++++++------
arch/arm/mach-omap2/timer-mpu.c | 40 ---------------------------------------
4 files changed, 35 insertions(+), 49 deletions(-)
delete mode 100644 arch/arm/mach-omap2/timer-mpu.c
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 19d5891..805d7b9 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -44,7 +44,8 @@ config ARCH_OMAP4
depends on ARCH_OMAP2PLUS
select CPU_V7
select ARM_GIC
- select LOCAL_TIMERS if SMP
+ select LOCAL_TIMER_DEVICES if SMP
+ select ARM_SMP_TWD
select PL310_ERRATA_588369
select PL310_ERRATA_727915
select ARM_ERRATA_720789
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b148077..f48c989 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..f2f0db6 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -35,10 +35,10 @@
#include <linux/irq.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
+#include <linux/platform_device.h>
#include <asm/mach/time.h>
#include <plat/dmtimer.h>
-#include <asm/localtimer.h>
#include <asm/sched_clock.h>
#include <plat/common.h>
#include <plat/omap_hwmod.h>
@@ -247,18 +247,44 @@ static void __init omap2_gp_clocksource_init(void)
}
#endif
+#ifdef CONFIG_ARM_SMP_TWD
+static struct resource omap2_gp_twd_resources[] = {
+ {
+ .start = OMAP44XX_LOCAL_TWD_BASE,
+ .end = OMAP44XX_LOCAL_TWD_BASE + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP44XX_IRQ_LOCALTIMER,
+ .end = OMAP44XX_IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device omap2_gp_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = omap2_gp_twd_resources,
+ .num_resources = ARRAY_SIZE(omap2_gp_twd_resources),
+};
+
+static struct platform_device *omap2_gp_early_devices[] = {
+ &omap2_gp_twd_device,
+};
+#endif
+
static void __init omap2_gp_timer_init(void)
{
-#ifdef CONFIG_LOCAL_TIMERS
- if (cpu_is_omap44xx()) {
- twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
- BUG_ON(!twd_base);
- }
-#endif
omap_dm_timer_init();
omap2_gp_clockevent_init();
omap2_gp_clocksource_init();
+#ifdef CONFIG_ARM_SMP_TWD
+ /* Local timers are not supprted on OMAP4430 ES1.0 */
+ if (omap_rev() != OMAP4430_REV_ES1_0)
+ early_platform_add_devices(omap2_gp_early_devices,
+ ARRAY_SIZE(omap2_gp_early_devices));
+#endif
}
struct sys_timer omap_timer = {
diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c
deleted file mode 100644
index 1fd5ca5..0000000
--- a/arch/arm/mach-omap2/timer-mpu.c
+++ /dev/null
@@ -1,40 +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/smp.h>
-#include <linux/clockchips.h>
-#include <asm/irq.h>
-#include <asm/smp_twd.h>
-#include <asm/localtimer.h>
-#include <asm/hardware/gic.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 = gic_ppi_to_vppi(OMAP44XX_IRQ_LOCALTIMER);
- twd_timer_setup(evt);
- return 0;
-}
-
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 08/16] ARM: local timers: move shmobile to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (6 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 07/16] ARM: local timers: move OMAP4 " Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 09/16] ARM: local timers: move ux500 " Marc Zyngier
` (9 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the shmobile platforms to use the new arm_smp_twd driver.
Add the platform device and register it as early platform device.
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/Kconfig | 2 ++
arch/arm/mach-shmobile/Makefile | 1 -
arch/arm/mach-shmobile/localtimer.c | 27 ---------------------------
arch/arm/mach-shmobile/platsmp.c | 1 -
arch/arm/mach-shmobile/setup-sh73a0.c | 21 +++++++++++++++++++++
arch/arm/mach-shmobile/smp-sh73a0.c | 6 ------
6 files changed, 23 insertions(+), 35 deletions(-)
delete mode 100644 arch/arm/mach-shmobile/localtimer.c
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 0c8f6cf..86befbc 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -26,6 +26,8 @@ config ARCH_SH73A0
select SH_CLK_CPG
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARM_GIC
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
comment "SH-Mobile Board Type"
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 612b270..82ec6e9 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 8a67b1c..0000000
--- a/arch/arm/mach-shmobile/localtimer.c
+++ /dev/null
@@ -1,27 +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>
-#include <asm/hardware/gic.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
- evt->irq = gic_ppi_to_vppi(29);
- twd_timer_setup(evt);
- return 0;
-}
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index f3888fe..5ac3b71 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -17,7 +17,6 @@
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/hardware/gic.h>
-#include <asm/localtimer.h>
#include <asm/mach-types.h>
#include <mach/common.h>
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index e46821c..8d26607 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -630,6 +630,26 @@ static struct platform_device dma0_device = {
},
};
+static struct resource twd_resources[] = {
+ {
+ .start = 0xf0000600,
+ .end = 0xf0000600 + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 29,
+ .end = 29,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = twd_resources,
+ .num_resources = ARRAY_SIZE(twd_resources),
+};
+
static struct platform_device *sh73a0_early_devices[] __initdata = {
&scif0_device,
&scif1_device,
@@ -643,6 +663,7 @@ static struct platform_device *sh73a0_early_devices[] __initdata = {
&cmt10_device,
&tmu00_device,
&tmu01_device,
+ &twd_device,
};
static struct platform_device *sh73a0_late_devices[] __initdata = {
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 3ffdbc9..d52c771 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -24,7 +24,6 @@
#include <linux/io.h>
#include <mach/common.h>
#include <asm/smp_scu.h>
-#include <asm/smp_twd.h>
#include <asm/hardware/gic.h>
#define WUPCR 0xe6151010
@@ -59,11 +58,6 @@ unsigned int __init sh73a0_get_core_count(void)
{
void __iomem *scu_base = scu_base_addr();
-#ifdef CONFIG_HAVE_ARM_TWD
- /* twd_base needs to be initialized before percpu_timer_setup() */
- twd_base = (void __iomem *)0xf0000600;
-#endif
-
return scu_get_core_count(scu_base);
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 09/16] ARM: local timers: move ux500 to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (7 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 08/16] ARM: local timers: move shmobile " Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 10/16] ARM: local timers: add exynos_mct driver to driver/clocksource Marc Zyngier
` (8 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the ux500 platforms to use the new arm_smp_twd driver.
Add the platform device and register it as early platform device.
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/Kconfig | 2 ++
arch/arm/mach-ux500/Makefile | 1 -
arch/arm/mach-ux500/cpu-db5500.c | 1 -
arch/arm/mach-ux500/cpu-db8500.c | 1 -
arch/arm/mach-ux500/cpu.c | 38 +++++++++++++++++++++++++++++++++-----
arch/arm/mach-ux500/localtimer.c | 30 ------------------------------
6 files changed, 35 insertions(+), 38 deletions(-)
delete mode 100644 arch/arm/mach-ux500/localtimer.c
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 96d546c..aa21fc0 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -5,6 +5,8 @@ config UX500_SOC_COMMON
default y
select ARM_GIC
select HAS_MTU
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD
select ARM_ERRATA_753970
menu "Ux500 SoC"
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 1694916..2e30a80 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
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index 22705d2..63eaa98 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -33,7 +33,6 @@ static struct map_desc u5500_io_desc[] __initdata = {
__IO_DEV_DESC(U5500_GIC_CPU_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K),
__IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K),
- __IO_DEV_DESC(U5500_TWD_BASE, SZ_4K),
__IO_DEV_DESC(U5500_MTU0_BASE, SZ_4K),
__IO_DEV_DESC(U5500_SCU_BASE, SZ_4K),
__IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K),
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 4598b06..dfad7c8 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -38,7 +38,6 @@ static struct map_desc u8500_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
__IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K),
- __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K),
__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_SCU_BASE, SZ_4K),
__IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K),
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 1da23bb..1dac06f 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -15,7 +15,6 @@
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/mach/map.h>
-#include <asm/localtimer.h>
#include <plat/mtu.h>
#include <mach/hardware.h>
@@ -120,17 +119,44 @@ static int ux500_l2x0_init(void)
early_initcall(ux500_l2x0_init);
#endif
+static struct resource ux500_twd_resources[] = {
+ {
+ .start = 0,
+ .end = 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_LOCALTIMER,
+ .end = IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ux500_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = ux500_twd_resources,
+ .num_resources = ARRAY_SIZE(ux500_twd_resources),
+};
+
+static struct platform_device *ux500_early_devices[] = {
+ &ux500_twd_device,
+};
+
static void __init ux500_timer_init(void)
{
-#ifdef CONFIG_LOCAL_TIMERS
+ unsigned long iobase = 0;
/* Setup the local timer base */
if (cpu_is_u5500())
- twd_base = __io_address(U5500_TWD_BASE);
+ iobase = U5500_TWD_BASE;
else if (cpu_is_u8500())
- twd_base = __io_address(U8500_TWD_BASE);
+ iobase = U8500_TWD_BASE;
else
ux500_unknown_soc();
-#endif
+
+ ux500_twd_resources[0].start += iobase;
+ ux500_twd_resources[0].end += iobase;
+
if (cpu_is_u5500())
mtu_base = __io_address(U5500_MTU0_BASE);
else if (cpu_is_u8500ed())
@@ -141,6 +167,8 @@ static void __init ux500_timer_init(void)
ux500_unknown_soc();
nmdk_timer_init();
+ early_platform_add_devices(ux500_early_devices,
+ ARRAY_SIZE(ux500_early_devices));
}
struct sys_timer ux500_timer = {
diff --git a/arch/arm/mach-ux500/localtimer.c b/arch/arm/mach-ux500/localtimer.c
deleted file mode 100644
index f027cef..0000000
--- a/arch/arm/mach-ux500/localtimer.c
+++ /dev/null
@@ -1,30 +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/smp.h>
-#include <linux/clockchips.h>
-
-#include <asm/irq.h>
-#include <asm/smp_twd.h>
-#include <asm/localtimer.h>
-#include <asm/hardware/gic.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
- evt->irq = gic_ppi_to_vppi(IRQ_LOCALTIMER);
- twd_timer_setup(evt);
- return 0;
-}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 10/16] ARM: local timers: add exynos_mct driver to driver/clocksource
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (8 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 09/16] ARM: local timers: move ux500 " Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-17 15:09 ` Arnd Bergmann
2011-06-16 19:06 ` [RFC PATCH 11/16] ARM: local timers: move exynos4 to LOCAL_TIMER_DEVICES/EXYNOS_MCT/ARM_SMP_TWD Marc Zyngier
` (7 subsequent siblings)
17 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Add a "new" driver to driver/clocksource to support the Samsung MCT
hardware. This is basically the local timer part of
arch/arm/mach-exynos4/mct.c, turned into a platform driver, and
with a CPU notifier being used to start/stop timers on secondary
cores.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/clocksource/Makefile | 1 +
drivers/clocksource/exynos4_mct.c | 283 +++++++++++++++++++++++++++++++++++++
2 files changed, 284 insertions(+), 0 deletions(-)
create mode 100644 drivers/clocksource/exynos4_mct.c
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index b7e6397..7b30585 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
obj-$(CONFIG_CLKBLD_I8253) += i8253.o
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
+obj-$(CONFIG_EXYNOS4_MCT) += exynos4_mct.o
diff --git a/drivers/clocksource/exynos4_mct.c b/drivers/clocksource/exynos4_mct.c
new file mode 100644
index 0000000..b07a9a9
--- /dev/null
+++ b/drivers/clocksource/exynos4_mct.c
@@ -0,0 +1,283 @@
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS4 MCT(Multi-Core Timer) support
+ *
+ * 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+
+#include <mach/regs-mct.h>
+
+static unsigned long clk_cnt_per_tick;
+static unsigned long clk_rate;
+
+struct mct_clock_event_device {
+ struct clock_event_device evt;
+ void __iomem *base;
+};
+
+static struct mct_clock_event_device __percpu *mct_tick;
+
+static void exynos4_mct_write(unsigned int value, void *addr)
+{
+ void __iomem *stat_addr;
+ u32 mask;
+ u32 i;
+
+ __raw_writel(value, addr);
+
+ switch ((u32) addr) {
+ case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
+ stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 3; /* L0_TCON write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
+ stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 3; /* L1_TCON write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 0; /* L0_TCNTB write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 0; /* L1_TCNTB write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 1; /* L0_ICNTB write status */
+ break;
+ case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
+ stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+ mask = 1 << 1; /* L1_ICNTB write status */
+ break;
+ default:
+ return;
+ }
+
+ /* Wait maximum 1 ms until written values are applied */
+ for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
+ if (__raw_readl(stat_addr) & mask) {
+ __raw_writel(mask, stat_addr);
+ return;
+ }
+
+ panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
+}
+
+/* Clock event handling */
+static void exynos4_mct_tick_stop(void *data)
+{
+ struct mct_clock_event_device *mevt = data;
+ unsigned long tmp;
+ unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
+ void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
+
+ tmp = __raw_readl(addr);
+ if (tmp & mask) {
+ tmp &= ~mask;
+ exynos4_mct_write(tmp, addr);
+ }
+}
+
+static void exynos4_mct_tick_start(unsigned long cycles,
+ struct mct_clock_event_device *mevt)
+{
+ unsigned long tmp;
+
+ exynos4_mct_tick_stop(mevt);
+
+ tmp = (1 << 31) | cycles; /* MCT_L_UPDATE_ICNTB */
+
+ /* update interrupt count buffer */
+ exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
+
+ /* enable MCT tick interrupt */
+ exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
+
+ tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
+ tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
+ MCT_L_TCON_INTERVAL_MODE;
+ exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
+}
+
+static int exynos4_tick_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ struct mct_clock_event_device *mevt;
+
+ mevt = container_of(evt, struct mct_clock_event_device, evt);
+ exynos4_mct_tick_start(cycles, mevt);
+
+ return 0;
+}
+
+static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct mct_clock_event_device *mevt;
+
+ mevt = container_of(evt, struct mct_clock_event_device, evt);
+ exynos4_mct_tick_stop(mevt);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ exynos4_mct_tick_start(clk_cnt_per_tick, mevt);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+ struct mct_clock_event_device *mevt = dev_id;
+ struct clock_event_device *evt = &mevt->evt;
+
+ /*
+ * This is for supporting oneshot mode.
+ * Mct would generate interrupt periodically
+ * without explicit stopping.
+ */
+ if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
+ exynos4_mct_tick_stop(mevt);
+
+ /* Clear the MCT tick interrupt */
+ exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction mct_tick0_event_irq = {
+ .name = "mct_tick0_irq",
+ .flags = IRQF_TIMER | IRQF_NOBALANCING,
+ .handler = exynos4_mct_tick_isr,
+};
+
+static struct irqaction mct_tick1_event_irq = {
+ .name = "mct_tick1_irq",
+ .flags = IRQF_TIMER | IRQF_NOBALANCING,
+ .handler = exynos4_mct_tick_isr,
+};
+
+static void exynos4_mct_tick_init(void *data)
+{
+ struct mct_clock_event_device *mevt = data;
+ struct clock_event_device *evt = &mevt->evt;
+ unsigned int cpu = smp_processor_id();
+
+ if (cpu == 0) {
+ mevt->base = EXYNOS4_MCT_L0_BASE;
+ evt->name = "mct_tick0";
+ } else {
+ mevt->base = EXYNOS4_MCT_L1_BASE;
+ evt->name = "mct_tick1";
+ }
+
+ evt->cpumask = cpumask_of(cpu);
+ evt->set_next_event = exynos4_tick_set_next_event;
+ evt->set_mode = exynos4_tick_set_mode;
+ evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ evt->rating = 450;
+
+ clockevents_calc_mult_shift(evt, clk_rate / 2, 5);
+ evt->max_delta_ns =
+ clockevent_delta2ns(0x7fffffff, evt);
+ evt->min_delta_ns =
+ clockevent_delta2ns(0xf, evt);
+
+ clockevents_register_device(evt);
+
+ exynos4_mct_write(0x1, mevt->base + MCT_L_TCNTB_OFFSET);
+
+ if (cpu == 0) {
+ mct_tick0_event_irq.dev_id = mevt;
+ setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+ } else {
+ mct_tick1_event_irq.dev_id = mevt;
+ irq_set_affinity(IRQ_MCT1, cpumask_of(1));
+ setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+ }
+}
+
+static int __cpuinit exynos4_mct_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ int cpu = (int)data;
+ struct mct_clock_event_device *mevt = per_cpu_ptr(mct_tick, cpu);
+
+ switch (action) {
+ case CPU_STARTING:
+ case CPU_STARTING_FROZEN:
+ smp_call_function_single(cpu, exynos4_mct_tick_init, mevt, 1);
+ break;
+
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ smp_call_function_single(cpu, exynos4_mct_tick_stop, mevt, 1);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata exynos4_mct_cpu_nb = {
+ .notifier_call = exynos4_mct_cpu_notify,
+};
+
+static int exynos4_mct_probe(struct platform_device *pdev)
+{
+ struct clk *mct_clk;
+ struct mct_clock_event_device *mevt;
+
+ if (mct_tick)
+ return -EBUSY;
+
+ mct_tick = alloc_percpu(struct mct_clock_event_device);
+ if (!mct_tick)
+ return -ENOMEM;
+
+ mct_clk = clk_get(NULL, "xtal");
+ clk_rate = clk_get_rate(mct_clk);
+
+ /* Immediately configure the timer on the boot CPU */
+ mevt = per_cpu_ptr(mct_tick, smp_processor_id());
+ exynos4_mct_tick_init(mevt);
+
+ register_cpu_notifier(&exynos4_mct_cpu_nb);
+
+ return 0;
+}
+
+static int exynos4_mct_remove(struct platform_device *pdev)
+{
+ return -EBUSY;
+}
+
+static struct platform_driver exynos4_mct_driver = {
+ .probe = exynos4_mct_probe,
+ .remove = __devexit_p(exynos4_mct_remove),
+ .driver = {
+ .name = "exynos4_mct",
+ },
+};
+
+early_platform_init("localtimer", &exynos4_mct_driver);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 11/16] ARM: local timers: move exynos4 to LOCAL_TIMER_DEVICES/EXYNOS_MCT/ARM_SMP_TWD
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (9 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 10/16] ARM: local timers: add exynos_mct driver to driver/clocksource Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 12/16] ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h Marc Zyngier
` (6 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the exynos4 platforms to use the new arm_smp_twd or exynos4_mct
drivers, depending on the configuration. arch/arm/mach-exynos4/mct.c
takes a major hit in the process.
Add the platform devices and register them as early platform devices.
Tested on a SMDK-v310 with TWD only.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-exynos4/Kconfig | 2 +
arch/arm/mach-exynos4/Makefile | 1 -
arch/arm/mach-exynos4/localtimer.c | 27 -----
arch/arm/mach-exynos4/mct.c | 197 ++---------------------------------
arch/arm/mach-exynos4/time.c | 33 +++++-
arch/arm/plat-s5p/s5p-time.c | 1 -
6 files changed, 41 insertions(+), 220 deletions(-)
delete mode 100644 arch/arm/mach-exynos4/localtimer.c
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..0db7aa3 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -12,6 +12,8 @@ if ARCH_EXYNOS4
config CPU_EXYNOS4210
bool
select S3C_PL330_DMA
+ select LOCAL_TIMER_DEVICES
+ select ARM_SMP_TWD if !EXYNOS4_MCT
help
Enable EXYNOS4210 CPU support
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index 1366995..b223972 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 315de6f..0000000
--- a/arch/arm/mach-exynos4/localtimer.c
+++ /dev/null
@@ -1,27 +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>
-#include <asm/hardware/gic.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
- evt->irq = gic_ppi_to_vppi(IRQ_LOCALTIMER);
- twd_timer_setup(evt);
- return 0;
-}
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index 14ac10b..5aea222 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -10,7 +10,6 @@
* published by the Free Software Foundation.
*/
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/err.h>
@@ -18,7 +17,6 @@
#include <linux/clockchips.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
-#include <linux/percpu.h>
#include <mach/map.h>
#include <mach/regs-mct.h>
@@ -27,13 +25,6 @@
static unsigned long clk_cnt_per_tick;
static unsigned long clk_rate;
-struct mct_clock_event_device {
- struct clock_event_device *evt;
- void __iomem *base;
-};
-
-struct mct_clock_event_device mct_tick[2];
-
static void exynos4_mct_write(unsigned int value, void *addr)
{
void __iomem *stat_addr;
@@ -67,30 +58,6 @@ static void exynos4_mct_write(unsigned int value, void *addr)
stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
mask = 1 << 1; /* G_CNT_U write status */
break;
- case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
- stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 3; /* L0_TCON write status */
- break;
- case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
- stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 3; /* L1_TCON write status */
- break;
- case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 0; /* L0_TCNTB write status */
- break;
- case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 0; /* L1_TCNTB write status */
- break;
- case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 1; /* L0_ICNTB write status */
- break;
- case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
- stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
- mask = 1 << 1; /* L1_ICNTB write status */
- break;
default:
return;
}
@@ -249,158 +216,6 @@ static void exynos4_clockevent_init(void)
setup_irq(IRQ_MCT_G0, &mct_comp_event_irq);
}
-#ifdef CONFIG_LOCAL_TIMERS
-/* Clock event handling */
-static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
-{
- unsigned long tmp;
- unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
- void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
-
- tmp = __raw_readl(addr);
- if (tmp & mask) {
- tmp &= ~mask;
- exynos4_mct_write(tmp, addr);
- }
-}
-
-static void exynos4_mct_tick_start(unsigned long cycles,
- struct mct_clock_event_device *mevt)
-{
- unsigned long tmp;
-
- exynos4_mct_tick_stop(mevt);
-
- tmp = (1 << 31) | cycles; /* MCT_L_UPDATE_ICNTB */
-
- /* update interrupt count buffer */
- exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
-
- /* enable MCT tick interrupt */
- exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
-
- tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
- tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
- MCT_L_TCON_INTERVAL_MODE;
- exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
-}
-
-static int exynos4_tick_set_next_event(unsigned long cycles,
- struct clock_event_device *evt)
-{
- struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
-
- exynos4_mct_tick_start(cycles, mevt);
-
- return 0;
-}
-
-static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
-
- exynos4_mct_tick_stop(mevt);
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- exynos4_mct_tick_start(clk_cnt_per_tick, mevt);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
-}
-
-static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
-{
- struct mct_clock_event_device *mevt = dev_id;
- struct clock_event_device *evt = mevt->evt;
-
- /*
- * This is for supporting oneshot mode.
- * Mct would generate interrupt periodically
- * without explicit stopping.
- */
- if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
- exynos4_mct_tick_stop(mevt);
-
- /* Clear the MCT tick interrupt */
- exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
-
- evt->event_handler(evt);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction mct_tick0_event_irq = {
- .name = "mct_tick0_irq",
- .flags = IRQF_TIMER | IRQF_NOBALANCING,
- .handler = exynos4_mct_tick_isr,
-};
-
-static struct irqaction mct_tick1_event_irq = {
- .name = "mct_tick1_irq",
- .flags = IRQF_TIMER | IRQF_NOBALANCING,
- .handler = exynos4_mct_tick_isr,
-};
-
-static void exynos4_mct_tick_init(struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
-
- mct_tick[cpu].evt = evt;
-
- if (cpu == 0) {
- mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
- evt->name = "mct_tick0";
- } else {
- mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
- evt->name = "mct_tick1";
- }
-
- evt->cpumask = cpumask_of(cpu);
- evt->set_next_event = exynos4_tick_set_next_event;
- evt->set_mode = exynos4_tick_set_mode;
- evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
- evt->rating = 450;
-
- clockevents_calc_mult_shift(evt, clk_rate / 2, 5);
- evt->max_delta_ns =
- clockevent_delta2ns(0x7fffffff, evt);
- evt->min_delta_ns =
- clockevent_delta2ns(0xf, evt);
-
- clockevents_register_device(evt);
-
- exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
-
- if (cpu == 0) {
- mct_tick0_event_irq.dev_id = &mct_tick[cpu];
- setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
- } else {
- mct_tick1_event_irq.dev_id = &mct_tick[cpu];
- 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);
-}
-
-int local_timer_ack(void)
-{
- return 0;
-}
-
-#endif /* CONFIG_LOCAL_TIMERS */
-
static void __init exynos4_timer_resources(void)
{
struct clk *mct_clk;
@@ -409,11 +224,23 @@ static void __init exynos4_timer_resources(void)
clk_rate = clk_get_rate(mct_clk);
}
+static struct platform_device exynos4_mct_device = {
+ .name = "exynos4_mct",
+ .id = -1,
+};
+
+static struct platform_device *exynos4_early_devices[] = {
+ &exynos4_mct_device,
+};
+
static void __init exynos4_timer_init(void)
{
exynos4_timer_resources();
exynos4_clocksource_init();
exynos4_clockevent_init();
+
+ early_platform_add_devices(exynos4_early_devices,
+ ARRAY_SIZE(exynos4_early_devices));
}
struct sys_timer exynos4_timer = {
diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c
index ebb8f38..be674d5 100644
--- a/arch/arm/mach-exynos4/time.c
+++ b/arch/arm/mach-exynos4/time.c
@@ -19,8 +19,6 @@
#include <linux/clockchips.h>
#include <linux/platform_device.h>
-#include <asm/smp_twd.h>
-
#include <mach/map.h>
#include <plat/regs-timer.h>
#include <asm/mach/time.h>
@@ -285,15 +283,38 @@ static void __init exynos4_timer_resources(void)
clk_enable(tin4);
}
+static struct resource exynos4_twd_resources[] = {
+ {
+ .start = EXYNOS4_PA_COREPERI + 0x600,
+ .end = EXYNOS4_PA_COREPERI + 0x600 + 0x10,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_LOCALTIMER,
+ .end = IRQ_LOCALTIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device exynos4_twd_device = {
+ .name = "arm_smp_twd",
+ .id = -1,
+ .resource = exynos4_twd_resources,
+ .num_resources = ARRAY_SIZE(exynos4_twd_resources),
+};
+
+static struct platform_device *exynos4_early_devices[] = {
+ &exynos4_twd_device,
+};
+
static void __init exynos4_timer_init(void)
{
-#ifdef CONFIG_LOCAL_TIMERS
- twd_base = S5P_VA_TWD;
-#endif
-
exynos4_timer_resources();
exynos4_clockevent_init();
exynos4_clocksource_init();
+
+ early_platform_add_devices(exynos4_early_devices,
+ ARRAY_SIZE(exynos4_early_devices));
}
struct sys_timer exynos4_timer = {
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c
index 899a8cc..f2a0915 100644
--- a/arch/arm/plat-s5p/s5p-time.c
+++ b/arch/arm/plat-s5p/s5p-time.c
@@ -18,7 +18,6 @@
#include <linux/clockchips.h>
#include <linux/platform_device.h>
-#include <asm/smp_twd.h>
#include <asm/mach/time.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 12/16] ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (10 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 11/16] ARM: local timers: move exynos4 to LOCAL_TIMER_DEVICES/EXYNOS_MCT/ARM_SMP_TWD Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-17 7:08 ` Wim Van Sebroeck
2011-06-16 19:06 ` [RFC PATCH 13/16] ARM: local timers: remove smp_twd from arch/arm Marc Zyngier
` (5 subsequent siblings)
17 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
As the life expectancy of asm/smp_twd.h seems rather limited,
move the few defines concerning mpcore_wdt to the driver itself.
Change the dependency to ARM_SMP_TWD as well.
Cc: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/watchdog/Kconfig | 2 +-
drivers/watchdog/mpcore_wdt.c | 7 ++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c70f82b..55647ac 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -197,7 +197,7 @@ config DW_WATCHDOG
config MPCORE_WATCHDOG
tristate "MPcore watchdog"
- depends on HAVE_ARM_TWD
+ depends on ARM_SMP_TWD
help
Watchdog timer embedded into the MPcore system.
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 2b4af22..f638206 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -33,7 +33,12 @@
#include <linux/slab.h>
#include <linux/io.h>
-#include <asm/smp_twd.h>
+#define TWD_WDOG_LOAD 0x20
+#define TWD_WDOG_COUNTER 0x24
+#define TWD_WDOG_CONTROL 0x28
+#define TWD_WDOG_INTSTAT 0x2C
+#define TWD_WDOG_RESETSTAT 0x30
+#define TWD_WDOG_DISABLE 0x34
struct mpcore_wdt {
unsigned long timer_alive;
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 13/16] ARM: local timers: remove smp_twd from arch/arm
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (11 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 12/16] ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 14/16] ARM: local timers: add msm_timer driver to driver/clocksource Marc Zyngier
` (4 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
There is no in-tree user of arch/arm/kernel/smp_twd.c, as they've
been all converted to driver/clocksource/arm_smp_twd.c.
Shed a tear, and get rid of it.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/Kconfig | 8 --
arch/arm/include/asm/localtimer.h | 10 ---
arch/arm/include/asm/smp_twd.h | 28 -------
arch/arm/kernel/Makefile | 1 -
arch/arm/kernel/smp_twd.c | 163 -------------------------------------
5 files changed, 0 insertions(+), 210 deletions(-)
delete mode 100644 arch/arm/include/asm/smp_twd.h
delete mode 100644 arch/arm/kernel/smp_twd.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dafb20a..f3c1124 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1370,13 +1370,6 @@ config HAVE_ARM_SCU
help
This option enables support for the ARM system coherency unit
-config HAVE_ARM_TWD
- bool
- depends on SMP
- select TICK_ONESHOT
- help
- This options enables support for the ARM timer and watchdog unit
-
choice
prompt "Memory split"
default VMSPLIT_3G
@@ -1417,7 +1410,6 @@ config LOCAL_TIMERS
bool "Use local timer interrupts"
depends on SMP && !LOCAL_TIMER_DEVICES
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/localtimer.h b/arch/arm/include/asm/localtimer.h
index 5c8acb4..74af2cd 100644
--- a/arch/arm/include/asm/localtimer.h
+++ b/arch/arm/include/asm/localtimer.h
@@ -26,22 +26,12 @@ irqreturn_t percpu_timer_handler(int irq, void *dev_id);
#ifdef CONFIG_LOCAL_TIMERS
-#ifdef CONFIG_HAVE_ARM_TWD
-
-#include "smp_twd.h"
-
-#define local_timer_ack() twd_timer_ack()
-
-#else
-
/*
* Platform provides this to acknowledge a local timer IRQ.
* Returns true if the local timer IRQ is to be processed.
*/
int local_timer_ack(void);
-#endif
-
/*
* Setup a local timer interrupt for a CPU.
*/
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
deleted file mode 100644
index fed9981..0000000
--- a/arch/arm/include/asm/smp_twd.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __ASMARM_SMP_TWD_H
-#define __ASMARM_SMP_TWD_H
-
-#define TWD_TIMER_LOAD 0x00
-#define TWD_TIMER_COUNTER 0x04
-#define TWD_TIMER_CONTROL 0x08
-#define TWD_TIMER_INTSTAT 0x0C
-
-#define TWD_WDOG_LOAD 0x20
-#define TWD_WDOG_COUNTER 0x24
-#define TWD_WDOG_CONTROL 0x28
-#define TWD_WDOG_INTSTAT 0x2C
-#define TWD_WDOG_RESETSTAT 0x30
-#define TWD_WDOG_DISABLE 0x34
-
-#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
-#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
-#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 *);
-
-#endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a5b31af..c6c6d8b 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -33,7 +33,6 @@ obj-$(CONFIG_PM_SLEEP) += 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_ARM_TWD) += smp_twd.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/smp_twd.c b/arch/arm/kernel/smp_twd.c
deleted file mode 100644
index aa99656..0000000
--- a/arch/arm/kernel/smp_twd.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * linux/arch/arm/kernel/smp_twd.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/kernel.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/smp.h>
-#include <linux/jiffies.h>
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <asm/smp_twd.h>
-#include <asm/localtimer.h>
-#include <asm/hardware/gic.h>
-
-/* set up by the platform code */
-void __iomem *twd_base;
-
-static unsigned long twd_timer_rate;
-static DEFINE_PER_CPU(bool, irq_reqd);
-
-static void twd_set_mode(enum clock_event_mode mode,
- struct clock_event_device *clk)
-{
- unsigned long ctrl;
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- /* timer load already set up */
- ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
- | TWD_TIMER_CONTROL_PERIODIC;
- __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- /* period set, and timer enabled in 'next_event' hook */
- ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
- break;
- case CLOCK_EVT_MODE_UNUSED:
- disable_irq(clk->irq);
- /* fall through */
- case CLOCK_EVT_MODE_SHUTDOWN:
- default:
- ctrl = 0;
- }
-
- __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
-}
-
-static int twd_set_next_event(unsigned long evt,
- struct clock_event_device *unused)
-{
- unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
-
- ctrl |= TWD_TIMER_CONTROL_ENABLE;
-
- __raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
- __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
-
- return 0;
-}
-
-/*
- * local_timer_ack: checks for a local timer interrupt.
- *
- * If a local timer interrupt has occurred, acknowledge and return 1.
- * Otherwise, return 0.
- */
-int twd_timer_ack(void)
-{
- if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
- __raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
- return 1;
- }
-
- return 0;
-}
-
-static void __cpuinit twd_calibrate_rate(void)
-{
- unsigned long count;
- u64 waitjiffies;
-
- /*
- * If this is the first time round, we need to work out how fast
- * the timer ticks
- */
- if (twd_timer_rate == 0) {
- printk(KERN_INFO "Calibrating local timer... ");
-
- /* Wait for a tick to start */
- waitjiffies = get_jiffies_64() + 1;
-
- while (get_jiffies_64() < waitjiffies)
- udelay(10);
-
- /* OK, now the tick has started, let's get the timer going */
- waitjiffies += 5;
-
- /* enable, no interrupt or reload */
- __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
-
- /* maximum value */
- __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
-
- while (get_jiffies_64() < waitjiffies)
- udelay(10);
-
- count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
-
- twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
-
- printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
- (twd_timer_rate / 1000000) % 100);
- }
-}
-
-/*
- * Setup the local clock events for a CPU.
- */
-void __cpuinit twd_timer_setup(struct clock_event_device *clk)
-{
- int err;
- bool *reqd;
-
- twd_calibrate_rate();
-
- clk->name = "local_timer";
- clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
- CLOCK_EVT_FEAT_C3STOP;
- clk->rating = 350;
- clk->set_mode = twd_set_mode;
- clk->set_next_event = twd_set_next_event;
- clk->shift = 20;
- clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift);
- clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
- clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
-
- reqd = &__get_cpu_var(irq_reqd);
- if (!*reqd) {
- err = request_irq(clk->irq, percpu_timer_handler,
- IRQF_PERCPU | IRQF_NOBALANCING | IRQF_TIMER,
- clk->name, clk);
- if (err) {
- pr_err("%s: can't register interrupt %d on cpu %d (%d)\n",
- clk->name, clk->irq, smp_processor_id(), err);
- return;
- }
-
- *reqd = true;
- } else
- enable_irq(clk->irq);
-
- clockevents_register_device(clk);
-}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 14/16] ARM: local timers: add msm_timer driver to driver/clocksource
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (12 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 13/16] ARM: local timers: remove smp_twd from arch/arm Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 15/16] ARM: local timers: move msm to LOCAL_TIMER_DEVICES/MSM_TIMER Marc Zyngier
` (3 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Add a "new" driver to driver/clocksource to support the MSM timer
hardware. This is basically a copy of arch/arm/mach-msm/timer.c
turned into a platform driver, with a CPU notifier being used
to start/stop the timer on secondary core.
Cc: David Brown <davidb@codeaurora.org>
Cc: Daniel Walker <dwalker@fifo99.com>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/clocksource/Kconfig | 3 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/msm_timer.c | 345 +++++++++++++++++++++++++++++++++++++++
3 files changed, 349 insertions(+), 0 deletions(-)
create mode 100644 drivers/clocksource/msm_timer.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a436dd4..c4cf8bc 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -12,3 +12,6 @@ config CLKSRC_MMIO
config ARM_SMP_TWD
bool
+
+config MSM_TIMER
+ bool
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 7b30585..ffb4186 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_CLKBLD_I8253) += i8253.o
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
obj-$(CONFIG_EXYNOS4_MCT) += exynos4_mct.o
+obj-$(CONFIG_MSM_TIMER) += msm_timer.o
diff --git a/drivers/clocksource/msm_timer.c b/drivers/clocksource/msm_timer.c
new file mode 100644
index 0000000..2ec66dd
--- /dev/null
+++ b/drivers/clocksource/msm_timer.c
@@ -0,0 +1,345 @@
+/*
+ *
+ * Copyright (C) 2007 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+
+#include <asm/hardware/gic.h>
+#include <mach/msm_iomap.h>
+#include <mach/cpu.h>
+
+#define TIMER_MATCH_VAL 0x0000
+#define TIMER_COUNT_VAL 0x0004
+#define TIMER_ENABLE 0x0008
+#define TIMER_ENABLE_CLR_ON_MATCH_EN 2
+#define TIMER_ENABLE_EN 1
+#define TIMER_CLEAR 0x000C
+#define DGT_CLK_CTL 0x0034
+enum {
+ DGT_CLK_CTL_DIV_1 = 0,
+ DGT_CLK_CTL_DIV_2 = 1,
+ DGT_CLK_CTL_DIV_3 = 2,
+ DGT_CLK_CTL_DIV_4 = 3,
+};
+#define CSR_PROTECTION 0x0020
+#define CSR_PROTECTION_EN 1
+
+#define GPT_HZ 32768
+
+enum timer_location {
+ LOCAL_TIMER = 0,
+ GLOBAL_TIMER = 1,
+};
+
+#define MSM_GLOBAL_TIMER MSM_CLOCK_DGT
+
+/* TODO: Remove these ifdefs */
+#if defined(CONFIG_ARCH_QSD8X50)
+#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
+#define MSM_DGT_SHIFT (0)
+#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \
+ defined(CONFIG_ARCH_MSM8960)
+#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
+#define MSM_DGT_SHIFT (0)
+#else
+#define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
+#define MSM_DGT_SHIFT (5)
+#endif
+
+struct msm_clock {
+ struct clock_event_device clockevent;
+ struct clocksource clocksource;
+ unsigned int irq;
+ void __iomem *regbase;
+ uint32_t freq;
+ uint32_t shift;
+ void __iomem *global_counter;
+ void __iomem *local_counter;
+};
+
+enum {
+ MSM_CLOCK_GPT,
+ MSM_CLOCK_DGT,
+ NR_TIMERS,
+};
+
+static struct msm_clock msm_clocks[];
+
+static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = dev_id;
+ if (evt->event_handler == NULL)
+ return IRQ_HANDLED;
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+}
+
+static cycle_t msm_read_timer_count(struct clocksource *cs)
+{
+ struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource);
+
+ return readl(clk->global_counter);
+}
+
+static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt)
+{
+ return container_of(evt, struct msm_clock, clockevent);
+}
+
+static int msm_timer_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ struct msm_clock *clock = clockevent_to_clock(evt);
+ uint32_t now = readl(clock->local_counter);
+ uint32_t alarm = now + (cycles << clock->shift);
+
+ writel(alarm, clock->regbase + TIMER_MATCH_VAL);
+ return 0;
+}
+
+static void msm_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct msm_clock *clock = clockevent_to_clock(evt);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_RESUME:
+ case CLOCK_EVT_MODE_PERIODIC:
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ disable_irq(evt->irq);
+ /* fall through */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ writel(0, clock->regbase + TIMER_ENABLE);
+ break;
+ }
+}
+
+static struct msm_clock msm_clocks[] = {
+ [MSM_CLOCK_GPT] = {
+ .clockevent = {
+ .name = "gp_timer",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .rating = 200,
+ .set_next_event = msm_timer_set_next_event,
+ .set_mode = msm_timer_set_mode,
+ },
+ .clocksource = {
+ .name = "gp_timer",
+ .rating = 200,
+ .read = msm_read_timer_count,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ },
+ .irq = INT_GP_TIMER_EXP,
+ .freq = GPT_HZ,
+ },
+ [MSM_CLOCK_DGT] = {
+ .clockevent = {
+ .name = "dg_timer",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32 + MSM_DGT_SHIFT,
+ .rating = 300,
+ .set_next_event = msm_timer_set_next_event,
+ .set_mode = msm_timer_set_mode,
+ },
+ .clocksource = {
+ .name = "dg_timer",
+ .rating = 300,
+ .read = msm_read_timer_count,
+ .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ },
+ .irq = INT_DEBUG_TIMER_EXP,
+ .freq = DGT_HZ >> MSM_DGT_SHIFT,
+ .shift = MSM_DGT_SHIFT,
+ }
+};
+
+static void __init msm_timer_primary_setup(void)
+{
+ int i;
+ int res;
+ int global_offset = 0;
+
+ if (cpu_is_msm7x01()) {
+ msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
+ msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+ } else if (cpu_is_msm7x30()) {
+ msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE + 0x04;
+ msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x24;
+ } else if (cpu_is_qsd8x50()) {
+ msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
+ msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+ } else if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+ msm_clocks[MSM_CLOCK_GPT].regbase = MSM_TMR_BASE + 0x04;
+ msm_clocks[MSM_CLOCK_DGT].regbase = MSM_TMR_BASE + 0x24;
+
+ /* Use CPU0's timer as the global timer. */
+ global_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
+ } else
+ BUG();
+
+#ifdef CONFIG_ARCH_MSM_SCORPIONMP
+ writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
+ struct msm_clock *clock = &msm_clocks[i];
+ struct clock_event_device *ce = &clock->clockevent;
+ struct clocksource *cs = &clock->clocksource;
+
+ clock->local_counter = clock->regbase + TIMER_COUNT_VAL;
+ clock->global_counter = clock->local_counter + global_offset;
+
+ writel(0, clock->regbase + TIMER_ENABLE);
+ writel(0, clock->regbase + TIMER_CLEAR);
+ writel(~0, clock->regbase + TIMER_MATCH_VAL);
+
+ ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift);
+ /* allow at least 10 seconds to notice that the timer wrapped */
+ ce->max_delta_ns =
+ clockevent_delta2ns(0xf0000000 >> clock->shift, ce);
+ /* 4 gets rounded down to 3 */
+ ce->min_delta_ns = clockevent_delta2ns(4, ce);
+ ce->cpumask = cpumask_of(0);
+
+ res = clocksource_register_hz(cs, clock->freq);
+ if (res)
+ printk(KERN_ERR "msm_timer_init: clocksource_register "
+ "failed for %s\n", cs->name);
+
+ ce->irq = gic_ppi_to_vppi(clock->irq);
+ res = request_irq(ce->irq, msm_timer_interrupt,
+ IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+ ce->name, ce);
+ if (res)
+ pr_err("msm_timer_init: request_irq failed for %s\n",
+ ce->name);
+
+ clockevents_register_device(ce);
+ }
+}
+
+#ifdef CONFIG_SMP
+static void __cpuinit msm_timer_secondary_setup(void *data)
+{
+ static bool local_timer_inited;
+ struct clock_event_device *evt = data;
+ struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
+ int res;
+
+ writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+
+ evt->irq = gic_ppi_to_vppi(clock->irq);
+ evt->name = "local_timer";
+ evt->features = CLOCK_EVT_FEAT_ONESHOT;
+ evt->rating = clock->clockevent.rating;
+ evt->set_mode = msm_timer_set_mode;
+ evt->set_next_event = msm_timer_set_next_event;
+ evt->shift = clock->clockevent.shift;
+ evt->mult = div_sc(clock->freq, NSEC_PER_SEC, evt->shift);
+ evt->max_delta_ns =
+ clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
+ evt->min_delta_ns = clockevent_delta2ns(4, evt);
+
+ if (!local_timer_inited) {
+ writel(0, clock->regbase + TIMER_ENABLE);
+ writel(0, clock->regbase + TIMER_CLEAR);
+ writel(~0, clock->regbase + TIMER_MATCH_VAL);
+
+ res = request_irq(evt->irq, msm_timer_interrupt,
+ IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+ clock->clockevent.name, evt);
+ if (res) {
+ pr_err("local_timer_setup: request_irq failed for %s\n",
+ clock->clockevent.name);
+ return;
+ }
+ local_timer_inited = true;
+ } else
+ enable_irq(evt->irq);
+
+ clockevents_register_device(evt);
+}
+
+static void __cpuinit msm_timer_secondary_teardown(void *data)
+{
+ struct clock_event_device *clk = data;
+ msm_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+}
+
+static int __cpuinit msm_timer_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ int cpu = (int)data;
+ struct clock_event_device *clk;
+
+ clk = &msm_clocks[MSM_GLOBAL_TIMER].clockevent;
+
+ switch (action) {
+ case CPU_STARTING:
+ case CPU_STARTING_FROZEN:
+ smp_call_function_single(cpu, msm_timer_secondary_setup,
+ clk, 1);
+ break;
+
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ smp_call_function_single(cpu, msm_timer_secondary_teardown,
+ clk, 1);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata msm_timer_cpu_nb = {
+ .notifier_call = msm_timer_cpu_notify,
+};
+#endif
+
+static int msm_timer_probe(struct platform_device *pdev)
+{
+ /* Immediately configure the timer on the boot CPU */
+ msm_timer_primary_setup();
+
+#ifdef CONFIG_SMP
+ register_cpu_notifier(&msm_timer_cpu_nb);
+#endif
+
+ return 0;
+}
+
+static int msm_timer_remove(struct platform_device *pdev)
+{
+ return -EBUSY;
+}
+
+static struct platform_driver msm_timer_driver = {
+ .probe = msm_timer_probe,
+ .remove = __devexit_p(msm_timer_remove),
+ .driver = {
+ .name = "msm_timer",
+ },
+};
+
+early_platform_init("localtimer", &msm_timer_driver);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 15/16] ARM: local timers: move msm to LOCAL_TIMER_DEVICES/MSM_TIMER
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (13 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 14/16] ARM: local timers: add msm_timer driver to driver/clocksource Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 16/16] ARM: local timers: remove local timer support from arch/arm Marc Zyngier
` (2 subsequent siblings)
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Convert the MSM platforms to use the new msm_timer driver.
Add the platform device and register it as early platform device.
In the process, timer.c is reduced to... erm... not a lot.
Cc: David Brown <davidb@codeaurora.org>
Cc: Daniel Walker <dwalker@fifo99.com>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-msm/Kconfig | 10 ++
arch/arm/mach-msm/timer.c | 290 ++-------------------------------------------
2 files changed, 18 insertions(+), 282 deletions(-)
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 1516896..65530ae 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -13,6 +13,8 @@ config ARCH_MSM7X00A
select CPU_V6
select MSM_PROC_COMM
select HAS_MSM_DEBUG_UART_PHYS
+ select LOCAL_TIMER_DEVICES
+ select MSM_TIMER
config ARCH_MSM7X30
bool "MSM7x30"
@@ -24,6 +26,8 @@ config ARCH_MSM7X30
select MSM_GPIOMUX
select MSM_PROC_COMM
select HAS_MSM_DEBUG_UART_PHYS
+ select LOCAL_TIMER_DEVICES
+ select MSM_TIMER
config ARCH_QSD8X50
bool "QSD8X50"
@@ -35,6 +39,8 @@ config ARCH_QSD8X50
select MSM_GPIOMUX
select MSM_PROC_COMM
select HAS_MSM_DEBUG_UART_PHYS
+ select LOCAL_TIMER_DEVICES
+ select MSM_TIMER
config ARCH_MSM8X60
bool "MSM8X60"
@@ -46,6 +52,8 @@ config ARCH_MSM8X60
select MSM_V2_TLMM
select MSM_GPIOMUX
select MSM_SCM if SMP
+ select LOCAL_TIMER_DEVICES
+ select MSM_TIMER
config ARCH_MSM8960
bool "MSM8960"
@@ -56,6 +64,8 @@ config ARCH_MSM8960
select MSM_V2_TLMM
select MSM_GPIOMUX
select MSM_SCM if SMP
+ select LOCAL_TIMER_DEVICES
+ select MSM_TIMER
endchoice
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index b2747cc..0ce27cf 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -13,299 +13,25 @@
*
*/
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/delay.h>
-#include <linux/io.h>
+#include <linux/platform_device.h>
#include <asm/mach/time.h>
-#include <asm/hardware/gic.h>
-#include <mach/msm_iomap.h>
-#include <mach/cpu.h>
-#define TIMER_MATCH_VAL 0x0000
-#define TIMER_COUNT_VAL 0x0004
-#define TIMER_ENABLE 0x0008
-#define TIMER_ENABLE_CLR_ON_MATCH_EN 2
-#define TIMER_ENABLE_EN 1
-#define TIMER_CLEAR 0x000C
-#define DGT_CLK_CTL 0x0034
-enum {
- DGT_CLK_CTL_DIV_1 = 0,
- DGT_CLK_CTL_DIV_2 = 1,
- DGT_CLK_CTL_DIV_3 = 2,
- DGT_CLK_CTL_DIV_4 = 3,
+static struct platform_device msm_timer_device = {
+ .name = "msm_timer",
+ .id = -1,
};
-#define CSR_PROTECTION 0x0020
-#define CSR_PROTECTION_EN 1
-#define GPT_HZ 32768
-
-enum timer_location {
- LOCAL_TIMER = 0,
- GLOBAL_TIMER = 1,
-};
-
-#define MSM_GLOBAL_TIMER MSM_CLOCK_DGT
-
-/* TODO: Remove these ifdefs */
-#if defined(CONFIG_ARCH_QSD8X50)
-#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
-#define MSM_DGT_SHIFT (0)
-#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \
- defined(CONFIG_ARCH_MSM8960)
-#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
-#define MSM_DGT_SHIFT (0)
-#else
-#define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
-#define MSM_DGT_SHIFT (5)
-#endif
-
-struct msm_clock {
- struct clock_event_device clockevent;
- struct clocksource clocksource;
- unsigned int irq;
- void __iomem *regbase;
- uint32_t freq;
- uint32_t shift;
- void __iomem *global_counter;
- void __iomem *local_counter;
-};
-
-enum {
- MSM_CLOCK_GPT,
- MSM_CLOCK_DGT,
- NR_TIMERS,
-};
-
-
-static struct msm_clock msm_clocks[];
-
-static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = dev_id;
- if (evt->event_handler == NULL)
- return IRQ_HANDLED;
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static cycle_t msm_read_timer_count(struct clocksource *cs)
-{
- struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource);
-
- return readl(clk->global_counter);
-}
-
-static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt)
-{
-#ifdef CONFIG_SMP
- int i;
- for (i = 0; i < NR_TIMERS; i++)
- if (evt == &(msm_clocks[i].clockevent))
- return &msm_clocks[i];
- return &msm_clocks[MSM_GLOBAL_TIMER];
-#else
- return container_of(evt, struct msm_clock, clockevent);
-#endif
-}
-
-static int msm_timer_set_next_event(unsigned long cycles,
- struct clock_event_device *evt)
-{
- struct msm_clock *clock = clockevent_to_clock(evt);
- uint32_t now = readl(clock->local_counter);
- uint32_t alarm = now + (cycles << clock->shift);
-
- writel(alarm, clock->regbase + TIMER_MATCH_VAL);
- return 0;
-}
-
-static void msm_timer_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- struct msm_clock *clock = clockevent_to_clock(evt);
-
- switch (mode) {
- case CLOCK_EVT_MODE_RESUME:
- case CLOCK_EVT_MODE_PERIODIC:
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
- break;
- case CLOCK_EVT_MODE_UNUSED:
- disable_irq(evt->irq);
- /* fall through */
- case CLOCK_EVT_MODE_SHUTDOWN:
- writel(0, clock->regbase + TIMER_ENABLE);
- break;
- }
-}
-
-static struct msm_clock msm_clocks[] = {
- [MSM_CLOCK_GPT] = {
- .clockevent = {
- .name = "gp_timer",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .shift = 32,
- .rating = 200,
- .set_next_event = msm_timer_set_next_event,
- .set_mode = msm_timer_set_mode,
- },
- .clocksource = {
- .name = "gp_timer",
- .rating = 200,
- .read = msm_read_timer_count,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- },
- .irq = INT_GP_TIMER_EXP,
- .freq = GPT_HZ,
- },
- [MSM_CLOCK_DGT] = {
- .clockevent = {
- .name = "dg_timer",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .shift = 32 + MSM_DGT_SHIFT,
- .rating = 300,
- .set_next_event = msm_timer_set_next_event,
- .set_mode = msm_timer_set_mode,
- },
- .clocksource = {
- .name = "dg_timer",
- .rating = 300,
- .read = msm_read_timer_count,
- .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- },
- .irq = INT_DEBUG_TIMER_EXP,
- .freq = DGT_HZ >> MSM_DGT_SHIFT,
- .shift = MSM_DGT_SHIFT,
- }
+static struct platform_device *msm_early_devices[] = {
+ &msm_timer_device,
};
static void __init msm_timer_init(void)
{
- int i;
- int res;
- int global_offset = 0;
-
- if (cpu_is_msm7x01()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
- } else if (cpu_is_msm7x30()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE + 0x04;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x24;
- } else if (cpu_is_qsd8x50()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
- } else if (cpu_is_msm8x60() || cpu_is_msm8960()) {
- msm_clocks[MSM_CLOCK_GPT].regbase = MSM_TMR_BASE + 0x04;
- msm_clocks[MSM_CLOCK_DGT].regbase = MSM_TMR_BASE + 0x24;
-
- /* Use CPU0's timer as the global timer. */
- global_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
- } else
- BUG();
-
-#ifdef CONFIG_ARCH_MSM_SCORPIONMP
- writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
-#endif
-
- for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
- struct msm_clock *clock = &msm_clocks[i];
- struct clock_event_device *ce = &clock->clockevent;
- struct clocksource *cs = &clock->clocksource;
-
- clock->local_counter = clock->regbase + TIMER_COUNT_VAL;
- clock->global_counter = clock->local_counter + global_offset;
-
- writel(0, clock->regbase + TIMER_ENABLE);
- writel(0, clock->regbase + TIMER_CLEAR);
- writel(~0, clock->regbase + TIMER_MATCH_VAL);
-
- ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift);
- /* allow at least 10 seconds to notice that the timer wrapped */
- ce->max_delta_ns =
- clockevent_delta2ns(0xf0000000 >> clock->shift, ce);
- /* 4 gets rounded down to 3 */
- ce->min_delta_ns = clockevent_delta2ns(4, ce);
- ce->cpumask = cpumask_of(0);
-
- res = clocksource_register_hz(cs, clock->freq);
- if (res)
- printk(KERN_ERR "msm_timer_init: clocksource_register "
- "failed for %s\n", cs->name);
-
- ce->irq = gic_ppi_to_vppi(clock->irq);
- res = request_irq(ce->irq, msm_timer_interrupt,
- IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
- ce->name, ce);
- if (res)
- pr_err("msm_timer_init: request_irq failed for %s\n",
- ce->name);
-
- clockevents_register_device(ce);
- }
-}
-
-#ifdef CONFIG_SMP
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
- static bool local_timer_inited;
- struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
- int res;
-
- /* Use existing clock_event for cpu 0 */
- if (!smp_processor_id())
- return 0;
-
- writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
-
- evt->irq = gic_ppi_to_vppi(clock->irq);
- evt->name = "local_timer";
- evt->features = CLOCK_EVT_FEAT_ONESHOT;
- evt->rating = clock->clockevent.rating;
- evt->set_mode = msm_timer_set_mode;
- evt->set_next_event = msm_timer_set_next_event;
- evt->shift = clock->clockevent.shift;
- evt->mult = div_sc(clock->freq, NSEC_PER_SEC, evt->shift);
- evt->max_delta_ns =
- clockevent_delta2ns(0xf0000000 >> clock->shift, evt);
- evt->min_delta_ns = clockevent_delta2ns(4, evt);
-
- if (!local_timer_inited) {
- writel(0, clock->regbase + TIMER_ENABLE);
- writel(0, clock->regbase + TIMER_CLEAR);
- writel(~0, clock->regbase + TIMER_MATCH_VAL);
-
- res = request_irq(evt->irq, msm_timer_interrupt,
- IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
- clock->clockevent.name, evt);
- if (res) {
- pr_err("local_timer_setup: request_irq failed for %s\n",
- clock->clockevent.name);
- return res;
- }
- local_timer_inited = true;
- } else
- enable_irq(evt->irq);
-
- clockevents_register_device(evt);
- return 0;
-}
-
-inline int local_timer_ack(void)
-{
- return 1;
+ early_platform_add_devices(msm_early_devices,
+ ARRAY_SIZE(msm_early_devices));
}
-#endif
-
struct sys_timer msm_timer = {
.init = msm_timer_init
};
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 16/16] ARM: local timers: remove local timer support from arch/arm
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (14 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 15/16] ARM: local timers: move msm to LOCAL_TIMER_DEVICES/MSM_TIMER Marc Zyngier
@ 2011-06-16 19:06 ` Marc Zyngier
2011-06-17 11:00 ` [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Linus Walleij
2011-06-17 15:07 ` Arnd Bergmann
17 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 19:06 UTC (permalink / raw)
To: linux-arm-kernel
Local timer support in arch/arm is now completely unused, as all
in-tree platforms are using LOCAL_TIMER_DEVICES.
It allows us to simplify the code, only preserving the broadcast timer.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/Kconfig | 10 -----
arch/arm/include/asm/localtimer.h | 48 -------------------------
arch/arm/kernel/smp.c | 70 +++++++-----------------------------
3 files changed, 14 insertions(+), 114 deletions(-)
delete mode 100644 arch/arm/include/asm/localtimer.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f3c1124..3f4eecd 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1406,16 +1406,6 @@ config HOTPLUG_CPU
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
-config LOCAL_TIMERS
- bool "Use local timer interrupts"
- depends on SMP && !LOCAL_TIMER_DEVICES
- default y
- help
- Enable support for local timers on SMP platforms, rather then the
- legacy IPI broadcast method. Local timers allows the system
- accounting to be spread across the timer interval, preventing a
- "thundering herd" at every timer tick.
-
config LOCAL_TIMER_DEVICES
bool
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
deleted file mode 100644
index 74af2cd..0000000
--- a/arch/arm/include/asm/localtimer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * arch/arm/include/asm/localtimer.h
- *
- * Copyright (C) 2004-2005 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.
- */
-#ifndef __ASM_ARM_LOCALTIMER_H
-#define __ASM_ARM_LOCALTIMER_H
-
-#include <linux/interrupt.h>
-
-struct clock_event_device;
-
-/*
- * Setup a per-cpu timer, whether it be a local timer or dummy broadcast
- */
-void percpu_timer_setup(void);
-
-/*
- * Per-cpu timer IRQ handler
- */
-irqreturn_t percpu_timer_handler(int irq, void *dev_id);
-
-#ifdef CONFIG_LOCAL_TIMERS
-
-/*
- * Platform provides this to acknowledge a local timer IRQ.
- * Returns true if the local timer IRQ is to be processed.
- */
-int local_timer_ack(void);
-
-/*
- * Setup a local timer interrupt for a CPU.
- */
-int local_timer_setup(struct clock_event_device *);
-
-#else
-
-static inline int local_timer_setup(struct clock_event_device *evt)
-{
- return -ENXIO;
-}
-#endif
-
-#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 35135b0..214dee3 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -38,7 +38,6 @@
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
-#include <asm/localtimer.h>
/*
* as from 2.5, kernels no longer have an init_tasks structure
@@ -154,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.
*/
@@ -181,11 +178,6 @@ int __cpu_disable(void)
migrate_irqs();
/*
- * Stop the local timer for this CPU.
- */
- percpu_timer_stop();
-
- /*
* Flush user cache and TLB mappings, and then remove this CPU
* from the vm mask set of all processes.
*/
@@ -270,6 +262,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
cpu_info->loops_per_jiffy = loops_per_jiffy;
}
+static void broadcast_timer_setup(void);
+
/*
* This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables.
@@ -309,9 +303,9 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
local_fiq_enable();
/*
- * Setup the percpu timer for this CPU.
+ * Setup the broadcast timer for this CPU.
*/
- percpu_timer_setup();
+ broadcast_timer_setup();
calibrate_delay();
@@ -364,10 +358,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
if (max_cpus > 1) {
/*
- * Enable the local timer or broadcast device for the
- * boot CPU, but only if we have more than one CPU.
+ * Enable the broadcast device for the boot CPU, but
+ * only if we have more than one CPU.
*/
- percpu_timer_setup();
+ broadcast_timer_setup();
/*
* Initialise the SCU if there are more than one CPU
@@ -430,7 +424,7 @@ 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);
@@ -442,20 +436,6 @@ static void ipi_timer(void)
irq_exit();
}
-#ifdef CONFIG_LOCAL_TIMERS
-irqreturn_t percpu_timer_handler(int irq, void *dev_id)
-{
- struct clock_event_device *evt = dev_id;
-
- if (local_timer_ack()) {
- evt->event_handler(evt);
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
-}
-#endif
-
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static void smp_timer_broadcast(const struct cpumask *mask)
{
@@ -470,8 +450,11 @@ static void broadcast_timer_set_mode(enum clock_event_mode mode,
{
}
-static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
+static void __cpuinit broadcast_timer_setup(void)
{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
+
evt->name = "dummy_timer";
evt->features = CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_PERIODIC |
@@ -479,37 +462,12 @@ static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
evt->rating = 400;
evt->mult = 1;
evt->set_mode = broadcast_timer_set_mode;
+ evt->cpumask = cpumask_of(cpu);
+ evt->broadcast = smp_timer_broadcast;
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);
/*
--
1.7.0.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [RFC PATCH 06/16] ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 ` [RFC PATCH 06/16] ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD Marc Zyngier
@ 2011-06-16 20:07 ` Stephen Warren
2011-06-16 20:22 ` Marc Zyngier
0 siblings, 1 reply; 46+ messages in thread
From: Stephen Warren @ 2011-06-16 20:07 UTC (permalink / raw)
To: linux-arm-kernel
Marc Zyngier wrote at Thursday, June 16, 2011 1:07 PM:
> Convert the Tegra platforms to use the new arm_smp_twd driver.
> Add the platform device and register it as early platform device.
...
> diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
> index 9035042..4e1ecd0 100644
> --- a/arch/arm/mach-tegra/timer.c
> +++ b/arch/arm/mach-tegra/timer.c
...
> +static struct platform_device *tegra_early_devices[] = {
> + &tegra_twd_device,
> +};
In the cases where the timer device is registered within a timer-specific
file, as here, and hence is likely the only device to be registered, does
it make sense to elide the platform_device array above, and ...
...
> @@ -241,6 +261,8 @@ static void __init tegra_init_timer(void)
> tegra_clockevent.cpumask = cpu_all_mask;
> tegra_clockevent.irq = tegra_timer_irq.irq;
> clockevents_register_device(&tegra_clockevent);
> + early_platform_add_devices(tegra_early_devices,
> + ARRAY_SIZE(tegra_early_devices));
> }
... and just refer to the single device directly here:
early_platform_add_devices(&tegra_twd_device, 1);
?
Or, is there likelihood that more devices would have to be added to that
array in the near future, or that such a change would make moving the
registration somewhere common later more complex?
--
nvpublic
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 06/16] ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 20:07 ` Stephen Warren
@ 2011-06-16 20:22 ` Marc Zyngier
0 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-16 20:22 UTC (permalink / raw)
To: linux-arm-kernel
On 16/06/11 21:07, Stephen Warren wrote:
> Marc Zyngier wrote at Thursday, June 16, 2011 1:07 PM:
>> Convert the Tegra platforms to use the new arm_smp_twd driver.
>> Add the platform device and register it as early platform device.
>
> ...
>> diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
>> index 9035042..4e1ecd0 100644
>> --- a/arch/arm/mach-tegra/timer.c
>> +++ b/arch/arm/mach-tegra/timer.c
>
> ...
>> +static struct platform_device *tegra_early_devices[] = {
>> + &tegra_twd_device,
>> +};
>
> In the cases where the timer device is registered within a timer-specific
> file, as here, and hence is likely the only device to be registered, does
> it make sense to elide the platform_device array above, and ...
>
> ...
>> @@ -241,6 +261,8 @@ static void __init tegra_init_timer(void)
>> tegra_clockevent.cpumask = cpu_all_mask;
>> tegra_clockevent.irq = tegra_timer_irq.irq;
>> clockevents_register_device(&tegra_clockevent);
>> + early_platform_add_devices(tegra_early_devices,
>> + ARRAY_SIZE(tegra_early_devices));
>> }
>
> ... and just refer to the single device directly here:
>
> early_platform_add_devices(&tegra_twd_device, 1);
>
> ?
Unfortunately not. From include/linux/platform_device.h:
void early_platform_add_devices(struct platform_device **devs, int num);
There is no equivalent of platform_device_register() for early devices,
so the array is mandatory.
Cheers,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 12/16] ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h
2011-06-16 19:06 ` [RFC PATCH 12/16] ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h Marc Zyngier
@ 2011-06-17 7:08 ` Wim Van Sebroeck
2011-06-17 8:04 ` Marc Zyngier
0 siblings, 1 reply; 46+ messages in thread
From: Wim Van Sebroeck @ 2011-06-17 7:08 UTC (permalink / raw)
To: linux-arm-kernel
Hi Marc,
> As the life expectancy of asm/smp_twd.h seems rather limited,
> move the few defines concerning mpcore_wdt to the driver itself.
>
> Change the dependency to ARM_SMP_TWD as well.
>
> Cc: Wim Van Sebroeck <wim@iguana.be>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
I presume you Will keep this patch together with the other patches?
Kind regards,
Wim.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 12/16] ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h
2011-06-17 7:08 ` Wim Van Sebroeck
@ 2011-06-17 8:04 ` Marc Zyngier
0 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-17 8:04 UTC (permalink / raw)
To: linux-arm-kernel
On 17/06/11 08:08, Wim Van Sebroeck wrote:
> Hi Marc,
>
>> As the life expectancy of asm/smp_twd.h seems rather limited,
>> move the few defines concerning mpcore_wdt to the driver itself.
>>
>> Change the dependency to ARM_SMP_TWD as well.
>>
>> Cc: Wim Van Sebroeck <wim@iguana.be>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>
> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
>
> I presume you Will keep this patch together with the other patches?
Most probably, though it is fairly independent from the whole series.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 07/16] ARM: local timers: move OMAP4 to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-16 19:06 ` [RFC PATCH 07/16] ARM: local timers: move OMAP4 " Marc Zyngier
@ 2011-06-17 8:16 ` Santosh Shilimkar
2011-06-17 8:39 ` Marc Zyngier
0 siblings, 1 reply; 46+ messages in thread
From: Santosh Shilimkar @ 2011-06-17 8:16 UTC (permalink / raw)
To: linux-arm-kernel
On 6/17/2011 12:36 AM, Marc Zyngier wrote:
> Convert the OMAP4 platforms to use the new arm_smp_twd driver.
> Add the platform device and register it as early platform device.
>
> Tested on a Pandaboard.
>
> Cc: Tony Lindgren<tony@atomide.com>
> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
> Signed-off-by: Marc Zyngier<marc.zyngier@arm.com>
> ---
> arch/arm/mach-omap2/Kconfig | 3 +-
> arch/arm/mach-omap2/Makefile | 1 -
> arch/arm/mach-omap2/timer-gp.c | 40 ++++++++++++++++++++++++++++++++------
> arch/arm/mach-omap2/timer-mpu.c | 40 ---------------------------------------
> 4 files changed, 35 insertions(+), 49 deletions(-)
> delete mode 100644 arch/arm/mach-omap2/timer-mpu.c
>
> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
> index 19d5891..805d7b9 100644
> --- a/arch/arm/mach-omap2/Kconfig
> +++ b/arch/arm/mach-omap2/Kconfig
> @@ -44,7 +44,8 @@ config ARCH_OMAP4
> depends on ARCH_OMAP2PLUS
> select CPU_V7
> select ARM_GIC
> - select LOCAL_TIMERS if SMP
> + select LOCAL_TIMER_DEVICES if SMP
> + select ARM_SMP_TWD
> select PL310_ERRATA_588369
> select PL310_ERRATA_727915
> select ARM_ERRATA_720789
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index b148077..f48c989 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..f2f0db6 100644
> --- a/arch/arm/mach-omap2/timer-gp.c
> +++ b/arch/arm/mach-omap2/timer-gp.c
> @@ -35,10 +35,10 @@
> #include<linux/irq.h>
> #include<linux/clocksource.h>
> #include<linux/clockchips.h>
> +#include<linux/platform_device.h>
>
> #include<asm/mach/time.h>
> #include<plat/dmtimer.h>
> -#include<asm/localtimer.h>
> #include<asm/sched_clock.h>
> #include<plat/common.h>
> #include<plat/omap_hwmod.h>
> @@ -247,18 +247,44 @@ static void __init omap2_gp_clocksource_init(void)
> }
> #endif
>
> +#ifdef CONFIG_ARM_SMP_TWD
> +static struct resource omap2_gp_twd_resources[] = {
> + {
> + .start = OMAP44XX_LOCAL_TWD_BASE,
> + .end = OMAP44XX_LOCAL_TWD_BASE + 0x10,
> + .flags = IORESOURCE_MEM,
> + },
> + {
> + .start = OMAP44XX_IRQ_LOCALTIMER,
> + .end = OMAP44XX_IRQ_LOCALTIMER,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +static struct platform_device omap2_gp_twd_device = {
> + .name = "arm_smp_twd",
> + .id = -1,
Why is the id set to -1 ?
> + .resource = omap2_gp_twd_resources,
> + .num_resources = ARRAY_SIZE(omap2_gp_twd_resources),
> +};
> +
> +static struct platform_device *omap2_gp_early_devices[] = {
> + &omap2_gp_twd_device,
> +};
> +#endif
> +
> static void __init omap2_gp_timer_init(void)
> {
> -#ifdef CONFIG_LOCAL_TIMERS
> - if (cpu_is_omap44xx()) {
> - twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
> - BUG_ON(!twd_base);
> - }
> -#endif
> omap_dm_timer_init();
>
> omap2_gp_clockevent_init();
> omap2_gp_clocksource_init();
> +#ifdef CONFIG_ARM_SMP_TWD
> + /* Local timers are not supprted on OMAP4430 ES1.0 */
> + if (omap_rev() != OMAP4430_REV_ES1_0)
> + early_platform_add_devices(omap2_gp_early_devices,
> + ARRAY_SIZE(omap2_gp_early_devices));
> +#endif
> }
>
These changes looks good.
> struct sys_timer omap_timer = {
> diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c
> deleted file mode 100644
> index 1fd5ca5..0000000
> --- a/arch/arm/mach-omap2/timer-mpu.c
> +++ /dev/null
> @@ -1,40 +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/smp.h>
> -#include<linux/clockchips.h>
> -#include<asm/irq.h>
> -#include<asm/smp_twd.h>
> -#include<asm/localtimer.h>
> -#include<asm/hardware/gic.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 = gic_ppi_to_vppi(OMAP44XX_IRQ_LOCALTIMER);
> - twd_timer_setup(evt);
> - return 0;
> -}
> -
And this one is even better. -40 lines from arch/arm/*omap*/
I am fine with all changes except the id value. With that
clarified,
Reviewedd-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Regards
Santosh
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 07/16] ARM: local timers: move OMAP4 to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-17 8:16 ` Santosh Shilimkar
@ 2011-06-17 8:39 ` Marc Zyngier
2011-06-17 8:42 ` Santosh Shilimkar
0 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-17 8:39 UTC (permalink / raw)
To: linux-arm-kernel
Hi Santosh,
On 17/06/11 09:16, Santosh Shilimkar wrote:
> On 6/17/2011 12:36 AM, Marc Zyngier wrote:
>> Convert the OMAP4 platforms to use the new arm_smp_twd driver.
>> Add the platform device and register it as early platform device.
>>
>> Tested on a Pandaboard.
>>
>> Cc: Tony Lindgren<tony@atomide.com>
>> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
>> Signed-off-by: Marc Zyngier<marc.zyngier@arm.com>
>> ---
>> arch/arm/mach-omap2/Kconfig | 3 +-
>> arch/arm/mach-omap2/Makefile | 1 -
>> arch/arm/mach-omap2/timer-gp.c | 40 ++++++++++++++++++++++++++++++++------
>> arch/arm/mach-omap2/timer-mpu.c | 40 ---------------------------------------
>> 4 files changed, 35 insertions(+), 49 deletions(-)
>> delete mode 100644 arch/arm/mach-omap2/timer-mpu.c
>>
>> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
>> index 19d5891..805d7b9 100644
>> --- a/arch/arm/mach-omap2/Kconfig
>> +++ b/arch/arm/mach-omap2/Kconfig
>> @@ -44,7 +44,8 @@ config ARCH_OMAP4
>> depends on ARCH_OMAP2PLUS
>> select CPU_V7
>> select ARM_GIC
>> - select LOCAL_TIMERS if SMP
>> + select LOCAL_TIMER_DEVICES if SMP
>> + select ARM_SMP_TWD
>> select PL310_ERRATA_588369
>> select PL310_ERRATA_727915
>> select ARM_ERRATA_720789
>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>> index b148077..f48c989 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..f2f0db6 100644
>> --- a/arch/arm/mach-omap2/timer-gp.c
>> +++ b/arch/arm/mach-omap2/timer-gp.c
>> @@ -35,10 +35,10 @@
>> #include<linux/irq.h>
>> #include<linux/clocksource.h>
>> #include<linux/clockchips.h>
>> +#include<linux/platform_device.h>
>>
>> #include<asm/mach/time.h>
>> #include<plat/dmtimer.h>
>> -#include<asm/localtimer.h>
>> #include<asm/sched_clock.h>
>> #include<plat/common.h>
>> #include<plat/omap_hwmod.h>
>> @@ -247,18 +247,44 @@ static void __init omap2_gp_clocksource_init(void)
>> }
>> #endif
>>
>> +#ifdef CONFIG_ARM_SMP_TWD
>> +static struct resource omap2_gp_twd_resources[] = {
>> + {
>> + .start = OMAP44XX_LOCAL_TWD_BASE,
>> + .end = OMAP44XX_LOCAL_TWD_BASE + 0x10,
>> + .flags = IORESOURCE_MEM,
>> + },
>> + {
>> + .start = OMAP44XX_IRQ_LOCALTIMER,
>> + .end = OMAP44XX_IRQ_LOCALTIMER,
>> + .flags = IORESOURCE_IRQ,
>> + },
>> +};
>> +
>> +static struct platform_device omap2_gp_twd_device = {
>> + .name = "arm_smp_twd",
>> + .id = -1,
> Why is the id set to -1 ?
This is the normal way of indicating that there is only one such device
in the system. The device ends being called "arm_smp_twd" instead of
"arm_smp_twd.0". See Documentation/driver-model/platform.txt for details.
>> + .resource = omap2_gp_twd_resources,
>> + .num_resources = ARRAY_SIZE(omap2_gp_twd_resources),
>> +};
>> +
>> +static struct platform_device *omap2_gp_early_devices[] = {
>> + &omap2_gp_twd_device,
>> +};
>> +#endif
>> +
>> static void __init omap2_gp_timer_init(void)
>> {
>> -#ifdef CONFIG_LOCAL_TIMERS
>> - if (cpu_is_omap44xx()) {
>> - twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
>> - BUG_ON(!twd_base);
>> - }
>> -#endif
>> omap_dm_timer_init();
>>
>> omap2_gp_clockevent_init();
>> omap2_gp_clocksource_init();
>> +#ifdef CONFIG_ARM_SMP_TWD
>> + /* Local timers are not supprted on OMAP4430 ES1.0 */
>> + if (omap_rev() != OMAP4430_REV_ES1_0)
>> + early_platform_add_devices(omap2_gp_early_devices,
>> + ARRAY_SIZE(omap2_gp_early_devices));
>> +#endif
>> }
>>
> These changes looks good.
>
>> struct sys_timer omap_timer = {
>> diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c
>> deleted file mode 100644
>> index 1fd5ca5..0000000
>> --- a/arch/arm/mach-omap2/timer-mpu.c
>> +++ /dev/null
>> @@ -1,40 +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/smp.h>
>> -#include<linux/clockchips.h>
>> -#include<asm/irq.h>
>> -#include<asm/smp_twd.h>
>> -#include<asm/localtimer.h>
>> -#include<asm/hardware/gic.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 = gic_ppi_to_vppi(OMAP44XX_IRQ_LOCALTIMER);
>> - twd_timer_setup(evt);
>> - return 0;
>> -}
>> -
> And this one is even better. -40 lines from arch/arm/*omap*/
>
> I am fine with all changes except the id value. With that
> clarified,
> Reviewedd-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Thanks for reviewing.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 07/16] ARM: local timers: move OMAP4 to LOCAL_TIMER_DEVICES/ARM_SMP_TWD
2011-06-17 8:39 ` Marc Zyngier
@ 2011-06-17 8:42 ` Santosh Shilimkar
0 siblings, 0 replies; 46+ messages in thread
From: Santosh Shilimkar @ 2011-06-17 8:42 UTC (permalink / raw)
To: linux-arm-kernel
On 6/17/2011 2:09 PM, Marc Zyngier wrote:
> Hi Santosh,
>
> On 17/06/11 09:16, Santosh Shilimkar wrote:
>> On 6/17/2011 12:36 AM, Marc Zyngier wrote:
>>> Convert the OMAP4 platforms to use the new arm_smp_twd driver.
>>> Add the platform device and register it as early platform device.
>>>
>>> Tested on a Pandaboard.
>>>
>>> Cc: Tony Lindgren<tony@atomide.com>
>>> Cc: Santosh Shilimkar<santosh.shilimkar@ti.com>
>>> Signed-off-by: Marc Zyngier<marc.zyngier@arm.com>
>>> ---
>>> arch/arm/mach-omap2/Kconfig | 3 +-
>>> arch/arm/mach-omap2/Makefile | 1 -
>>> arch/arm/mach-omap2/timer-gp.c | 40 ++++++++++++++++++++++++++++++++------
>>> arch/arm/mach-omap2/timer-mpu.c | 40 ---------------------------------------
>>> 4 files changed, 35 insertions(+), 49 deletions(-)
>>> delete mode 100644 arch/arm/mach-omap2/timer-mpu.c
>>>
>>> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
>>> index 19d5891..805d7b9 100644
>>> --- a/arch/arm/mach-omap2/Kconfig
>>> +++ b/arch/arm/mach-omap2/Kconfig
>>> @@ -44,7 +44,8 @@ config ARCH_OMAP4
>>> depends on ARCH_OMAP2PLUS
>>> select CPU_V7
>>> select ARM_GIC
>>> - select LOCAL_TIMERS if SMP
>>> + select LOCAL_TIMER_DEVICES if SMP
>>> + select ARM_SMP_TWD
>>> select PL310_ERRATA_588369
>>> select PL310_ERRATA_727915
>>> select ARM_ERRATA_720789
>>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>>> index b148077..f48c989 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..f2f0db6 100644
>>> --- a/arch/arm/mach-omap2/timer-gp.c
>>> +++ b/arch/arm/mach-omap2/timer-gp.c
>>> @@ -35,10 +35,10 @@
>>> #include<linux/irq.h>
>>> #include<linux/clocksource.h>
>>> #include<linux/clockchips.h>
>>> +#include<linux/platform_device.h>
>>>
>>> #include<asm/mach/time.h>
>>> #include<plat/dmtimer.h>
>>> -#include<asm/localtimer.h>
>>> #include<asm/sched_clock.h>
>>> #include<plat/common.h>
>>> #include<plat/omap_hwmod.h>
>>> @@ -247,18 +247,44 @@ static void __init omap2_gp_clocksource_init(void)
>>> }
>>> #endif
>>>
>>> +#ifdef CONFIG_ARM_SMP_TWD
>>> +static struct resource omap2_gp_twd_resources[] = {
>>> + {
>>> + .start = OMAP44XX_LOCAL_TWD_BASE,
>>> + .end = OMAP44XX_LOCAL_TWD_BASE + 0x10,
>>> + .flags = IORESOURCE_MEM,
>>> + },
>>> + {
>>> + .start = OMAP44XX_IRQ_LOCALTIMER,
>>> + .end = OMAP44XX_IRQ_LOCALTIMER,
>>> + .flags = IORESOURCE_IRQ,
>>> + },
>>> +};
>>> +
>>> +static struct platform_device omap2_gp_twd_device = {
>>> + .name = "arm_smp_twd",
>>> + .id = -1,
>> Why is the id set to -1 ?
>
> This is the normal way of indicating that there is only one such device
> in the system. The device ends being called "arm_smp_twd" instead of
> "arm_smp_twd.0". See Documentation/driver-model/platform.txt for details.
>
Thanks. It's clear to me.
Regards
Santosh
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (15 preceding siblings ...)
2011-06-16 19:06 ` [RFC PATCH 16/16] ARM: local timers: remove local timer support from arch/arm Marc Zyngier
@ 2011-06-17 11:00 ` Linus Walleij
2011-06-17 13:27 ` Marc Zyngier
2011-06-17 15:07 ` Arnd Bergmann
17 siblings, 1 reply; 46+ messages in thread
From: Linus Walleij @ 2011-06-17 11:00 UTC (permalink / raw)
To: linux-arm-kernel
Thanks for an excellent patch set Marc, take that as an Acked-by from me FWIW.
On Thu, Jun 16, 2011 at 9:06 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> Patches against next-20110615 + my earlier GIC-PPI series. Tested on
> VExpress, PB11MP, Pandaboard, Tegra Harmony and Exynos4 SMDK-v310.
This is making it hopeless for me to test on a plain -rc3 kernel,
do you have a public git branch I can just pull in to get all this?
I would like to test on U8500 and also rebase Colins TWD
CPUfreq patch on top of this so it can go in on top of the
consolidations.
Thanks,
Linus Walleij
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-17 11:00 ` [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Linus Walleij
@ 2011-06-17 13:27 ` Marc Zyngier
2011-06-20 8:21 ` Linus Walleij
0 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-17 13:27 UTC (permalink / raw)
To: linux-arm-kernel
Hi Linus,
On 17/06/11 12:00, Linus Walleij wrote:
> Thanks for an excellent patch set Marc, take that as an Acked-by from me FWIW.
>
> On Thu, Jun 16, 2011 at 9:06 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
>
>> Patches against next-20110615 + my earlier GIC-PPI series. Tested on
>> VExpress, PB11MP, Pandaboard, Tegra Harmony and Exynos4 SMDK-v310.
>
> This is making it hopeless for me to test on a plain -rc3 kernel,
> do you have a public git branch I can just pull in to get all this?
>
> I would like to test on U8500 and also rebase Colins TWD
> CPUfreq patch on top of this so it can go in on top of the
> consolidations.
I've created a new repository on git.kernel.org:
git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
and rebased my stuff on top of -rc3 in the "local_timer_devices" branch.
Tested on a PB11MP.
It may take some time for the mirrors to catch up...
Cheers,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 01/16] ARM: local timers: early device probing hooks
2011-06-16 19:06 ` [RFC PATCH 01/16] ARM: local timers: early device probing hooks Marc Zyngier
@ 2011-06-17 14:56 ` Arnd Bergmann
2011-06-17 15:13 ` Marc Zyngier
0 siblings, 1 reply; 46+ messages in thread
From: Arnd Bergmann @ 2011-06-17 14:56 UTC (permalink / raw)
To: linux-arm-kernel
On Thursday 16 June 2011, Marc Zyngier wrote:
> @@ -147,6 +148,19 @@ static int __init timer_init_syscore_ops(void)
>
> device_initcall(timer_init_syscore_ops);
>
> +void (* __initdata arm_late_time_init)(void);
> +
> +static void __init __arm_late_time_init(void)
> +{
> + if (arm_late_time_init)
> + arm_late_time_init();
> +
> +#ifdef CONFIG_LOCAL_TIMER_DEVICES
> + early_platform_driver_register_all("localtimer");
> + early_platform_driver_probe("localtimer", 1, 0);
> +#endif
> +}
> +
> void __init time_init(void)
> {
> system_timer = machine_desc->timer;
Instead of having two separate global pointers, should we make the ARM specific
callback a machine_desc callback?
Arnd
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
` (16 preceding siblings ...)
2011-06-17 11:00 ` [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Linus Walleij
@ 2011-06-17 15:07 ` Arnd Bergmann
2011-06-17 15:24 ` Marc Zyngier
` (2 more replies)
17 siblings, 3 replies; 46+ messages in thread
From: Arnd Bergmann @ 2011-06-17 15:07 UTC (permalink / raw)
To: linux-arm-kernel
On Thursday 16 June 2011, Marc Zyngier wrote:
> Patches against next-20110615 + my earlier GIC-PPI series. Tested on
> VExpress, PB11MP, Pandaboard, Tegra Harmony and Exynos4 SMDK-v310.
>
> Thomas and Arnd cc-ed on the whole series, as this could be
> consolidation material.
Very nice stuff. Should we take this all in one branch in the arm-soc tree,
pending Acks from the subarch maintainers?
We could also push it through the individual subarch branches, but my feeling
is that would be more work.
Arnd
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 10/16] ARM: local timers: add exynos_mct driver to driver/clocksource
2011-06-16 19:06 ` [RFC PATCH 10/16] ARM: local timers: add exynos_mct driver to driver/clocksource Marc Zyngier
@ 2011-06-17 15:09 ` Arnd Bergmann
2011-06-17 15:17 ` Marc Zyngier
0 siblings, 1 reply; 46+ messages in thread
From: Arnd Bergmann @ 2011-06-17 15:09 UTC (permalink / raw)
To: linux-arm-kernel
On Thursday 16 June 2011, Marc Zyngier wrote:
>
> Add a "new" driver to driver/clocksource to support the Samsung MCT
> hardware. This is basically the local timer part of
> arch/arm/mach-exynos4/mct.c, turned into a platform driver, and
> with a CPU notifier being used to start/stop timers on secondary
> cores.
>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
My feeling is that it would be nicer to do this as an atomic change together
with the removal of the existing code, rather than two patches.
Arnd
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 01/16] ARM: local timers: early device probing hooks
2011-06-17 14:56 ` Arnd Bergmann
@ 2011-06-17 15:13 ` Marc Zyngier
2011-06-17 16:10 ` Arnd Bergmann
0 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-17 15:13 UTC (permalink / raw)
To: linux-arm-kernel
On 17/06/11 15:56, Arnd Bergmann wrote:
> On Thursday 16 June 2011, Marc Zyngier wrote:
>> @@ -147,6 +148,19 @@ static int __init timer_init_syscore_ops(void)
>>
>> device_initcall(timer_init_syscore_ops);
>>
>> +void (* __initdata arm_late_time_init)(void);
>> +
>> +static void __init __arm_late_time_init(void)
>> +{
>> + if (arm_late_time_init)
>> + arm_late_time_init();
>> +
>> +#ifdef CONFIG_LOCAL_TIMER_DEVICES
>> + early_platform_driver_register_all("localtimer");
>> + early_platform_driver_probe("localtimer", 1, 0);
>> +#endif
>> +}
>> +
>> void __init time_init(void)
>> {
>> system_timer = machine_desc->timer;
>
> Instead of having two separate global pointers, should we make the ARM specific
> callback a machine_desc callback?
Probably not. I only see this arm_late_time_init pointer as a temporary
measure. The only user (shmobile) uses this hook to install its own
early timers, and there is a patch floating around to move that code to
time.c. Unless we have other uses for such a callback, of course.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 10/16] ARM: local timers: add exynos_mct driver to driver/clocksource
2011-06-17 15:09 ` Arnd Bergmann
@ 2011-06-17 15:17 ` Marc Zyngier
0 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-17 15:17 UTC (permalink / raw)
To: linux-arm-kernel
On 17/06/11 16:09, Arnd Bergmann wrote:
> On Thursday 16 June 2011, Marc Zyngier wrote:
>>
>> Add a "new" driver to driver/clocksource to support the Samsung MCT
>> hardware. This is basically the local timer part of
>> arch/arm/mach-exynos4/mct.c, turned into a platform driver, and
>> with a CPU notifier being used to start/stop timers on secondary
>> cores.
>>
>> Cc: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>
> My feeling is that it would be nicer to do this as an atomic change together
> with the removal of the existing code, rather than two patches.
Happy either way.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-17 15:07 ` Arnd Bergmann
@ 2011-06-17 15:24 ` Marc Zyngier
2011-06-17 17:25 ` Rob Herring
2011-06-20 8:23 ` Linus Walleij
2 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-17 15:24 UTC (permalink / raw)
To: linux-arm-kernel
On 17/06/11 16:07, Arnd Bergmann wrote:
> On Thursday 16 June 2011, Marc Zyngier wrote:
>> Patches against next-20110615 + my earlier GIC-PPI series. Tested on
>> VExpress, PB11MP, Pandaboard, Tegra Harmony and Exynos4 SMDK-v310.
>>
>> Thomas and Arnd cc-ed on the whole series, as this could be
>> consolidation material.
>
> Very nice stuff. Should we take this all in one branch in the arm-soc tree,
> pending Acks from the subarch maintainers?
>
> We could also push it through the individual subarch branches, but my feeling
> is that would be more work.
It seems far more work than it's worth, really. As long as the
individual maintainers are happy with it, the single branch option seem
nicer.
Cheers,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 01/16] ARM: local timers: early device probing hooks
2011-06-17 15:13 ` Marc Zyngier
@ 2011-06-17 16:10 ` Arnd Bergmann
0 siblings, 0 replies; 46+ messages in thread
From: Arnd Bergmann @ 2011-06-17 16:10 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 17 June 2011, Marc Zyngier wrote:
> >
> > Instead of having two separate global pointers, should we make the ARM specific
> > callback a machine_desc callback?
>
> Probably not. I only see this arm_late_time_init pointer as a temporary
> measure. The only user (shmobile) uses this hook to install its own
> early timers, and there is a patch floating around to move that code to
> time.c. Unless we have other uses for such a callback, of course.
Ok, fair enough.
Arnd
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-17 15:07 ` Arnd Bergmann
2011-06-17 15:24 ` Marc Zyngier
@ 2011-06-17 17:25 ` Rob Herring
2011-06-20 8:25 ` Marc Zyngier
2011-06-21 11:13 ` Marc Zyngier
2011-06-20 8:23 ` Linus Walleij
2 siblings, 2 replies; 46+ messages in thread
From: Rob Herring @ 2011-06-17 17:25 UTC (permalink / raw)
To: linux-arm-kernel
Arnd,
On 06/17/2011 10:07 AM, Arnd Bergmann wrote:
> On Thursday 16 June 2011, Marc Zyngier wrote:
>> Patches against next-20110615 + my earlier GIC-PPI series. Tested on
>> VExpress, PB11MP, Pandaboard, Tegra Harmony and Exynos4 SMDK-v310.
>>
>> Thomas and Arnd cc-ed on the whole series, as this could be
>> consolidation material.
>
> Very nice stuff. Should we take this all in one branch in the arm-soc tree,
> pending Acks from the subarch maintainers?
>
> We could also push it through the individual subarch branches, but my feeling
> is that would be more work.
>
If this is the direction to go, then there are a lot of other timers
that can be moved besides just local timers. But Russell didn't really
like the shmobile patches for early platform devices which this relies
on. So we should get agreement on the small bit of infrastructure needed
first, then start moving individual timers.
Also, device tree support for early platform devices would be useful for
this.
Rob
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-17 13:27 ` Marc Zyngier
@ 2011-06-20 8:21 ` Linus Walleij
0 siblings, 0 replies; 46+ messages in thread
From: Linus Walleij @ 2011-06-20 8:21 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Jun 17, 2011 at 3:27 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> [Me]
>> I would like to test on U8500 and also rebase Colins TWD
>> CPUfreq patch on top of this so it can go in on top of the
>> consolidations.
>
> I've created a new repository on git.kernel.org:
> git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
> and rebased my stuff on top of -rc3 in the "local_timer_devices" branch.
I pulled it into my tree and booted on U8500, and it works
like a charm. The GIC PPI stuff seems to be working too
atleast from looking in /proc/interrupts:
689: 933 0 GIC-PPI arm_smp_twd
692: 0 434 GIC-PPI arm_smp_twd
IPI0: 0 0 Timer broadcast interrupts
IPI1: 586 695 Rescheduling interrupts
IPI2: 0 0 Function call interrupts
IPI3: 4 5 Single function call interrupts
IPI4: 0 0 CPU stop interrupts
So:
Tested-by: Linus Walleij <linus.walleij@linaro.org>
For the general stuff and the Ux500 patch.
Thanks,
Linus Walleij
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-17 15:07 ` Arnd Bergmann
2011-06-17 15:24 ` Marc Zyngier
2011-06-17 17:25 ` Rob Herring
@ 2011-06-20 8:23 ` Linus Walleij
2 siblings, 0 replies; 46+ messages in thread
From: Linus Walleij @ 2011-06-20 8:23 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Jun 17, 2011 at 5:07 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> Very nice stuff. Should we take this all in one branch in the arm-soc tree,
> pending Acks from the subarch maintainers?
Yes please. If Marc feels the patch set is ready I suggest you
bring it into arm-soc so it gets some testing in linux-next and
any conflicts smoked out.
> We could also push it through the individual subarch branches, but my feeling
> is that would be more work.
I agree.
Thanks,
Linus Walleij
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-17 17:25 ` Rob Herring
@ 2011-06-20 8:25 ` Marc Zyngier
2011-06-20 8:32 ` Russell King - ARM Linux
2011-06-21 11:13 ` Marc Zyngier
1 sibling, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-20 8:25 UTC (permalink / raw)
To: linux-arm-kernel
On 17/06/11 18:25, Rob Herring wrote:
> Arnd,
>
> On 06/17/2011 10:07 AM, Arnd Bergmann wrote:
>> On Thursday 16 June 2011, Marc Zyngier wrote:
>>> Patches against next-20110615 + my earlier GIC-PPI series. Tested on
>>> VExpress, PB11MP, Pandaboard, Tegra Harmony and Exynos4 SMDK-v310.
>>>
>>> Thomas and Arnd cc-ed on the whole series, as this could be
>>> consolidation material.
>>
>> Very nice stuff. Should we take this all in one branch in the arm-soc tree,
>> pending Acks from the subarch maintainers?
>>
>> We could also push it through the individual subarch branches, but my feeling
>> is that would be more work.
>>
>
> If this is the direction to go, then there are a lot of other timers
> that can be moved besides just local timers. But Russell didn't really
> like the shmobile patches for early platform devices which this relies
> on. So we should get agreement on the small bit of infrastructure needed
> first, then start moving individual timers.
I'm open to suggestions. Should the early platform infrastructure be
flagged as unsuitable, I'd be happy to switch to something else, as long
as it is minimal, and does not create another ARM-specific API (been
there, done that...).
> Also, device tree support for early platform devices would be useful for
> this.
Indeed.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-20 8:25 ` Marc Zyngier
@ 2011-06-20 8:32 ` Russell King - ARM Linux
2011-06-22 0:54 ` Magnus Damm
2011-06-26 7:00 ` Grant Likely
0 siblings, 2 replies; 46+ messages in thread
From: Russell King - ARM Linux @ 2011-06-20 8:32 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jun 20, 2011 at 09:25:30AM +0100, Marc Zyngier wrote:
> On 17/06/11 18:25, Rob Herring wrote:
> > If this is the direction to go, then there are a lot of other timers
> > that can be moved besides just local timers. But Russell didn't really
> > like the shmobile patches for early platform devices which this relies
> > on. So we should get agreement on the small bit of infrastructure needed
> > first, then start moving individual timers.
>
> I'm open to suggestions. Should the early platform infrastructure be
> flagged as unsuitable, I'd be happy to switch to something else, as long
> as it is minimal, and does not create another ARM-specific API (been
> there, done that...).
I am most certainly not a fan of the early platform device stuff as I've
said in the past.
It looks to me like:
1. it's overcomplex and fragile.
2. it abuses the early command line system.
3. it abuses platform devices etc.
4. it requires more initialization calls.
Lastly, and probably more importantly for the direction we're going, I
can't see how it would hook into DT other than using the DT provided
command line, which also appears to be an abuse there too.
Surely there's a better solution.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-17 17:25 ` Rob Herring
2011-06-20 8:25 ` Marc Zyngier
@ 2011-06-21 11:13 ` Marc Zyngier
2011-06-21 12:51 ` Rob Herring
1 sibling, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-21 11:13 UTC (permalink / raw)
To: linux-arm-kernel
On 17/06/11 18:25, Rob Herring wrote:
> Also, device tree support for early platform devices would be useful for
> this.
What about the attached patch? I've used it to boot a VExpress board
with the following DT snippet (and the corresponding support in the
amp_smp_twd driver):
localtimer at 2c000600 {
device_type = "localtimer";
compatible = "arm,smp-twd";
reg = <0x2c000600 0x1000>;
interrupts = <29>;
};
Cheers,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-21 11:13 ` Marc Zyngier
@ 2011-06-21 12:51 ` Rob Herring
2011-06-21 13:02 ` Marc Zyngier
0 siblings, 1 reply; 46+ messages in thread
From: Rob Herring @ 2011-06-21 12:51 UTC (permalink / raw)
To: linux-arm-kernel
Marc,
On 06/21/2011 06:13 AM, Marc Zyngier wrote:
> On 17/06/11 18:25, Rob Herring wrote:
>> Also, device tree support for early platform devices would be useful for
>> this.
>
> What about the attached patch? I've used it to boot a VExpress board
> with the following DT snippet (and the corresponding support in the
> amp_smp_twd driver):
>
> localtimer at 2c000600 {
> device_type = "localtimer";
My understanding is device_type is only supposed to be used for devices
with real OpenFirmware. You could just add localtimer or timer as a 2nd
compatible string. I think localtimer is a bit of a Linux name, so just
timer may be better.
Rob
> compatible = "arm,smp-twd";
> reg = <0x2c000600 0x1000>;
> interrupts = <29>;
> };
>
> Cheers,
>
> M.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-21 12:51 ` Rob Herring
@ 2011-06-21 13:02 ` Marc Zyngier
2011-06-21 13:18 ` Rob Herring
0 siblings, 1 reply; 46+ messages in thread
From: Marc Zyngier @ 2011-06-21 13:02 UTC (permalink / raw)
To: linux-arm-kernel
On 21/06/11 13:51, Rob Herring wrote:
> Marc,
>
> On 06/21/2011 06:13 AM, Marc Zyngier wrote:
>> On 17/06/11 18:25, Rob Herring wrote:
>>> Also, device tree support for early platform devices would be useful for
>>> this.
>>
>> What about the attached patch? I've used it to boot a VExpress board
>> with the following DT snippet (and the corresponding support in the
>> amp_smp_twd driver):
>>
>> localtimer at 2c000600 {
>> device_type = "localtimer";
>
> My understanding is device_type is only supposed to be used for devices
> with real OpenFirmware. You could just add localtimer or timer as a 2nd
> compatible string. I think localtimer is a bit of a Linux name, so just
> timer may be better.
Using "compatible" would not work. You'd have to add the same compatible
string to all drivers, and get drivers probing the wrong device. Any
other property we could use instead?
As for the "localtimer" string, this is to differentiate the per-cpu
timers versus the global timers, and they may need to be probed in a
specific order (global first, and then local).
The reason for this is that TWD needs to be calibrated, hence the need
for a global timer running. Colin's patch could help getting rid of this
restriction though.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-21 13:02 ` Marc Zyngier
@ 2011-06-21 13:18 ` Rob Herring
2011-06-21 13:46 ` Marc Zyngier
0 siblings, 1 reply; 46+ messages in thread
From: Rob Herring @ 2011-06-21 13:18 UTC (permalink / raw)
To: linux-arm-kernel
On 06/21/2011 08:02 AM, Marc Zyngier wrote:
> On 21/06/11 13:51, Rob Herring wrote:
>> Marc,
>>
>> On 06/21/2011 06:13 AM, Marc Zyngier wrote:
>>> On 17/06/11 18:25, Rob Herring wrote:
>>>> Also, device tree support for early platform devices would be useful for
>>>> this.
>>>
>>> What about the attached patch? I've used it to boot a VExpress board
>>> with the following DT snippet (and the corresponding support in the
>>> amp_smp_twd driver):
>>>
>>> localtimer at 2c000600 {
>>> device_type = "localtimer";
>>
>> My understanding is device_type is only supposed to be used for devices
>> with real OpenFirmware. You could just add localtimer or timer as a 2nd
>> compatible string. I think localtimer is a bit of a Linux name, so just
>> timer may be better.
>
> Using "compatible" would not work. You'd have to add the same compatible
> string to all drivers, and get drivers probing the wrong device. Any
> other property we could use instead?
No, I'm saying you have a compatible property like this:
compatible = "arm,smp-twd", "timer";
You create the early platform device(s) based on matches with "timer",
but match the driver based on "arm,smp-twd".
>
> As for the "localtimer" string, this is to differentiate the per-cpu
> timers versus the global timers, and they may need to be probed in a
> specific order (global first, and then local).
>
> The reason for this is that TWD needs to be calibrated, hence the need
> for a global timer running. Colin's patch could help getting rid of this
> restriction though.
Yes, my original patch adding clock api allowed just that.
Rob
>
> M.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-21 13:18 ` Rob Herring
@ 2011-06-21 13:46 ` Marc Zyngier
0 siblings, 0 replies; 46+ messages in thread
From: Marc Zyngier @ 2011-06-21 13:46 UTC (permalink / raw)
To: linux-arm-kernel
On 21/06/11 14:18, Rob Herring wrote:
> On 06/21/2011 08:02 AM, Marc Zyngier wrote:
>> On 21/06/11 13:51, Rob Herring wrote:
>>> Marc,
>>>
>>> On 06/21/2011 06:13 AM, Marc Zyngier wrote:
>>>> On 17/06/11 18:25, Rob Herring wrote:
>>>>> Also, device tree support for early platform devices would be useful for
>>>>> this.
>>>>
>>>> What about the attached patch? I've used it to boot a VExpress board
>>>> with the following DT snippet (and the corresponding support in the
>>>> amp_smp_twd driver):
>>>>
>>>> localtimer at 2c000600 {
>>>> device_type = "localtimer";
>>>
>>> My understanding is device_type is only supposed to be used for devices
>>> with real OpenFirmware. You could just add localtimer or timer as a 2nd
>>> compatible string. I think localtimer is a bit of a Linux name, so just
>>> timer may be better.
>>
>> Using "compatible" would not work. You'd have to add the same compatible
>> string to all drivers, and get drivers probing the wrong device. Any
>> other property we could use instead?
>
> No, I'm saying you have a compatible property like this:
>
> compatible = "arm,smp-twd", "timer";
>
> You create the early platform device(s) based on matches with "timer",
> but match the driver based on "arm,smp-twd".
Right. What about the attached patch? Test-booted on the same VE with
the above "compatible" property.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-20 8:32 ` Russell King - ARM Linux
@ 2011-06-22 0:54 ` Magnus Damm
2011-06-26 7:00 ` Grant Likely
1 sibling, 0 replies; 46+ messages in thread
From: Magnus Damm @ 2011-06-22 0:54 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jun 20, 2011 at 5:32 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Jun 20, 2011 at 09:25:30AM +0100, Marc Zyngier wrote:
>> On 17/06/11 18:25, Rob Herring wrote:
>> > If this is the direction to go, then there are a lot of other timers
>> > that can be moved besides just local timers. But Russell didn't really
>> > like the shmobile patches for early platform devices which this relies
>> > on. So we should get agreement on the small bit of infrastructure needed
>> > first, then start moving individual timers.
>>
>> I'm open to suggestions. Should the early platform infrastructure be
>> flagged as unsuitable, I'd be happy to switch to something else, as long
>> as it is minimal, and does not create another ARM-specific API (been
>> there, done that...).
>
> I am most certainly not a fan of the early platform device stuff as I've
> said in the past.
>
> It looks to me like:
>
> 1. it's overcomplex and fragile.
> 2. it abuses the early command line system.
> 3. it abuses platform devices etc.
> 4. it requires more initialization calls.
>
> Lastly, and probably more importantly for the direction we're going, I
> can't see how it would hook into DT other than using the DT provided
> command line, which also appears to be an abuse there too.
>
> Surely there's a better solution.
Which is?
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-20 8:32 ` Russell King - ARM Linux
2011-06-22 0:54 ` Magnus Damm
@ 2011-06-26 7:00 ` Grant Likely
2011-06-27 4:53 ` Magnus Damm
1 sibling, 1 reply; 46+ messages in thread
From: Grant Likely @ 2011-06-26 7:00 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jun 20, 2011 at 2:32 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Jun 20, 2011 at 09:25:30AM +0100, Marc Zyngier wrote:
>> On 17/06/11 18:25, Rob Herring wrote:
>> > If this is the direction to go, then there are a lot of other timers
>> > that can be moved besides just local timers. But Russell didn't really
>> > like the shmobile patches for early platform devices which this relies
>> > on. So we should get agreement on the small bit of infrastructure needed
>> > first, then start moving individual timers.
>>
>> I'm open to suggestions. Should the early platform infrastructure be
>> flagged as unsuitable, I'd be happy to switch to something else, as long
>> as it is minimal, and does not create another ARM-specific API (been
>> there, done that...).
>
> I am most certainly not a fan of the early platform device stuff as I've
> said in the past.
>
> It looks to me like:
>
> 1. it's overcomplex and fragile.
> 2. it abuses the early command line system.
> 3. it abuses platform devices etc.
> 4. it requires more initialization calls.
>
> Lastly, and probably more importantly for the direction we're going, I
> can't see how it would hook into DT other than using the DT provided
> command line, which also appears to be an abuse there too.
I'm going to second that opinion. I just looked through the early
platform stuff, and I'm not thrilled with the model.
Setting up timers does not need to plug into the device model. Unless
I'm completely reading the ARM code wrong, these timers are pretty
fundamental to the operating system, and thus aren't really like other
devices. I don't see any problem with individual timer init functions
populated in machine_desc assuming that multiple boards with the same
SoC will not require different timer initialization.
g.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource
2011-06-26 7:00 ` Grant Likely
@ 2011-06-27 4:53 ` Magnus Damm
0 siblings, 0 replies; 46+ messages in thread
From: Magnus Damm @ 2011-06-27 4:53 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Jun 26, 2011 at 4:00 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Mon, Jun 20, 2011 at 2:32 AM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Mon, Jun 20, 2011 at 09:25:30AM +0100, Marc Zyngier wrote:
>>> On 17/06/11 18:25, Rob Herring wrote:
>>> > If this is the direction to go, then there are a lot of other timers
>>> > that can be moved besides just local timers. But Russell didn't really
>>> > like the shmobile patches for early platform devices which this relies
>>> > on. So we should get agreement on the small bit of infrastructure needed
>>> > first, then start moving individual timers.
>>>
>>> I'm open to suggestions. Should the early platform infrastructure be
>>> flagged as unsuitable, I'd be happy to switch to something else, as long
>>> as it is minimal, and does not create another ARM-specific API (been
>>> there, done that...).
>>
>> I am most certainly not a fan of the early platform device stuff as I've
>> said in the past.
>>
>> It looks to me like:
>>
>> 1. it's overcomplex and fragile.
>> 2. it abuses the early command line system.
>> 3. it abuses platform devices etc.
>> 4. it requires more initialization calls.
>>
>> Lastly, and probably more importantly for the direction we're going, I
>> can't see how it would hook into DT other than using the DT provided
>> command line, which also appears to be an abuse there too.
>
> I'm going to second that opinion. ?I just looked through the early
> platform stuff, and I'm not thrilled with the model.
>
> Setting up timers does not need to plug into the device model. ?Unless
> I'm completely reading the ARM code wrong, these timers are pretty
> fundamental to the operating system, and thus aren't really like other
> devices. ?I don't see any problem with individual timer init functions
> populated in machine_desc assuming that multiple boards with the same
> SoC will not require different timer initialization.
Perhaps that's the case for some ARM platforms, but at least the
sh7372 ARM platform is using general purpose timers as system timers.
We have to since there are not other timers dedicated as system
timers. Same for the SH architecture. I suspect that's the case for
most other SoCs too actually, with the exception of platforms making
use of ARM IP such as the TWD found in for instance Cortex-A9.
On most SoCs there are a wide range of SoC-specific timer channels to
choose from. We want to reuse the same driver for multiple SoCs so
separating the device configuration parameters (such as I/O base and
IRQ) from the actual driver is desired.
The reason why we want to select timer channel is that some timer
channels are tied to GPIO pins, and those GPIO pins may be used to
driver board-specific hardware. So timer channel #2 may be great as
clock source for board X but on board Y channel #2 is used to drive
the PWM for the LCD backlight.
I fail to see what is wrong with separating device configuration from
the actual driver.
Thanks,
/ magnus
^ permalink raw reply [flat|nested] 46+ messages in thread
end of thread, other threads:[~2011-06-27 4:53 UTC | newest]
Thread overview: 46+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-16 19:06 [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 01/16] ARM: local timers: early device probing hooks Marc Zyngier
2011-06-17 14:56 ` Arnd Bergmann
2011-06-17 15:13 ` Marc Zyngier
2011-06-17 16:10 ` Arnd Bergmann
2011-06-16 19:06 ` [RFC PATCH 02/16] ARM: local timers: add arm_smp_twd driver to driver/clocksource Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 03/16] ARM: local timers: move realview to LOCAL_TIMER_DEVICES/ARM_SMP_TWD Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 04/16] ARM: local timers: move vexpress " Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 05/16] ARM: local timers: remove localtimer.c from plat-versatile Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 06/16] ARM: local timers: move Tegra to LOCAL_TIMER_DEVICES/ARM_SMP_TWD Marc Zyngier
2011-06-16 20:07 ` Stephen Warren
2011-06-16 20:22 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 07/16] ARM: local timers: move OMAP4 " Marc Zyngier
2011-06-17 8:16 ` Santosh Shilimkar
2011-06-17 8:39 ` Marc Zyngier
2011-06-17 8:42 ` Santosh Shilimkar
2011-06-16 19:06 ` [RFC PATCH 08/16] ARM: local timers: move shmobile " Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 09/16] ARM: local timers: move ux500 " Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 10/16] ARM: local timers: add exynos_mct driver to driver/clocksource Marc Zyngier
2011-06-17 15:09 ` Arnd Bergmann
2011-06-17 15:17 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 11/16] ARM: local timers: move exynos4 to LOCAL_TIMER_DEVICES/EXYNOS_MCT/ARM_SMP_TWD Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 12/16] ARM: watchdog: make mpcore_wdt independant from asm/smp_twd.h Marc Zyngier
2011-06-17 7:08 ` Wim Van Sebroeck
2011-06-17 8:04 ` Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 13/16] ARM: local timers: remove smp_twd from arch/arm Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 14/16] ARM: local timers: add msm_timer driver to driver/clocksource Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 15/16] ARM: local timers: move msm to LOCAL_TIMER_DEVICES/MSM_TIMER Marc Zyngier
2011-06-16 19:06 ` [RFC PATCH 16/16] ARM: local timers: remove local timer support from arch/arm Marc Zyngier
2011-06-17 11:00 ` [RFC PATCH 00/16] Consolidation: move SMP local timers to driver/clocksource Linus Walleij
2011-06-17 13:27 ` Marc Zyngier
2011-06-20 8:21 ` Linus Walleij
2011-06-17 15:07 ` Arnd Bergmann
2011-06-17 15:24 ` Marc Zyngier
2011-06-17 17:25 ` Rob Herring
2011-06-20 8:25 ` Marc Zyngier
2011-06-20 8:32 ` Russell King - ARM Linux
2011-06-22 0:54 ` Magnus Damm
2011-06-26 7:00 ` Grant Likely
2011-06-27 4:53 ` Magnus Damm
2011-06-21 11:13 ` Marc Zyngier
2011-06-21 12:51 ` Rob Herring
2011-06-21 13:02 ` Marc Zyngier
2011-06-21 13:18 ` Rob Herring
2011-06-21 13:46 ` Marc Zyngier
2011-06-20 8:23 ` Linus Walleij
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).