ARM: smp_twd: Divorce smp_twd from local timer API
authorStephen Boyd <sboyd@codeaurora.org>
Sat, 16 Feb 2013 00:02:20 +0000 (16:02 -0800)
committerStephen Boyd <sboyd@codeaurora.org>
Tue, 25 Jun 2013 00:45:58 +0000 (17:45 -0700)
Separate the smp_twd timers from the local timer API. This will
allow us to remove ARM local timer support in the near future and
gets us closer to moving this driver to drivers/clocksource.

Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
arch/arm/Kconfig
arch/arm/kernel/smp_twd.c
arch/arm/mach-highbank/Kconfig
arch/arm/mach-imx/Kconfig
arch/arm/mach-omap2/Kconfig
arch/arm/mach-realview/Kconfig
arch/arm/mach-spear/Kconfig
arch/arm/mach-tegra/Kconfig
arch/arm/mach-ux500/Kconfig
arch/arm/mach-vexpress/Kconfig
arch/arm/mach-zynq/Kconfig

index 53d3a356f61f877acebc12a22fc7b3d884a7cfc8..374a1d8900ecf39b42adde2b212e4101c85a6778 100644 (file)
@@ -638,7 +638,7 @@ config ARCH_SHMOBILE
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_CLK
        select HAVE_MACH_CLKDEV
        select HAVE_SMP
index 90525d9d290b9c25e3b40d5bdeedfc6a6f524cf6..aac1495b44dec142de71dff6c58509c63ce2570d 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -24,7 +25,6 @@
 
 #include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
-#include <asm/localtimer.h>
 
 /* set up by the platform code */
 static void __iomem *twd_base;
@@ -33,7 +33,7 @@ static struct clk *twd_clk;
 static unsigned long twd_timer_rate;
 static DEFINE_PER_CPU(bool, percpu_setup_called);
 
-static struct clock_event_device __percpu **twd_evt;
+static struct clock_event_device __percpu *twd_evt;
 static int twd_ppi;
 
 static void twd_set_mode(enum clock_event_mode mode,
@@ -90,8 +90,10 @@ static int twd_timer_ack(void)
        return 0;
 }
 
-static void twd_timer_stop(struct clock_event_device *clk)
+static void twd_timer_stop(void)
 {
+       struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
+
        twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
        disable_percpu_irq(clk->irq);
 }
