]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'clksrc-cleanup-for-3.10-part2' of git://sources.calxeda.com/kernel/linux...
authorOlof Johansson <olof@lixom.net>
Wed, 17 Apr 2013 17:10:01 +0000 (10:10 -0700)
committerOlof Johansson <olof@lixom.net>
Wed, 17 Apr 2013 17:10:01 +0000 (10:10 -0700)
This is the 2nd part of ARM timer clean-ups for 3.10. This series has
the following changes:

- Add sched_clock selection logic to select the highest frequency clock
- Use full 64-bit arch timer counter for sched_clock
- Convert arch timer, sp804 and integrator-cp timers to CLKSRC_OF and
adapt all users to use clocksource_of_init

* tag 'clksrc-cleanup-for-3.10-part2' of git://sources.calxeda.com/kernel/linux:
  devtree: add binding documentation for sp804
  ARM: integrator-cp: convert use CLKSRC_OF for timer init
  ARM: versatile: use OF init for sp804 timer
  ARM: versatile: add versatile dtbs to dtbs target
  ARM: vexpress: remove extra timer-sp control register clearing
  ARM: dts: vexpress: disable CA9 core tile sp804 timer
  ARM: vexpress: remove sp804 OF init
  ARM: highbank: use OF init for sp804 timer
  ARM: timer-sp: convert to use CLKSRC_OF init
  OF: add empty of_device_is_available for !OF
  ARM: convert arm/arm64 arch timer to use CLKSRC_OF init
  ARM: make machine_desc->init_time default to clocksource_of_init
  ARM: arch_timer: use full 64-bit counter for sched_clock
  ARM: make sched_clock just call a function pointer
  ARM: sched_clock: allow changing to higher frequency counter

Signed-off-by: Olof Johansson <olof@lixom.net>
This has a nasty set of conflicts with the exynos MCT code, which was
moved in a separate branch, and then fixed up when merged in, but still
conflicts a bit here. It should have been sorted out by this merge though.

34 files changed:
Documentation/devicetree/bindings/timer/arm,sp804.txt [new file with mode: 0644]
arch/arm/Kconfig
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/integratorcp.dts
arch/arm/boot/dts/versatile-ab.dts
arch/arm/boot/dts/vexpress-v2p-ca9.dts
arch/arm/common/timer-sp.c
arch/arm/include/asm/arch_timer.h
arch/arm/include/asm/hardware/timer-sp.h
arch/arm/include/asm/sched_clock.h
arch/arm/kernel/arch_timer.c
arch/arm/kernel/sched_clock.c
arch/arm/kernel/time.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-shmobile/board-kzm9d.c
arch/arm/mach-shmobile/setup-emev2.c
arch/arm/mach-shmobile/setup-r8a7740.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/timer.c
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/versatile_dt.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-virt/virt.c
arch/arm64/include/asm/arch_timer.h
arch/arm64/kernel/time.c
drivers/clocksource/Kconfig
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/exynos_mct.c
include/clocksource/arm_arch_timer.h
include/linux/of.h

diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
new file mode 100644 (file)
index 0000000..5cd8eee
--- /dev/null
@@ -0,0 +1,29 @@
+ARM sp804 Dual Timers
+---------------------------------------
+
+Required properties:
+- compatible: Should be "arm,sp804" & "arm,primecell"
+- interrupts: Should contain the list of Dual Timer interrupts. This is the
+       interrupt for timer 1 and timer 2. In the case of a single entry, it is
+       the combined interrupt or if "arm,sp804-has-irq" is present that
+       specifies which timer interrupt is connected.
+- reg: Should contain location and length for dual timer register.
+- clocks: clocks driving the dual timer hardware. This list should be 1 or 3
+       clocks. With 3 clocks, the order is timer0 clock, timer1 clock,
+       apb_pclk. A single clock can also be specified if the same clock is
+       used for all clock inputs.
+
+Optional properties:
+- arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
+       specifies if the irq connection is for timer 1 or timer 2. A value of 1
+       or 2 should be used.
+
+Example:
+
+       timer0: timer@fc800000 {
+               compatible = "arm,sp804", "arm,primecell";
+               reg = <0xfc800000 0x1000>;
+               interrupts = <0 0 4>, <0 1 4>;
+               clocks = <&timclk1 &timclk2 &pclk>;
+               clock-names = "timer1", "timer2", "apb_pclk";
+       };
index 03301cb114ac68d902c4b30a8e2ea0f022a17b9f..1571a4150439c4e64294b876ba57cea3fbc1c24e 100644 (file)
@@ -1180,6 +1180,7 @@ config PLAT_VERSATILE
 config ARM_TIMER_SP804
        bool
        select CLKSRC_MMIO
