linux/drivers/clocksource/time-armada-370-xp.c
<<
>>
Prefs
   1/*
   2 * Marvell Armada 370/XP SoC timer handling.
   3 *
   4 * Copyright (C) 2012 Marvell
   5 *
   6 * Lior Amsalem <alior@marvell.com>
   7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
   8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
   9 *
  10 * This file is licensed under the terms of the GNU General Public
  11 * License version 2.  This program is licensed "as is" without any
  12 * warranty of any kind, whether express or implied.
  13 *
  14 * Timer 0 is used as free-running clocksource, while timer 1 is
  15 * used as clock_event_device.
  16 *
  17 * ---
  18 * Clocksource driver for Armada 370 and Armada XP SoC.
  19 * This driver implements one compatible string for each SoC, given
  20 * each has its own characteristics:
  21 *
  22 *   * Armada 370 has no 25 MHz fixed timer.
  23 *
  24 *   * Armada XP cannot work properly without such 25 MHz fixed timer as
  25 *     doing otherwise leads to using a clocksource whose frequency varies
  26 *     when doing cpufreq frequency changes.
  27 *
  28 * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
  29 */
  30
  31#include <linux/init.h>
  32#include <linux/platform_device.h>
  33#include <linux/kernel.h>
  34#include <linux/clk.h>
  35#include <linux/cpu.h>
  36#include <linux/timer.h>
  37#include <linux/clockchips.h>
  38#include <linux/interrupt.h>
  39#include <linux/of.h>
  40#include <linux/of_irq.h>
  41#include <linux/of_address.h>
  42#include <linux/irq.h>
  43#include <linux/module.h>
  44#include <linux/sched_clock.h>
  45#include <linux/percpu.h>
  46#include <linux/syscore_ops.h>
  47
  48#include <asm/delay.h>
  49
  50/*
  51 * Timer block registers.
  52 */
  53#define TIMER_CTRL_OFF          0x0000
  54#define  TIMER0_EN               BIT(0)
  55#define  TIMER0_RELOAD_EN        BIT(1)
  56#define  TIMER0_25MHZ            BIT(11)
  57#define  TIMER0_DIV(div)         ((div) << 19)
  58#define  TIMER1_EN               BIT(2)
  59#define  TIMER1_RELOAD_EN        BIT(3)
  60#define  TIMER1_25MHZ            BIT(12)
  61#define  TIMER1_DIV(div)         ((div) << 22)
  62#define TIMER_EVENTS_STATUS     0x0004
  63#define  TIMER0_CLR_MASK         (~0x1)
  64#define  TIMER1_CLR_MASK         (~0x100)
  65#define TIMER0_RELOAD_OFF       0x0010
  66#define TIMER0_VAL_OFF          0x0014
  67#define TIMER1_RELOAD_OFF       0x0018
  68#define TIMER1_VAL_OFF          0x001c
  69
  70#define LCL_TIMER_EVENTS_STATUS 0x0028
  71/* Global timers are connected to the coherency fabric clock, and the
  72   below divider reduces their incrementing frequency. */
  73#define TIMER_DIVIDER_SHIFT     5
  74#define TIMER_DIVIDER           (1 << TIMER_DIVIDER_SHIFT)
  75
  76/*
  77 * SoC-specific data.
  78 */
  79static void __iomem *timer_base, *local_base;
  80static unsigned int timer_clk;
  81static bool timer25Mhz = true;
  82static u32 enable_mask;
  83
  84/*
  85 * Number of timer ticks per jiffy.
  86 */
  87static u32 ticks_per_jiffy;
  88
  89static struct clock_event_device __percpu *armada_370_xp_evt;
  90
  91static void local_timer_ctrl_clrset(u32 clr, u32 set)
  92{
  93        writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set,
  94                local_base + TIMER_CTRL_OFF);
  95}
  96
  97static u64 notrace armada_370_xp_read_sched_clock(void)
  98{
  99        return ~readl(timer_base + TIMER0_VAL_OFF);
 100}
 101
 102/*
 103 * Clockevent handling.
 104 */
 105static int
 106armada_370_xp_clkevt_next_event(unsigned long delta,
 107                                struct clock_event_device *dev)
 108{
 109        /*
 110         * Clear clockevent timer interrupt.
 111         */
 112        writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
 113
 114        /*
 115         * Setup new clockevent timer value.
 116         */
 117        writel(delta, local_base + TIMER0_VAL_OFF);
 118
 119        /*
 120         * Enable the timer.
 121         */
 122        local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask);
 123        return 0;
 124}
 125
 126static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt)
 127{
 128        /*
 129         * Disable timer.
 130         */
 131        local_timer_ctrl_clrset(TIMER0_EN, 0);
 132
 133        /*
 134         * ACK pending timer interrupt.
 135         */
 136        writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
 137        return 0;
 138}
 139
 140static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt)
 141{
 142        /*
 143         * Setup timer to fire at 1/HZ intervals.
 144         */
 145        writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF);
 146        writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF);
 147
 148        /*
 149         * Enable timer.
 150         */
 151        local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
 152        return 0;
 153}
 154
 155static int armada_370_xp_clkevt_irq;
 156
 157static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
 158{
 159        /*
 160         * ACK timer interrupt and call event handler.
 161         */
 162        struct clock_event_device *evt = dev_id;
 163
 164        writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
 165        evt->event_handler(evt);
 166
 167        return IRQ_HANDLED;
 168}
 169
 170/*
 171 * Setup the local clock events for a CPU.
 172 */
 173static int armada_370_xp_timer_setup(struct clock_event_device *evt)
 174{
 175        u32 clr = 0, set = 0;
 176        int cpu = smp_processor_id();
 177
 178        if (timer25Mhz)
 179                set = TIMER0_25MHZ;
 180        else
 181                clr = TIMER0_25MHZ;
 182        local_timer_ctrl_clrset(clr, set);
 183
 184        evt->name               = "armada_370_xp_per_cpu_tick",
 185        evt->features           = CLOCK_EVT_FEAT_ONESHOT |
 186                                  CLOCK_EVT_FEAT_PERIODIC;
 187        evt->shift              = 32,
 188        evt->rating             = 300,
 189        evt->set_next_event     = armada_370_xp_clkevt_next_event,
 190        evt->set_state_shutdown = armada_370_xp_clkevt_shutdown;
 191        evt->set_state_periodic = armada_370_xp_clkevt_set_periodic;
 192        evt->set_state_oneshot  = armada_370_xp_clkevt_shutdown;
 193        evt->tick_resume        = armada_370_xp_clkevt_shutdown;
 194        evt->irq                = armada_370_xp_clkevt_irq;
 195        evt->cpumask            = cpumask_of(cpu);
 196
 197        clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe);
 198        enable_percpu_irq(evt->irq, 0);
 199
 200        return 0;
 201}
 202
 203static void armada_370_xp_timer_stop(struct clock_event_device *evt)
 204{
 205        evt->set_state_shutdown(evt);
 206        disable_percpu_irq(evt->irq);
 207}
 208
 209static int armada_370_xp_timer_cpu_notify(struct notifier_block *self,
 210                                           unsigned long action, void *hcpu)
 211{
 212        /*
 213         * Grab cpu pointer in each case to avoid spurious
 214         * preemptible warnings
 215         */
 216        switch (action & ~CPU_TASKS_FROZEN) {
 217        case CPU_STARTING:
 218                armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
 219                break;
 220        case CPU_DYING:
 221                armada_370_xp_timer_stop(this_cpu_ptr(armada_370_xp_evt));
 222                break;
 223        }
 224
 225        return NOTIFY_OK;
 226}
 227
 228static struct notifier_block armada_370_xp_timer_cpu_nb = {
 229        .notifier_call = armada_370_xp_timer_cpu_notify,
 230};
 231
 232static u32 timer0_ctrl_reg, timer0_local_ctrl_reg;
 233
 234static int armada_370_xp_timer_suspend(void)
 235{
 236        timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF);
 237        timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF);
 238        return 0;
 239}
 240
 241static void armada_370_xp_timer_resume(void)
 242{
 243        writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
 244        writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
 245        writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF);
 246        writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF);
 247}
 248
 249struct syscore_ops armada_370_xp_timer_syscore_ops = {
 250        .suspend        = armada_370_xp_timer_suspend,
 251        .resume         = armada_370_xp_timer_resume,
 252};
 253
 254static unsigned long armada_370_delay_timer_read(void)
 255{
 256        return ~readl(timer_base + TIMER0_VAL_OFF);
 257}
 258
 259static struct delay_timer armada_370_delay_timer = {
 260        .read_current_timer = armada_370_delay_timer_read,
 261};
 262
 263static void __init armada_370_xp_timer_common_init(struct device_node *np)
 264{
 265        u32 clr = 0, set = 0;
 266        int res;
 267
 268        timer_base = of_iomap(np, 0);
 269        WARN_ON(!timer_base);
 270        local_base = of_iomap(np, 1);
 271
 272        if (timer25Mhz) {
 273                set = TIMER0_25MHZ;             
 274                enable_mask = TIMER0_EN;
 275        } else {
 276                clr = TIMER0_25MHZ;
 277                enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT);
 278        }
 279        atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set);
 280        local_timer_ctrl_clrset(clr, set);
 281
 282        /*
 283         * We use timer 0 as clocksource, and private(local) timer 0
 284         * for clockevents
 285         */
 286        armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4);
 287
 288        ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
 289
 290        /*
 291         * Setup free-running clocksource timer (interrupts
 292         * disabled).
 293         */
 294        writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
 295        writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
 296
 297        atomic_io_modify(timer_base + TIMER_CTRL_OFF,
 298                TIMER0_RELOAD_EN | enable_mask,
 299                TIMER0_RELOAD_EN | enable_mask);
 300
 301        armada_370_delay_timer.freq = timer_clk;
 302        register_current_timer_delay(&armada_370_delay_timer);
 303
 304        /*
 305         * Set scale and timer for sched_clock.
 306         */
 307        sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
 308
 309        clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
 310                              "armada_370_xp_clocksource",
 311                              timer_clk, 300, 32, clocksource_mmio_readl_down);
 312
 313        register_cpu_notifier(&armada_370_xp_timer_cpu_nb);
 314
 315        armada_370_xp_evt = alloc_percpu(struct clock_event_device);
 316
 317
 318        /*
 319         * Setup clockevent timer (interrupt-driven).
 320         */
 321        res = request_percpu_irq(armada_370_xp_clkevt_irq,
 322                                armada_370_xp_timer_interrupt,
 323                                "armada_370_xp_per_cpu_tick",
 324                                armada_370_xp_evt);
 325        /* Immediately configure the timer on the boot CPU */
 326        if (!res)
 327                armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
 328
 329        register_syscore_ops(&armada_370_xp_timer_syscore_ops);
 330}
 331
 332static void __init armada_xp_timer_init(struct device_node *np)
 333{
 334        struct clk *clk = of_clk_get_by_name(np, "fixed");
 335
 336        /* The 25Mhz fixed clock is mandatory, and must always be available */
 337        BUG_ON(IS_ERR(clk));
 338        clk_prepare_enable(clk);
 339        timer_clk = clk_get_rate(clk);
 340
 341        armada_370_xp_timer_common_init(np);
 342}
 343CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
 344                       armada_xp_timer_init);
 345
 346static void __init armada_375_timer_init(struct device_node *np)
 347{
 348        struct clk *clk;
 349
 350        clk = of_clk_get_by_name(np, "fixed");
 351        if (!IS_ERR(clk)) {
 352                clk_prepare_enable(clk);
 353                timer_clk = clk_get_rate(clk);
 354        } else {
 355
 356                /*
 357                 * This fallback is required in order to retain proper
 358                 * devicetree backwards compatibility.
 359                 */
 360                clk = of_clk_get(np, 0);
 361
 362                /* Must have at least a clock */
 363                BUG_ON(IS_ERR(clk));
 364                clk_prepare_enable(clk);
 365                timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
 366                timer25Mhz = false;
 367        }
 368
 369        armada_370_xp_timer_common_init(np);
 370}
 371CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer",
 372                       armada_375_timer_init);
 373
 374static void __init armada_370_timer_init(struct device_node *np)
 375{
 376        struct clk *clk = of_clk_get(np, 0);
 377
 378        BUG_ON(IS_ERR(clk));
 379        clk_prepare_enable(clk);
 380        timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
 381        timer25Mhz = false;
 382
 383        armada_370_xp_timer_common_init(np);
 384}
 385CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer",
 386                       armada_370_timer_init);
 387