@@ -106,7 +108,7 @@ static void twd_update_frequency(void *new_rate)
 {
        twd_timer_rate = *((unsigned long *) new_rate);
 
-       clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+       clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
 }
 
 static int twd_rate_change(struct notifier_block *nb,
@@ -132,7 +134,7 @@ static struct notifier_block twd_clk_nb = {
 
 static int twd_clk_init(void)
 {
-       if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+       if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
                return clk_notifier_register(twd_clk, &twd_clk_nb);
 
        return 0;
@@ -151,7 +153,7 @@ static void twd_update_frequency(void *data)
 {
        twd_timer_rate = clk_get_rate(twd_clk);
 
-       clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+       clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
 }
 
 static int twd_cpufreq_transition(struct notifier_block *nb,
@@ -177,7 +179,7 @@ static struct notifier_block twd_cpufreq_nb = {
 
 static int twd_cpufreq_init(void)
 {
-       if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+       if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
                return cpufreq_register_notifier(&twd_cpufreq_nb,
                        CPUFREQ_TRANSITION_NOTIFIER);
 
@@ -228,7 +230,7 @@ static void __cpuinit twd_calibrate_rate(void)
 
 static irqreturn_t twd_handler(int irq, void *dev_id)
 {
-       struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+       struct clock_event_device *evt = dev_id;
 
        if (twd_timer_ack()) {
                evt->event_handler(evt);
@@ -265,9 +267,9 @@ static void twd_get_clock(struct device_node *np)
 /*
  * Setup the local clock events for a CPU.
  */
-static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
+static void __cpuinit twd_timer_setup(void)
 {
-       struct clock_event_device **this_cpu_clk;
+       struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
        int cpu = smp_processor_id();
 
        /*
@@ -276,9 +278,9 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
         */
        if (per_cpu(percpu_setup_called, cpu)) {
                __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-               clockevents_register_device(*__this_cpu_ptr(twd_evt));
+               clockevents_register_device(clk);
                enable_percpu_irq(clk->irq, 0);
-               return 0;
+               return;
        }
        per_cpu(percpu_setup_called, cpu) = true;
 
@@ -297,27 +299,37 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
        clk->set_mode = twd_set_mode;
        clk->set_next_event = twd_set_next_event;
        clk->irq = twd_ppi;
-
-       this_cpu_clk = __this_cpu_ptr(twd_evt);
-       *this_cpu_clk = clk;
+       clk->cpumask = cpumask_of(cpu);
 
        clockevents_config_and_register(clk, twd_timer_rate,
                                        0xf, 0xffffffff);
        enable_percpu_irq(clk->irq, 0);
+}
 
-       return 0;
+static int __cpuinit twd_timer_cpu_notify(struct notifier_block *self,
+                                          unsigned long action, void *hcpu)
+{
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               twd_timer_setup();
+               break;
+       case CPU_DYING:
+               twd_timer_stop();
+               break;
+       }
+
+       return NOTIFY_OK;
 }
 
-static struct local_timer_ops twd_lt_ops __cpuinitdata = {
-       .setup  = twd_timer_setup,
-       .stop   = twd_timer_stop,
+static struct notifier_block twd_timer_cpu_nb __cpuinitdata = {
+       .notifier_call = twd_timer_cpu_notify,
 };
 
 static int __init twd_local_timer_common_register(struct device_node *np)
 {
        int err;
 
-       twd_evt = alloc_percpu(struct clock_event_device *);
+       twd_evt = alloc_percpu(struct clock_event_device);
        if (!twd_evt) {
                err = -ENOMEM;
                goto out_free;
@@ -329,12 +341,22 @@ static int __init twd_local_timer_common_register(struct device_node *np)
                goto out_free;
        }
 
-       err = local_timer_register(&twd_lt_ops);
+       err = register_cpu_notifier(&twd_timer_cpu_nb);
        if (err)
                goto out_irq;
 
        twd_get_clock(np);
 
+       /*
+        * Immediately configure the timer on the boot CPU, unless we need
+        * jiffies to be incrementing to calibrate the rate in which case
+        * setup the timer in late_time_init.
+        */
+       if (twd_timer_rate)
+               twd_timer_setup();
+       else
+               late_time_init = twd_timer_setup;
+
        return 0;
 
 out_irq:
index cd9fcb1cd7ab3ac1472704c375b0ef31717b25bc..6acbdabf62226d01063f8468e883c38dc50c8f80 100644 (file)
@@ -12,7 +12,7 @@ config ARCH_HIGHBANK
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MAILBOX
        select PL320_MBOX
index ba44328464f37c0cdce9eb9039fcfce8ad8dc743..c8adc79028b8fead4594e41b7ae17aca7e53ad85 100644 (file)
@@ -798,7 +798,7 @@ config SOC_IMX6Q
        select COMMON_CLK
        select CPU_V7
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_ANATOP
        select HAVE_IMX_GPC
index f49cd51e162afcc6055d9143ced540d8fa888ab5..edb950a1af05a5992a567788291e38cdce6cc175 100644 (file)
@@ -90,7 +90,7 @@ config ARCH_OMAP4
        select CACHE_L2X0
        select CPU_V7
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select LOCAL_TIMERS if SMP
        select OMAP_INTERCONNECT
index d210c0f9c2c4912518313f1451b814af8f181484..9db2029aa6321a99fe8948176f41bcf02fdac529 100644 (file)
@@ -13,7 +13,7 @@ config REALVIEW_EB_A9MP
        depends on MACH_REALVIEW_EB
        select CPU_V7
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        help
@@ -26,7 +26,7 @@ config REALVIEW_EB_ARM11MP
        select ARCH_HAS_BARRIERS if SMP
        select CPU_V6K
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        help
@@ -48,7 +48,7 @@ config MACH_REALVIEW_PB11MP
        select ARM_GIC
        select CPU_V6K
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_PATA_PLATFORM
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
@@ -92,7 +92,7 @@ config MACH_REALVIEW_PBX
        select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
        select ARM_GIC
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_PATA_PLATFORM
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
index 442917eedff3f56adf033ab00ea1228c09687db3..df0d59afeb402a63ba2dad7bd86a81e12211e1b3 100644 (file)
@@ -23,7 +23,7 @@ config ARCH_SPEAR13XX
        select CPU_V7
        select GPIO_SPEAR_SPICS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        select PINCTRL
index 84d72fc36dfea1434431cb0b98a388f4b178e667..1f3ea1f6cedf5e0b9b3b48fdc4db428e43e8d980 100644 (file)
@@ -8,7 +8,7 @@ config ARCH_TEGRA
        select COMMON_CLK
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_CLK
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
index 6a4387e39df809f1b21d899b89d2212924ae19cd..0614ee2b052394c19954cb887e7110ff4f669e4e 100644 (file)
@@ -8,7 +8,7 @@ config ARCH_U8500
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        help
index 5907e10c37fd6eef7616a1bd6020a986a200c3d9..5bfdd73dea19de00decfb7dddeab1c9d43d39d8c 100644 (file)
@@ -10,7 +10,7 @@ config ARCH_VEXPRESS
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_CLK
        select HAVE_PATA_PLATFORM
        select HAVE_SMP
index c1d61f281e68d424b82060caf6b0601e6ecbf967..04f8a4a6e755e79b4c519cdbb0e487e6fcb99b78 100644 (file)
@@ -6,7 +6,7 @@ config ARCH_ZYNQ
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select ICST
        select MIGHT_HAVE_CACHE_L2X0
        select USE_OF