+       select CLKSRC_OF if OF
        select HAVE_SCHED_CLOCK
 
 source arch/arm/mm/Kconfig
index 9c6255884cbbd51f7efd83c5c4b6327156fc5c6c..08d298db0090aae3b40bf162344783f806424bb2 100644 (file)
@@ -165,6 +165,8 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
        tegra30-cardhu-a04.dtb \
        tegra114-dalmore.dtb \
        tegra114-pluto.dtb
+dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \
+       versatile-pb.dtb
 dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
        vexpress-v2p-ca9.dtb \
        vexpress-v2p-ca15-tc1.dtb \
index 8b119399025a16067330562ea9136abc0363d134..ff1aea0ee04322bf26688e1bf8892b60b02a69ce 100644 (file)
        };
 
        timer0: timer@13000000 {
-               compatible = "arm,sp804", "arm,primecell";
+               compatible = "arm,integrator-cp-timer";
        };
 
        timer1: timer@13000100 {
-               compatible = "arm,sp804", "arm,primecell";
+               compatible = "arm,integrator-cp-timer";
        };
 
        timer2: timer@13000200 {
-               compatible = "arm,sp804", "arm,primecell";
+               compatible = "arm,integrator-cp-timer";
        };
 
        pic: pic@14000000 {
index e2fe3195c0d109c6a31853455171627724c2e2d8..dde75ae8b4b10a071c80f3b79ec0f0d0a2f9e060 100644 (file)
                        interrupts = <0>;
                };
 
