]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'timers/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 16 Sep 2013 20:10:26 +0000 (16:10 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 16 Sep 2013 20:10:26 +0000 (16:10 -0400)
Pull timer code update from Thomas Gleixner:
 - armada SoC clocksource overhaul with a trivial merge conflict
 - Minor improvements to various SoC clocksource drivers

* 'timers/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  clocksource: armada-370-xp: Add detailed clock requirements in devicetree binding
  clocksource: armada-370-xp: Get reference fixed-clock by name
  clocksource: armada-370-xp: Replace WARN_ON with BUG_ON
  clocksource: armada-370-xp: Fix device-tree binding
  clocksource: armada-370-xp: Introduce new compatibles
  clocksource: armada-370-xp: Use CLOCKSOURCE_OF_DECLARE
  clocksource: armada-370-xp: Simplify TIMER_CTRL register access
  clocksource: armada-370-xp: Use BIT()
  ARM: timer-sp: Set dynamic irq affinity
  ARM: nomadik: add dynamic irq flag to the timer
  clocksource: sh_cmt: 32-bit control register support
  clocksource: em_sti: Convert to devm_* managed helpers

1  2 
arch/arm/mach-mvebu/armada-370-xp.c
drivers/clocksource/time-armada-370-xp.c

index 829b5730632864b7da0158e8e6c6f833e421e579,4ea03ad4117971060d3807d7a5f88f3460a02ef6..e2acff98e750a013dd54356249306259cb055091
@@@ -18,7 -18,7 +18,7 @@@
  #include <linux/of_address.h>
  #include <linux/of_platform.h>
  #include <linux/io.h>
- #include <linux/time-armada-370-xp.h>
+ #include <linux/clocksource.h>
  #include <linux/dma-mapping.h>
  #include <linux/mbus.h>
  #include <asm/hardware/cache-l2x0.h>
