linux/drivers/clocksource/exynos_mct.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* linux/arch/arm/mach-exynos4/mct.c
   3 *
   4 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
   5 *              http://www.samsung.com
   6 *
   7 * Exynos4 MCT(Multi-Core Timer) support
   8*/
   9
  10#include <linux/interrupt.h>
  11#include <linux/irq.h>
  12#include <linux/err.h>
  13#include <linux/clk.h>
  14#include <linux/clockchips.h>
  15#include <linux/cpu.h>
  16#include <linux/delay.h>
  17#include <linux/percpu.h>
  18#include <linux/of.h>
  19#include <linux/of_irq.h>
  20#include <linux/of_address.h>
  21#include <linux/clocksource.h>
  22#include <linux/sched_clock.h>
  23
  24#define EXYNOS4_MCTREG(x)               (x)
  25#define EXYNOS4_MCT_G_CNT_L             EXYNOS4_MCTREG(0x100)
  26#define EXYNOS4_MCT_G_CNT_U             EXYNOS4_MCTREG(0x104)
  27#define EXYNOS4_MCT_G_CNT_WSTAT         EXYNOS4_MCTREG(0x110)
  28#define EXYNOS4_MCT_G_COMP0_L           EXYNOS4_MCTREG(0x200)
  29#define EXYNOS4_MCT_G_COMP0_U           EXYNOS4_MCTREG(0x204)
  30#define EXYNOS4_MCT_G_COMP0_ADD_INCR    EXYNOS4_MCTREG(0x208)
  31#define EXYNOS4_MCT_G_TCON              EXYNOS4_MCTREG(0x240)
  32#define EXYNOS4_MCT_G_INT_CSTAT         EXYNOS4_MCTREG(0x244)
  33#define EXYNOS4_MCT_G_INT_ENB           EXYNOS4_MCTREG(0x248)
  34#define EXYNOS4_MCT_G_WSTAT             EXYNOS4_MCTREG(0x24C)
  35#define _EXYNOS4_MCT_L_BASE             EXYNOS4_MCTREG(0x300)
  36#define EXYNOS4_MCT_L_BASE(x)           (_EXYNOS4_MCT_L_BASE + (0x100 * x))
  37#define EXYNOS4_MCT_L_MASK              (0xffffff00)
  38
  39#define MCT_L_TCNTB_OFFSET              (0x00)
  40#define MCT_L_ICNTB_OFFSET              (0x08)
  41#define MCT_L_TCON_OFFSET               (0x20)
  42#define MCT_L_INT_CSTAT_OFFSET          (0x30)
  43#define MCT_L_INT_ENB_OFFSET            (0x34)
  44#define MCT_L_WSTAT_OFFSET              (0x40)
  45#define MCT_G_TCON_START                (1 << 8)
  46#define MCT_G_TCON_COMP0_AUTO_INC       (1 << 1)
  47#define MCT_G_TCON_COMP0_ENABLE         (1 << 0)
  48#define MCT_L_TCON_INTERVAL_MODE        (1 << 2)
  49#define MCT_L_TCON_INT_START            (1 << 1)
  50#define MCT_L_TCON_TIMER_START          (1 << 0)
  51
  52#define TICK_BASE_CNT   1
  53
  54#ifdef CONFIG_ARM
  55/* Use values higher than ARM arch timer. See 6282edb72bed. */
  56#define MCT_CLKSOURCE_RATING            450
  57#define MCT_CLKEVENTS_RATING            500
  58#else
  59#define MCT_CLKSOURCE_RATING            350
  60#define MCT_CLKEVENTS_RATING            350
  61#endif
  62
  63enum {
  64        MCT_INT_SPI,
  65        MCT_INT_PPI
  66};
  67
  68enum {
  69        MCT_G0_IRQ,
  70        MCT_G1_IRQ,
  71        MCT_G2_IRQ,
  72        MCT_G3_IRQ,
  73        MCT_L0_IRQ,
  74        MCT_L1_IRQ,
  75        MCT_L2_IRQ,
  76        MCT_L3_IRQ,
  77        MCT_L4_IRQ,
  78        MCT_L5_IRQ,
  79        MCT_L6_IRQ,
  80        MCT_L7_IRQ,
  81        MCT_NR_IRQS,
  82};
  83
  84static void __iomem *reg_base;
  85static unsigned long clk_rate;
  86static unsigned int mct_int_type;
  87static int mct_irqs[MCT_NR_IRQS];
  88
  89struct mct_clock_event_device {
  90        struct clock_event_device evt;
  91        unsigned long base;
  92        char name[10];
  93};
  94
  95static void exynos4_mct_write(unsigned int value, unsigned long offset)
  96{
  97        unsigned long stat_addr;
  98        u32 mask;
  99        u32 i;
 100
 101        writel_relaxed(value, reg_base + offset);
 102
 103        if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
 104                stat_addr = (offset & EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
 105                switch (offset & ~EXYNOS4_MCT_L_MASK) {
 106                case MCT_L_TCON_OFFSET:
 107                        mask = 1 << 3;          /* L_TCON write status */
 108                        break;
 109                case MCT_L_ICNTB_OFFSET:
 110                        mask = 1 << 1;          /* L_ICNTB write status */
 111                        break;
 112                case MCT_L_TCNTB_OFFSET:
 113                        mask = 1 << 0;          /* L_TCNTB write status */
 114                        break;
 115                default:
 116                        return;
 117                }
 118        } else {
 119                switch (offset) {
 120                case EXYNOS4_MCT_G_TCON:
 121                        stat_addr = EXYNOS4_MCT_G_WSTAT;
 122                        mask = 1 << 16;         /* G_TCON write status */
 123                        break;
 124                case EXYNOS4_MCT_G_COMP0_L:
 125                        stat_addr = EXYNOS4_MCT_G_WSTAT;
 126                        mask = 1 << 0;          /* G_COMP0_L write status */
 127                        break;
 128                case EXYNOS4_MCT_G_COMP0_U:
 129                        stat_addr = EXYNOS4_MCT_G_WSTAT;
 130                        mask = 1 << 1;          /* G_COMP0_U write status */
 131                        break;
 132                case EXYNOS4_MCT_G_COMP0_ADD_INCR:
 133                        stat_addr = EXYNOS4_MCT_G_WSTAT;
 134                        mask = 1 << 2;          /* G_COMP0_ADD_INCR w status */
 135                        break;
 136                case EXYNOS4_MCT_G_CNT_L:
 137                        stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 138                        mask = 1 << 0;          /* G_CNT_L write status */
 139                        break;
 140                case EXYNOS4_MCT_G_CNT_U:
 141                        stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 142                        mask = 1 << 1;          /* G_CNT_U write status */
 143                        break;
 144                default:
 145                        return;
 146                }
 147        }
 148
 149        /* Wait maximum 1 ms until written values are applied */
 150        for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
 151                if (readl_relaxed(reg_base + stat_addr) & mask) {
 152                        writel_relaxed(mask, reg_base + stat_addr);
 153                        return;
 154                }
 155
 156        panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
 157}
 158
 159/* Clocksource handling */
 160static void exynos4_mct_frc_start(void)
 161{
 162        u32 reg;
 163
 164        reg = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
 165        reg |= MCT_G_TCON_START;
 166        exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
 167}
 168
 169/**
 170 * exynos4_read_count_64 - Read all 64-bits of the global counter
 171 *
 172 * This will read all 64-bits of the global counter taking care to make sure
 173 * that the upper and lower half match.  Note that reading the MCT can be quite
 174 * slow (hundreds of nanoseconds) so you should use the 32-bit (lower half
 175 * only) version when possible.
 176 *
 177 * Returns the number of cycles in the global counter.
 178 */
 179static u64 exynos4_read_count_64(void)
 180{
 181        unsigned int lo, hi;
 182        u32 hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
 183
 184        do {
 185                hi = hi2;
 186                lo = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
 187                hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
 188        } while (hi != hi2);
 189
 190        return ((u64)hi << 32) | lo;
 191}
 192
 193/**
 194 * exynos4_read_count_32 - Read the lower 32-bits of the global counter
 195 *
 196 * This will read just the lower 32-bits of the global counter.  This is marked
 197 * as notrace so it can be used by the scheduler clock.
 198 *
 199 * Returns the number of cycles in the global counter (lower 32 bits).
 200 */
 201static u32 notrace exynos4_read_count_32(void)
 202{
 203        return readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
 204}
 205
 206static u64 exynos4_frc_read(struct clocksource *cs)
 207{
 208        return exynos4_read_count_32();
 209}
 210
 211static void exynos4_frc_resume(struct clocksource *cs)
 212{
 213        exynos4_mct_frc_start();
 214}
 215
 216static struct clocksource mct_frc = {
 217        .name           = "mct-frc",
 218        .rating         = MCT_CLKSOURCE_RATING,
 219        .read           = exynos4_frc_read,
 220        .mask           = CLOCKSOURCE_MASK(32),
 221        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 222        .resume         = exynos4_frc_resume,
 223};
 224
 225static u64 notrace exynos4_read_sched_clock(void)
 226{
 227        return exynos4_read_count_32();
 228}
 229
 230#if defined(CONFIG_ARM)
 231static struct delay_timer exynos4_delay_timer;
 232
 233static cycles_t exynos4_read_current_timer(void)
 234{
 235        BUILD_BUG_ON_MSG(sizeof(cycles_t) != sizeof(u32),
 236                         "cycles_t needs to move to 32-bit for ARM64 usage");
 237        return exynos4_read_count_32();
 238}
 239#endif
 240
 241static int __init exynos4_clocksource_init(void)
 242{
 243        exynos4_mct_frc_start();
 244
 245#if defined(CONFIG_ARM)
 246        exynos4_delay_timer.read_current_timer = &exynos4_read_current_timer;
 247        exynos4_delay_timer.freq = clk_rate;
 248        register_current_timer_delay(&exynos4_delay_timer);
 249#endif
 250
 251        if (clocksource_register_hz(&mct_frc, clk_rate))
 252                panic("%s: can't register clocksource\n", mct_frc.name);
 253
 254        sched_clock_register(exynos4_read_sched_clock, 32, clk_rate);
 255
 256        return 0;
 257}
 258
 259static void exynos4_mct_comp0_stop(void)
 260{
 261        unsigned int tcon;
 262
 263        tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
 264        tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
 265
 266        exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
 267        exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
 268}
 269
 270static void exynos4_mct_comp0_start(bool periodic, unsigned long cycles)
 271{
 272        unsigned int tcon;
 273        u64 comp_cycle;
 274
 275        tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
 276
 277        if (periodic) {
 278                tcon |= MCT_G_TCON_COMP0_AUTO_INC;
 279                exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
 280        }
 281
 282        comp_cycle = exynos4_read_count_64() + cycles;
 283        exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
 284        exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
 285
 286        exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
 287
 288        tcon |= MCT_G_TCON_COMP0_ENABLE;
 289        exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
 290}
 291
 292static int exynos4_comp_set_next_event(unsigned long cycles,
 293                                       struct clock_event_device *evt)
 294{
 295        exynos4_mct_comp0_start(false, cycles);
 296
 297        return 0;
 298}
 299
 300static int mct_set_state_shutdown(struct clock_event_device *evt)
 301{
 302        exynos4_mct_comp0_stop();
 303        return 0;
 304}
 305
 306static int mct_set_state_periodic(struct clock_event_device *evt)
 307{
 308        unsigned long cycles_per_jiffy;
 309
 310        cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
 311                            >> evt->shift);
 312        exynos4_mct_comp0_stop();
 313        exynos4_mct_comp0_start(true, cycles_per_jiffy);
 314        return 0;
 315}
 316
 317static struct clock_event_device mct_comp_device = {
 318        .name                   = "mct-comp",
 319        .features               = CLOCK_EVT_FEAT_PERIODIC |
 320                                  CLOCK_EVT_FEAT_ONESHOT,
 321        .rating                 = 250,
 322        .set_next_event         = exynos4_comp_set_next_event,
 323        .set_state_periodic     = mct_set_state_periodic,
 324        .set_state_shutdown     = mct_set_state_shutdown,
 325        .set_state_oneshot      = mct_set_state_shutdown,
 326        .set_state_oneshot_stopped = mct_set_state_shutdown,
 327        .tick_resume            = mct_set_state_shutdown,
 328};
 329
 330static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
 331{
 332        struct clock_event_device *evt = dev_id;
 333
 334        exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_CSTAT);
 335
 336        evt->event_handler(evt);
 337
 338        return IRQ_HANDLED;
 339}
 340
 341static int exynos4_clockevent_init(void)
 342{
 343        mct_comp_device.cpumask = cpumask_of(0);
 344        clockevents_config_and_register(&mct_comp_device, clk_rate,
 345                                        0xf, 0xffffffff);
 346        if (request_irq(mct_irqs[MCT_G0_IRQ], exynos4_mct_comp_isr,
 347                        IRQF_TIMER | IRQF_IRQPOLL, "mct_comp_irq",
 348                        &mct_comp_device))
 349                pr_err("%s: request_irq() failed\n", "mct_comp_irq");
 350
 351        return 0;
 352}
 353
 354static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
 355
 356/* Clock event handling */
 357static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
 358{
 359        unsigned long tmp;
 360        unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
 361        unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
 362
 363        tmp = readl_relaxed(reg_base + offset);
 364        if (tmp & mask) {
 365                tmp &= ~mask;
 366                exynos4_mct_write(tmp, offset);
 367        }
 368}
 369
 370static void exynos4_mct_tick_start(unsigned long cycles,
 371                                   struct mct_clock_event_device *mevt)
 372{
 373        unsigned long tmp;
 374
 375        exynos4_mct_tick_stop(mevt);
 376
 377        tmp = (1 << 31) | cycles;       /* MCT_L_UPDATE_ICNTB */
 378
 379        /* update interrupt count buffer */
 380        exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
 381
 382        /* enable MCT tick interrupt */
 383        exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 384
 385        tmp = readl_relaxed(reg_base + mevt->base + MCT_L_TCON_OFFSET);
 386        tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
 387               MCT_L_TCON_INTERVAL_MODE;
 388        exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
 389}
 390
 391static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
 392{
 393        /* Clear the MCT tick interrupt */
 394        if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1)
 395                exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 396}
 397
 398static int exynos4_tick_set_next_event(unsigned long cycles,
 399                                       struct clock_event_device *evt)
 400{
 401        struct mct_clock_event_device *mevt;
 402
 403        mevt = container_of(evt, struct mct_clock_event_device, evt);
 404        exynos4_mct_tick_start(cycles, mevt);
 405        return 0;
 406}
 407
 408static int set_state_shutdown(struct clock_event_device *evt)
 409{
 410        struct mct_clock_event_device *mevt;
 411
 412        mevt = container_of(evt, struct mct_clock_event_device, evt);
 413        exynos4_mct_tick_stop(mevt);
 414        exynos4_mct_tick_clear(mevt);
 415        return 0;
 416}
 417
 418static int set_state_periodic(struct clock_event_device *evt)
 419{
 420        struct mct_clock_event_device *mevt;
 421        unsigned long cycles_per_jiffy;
 422
 423        mevt = container_of(evt, struct mct_clock_event_device, evt);
 424        cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
 425                            >> evt->shift);
 426        exynos4_mct_tick_stop(mevt);
 427        exynos4_mct_tick_start(cycles_per_jiffy, mevt);
 428        return 0;
 429}
 430
 431static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
 432{
 433        struct mct_clock_event_device *mevt = dev_id;
 434        struct clock_event_device *evt = &mevt->evt;
 435
 436        /*
 437         * This is for supporting oneshot mode.
 438         * Mct would generate interrupt periodically
 439         * without explicit stopping.
 440         */
 441        if (!clockevent_state_periodic(&mevt->evt))
 442                exynos4_mct_tick_stop(mevt);
 443
 444        exynos4_mct_tick_clear(mevt);
 445
 446        evt->event_handler(evt);
 447
 448        return IRQ_HANDLED;
 449}
 450
 451static int exynos4_mct_starting_cpu(unsigned int cpu)
 452{
 453        struct mct_clock_event_device *mevt =
 454                per_cpu_ptr(&percpu_mct_tick, cpu);
 455        struct clock_event_device *evt = &mevt->evt;
 456
 457        mevt->base = EXYNOS4_MCT_L_BASE(cpu);
 458        snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu);
 459
 460        evt->name = mevt->name;
 461        evt->cpumask = cpumask_of(cpu);
 462        evt->set_next_event = exynos4_tick_set_next_event;
 463        evt->set_state_periodic = set_state_periodic;
 464        evt->set_state_shutdown = set_state_shutdown;
 465        evt->set_state_oneshot = set_state_shutdown;
 466        evt->set_state_oneshot_stopped = set_state_shutdown;
 467        evt->tick_resume = set_state_shutdown;
 468        evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
 469                        CLOCK_EVT_FEAT_PERCPU;
 470        evt->rating = MCT_CLKEVENTS_RATING,
 471
 472        exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
 473
 474        if (mct_int_type == MCT_INT_SPI) {
 475
 476                if (evt->irq == -1)
 477                        return -EIO;
 478
 479                irq_force_affinity(evt->irq, cpumask_of(cpu));
 480                enable_irq(evt->irq);
 481        } else {
 482                enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
 483        }
 484        clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1),
 485                                        0xf, 0x7fffffff);
 486
 487        return 0;
 488}
 489
 490static int exynos4_mct_dying_cpu(unsigned int cpu)
 491{
 492        struct mct_clock_event_device *mevt =
 493                per_cpu_ptr(&percpu_mct_tick, cpu);
 494        struct clock_event_device *evt = &mevt->evt;
 495
 496        evt->set_state_shutdown(evt);
 497        if (mct_int_type == MCT_INT_SPI) {
 498                if (evt->irq != -1)
 499                        disable_irq_nosync(evt->irq);
 500                exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 501        } else {
 502                disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 503        }
 504        return 0;
 505}
 506
 507static int __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
 508{
 509        int err, cpu;
 510        struct clk *mct_clk, *tick_clk;
 511
 512        tick_clk = of_clk_get_by_name(np, "fin_pll");
 513        if (IS_ERR(tick_clk))
 514                panic("%s: unable to determine tick clock rate\n", __func__);
 515        clk_rate = clk_get_rate(tick_clk);
 516
 517        mct_clk = of_clk_get_by_name(np, "mct");
 518        if (IS_ERR(mct_clk))
 519                panic("%s: unable to retrieve mct clock instance\n", __func__);
 520        clk_prepare_enable(mct_clk);
 521
 522        reg_base = base;
 523        if (!reg_base)
 524                panic("%s: unable to ioremap mct address space\n", __func__);
 525
 526        if (mct_int_type == MCT_INT_PPI) {
 527
 528                err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
 529                                         exynos4_mct_tick_isr, "MCT",
 530                                         &percpu_mct_tick);
 531                WARN(err, "MCT: can't request IRQ %d (%d)\n",
 532                     mct_irqs[MCT_L0_IRQ], err);
 533        } else {
 534                for_each_possible_cpu(cpu) {
 535                        int mct_irq = mct_irqs[MCT_L0_IRQ + cpu];
 536                        struct mct_clock_event_device *pcpu_mevt =
 537                                per_cpu_ptr(&percpu_mct_tick, cpu);
 538
 539                        pcpu_mevt->evt.irq = -1;
 540
 541                        irq_set_status_flags(mct_irq, IRQ_NOAUTOEN);
 542                        if (request_irq(mct_irq,
 543                                        exynos4_mct_tick_isr,
 544                                        IRQF_TIMER | IRQF_NOBALANCING,
 545                                        pcpu_mevt->name, pcpu_mevt)) {
 546                                pr_err("exynos-mct: cannot register IRQ (cpu%d)\n",
 547                                                                        cpu);
 548
 549                                continue;
 550                        }
 551                        pcpu_mevt->evt.irq = mct_irq;
 552                }
 553        }
 554
 555        /* Install hotplug callbacks which configure the timer on this CPU */
 556        err = cpuhp_setup_state(CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING,
 557                                "clockevents/exynos4/mct_timer:starting",
 558                                exynos4_mct_starting_cpu,
 559                                exynos4_mct_dying_cpu);
 560        if (err)
 561                goto out_irq;
 562
 563        return 0;
 564
 565out_irq:
 566        if (mct_int_type == MCT_INT_PPI) {
 567                free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
 568        } else {
 569                for_each_possible_cpu(cpu) {
 570                        struct mct_clock_event_device *pcpu_mevt =
 571                                per_cpu_ptr(&percpu_mct_tick, cpu);
 572
 573                        if (pcpu_mevt->evt.irq != -1) {
 574                                free_irq(pcpu_mevt->evt.irq, pcpu_mevt);
 575                                pcpu_mevt->evt.irq = -1;
 576                        }
 577                }
 578        }
 579        return err;
 580}
 581
 582static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
 583{
 584        u32 nr_irqs, i;
 585        int ret;
 586
 587        mct_int_type = int_type;
 588
 589        /* This driver uses only one global timer interrupt */
 590        mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
 591
 592        /*
 593         * Find out the number of local irqs specified. The local
 594         * timer irqs are specified after the four global timer
 595         * irqs are specified.
 596         */
 597        nr_irqs = of_irq_count(np);
 598        for (i = MCT_L0_IRQ; i < nr_irqs; i++)
 599                mct_irqs[i] = irq_of_parse_and_map(np, i);
 600
 601        ret = exynos4_timer_resources(np, of_iomap(np, 0));
 602        if (ret)
 603                return ret;
 604
 605        ret = exynos4_clocksource_init();
 606        if (ret)
 607                return ret;
 608
 609        return exynos4_clockevent_init();
 610}
 611
 612
 613static int __init mct_init_spi(struct device_node *np)
 614{
 615        return mct_init_dt(np, MCT_INT_SPI);
 616}
 617
 618static int __init mct_init_ppi(struct device_node *np)
 619{
 620        return mct_init_dt(np, MCT_INT_PPI);
 621}
 622TIMER_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
 623TIMER_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
 624