+               timer@101e2000 {
+                       compatible = "arm,sp804", "arm,primecell";
+                       reg = <0x101e2000 0x1000>;
+                       interrupts = <4>;
+               };
+
+               timer@101e3000 {
+                       compatible = "arm,sp804", "arm,primecell";
+                       reg = <0x101e3000 0x1000>;
+                       interrupts = <5>;
+               };
+
                gpio0: gpio@101e4000 {
                        compatible = "arm,pl061", "arm,primecell";
                        reg = <0x101e4000 0x1000>;
index 1420bb14d95c9bdeecea3aff5598612df359b924..62d9b225dcceec8b27464027cd9dba60640c33f5 100644 (file)
@@ -98,6 +98,7 @@
                             <0 49 4>;
                clocks = <&oscclk2>, <&oscclk2>;
                clock-names = "timclk", "apb_pclk";
+               status = "disabled";
        };
 
        watchdog@100e5000 {
index 9d2d3ba339ff9e79593b233245804f36f6e2e7a2..ddc740769601a58ecc4f1c430fd20cf3a45ac794 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/sched_clock.h>
 #include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
 
-static long __init sp804_get_clock_rate(const char *name)
+static long __init sp804_get_clock_rate(struct clk *clk)
 {
-       struct clk *clk;
        long rate;
        int err;
 
-       clk = clk_get_sys("sp804", name);
-       if (IS_ERR(clk)) {
-               pr_err("sp804: %s clock not found: %d\n", name,
-                       (int)PTR_ERR(clk));
-               return PTR_ERR(clk);
-       }
-
        err = clk_prepare(clk);
        if (err) {
-               pr_err("sp804: %s clock failed to prepare: %d\n", name, err);
+               pr_err("sp804: clock failed to prepare: %d\n", err);
                clk_put(clk);
                return err;
        }
 
        err = clk_enable(clk);
        if (err) {
-               pr_err("sp804: %s clock failed to enable: %d\n", name, err);
+               pr_err("sp804: clock failed to enable: %d\n", err);
                clk_unprepare(clk);
                clk_put(clk);
                return err;
@@ -59,7 +55,7 @@ static long __init sp804_get_clock_rate(const char *name)
 
        rate = clk_get_rate(clk);
        if (rate < 0) {
-               pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
+               pr_err("sp804: clock failed to get rate: %ld\n", rate);
                clk_disable(clk);
                clk_unprepare(clk);
                clk_put(clk);
@@ -77,9 +73,21 @@ static u32 sp804_read(void)
 
 void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
                                                     const char *name,
+                                                    struct clk *clk,
                                                     int use_sched_clock)
 {
-       long rate = sp804_get_clock_rate(name);
+       long rate;
+
+       if (!clk) {
+               clk = clk_get_sys("sp804", name);
+               if (IS_ERR(clk)) {
+                       pr_err("sp804: clock not found: %d\n",
+                              (int)PTR_ERR(clk));
+                       return;
+               }
+       }
+
+       rate = sp804_get_clock_rate(clk);
 
        if (rate < 0)
                return;
@@ -171,12 +179,20 @@ static struct irqaction sp804_timer_irq = {
        .dev_id         = &sp804_clockevent,
 };
 
-void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
-       const char *name)
+void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
 {
        struct clock_event_device *evt = &sp804_clockevent;
-       long rate = sp804_get_clock_rate(name);
+       long rate;
 
+       if (!clk)
+               clk = clk_get_sys("sp804", name);
+       if (IS_ERR(clk)) {
+               pr_err("sp804: %s clock not found: %d\n", name,
+                       (int)PTR_ERR(clk));
+               return;
+       }
+
+       rate = sp804_get_clock_rate(clk);
        if (rate < 0)
                return;
 
@@ -186,6 +202,98 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
        evt->irq = irq;
        evt->cpumask = cpu_possible_mask;
 
+       writel(0, base + TIMER_CTRL);
+
        setup_irq(irq, &sp804_timer_irq);
        clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
 }
+
+static void __init sp804_of_init(struct device_node *np)
+{
+       static bool initialized = false;
+       void __iomem *base;
+       int irq;
+       u32 irq_num = 0;
+       struct clk *clk1, *clk2;
+       const char *name = of_get_property(np, "compatible", NULL);
+
+       base = of_iomap(np, 0);
+       if (WARN_ON(!base))
+               return;
+
+       /* Ensure timers are disabled */
+       writel(0, base + TIMER_CTRL);
+       writel(0, base + TIMER_2_BASE + TIMER_CTRL);
+
+       if (initialized || !of_device_is_available(np))
+               goto err;
+
+       clk1 = of_clk_get(np, 0);
+       if (IS_ERR(clk1))
+               clk1 = NULL;
+
+       /* Get the 2nd clock if the timer has 2 timer clocks */
+       if (of_count_phandle_with_args(np, "clocks", "#clock-cells") == 3) {
+               clk2 = of_clk_get(np, 1);
+               if (IS_ERR(clk2)) {
+                       pr_err("sp804: %s clock not found: %d\n", np->name,
+                               (int)PTR_ERR(clk2));
+                       goto err;
+               }
+       } else
+               clk2 = clk1;
+
+       irq = irq_of_parse_and_map(np, 0);
+       if (irq <= 0)
+               goto err;
+
+       of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
+       if (irq_num == 2) {
+               __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
+               __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
+       } else {
+               __sp804_clockevents_init(base, irq, clk1 , name);
+               __sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
+                                                        name, clk2, 1);
+       }
+       initialized = true;
+
+       return;
+err:
+       iounmap(base);
+}
+CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);
+
+static void __init integrator_cp_of_init(struct device_node *np)
+{
+       static int init_count = 0;
+       void __iomem *base;
+       int irq;
+       const char *name = of_get_property(np, "compatible", NULL);
+
+       base = of_iomap(np, 0);
+       if (WARN_ON(!base))
+               return;
+
+       /* Ensure timer is disabled */
+       writel(0, base + TIMER_CTRL);
+
+       if (init_count == 2 || !of_device_is_available(np))
+               goto err;
+
+       if (!init_count)
+               sp804_clocksource_init(base, name);
+       else {
+               irq = irq_of_parse_and_map(np, 0);
+               if (irq <= 0)
+                       goto err;
+
+               sp804_clockevents_init(base, irq, name);
+       }
+
+       init_count++;
+       return;
+err:
+       iounmap(base);
+}
+CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init);
index 7ade91d8cc6fa4d723016e1e538e16881092f33c..7c1bfc0aea0c200a268ec82c62fd4cb624c17ecf 100644 (file)
@@ -10,8 +10,7 @@
 #include <clocksource/arm_arch_timer.h>
 
 #ifdef CONFIG_ARM_ARCH_TIMER