@@@ -34,12 -34,44 +34,12 @@@ static void __init armada_370_xp_map_io
        debug_ll_io_init();
  }
  
 -/*
 - * This initialization will be replaced by a DT-based
 - * initialization once the mvebu-mbus driver gains DT support.
 - */
 -
 -#define ARMADA_370_XP_MBUS_WINS_OFFS   0x20000
 -#define ARMADA_370_XP_MBUS_WINS_SIZE   0x100
 -#define ARMADA_370_XP_SDRAM_WINS_OFFS  0x20180
 -#define ARMADA_370_XP_SDRAM_WINS_SIZE  0x20
 -
 -static void __init armada_370_xp_mbus_init(void)
 -{
 -      char *mbus_soc_name;
 -      struct device_node *dn;
 -      const __be32 mbus_wins_offs = cpu_to_be32(ARMADA_370_XP_MBUS_WINS_OFFS);
 -      const __be32 sdram_wins_offs = cpu_to_be32(ARMADA_370_XP_SDRAM_WINS_OFFS);
 -
 -      if (of_machine_is_compatible("marvell,armada370"))
 -              mbus_soc_name = "marvell,armada370-mbus";
 -      else
 -              mbus_soc_name = "marvell,armadaxp-mbus";
 -
 -      dn = of_find_node_by_name(NULL, "internal-regs");
 -      BUG_ON(!dn);
 -
 -      mvebu_mbus_init(mbus_soc_name,
 -                      of_translate_address(dn, &mbus_wins_offs),
 -                      ARMADA_370_XP_MBUS_WINS_SIZE,
 -                      of_translate_address(dn, &sdram_wins_offs),
 -                      ARMADA_370_XP_SDRAM_WINS_SIZE);
 -}
 -
  static void __init armada_370_xp_timer_and_clk_init(void)
  {
        of_clk_init(NULL);
-       armada_370_xp_timer_init();
+       clocksource_of_init();
        coherency_init();
 -      armada_370_xp_mbus_init();
 +      BUG_ON(mvebu_mbus_dt_init());
  #ifdef CONFIG_CACHE_L2X0
        l2x0_of_init(0, ~0UL);
  #endif
index 847cab6f6e31009f9a97560642ee4685497ead18,44c4fff2f58cc086f8bcd5e94c9bd7b7c8e1fd55..0198504ef6b02388c8847bc4897eca4e58328479
   *
   * Timer 0 is used as free-running clocksource, while timer 1 is
   * used as clock_event_device.
+  *
+  * ---
+  * Clocksource driver for Armada 370 and Armada XP SoC.
+  * This driver implements one compatible string for each SoC, given
+  * each has its own characteristics:
+  *
+  *   * Armada 370 has no 25 MHz fixed timer.
+  *
+  *   * Armada XP cannot work properly without such 25 MHz fixed timer as
+  *     doing otherwise leads to using a clocksource whose frequency varies
+  *     when doing cpufreq frequency changes.
+  *
+  * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
   */
  
  #include <linux/init.h>
  #include <linux/platform_device.h>
  #include <linux/kernel.h>
  #include <linux/clk.h>
 +#include <linux/cpu.h>
  #include <linux/timer.h>
  #include <linux/clockchips.h>
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  #include <linux/module.h>
  #include <linux/sched_clock.h>
 -
 -#include <asm/localtimer.h>
  #include <linux/percpu.h>
- #include <linux/time-armada-370-xp.h>
 +
  /*
   * Timer block registers.
   */
  #define TIMER_CTRL_OFF                0x0000
- #define  TIMER0_EN             0x0001
- #define  TIMER0_RELOAD_EN      0x0002
- #define  TIMER0_25MHZ            0x0800
+ #define  TIMER0_EN             BIT(0)
+ #define  TIMER0_RELOAD_EN      BIT(1)
+ #define  TIMER0_25MHZ            BIT(11)
  #define  TIMER0_DIV(div)         ((div) << 19)
- #define  TIMER1_EN             0x0004
- #define  TIMER1_RELOAD_EN      0x0008
- #define  TIMER1_25MHZ            0x1000
+ #define  TIMER1_EN             BIT(2)
+ #define  TIMER1_RELOAD_EN      BIT(3)
+ #define  TIMER1_25MHZ            BIT(12)
  #define  TIMER1_DIV(div)         ((div) << 22)
  #define TIMER_EVENTS_STATUS   0x0004
  #define  TIMER0_CLR_MASK         (~0x1)
@@@ -70,8 -82,20 +82,20 @@@ static bool timer25Mhz = true
   */
  static u32 ticks_per_jiffy;
  
 -static struct clock_event_device __percpu **percpu_armada_370_xp_evt;
 +static struct clock_event_device __percpu *armada_370_xp_evt;
  
+ static void timer_ctrl_clrset(u32 clr, u32 set)
+ {
+       writel((readl(timer_base + TIMER_CTRL_OFF) & ~clr) | set,
+               timer_base + TIMER_CTRL_OFF);
+ }
+ static void local_timer_ctrl_clrset(u32 clr, u32 set)
+ {
+       writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set,
+               local_base + TIMER_CTRL_OFF);
+ }
  static u32 notrace armada_370_xp_read_sched_clock(void)
  {
        return ~readl(timer_base + TIMER0_VAL_OFF);
@@@ -84,7 -108,6 +108,6 @@@ static in
  armada_370_xp_clkevt_next_event(unsigned long delta,
                                struct clock_event_device *dev)
  {
-       u32 u;
        /*
         * Clear clockevent timer interrupt.
         */
        /*
         * Enable the timer.
         */
-       u = readl(local_base + TIMER_CTRL_OFF);
-       u = ((u & ~TIMER0_RELOAD_EN) | TIMER0_EN |
-            TIMER0_DIV(TIMER_DIVIDER_SHIFT));
-       writel(u, local_base + TIMER_CTRL_OFF);
+       local_timer_ctrl_clrset(TIMER0_RELOAD_EN,
+                               TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT));
        return 0;
  }
  