-int arch_timer_of_register(void);
-int arch_timer_sched_clock_init(void);
+int arch_timer_arch_init(void);
 
 /*
  * These register accessors are marked inline so the compiler can
@@ -110,16 +109,6 @@ static inline void __cpuinit arch_counter_set_user_access(void)
 
        asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
 }
-#else
-static inline int arch_timer_of_register(void)
-{
-       return -ENXIO;
-}
-
-static inline int arch_timer_sched_clock_init(void)
-{
-       return -ENXIO;
-}
 #endif
 
 #endif
index 2dd9d3f83f2963282ad5c593b94aebbc59df421a..bb28af7c32deb04326418c6ba09675334bbe5cec 100644 (file)
@@ -1,15 +1,23 @@
+struct clk;
+
 void __sp804_clocksource_and_sched_clock_init(void __iomem *,
-                                             const char *, int);
+                                             const char *, struct clk *, int);
+void __sp804_clockevents_init(void __iomem *, unsigned int,
+                             struct clk *, const char *);
 
 static inline void sp804_clocksource_init(void __iomem *base, const char *name)
 {
-       __sp804_clocksource_and_sched_clock_init(base, name, 0);
+       __sp804_clocksource_and_sched_clock_init(base, name, NULL, 0);
 }
 
 static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
                                                          const char *name)
 {
-       __sp804_clocksource_and_sched_clock_init(base, name, 1);
+       __sp804_clocksource_and_sched_clock_init(base, name, NULL, 1);
 }
 
-void sp804_clockevents_init(void __iomem *, unsigned int, const char *);
+static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name)
+{
+       __sp804_clockevents_init(base, irq, NULL, name);
+
+}
index e3f7572634381bd28fbf3225eb375788431ee3fc..3d520ddca61bba9f58cd53f914af87fe86b30e83 100644 (file)
@@ -11,4 +11,6 @@
 extern void sched_clock_postinit(void);
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
 
+extern unsigned long long (*sched_clock_func)(void);
+
 #endif
index d957a51435d808eb73743886a888e356b00f0bf2..59dcdced6e30df8e3603ae64c3df076859a0ce82 100644 (file)
@@ -22,9 +22,11 @@ static unsigned long arch_timer_read_counter_long(void)
        return arch_timer_read_counter();
 }
 
-static u32 arch_timer_read_counter_u32(void)
+static u32 sched_clock_mult __read_mostly;
+
+static unsigned long long notrace arch_timer_sched_clock(void)
 {
-       return arch_timer_read_counter();
+       return arch_timer_read_counter() * sched_clock_mult;
 }
 
 static struct delay_timer arch_delay_timer;
@@ -37,25 +39,20 @@ static void __init arch_timer_delay_timer_register(void)
        register_current_timer_delay(&arch_delay_timer);
 }
 
-int __init arch_timer_of_register(void)
+int __init arch_timer_arch_init(void)
 {
-       int ret;
+        u32 arch_timer_rate = arch_timer_get_rate();
 
-       ret = arch_timer_init();
-       if (ret)
-               return ret;
+       if (arch_timer_rate == 0)
+               return -ENXIO;
 
        arch_timer_delay_timer_register();
 
-       return 0;
-}
-
-int __init arch_timer_sched_clock_init(void)
-{
-       if (arch_timer_get_rate() == 0)
-               return -ENXIO;
+       /* Cache the sched_clock multiplier to save a divide in the hot path. */
+       sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
+       sched_clock_func = arch_timer_sched_clock;
+       pr_info("sched_clock: ARM arch timer >56 bits at %ukHz, resolution %uns\n",
+               arch_timer_rate / 1000, sched_clock_mult);
 
-       setup_sched_clock(arch_timer_read_counter_u32,
-                         32, arch_timer_get_rate());
        return 0;
 }
index bd6f56b9ec2101534b7477c11c9f6ef0a3a6e68b..880584852fca660d9726101e28270004f4f74675 100644 (file)
@@ -20,6 +20,7 @@ struct clock_data {
        u64 epoch_ns;
        u32 epoch_cyc;
        u32 epoch_cyc_copy;
+       unsigned long rate;
        u32 mult;
        u32 shift;
        bool suspended;
@@ -113,11 +114,14 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
        u64 res, wrap;
        char r_unit;
 
+       if (cd.rate > rate)
+               return;
+
        BUG_ON(bits > 32);
        WARN_ON(!irqs_disabled());
-       WARN_ON(read_sched_clock != jiffy_sched_clock_read);
        read_sched_clock = read;
        sched_clock_mask = (1 << bits) - 1;
+       cd.rate = rate;
 
        /* calculate the mult/shift to convert counter ticks to ns. */
        clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0);
@@ -161,12 +165,19 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
        pr_debug("Registered %pF as sched_clock source\n", read);
 }
 
-unsigned long long notrace sched_clock(void)
+static unsigned long long notrace sched_clock_32(void)
 {
        u32 cyc = read_sched_clock();
        return cyc_to_sched_clock(cyc, sched_clock_mask);
 }
 
+unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32;
+
+unsigned long long notrace sched_clock(void)
+{
+       return sched_clock_func();
+}
+
 void __init sched_clock_postinit(void)
 {
        /*
index 955d92d265e5d9496289ed7613bdd6ceffba04d7..abff4e9aaee07c518f1101469d3032626334c695 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/profile.h>
 #include <linux/timer.h>
+#include <linux/clocksource.h>
 #include <linux/irq.h>
 
 #include <asm/thread_info.h>
@@ -115,6 +116,10 @@ int __init register_persistent_clock(clock_access_fn read_boot,
 
 void __init time_init(void)
 {
-       machine_desc->init_time();
+       if (machine_desc->init_time)
+               machine_desc->init_time();
+       else
+               clocksource_of_init();
+
        sched_clock_postinit();
 }
index 7da4791bfb8b31de8614332842c807770b7b4b9b..be7eaac0df01e911719f9b6bdd843e5abcc62552 100644 (file)
@@ -217,7 +217,6 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
        .map_io         = exynos5_dt_map_io,
        .init_machine   = exynos5_dt_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = clocksource_of_init,
        .dt_compat      = exynos5_dt_compat,
        .restart        = exynos5_restart,
        .reserve        = exynos5_reserve,
index 76c1170b35284a0c96646413bb29476add96c7c3..e7df2dd43a40f5d8c956aef5721fd504a90f8b5b 100644 (file)
@@ -15,6 +15,7 @@
  */
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/amba/bus.h>
 #include <linux/clk-provider.h>
 
-#include <asm/arch_timer.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <asm/smp_plat.h>
-#include <asm/hardware/arm_timer.h>
-#include <asm/hardware/timer-sp.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -90,36 +88,16 @@ static void __init highbank_init_irq(void)
 #endif
 }
 
-static struct clk_lookup lookup = {
-       .dev_id = "sp804",
-       .con_id = NULL,
-};
-
 static void __init highbank_timer_init(void)
 {
-       int irq;
        struct device_node *np;
-       void __iomem *timer_base;
 
        /* Map system registers */
        np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
        sregs_base = of_iomap(np, 0);
        WARN_ON(!sregs_base);
 
-       np = of_find_compatible_node(NULL, NULL, "arm,sp804");
-       timer_base = of_iomap(np, 0);
-       WARN_ON(!timer_base);
-       irq = irq_of_parse_and_map(np, 0);
-
        of_clk_init(NULL);
-       lookup.clk = of_clk_get(np, 0);
-       clkdev_add(&lookup);
-
-       sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1");
-       sp804_clockevents_init(timer_base, irq, "timer0");
-
-       arch_timer_of_register();
-       arch_timer_sched_clock_init();
 
        clocksource_of_init();
 }
index da1091be0887bd1344a9ba33daf743d1d0a05b3a..8c60fcb08a98ff43db4f115c45306c83b5a3bb65 100644 (file)
@@ -250,39 +250,6 @@ static void __init intcp_init_early(void)
 }
 
 #ifdef CONFIG_OF
-
-static void __init cp_of_timer_init(void)
-{
-       struct device_node *node;
-       const char *path;
-       void __iomem *base;
-       int err;
-       int irq;
-
-       err = of_property_read_string(of_aliases,
-                               "arm,timer-primary", &path);
-       if (WARN_ON(err))
-               return;
-       node = of_find_node_by_path(path);
-       base = of_iomap(node, 0);
-       if (WARN_ON(!base))
-               return;
-       writel(0, base + TIMER_CTRL);
-       sp804_clocksource_init(base, node->name);
-
-       err = of_property_read_string(of_aliases,
-                               "arm,timer-secondary", &path);
-       if (WARN_ON(err))
-               return;
-       node = of_find_node_by_path(path);
-       base = of_iomap(node, 0);
-       if (WARN_ON(!base))
-               return;
-       irq = irq_of_parse_and_map(node, 0);
-       writel(0, base + TIMER_CTRL);
-       sp804_clockevents_init(base, irq, node->name);
-}
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
        { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
        { /* Sentinel */ }
@@ -383,7 +350,6 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq_of,
        .handle_irq     = fpga_handle_irq,
-       .init_time      = cp_of_timer_init,
        .init_machine   = intcp_init_of,
        .restart        = integrator_restart,
        .dt_compat      = intcp_dt_board_compat,
index f12aa6c15da4db1da20a4abbda6368b48a4d3b1a..d5a13dcb64b80f4d4f095f8075444aadce1abf93 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/smp_twd.h>
 #include <asm/sched_clock.h>
 
-#include <asm/arch_timer.h>
 #include "omap_hwmod.h"
 #include "omap_device.h"
 #include <plat/counter-32k.h>
@@ -627,9 +626,7 @@ void __init omap5_realtime_timer_init(void)
        omap4_sync32k_timer_init();
        realtime_counter_init();
 
-       err = arch_timer_of_register();
-       if (err)
-               pr_err("%s: arch_timer_register failed %d\n", __func__, err);
+        clocksource_of_init();
 }
 #endif /* CONFIG_SOC_OMAP5 */
 