@@@ -110,8 -130,6 +130,6 @@@ static voi
  armada_370_xp_clkevt_mode(enum clock_event_mode mode,
                          struct clock_event_device *dev)
  {
-       u32 u;
        if (mode == CLOCK_EVT_MODE_PERIODIC) {
  
                /*
                /*
                 * Enable timer.
                 */
-               u = readl(local_base + TIMER_CTRL_OFF);
-               writel((u | TIMER0_EN | TIMER0_RELOAD_EN |
-                       TIMER0_DIV(TIMER_DIVIDER_SHIFT)),
-                       local_base + TIMER_CTRL_OFF);
+               local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN |
+                                          TIMER0_EN |
+                                          TIMER0_DIV(TIMER_DIVIDER_SHIFT));
        } else {
                /*
                 * Disable timer.
                 */
-               u = readl(local_base + TIMER_CTRL_OFF);
-               writel(u & ~TIMER0_EN, local_base + TIMER_CTRL_OFF);
+               local_timer_ctrl_clrset(TIMER0_EN, 0);
  
                /*
                 * ACK pending timer interrupt.
        }
  }
  
 -static struct clock_event_device armada_370_xp_clkevt = {
 -      .name           = "armada_370_xp_per_cpu_tick",
 -      .features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
 -      .shift          = 32,
 -      .rating         = 300,
 -      .set_next_event = armada_370_xp_clkevt_next_event,
 -      .set_mode       = armada_370_xp_clkevt_mode,
 -};
 +static int armada_370_xp_clkevt_irq;
  
  static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
  {
        /*
         * ACK timer interrupt and call event handler.
         */
 -      struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
 +      struct clock_event_device *evt = dev_id;
  
        writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
        evt->event_handler(evt);
   */
  static int armada_370_xp_timer_setup(struct clock_event_device *evt)
  {
-       u32 u;
+       u32 clr = 0, set = 0;
        int cpu = smp_processor_id();
  
-       u = readl(local_base + TIMER_CTRL_OFF);
 -      /* Use existing clock_event for cpu 0 */
 -      if (!smp_processor_id())
 -              return 0;
 -
        if (timer25Mhz)
-               writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
+               set = TIMER0_25MHZ;
        else
-               writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
+               clr = TIMER0_25MHZ;
+       local_timer_ctrl_clrset(clr, set);
  
 -      evt->name               = armada_370_xp_clkevt.name;
 -      evt->irq                = armada_370_xp_clkevt.irq;
 -      evt->features           = armada_370_xp_clkevt.features;
 -      evt->shift              = armada_370_xp_clkevt.shift;
 -      evt->rating             = armada_370_xp_clkevt.rating,
 +      evt->name               = "armada_370_xp_per_cpu_tick",
 +      evt->features           = CLOCK_EVT_FEAT_ONESHOT |
 +                                CLOCK_EVT_FEAT_PERIODIC;
 +      evt->shift              = 32,
 +      evt->rating             = 300,
        evt->set_next_event     = armada_370_xp_clkevt_next_event,
        evt->set_mode           = armada_370_xp_clkevt_mode,
 +      evt->irq                = armada_370_xp_clkevt_irq;
        evt->cpumask            = cpumask_of(cpu);
  
 -      *__this_cpu_ptr(percpu_armada_370_xp_evt) = evt;
 -
        clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe);
        enable_percpu_irq(evt->irq, 0);
  
        return 0;
  }
  
 -static void  armada_370_xp_timer_stop(struct clock_event_device *evt)
 +static void armada_370_xp_timer_stop(struct clock_event_device *evt)
  {
        evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
        disable_percpu_irq(evt->irq);
  }
  
 -static struct local_timer_ops armada_370_xp_local_timer_ops = {
 -      .setup  = armada_370_xp_timer_setup,
 -      .stop   =  armada_370_xp_timer_stop,
 +static int armada_370_xp_timer_cpu_notify(struct notifier_block *self,
 +                                         unsigned long action, void *hcpu)
 +{
 +      /*
 +       * Grab cpu pointer in each case to avoid spurious
 +       * preemptible warnings
 +       */
 +      switch (action & ~CPU_TASKS_FROZEN) {
 +      case CPU_STARTING:
 +              armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
 +              break;
 +      case CPU_DYING:
 +              armada_370_xp_timer_stop(this_cpu_ptr(armada_370_xp_evt));
 +              break;
 +      }
 +
 +      return NOTIFY_OK;
 +}
 +
 +static struct notifier_block armada_370_xp_timer_cpu_nb = {
 +      .notifier_call = armada_370_xp_timer_cpu_notify,
  };
  
void __init armada_370_xp_timer_init(void)
static void __init armada_370_xp_timer_common_init(struct device_node *np)
  {
-       u32 u;
-       struct device_node *np;
+       u32 clr = 0, set = 0;
        int res;
  
-       np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer");
        timer_base = of_iomap(np, 0);
        WARN_ON(!timer_base);
        local_base = of_iomap(np, 1);
  
-       if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
-               /* The fixed 25MHz timer is available so let's use it */
-               u = readl(timer_base + TIMER_CTRL_OFF);
-               writel(u | TIMER0_25MHZ,
-                      timer_base + TIMER_CTRL_OFF);
-               timer_clk = 25000000;
-       } else {
-               unsigned long rate = 0;
-               struct clk *clk = of_clk_get(np, 0);
-               WARN_ON(IS_ERR(clk));
-               rate =  clk_get_rate(clk);
-               u = readl(timer_base + TIMER_CTRL_OFF);
-               writel(u & ~(TIMER0_25MHZ),
-                      timer_base + TIMER_CTRL_OFF);
-               timer_clk = rate / TIMER_DIVIDER;
-               timer25Mhz = false;
-       }
+       if (timer25Mhz)
 -              set = TIMER0_25MHZ;
++              set = TIMER0_25MHZ;             
+       else
+               clr = TIMER0_25MHZ;
+       timer_ctrl_clrset(clr, set);
+       local_timer_ctrl_clrset(clr, set);
  
        /*
         * We use timer 0 as clocksource, and private(local) timer 0
         * for clockevents
         */
 -      armada_370_xp_clkevt.irq = irq_of_parse_and_map(np, 4);
 +      armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4);
  
        ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
  
        writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
        writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
  