index c254782aa7276c59297273ab6c7d40ede2a15097..c016ccd92433ce575ae2466759d6d67eb7e8d7ed 100644 (file)
@@ -90,6 +90,5 @@ DT_MACHINE_START(KZM9D_DT, "kzm9d")
        .init_irq       = emev2_init_irq,
        .init_machine   = kzm9d_add_standard_devices,
        .init_late      = shmobile_init_late,
-       .init_time      = shmobile_timer_init,
        .dt_compat      = kzm9d_boards_compat_dt,
 MACHINE_END
index e4545c152722e3361fd273fefb90c54f26753dea..899a86c31ec92213520793c4c757628a5d4b0504 100644 (file)
@@ -456,7 +456,6 @@ DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
        .nr_irqs        = NR_IRQS_LEGACY,
        .init_irq       = irqchip_init,
        .init_machine   = emev2_add_standard_devices_dt,
-       .init_time      = shmobile_timer_init,
        .dt_compat      = emev2_boards_compat_dt,
 MACHINE_END
 
index 8b85d4d8fab6692861dbd7a642b7a803ef8afbd6..104b474a2ccfeeb9527d9507e0dd5ad9efab204e 100644 (file)
@@ -906,7 +906,6 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
        .init_irq       = r8a7740_init_irq,
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = r8a7740_add_standard_devices_dt,
-       .init_time      = shmobile_timer_init,
        .dt_compat      = r8a7740_boards_compat_dt,
 MACHINE_END
 
index 59c7146bf66f6221c1fe6d47c4a6134aa775d454..5502d624aca6cca299302f9aa975f420793cbcee 100644 (file)
@@ -1175,7 +1175,6 @@ DT_MACHINE_START(SH7372_DT, "Generic SH7372 (Flattened Device Tree)")
        .init_irq       = sh7372_init_irq,
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = sh7372_add_standard_devices_dt,
-       .init_time      = shmobile_timer_init,
        .dt_compat      = sh7372_boards_compat_dt,
 MACHINE_END
 
index e8cd93a5c5503cdbd86342f0e3742fedcdca531b..fdf3894b1cc31e0291d2fc00e35bfbe61185f735 100644 (file)
@@ -1037,7 +1037,6 @@ DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
        .nr_irqs        = NR_IRQS_LEGACY,
        .init_irq       = irqchip_init,
        .init_machine   = sh73a0_add_standard_devices_dt,
-       .init_time      = shmobile_timer_init,
        .dt_compat      = sh73a0_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
index 3d16d4dff01b68735a3a02d1c5bba490ce4cb2e7..f321dbeb23795b7af850985ae59d16bffdcfc8c6 100644 (file)
  *
  */
 #include <linux/platform_device.h>
+#include <linux/clocksource.h>
 #include <linux/delay.h>
-#include <asm/arch_timer.h>
-#include <asm/mach/time.h>
-#include <asm/smp_twd.h>
 
 void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
                                 unsigned int mult, unsigned int div)
@@ -63,6 +61,5 @@ void __init shmobile_earlytimer_init(void)
 
 void __init shmobile_timer_init(void)
 {
-       arch_timer_of_register();
-       arch_timer_sched_clock_init();
+       clocksource_of_init();
 }
index 25160aeaa3b7fe30b9e0cd26cc5e5449b444ca5f..54bb80b012aceca7fdf925fd249b96abda646ece 100644 (file)
@@ -749,12 +749,25 @@ void versatile_restart(char mode, const char *cmd)
 /* Early initializations */
 void __init versatile_init_early(void)
 {
+       u32 val;
        void __iomem *sys = __io_address(VERSATILE_SYS_BASE);
 
        osc4_clk.vcoreg = sys + VERSATILE_SYS_OSCCLCD_OFFSET;
        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
        versatile_sched_clock_init(sys + VERSATILE_SYS_24MHz_OFFSET, 24000000);
+
+       /*
+        * set clock frequency:
+        *      VERSATILE_REFCLK is 32KHz
+        *      VERSATILE_TIMCLK is 1MHz
+        */
+       val = readl(__io_address(VERSATILE_SCTL_BASE));
+       writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
+              (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) |
+              (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
+              (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
+              __io_address(VERSATILE_SCTL_BASE));
 }
 
 void __init versatile_init(void)
@@ -785,19 +798,6 @@ void __init versatile_init(void)
  */
 void __init versatile_timer_init(void)
 {
-       u32 val;
-
-       /* 
-        * set clock frequency: 
-        *      VERSATILE_REFCLK is 32KHz
-        *      VERSATILE_TIMCLK is 1MHz
-        */
-       val = readl(__io_address(VERSATILE_SCTL_BASE));
-       writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
-              (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
-              (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
-              (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
-              __io_address(VERSATILE_SCTL_BASE));
 
        /*
         * Initialise to a known state (all timers off)
index 2558f2e957c37cb63f32d1efd8c2d487e3add7b7..3621b000a0f6ea04ce2d0de62ed5ffde114003d0 100644 (file)
@@ -45,7 +45,6 @@ DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
        .map_io         = versatile_map_io,
        .init_early     = versatile_init_early,
        .init_irq       = versatile_init_irq,
-       .init_time      = versatile_timer_init,
        .init_machine   = versatile_dt_init,
        .dt_compat      = versatile_dt_match,
        .restart        = versatile_restart,
index d0ad78998cb628c34feee844b81a4293cb28f253..09e571ddc984731266da692f8923c295ff8fb40a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Versatile Express V2M Motherboard Support
  */
+#include <linux/clocksource.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/mmci.h>
@@ -23,7 +24,6 @@
 #include <linux/regulator/machine.h>
 #include <linux/vexpress.h>
 
-#include <asm/arch_timer.h>
 #include <asm/mach-types.h>
 #include <asm/sizes.h>
 #include <asm/mach/arch.h>
@@ -61,9 +61,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
        if (WARN_ON(!base || irq == NO_IRQ))
                return;
 
-       writel(0, base + TIMER_1_BASE + TIMER_CTRL);
-       writel(0, base + TIMER_2_BASE + TIMER_CTRL);
-
        sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1");
        sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
 }
@@ -431,25 +428,11 @@ void __init v2m_dt_init_early(void)
 
 static void __init v2m_dt_timer_init(void)
 {
-       struct device_node *node = NULL;
-
        vexpress_clk_of_init();
 
        clocksource_of_init();
-       do {
-               node = of_find_compatible_node(node, NULL, "arm,sp804");
-       } while (node && vexpress_get_site_by_node(node) != VEXPRESS_SITE_MB);
-       if (node) {
-               pr_info("Using SP804 '%s' as a clock & events source\n",
-                               node->full_name);
-               v2m_sp804_init(of_iomap(node, 0),
-                               irq_of_parse_and_map(node, 0));
-       }
-
-       arch_timer_of_register();
 
-       if (arch_timer_sched_clock_init() != 0)
-               versatile_sched_clock_init(vexpress_get_24mhz_clock_base(),
+       versatile_sched_clock_init(vexpress_get_24mhz_clock_base(),
                                24000000);
 }
 
index 31666f6b43736fca58ebebaa7cb4d02562b6c25a..adc0945255aea2dee90e170d2426c7a25fc128e0 100644 (file)
 #include <linux/of_platform.h>
 #include <linux/smp.h>
 
-#include <asm/arch_timer.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/time.h>
 
 static void __init virt_init(void)
 {
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init virt_timer_init(void)
-{
-       WARN_ON(arch_timer_of_register() != 0);
-       WARN_ON(arch_timer_sched_clock_init() != 0);
-}
-
 static const char *virt_dt_match[] = {
        "linux,dummy-virt",
        NULL
@@ -47,7 +39,6 @@ extern struct smp_operations virt_smp_ops;
 
 DT_MACHINE_START(VIRT, "Dummy Virtual Machine")
        .init_irq       = irqchip_init,
-       .init_time      = virt_timer_init,
        .init_machine   = virt_init,
        .smp            = smp_ops(virt_smp_ops),
        .dt_compat      = virt_dt_match,
index 91e2a6a6fcd44cec02cbf47ee9c987d27752228c..bf6ab242f04725e56e8cf93d3ab6e930668651f0 100644 (file)
@@ -130,4 +130,9 @@ static inline u64 arch_counter_get_cntvct(void)
        return cval;
 }
 
+static inline int arch_timer_arch_init(void)
+{
+       return 0;
+}
+
 #endif
index b0ef18d14c3bec15d444b11f622596de68dff255..a551f88ae2c13e173749e75c80a2776f8d2a80cf 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/timer.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/clocksource.h>
 
 #include <clocksource/arm_arch_timer.h>
 
@@ -77,10 +78,11 @@ void __init time_init(void)
 {
        u32 arch_timer_rate;
 
-       if (arch_timer_init())
-               panic("Unable to initialise architected timer.\n");
+       clocksource_of_init();
 
        arch_timer_rate = arch_timer_get_rate();
+       if (!arch_timer_rate)
+               panic("Unable to initialise architected timer.\n");
 
        /* Cache the sched_clock multiplier to save a divide in the hot path. */
        sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
index 73fcddb8314d4c1fba7277ddb98d8d06aaad526a..29ba35e6a143d0ef7ccdea34587a7749369cc101 100644 (file)
@@ -65,6 +65,7 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 
 config ARM_ARCH_TIMER
        bool
+       select CLKSRC_OF if OF
 
 config CLKSRC_METAG_GENERIC
        def_bool y if METAG
index d7ad425ab9b3515f4e2d47fab6129ebd288a3090..122ff05628b5b7419d47b5368719234d9c7d352f 100644 (file)
@@ -337,22 +337,14 @@ out:
        return err;
 }
 
-static const struct of_device_id arch_timer_of_match[] __initconst = {
-       { .compatible   = "arm,armv7-timer",    },
-       { .compatible   = "arm,armv8-timer",    },
-       {},
-};
-
-int __init arch_timer_init(void)
+static void __init arch_timer_init(struct device_node *np)
 {
-       struct device_node *np;
        u32 freq;
        int i;
 
-       np = of_find_matching_node(NULL, arch_timer_of_match);
-       if (!np) {
-               pr_err("arch_timer: can't find DT node\n");
-               return -ENODEV;
+       if (arch_timer_get_rate()) {
+               pr_warn("arch_timer: multiple nodes in dt, skipping\n");
+               return;
        }
 
        /* Try to determine the frequency from the device tree or CNTFRQ */
@@ -378,7 +370,7 @@ int __init arch_timer_init(void)
                if (!arch_timer_ppi[PHYS_SECURE_PPI] ||
                    !arch_timer_ppi[PHYS_NONSECURE_PPI]) {
                        pr_warn("arch_timer: No interrupt available, giving up\n");
-                       return -EINVAL;
+                       return;
                }
        }
 
@@ -387,5 +379,8 @@ int __init arch_timer_init(void)
        else
                arch_timer_read_counter = arch_counter_get_cntpct;
 
-       return arch_timer_register();
+       arch_timer_register();
+       arch_timer_arch_init();
 }
+CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init);
+CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init);
index 957af8636c9d666f428a703eb4ff9bb465831cc0..b078d7cbc93089f08860e4fac3ea2cc7facabd29 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/of_address.h>
 #include <linux/clocksource.h>
 
-#include <asm/arch_timer.h>
 #include <asm/localtimer.h>
 
 #include <plat/cpu.h>
index 2603267b1a29282f10ef96a2203654fc44b75b98..e6c9c4cc9b23415fad39dfd142a6ce3bd44f4b7c 100644 (file)
 
 #ifdef CONFIG_ARM_ARCH_TIMER
 
-extern int arch_timer_init(void);
 extern u32 arch_timer_get_rate(void);
 extern u64 (*arch_timer_read_counter)(void);
 extern struct timecounter *arch_timer_get_timecounter(void);
 
 #else
 
-static inline int arch_timer_init(void)
-{
-       return -ENXIO;
-}
-
 static inline u32 arch_timer_get_rate(void)
 {
        return 0;
index c0747a44eafffad720fe4e625866cdb6639b8cf7..b0f3bbd0216bb69e386e652a75044dd239e3f65e 100644 (file)
@@ -382,6 +382,11 @@ static inline int of_device_is_compatible(const struct device_node *device,
        return 0;
 }
 
+static inline int of_device_is_available(const struct device_node *device)
+{
+       return 0;
+}
+
 static inline struct property *of_find_property(const struct device_node *np,
                                                const char *name,
                                                int *lenp)