-       u = readl(timer_base + TIMER_CTRL_OFF);
-       writel((u | TIMER0_EN | TIMER0_RELOAD_EN |
-               TIMER0_DIV(TIMER_DIVIDER_SHIFT)), timer_base + TIMER_CTRL_OFF);
+       timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN |
+                            TIMER0_DIV(TIMER_DIVIDER_SHIFT));
  
        clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
                              "armada_370_xp_clocksource",
                              timer_clk, 300, 32, clocksource_mmio_readl_down);
  
 -      /* Register the clockevent on the private timer of CPU 0 */
 -      armada_370_xp_clkevt.cpumask = cpumask_of(0);
 -      clockevents_config_and_register(&armada_370_xp_clkevt,
 -                                      timer_clk, 1, 0xfffffffe);
 +      register_cpu_notifier(&armada_370_xp_timer_cpu_nb);
  
 -      percpu_armada_370_xp_evt = alloc_percpu(struct clock_event_device *);
 +      armada_370_xp_evt = alloc_percpu(struct clock_event_device);
  
  
        /*
         * Setup clockevent timer (interrupt-driven).
         */
 -      *__this_cpu_ptr(percpu_armada_370_xp_evt) = &armada_370_xp_clkevt;
 -      res = request_percpu_irq(armada_370_xp_clkevt.irq,
 +      res = request_percpu_irq(armada_370_xp_clkevt_irq,
                                armada_370_xp_timer_interrupt,
 -                              armada_370_xp_clkevt.name,
 -                              percpu_armada_370_xp_evt);
 -      if (!res) {
 -              enable_percpu_irq(armada_370_xp_clkevt.irq, 0);
 -#ifdef CONFIG_LOCAL_TIMERS
 -              local_timer_register(&armada_370_xp_local_timer_ops);
 -#endif
 -      }
 +                              "armada_370_xp_per_cpu_tick",
 +                              armada_370_xp_evt);
 +      /* Immediately configure the timer on the boot CPU */
 +      if (!res)
 +              armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
  }
+ static void __init armada_xp_timer_init(struct device_node *np)
+ {
+       struct clk *clk = of_clk_get_by_name(np, "fixed");
+       /* The 25Mhz fixed clock is mandatory, and must always be available */
+       BUG_ON(IS_ERR(clk));
+       timer_clk = clk_get_rate(clk);
+       armada_370_xp_timer_common_init(np);
+ }
+ CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
+                      armada_xp_timer_init);
+ static void __init armada_370_timer_init(struct device_node *np)
+ {
+       struct clk *clk = of_clk_get(np, 0);
+       BUG_ON(IS_ERR(clk));
+       timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
+       timer25Mhz = false;
+       armada_370_xp_timer_common_init(np);
+ }
+ CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer",
+                      armada_370_timer_init);