linux/drivers/clocksource/timer-ti-dm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * linux/arch/arm/plat-omap/dmtimer.c
   4 *
   5 * OMAP Dual-Mode Timers
   6 *
   7 * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
   8 * Tarun Kanti DebBarma <tarun.kanti@ti.com>
   9 * Thara Gopinath <thara@ti.com>
  10 *
  11 * dmtimer adaptation to platform_driver.
  12 *
  13 * Copyright (C) 2005 Nokia Corporation
  14 * OMAP2 support by Juha Yrjola
  15 * API improvements and OMAP2 clock framework support by Timo Teras
  16 *
  17 * Copyright (C) 2009 Texas Instruments
  18 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  19 */
  20
  21#include <linux/clk.h>
  22#include <linux/clk-provider.h>
  23#include <linux/cpu_pm.h>
  24#include <linux/module.h>
  25#include <linux/io.h>
  26#include <linux/device.h>
  27#include <linux/err.h>
  28#include <linux/pm_runtime.h>
  29#include <linux/of.h>
  30#include <linux/of_device.h>
  31#include <linux/platform_device.h>
  32#include <linux/platform_data/dmtimer-omap.h>
  33
  34#include <clocksource/timer-ti-dm.h>
  35
  36static u32 omap_reserved_systimers;
  37static LIST_HEAD(omap_timer_list);
  38static DEFINE_SPINLOCK(dm_timer_lock);
  39
  40enum {
  41        REQUEST_ANY = 0,
  42        REQUEST_BY_ID,
  43        REQUEST_BY_CAP,
  44        REQUEST_BY_NODE,
  45};
  46
  47/**
  48 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
  49 * @timer:      timer pointer over which read operation to perform
  50 * @reg:        lowest byte holds the register offset
  51 *
  52 * The posted mode bit is encoded in reg. Note that in posted mode write
  53 * pending bit must be checked. Otherwise a read of a non completed write
  54 * will produce an error.
  55 */
  56static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
  57{
  58        WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  59        return __omap_dm_timer_read(timer, reg, timer->posted);
  60}
  61
  62/**
  63 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
  64 * @timer:      timer pointer over which write operation is to perform
  65 * @reg:        lowest byte holds the register offset
  66 * @value:      data to write into the register
  67 *
  68 * The posted mode bit is encoded in reg. Note that in posted mode the write
  69 * pending bit must be checked. Otherwise a write on a register which has a
  70 * pending write will be lost.
  71 */
  72static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
  73                                                u32 value)
  74{
  75        WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  76        __omap_dm_timer_write(timer, reg, value, timer->posted);
  77}
  78
  79static void omap_timer_restore_context(struct omap_dm_timer *timer)
  80{
  81        __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET,
  82                              timer->context.ocp_cfg, 0);
  83
  84        omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
  85                                timer->context.twer);
  86        omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
  87                                timer->context.tcrr);
  88        omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
  89                                timer->context.tldr);
  90        omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
  91                                timer->context.tmar);
  92        omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
  93                                timer->context.tsicr);
  94        writel_relaxed(timer->context.tier, timer->irq_ena);
  95        omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
  96                                timer->context.tclr);
  97}
  98
  99static void omap_timer_save_context(struct omap_dm_timer *timer)
 100{
 101        timer->context.ocp_cfg =
 102                __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
 103
 104        timer->context.tclr =
 105                        omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 106        timer->context.twer =
 107                        omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG);
 108        timer->context.tldr =
 109                        omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG);
 110        timer->context.tmar =
 111                        omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG);
 112        timer->context.tier = readl_relaxed(timer->irq_ena);
 113        timer->context.tsicr =
 114                        omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG);
 115}
 116
 117static int omap_timer_context_notifier(struct notifier_block *nb,
 118                                       unsigned long cmd, void *v)
 119{
 120        struct omap_dm_timer *timer;
 121
 122        timer = container_of(nb, struct omap_dm_timer, nb);
 123
 124        switch (cmd) {
 125        case CPU_CLUSTER_PM_ENTER:
 126                if ((timer->capability & OMAP_TIMER_ALWON) ||
 127                    !atomic_read(&timer->enabled))
 128                        break;
 129                omap_timer_save_context(timer);
 130                break;
 131        case CPU_CLUSTER_PM_ENTER_FAILED:
 132        case CPU_CLUSTER_PM_EXIT:
 133                if ((timer->capability & OMAP_TIMER_ALWON) ||
 134                    !atomic_read(&timer->enabled))
 135                        break;
 136                omap_timer_restore_context(timer);
 137                break;
 138        }
 139
 140        return NOTIFY_OK;
 141}
 142
 143static int omap_dm_timer_reset(struct omap_dm_timer *timer)
 144{
 145        u32 l, timeout = 100000;
 146
 147        if (timer->revision != 1)
 148                return -EINVAL;
 149
 150        omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
 151
 152        do {
 153                l = __omap_dm_timer_read(timer,
 154                                         OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
 155        } while (!l && timeout--);
 156
 157        if (!timeout) {
 158                dev_err(&timer->pdev->dev, "Timer failed to reset\n");
 159                return -ETIMEDOUT;
 160        }
 161
 162        /* Configure timer for smart-idle mode */
 163        l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
 164        l |= 0x2 << 0x3;
 165        __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
 166
 167        timer->posted = 0;
 168
 169        return 0;
 170}
 171
 172static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 173{
 174        int ret;
 175        const char *parent_name;
 176        struct clk *parent;
 177        struct dmtimer_platform_data *pdata;
 178
 179        if (unlikely(!timer) || IS_ERR(timer->fclk))
 180                return -EINVAL;
 181
 182        switch (source) {
 183        case OMAP_TIMER_SRC_SYS_CLK:
 184                parent_name = "timer_sys_ck";
 185                break;
 186        case OMAP_TIMER_SRC_32_KHZ:
 187                parent_name = "timer_32k_ck";
 188                break;
 189        case OMAP_TIMER_SRC_EXT_CLK:
 190                parent_name = "timer_ext_ck";
 191                break;
 192        default:
 193                return -EINVAL;
 194        }
 195
 196        pdata = timer->pdev->dev.platform_data;
 197
 198        /*
 199         * FIXME: Used for OMAP1 devices only because they do not currently
 200         * use the clock framework to set the parent clock. To be removed
 201         * once OMAP1 migrated to using clock framework for dmtimers
 202         */
 203        if (pdata && pdata->set_timer_src)
 204                return pdata->set_timer_src(timer->pdev, source);
 205
 206#if defined(CONFIG_COMMON_CLK)
 207        /* Check if the clock has configurable parents */
 208        if (clk_hw_get_num_parents(__clk_get_hw(timer->fclk)) < 2)
 209                return 0;
 210#endif
 211
 212        parent = clk_get(&timer->pdev->dev, parent_name);
 213        if (IS_ERR(parent)) {
 214                pr_err("%s: %s not found\n", __func__, parent_name);
 215                return -EINVAL;
 216        }
 217
 218        ret = clk_set_parent(timer->fclk, parent);
 219        if (ret < 0)
 220                pr_err("%s: failed to set %s as parent\n", __func__,
 221                        parent_name);
 222
 223        clk_put(parent);
 224
 225        return ret;
 226}
 227
 228static void omap_dm_timer_enable(struct omap_dm_timer *timer)
 229{
 230        pm_runtime_get_sync(&timer->pdev->dev);
 231}
 232
 233static void omap_dm_timer_disable(struct omap_dm_timer *timer)
 234{
 235        pm_runtime_put_sync(&timer->pdev->dev);
 236}
 237
 238static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 239{
 240        int rc;
 241
 242        /*
 243         * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
 244         * do not call clk_get() for these devices.
 245         */
 246        if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
 247                timer->fclk = clk_get(&timer->pdev->dev, "fck");
 248                if (WARN_ON_ONCE(IS_ERR(timer->fclk))) {
 249                        dev_err(&timer->pdev->dev, ": No fclk handle.\n");
 250                        return -EINVAL;
 251                }
 252        }
 253
 254        omap_dm_timer_enable(timer);
 255
 256        if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
 257                rc = omap_dm_timer_reset(timer);
 258                if (rc) {
 259                        omap_dm_timer_disable(timer);
 260                        return rc;
 261                }
 262        }
 263
 264        __omap_dm_timer_enable_posted(timer);
 265        omap_dm_timer_disable(timer);
 266
 267        return 0;
 268}
 269
 270static inline u32 omap_dm_timer_reserved_systimer(int id)
 271{
 272        return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
 273}
 274
 275int omap_dm_timer_reserve_systimer(int id)
 276{
 277        if (omap_dm_timer_reserved_systimer(id))
 278                return -ENODEV;
 279
 280        omap_reserved_systimers |= (1 << (id - 1));
 281
 282        return 0;
 283}
 284
 285static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data)
 286{
 287        struct omap_dm_timer *timer = NULL, *t;
 288        struct device_node *np = NULL;
 289        unsigned long flags;
 290        u32 cap = 0;
 291        int id = 0;
 292
 293        switch (req_type) {
 294        case REQUEST_BY_ID:
 295                id = *(int *)data;
 296                break;
 297        case REQUEST_BY_CAP:
 298                cap = *(u32 *)data;
 299                break;
 300        case REQUEST_BY_NODE:
 301                np = (struct device_node *)data;
 302                break;
 303        default:
 304                /* REQUEST_ANY */
 305                break;
 306        }
 307
 308        spin_lock_irqsave(&dm_timer_lock, flags);
 309        list_for_each_entry(t, &omap_timer_list, node) {
 310                if (t->reserved)
 311                        continue;
 312
 313                switch (req_type) {
 314                case REQUEST_BY_ID:
 315                        if (id == t->pdev->id) {
 316                                timer = t;
 317                                timer->reserved = 1;
 318                                goto found;
 319                        }
 320                        break;
 321                case REQUEST_BY_CAP:
 322                        if (cap == (t->capability & cap)) {
 323                                /*
 324                                 * If timer is not NULL, we have already found
 325                                 * one timer. But it was not an exact match
 326                                 * because it had more capabilities than what
 327                                 * was required. Therefore, unreserve the last
 328                                 * timer found and see if this one is a better
 329                                 * match.
 330                                 */
 331                                if (timer)
 332                                        timer->reserved = 0;
 333                                timer = t;
 334                                timer->reserved = 1;
 335
 336                                /* Exit loop early if we find an exact match */
 337                                if (t->capability == cap)
 338                                        goto found;
 339                        }
 340                        break;
 341                case REQUEST_BY_NODE:
 342                        if (np == t->pdev->dev.of_node) {
 343                                timer = t;
 344                                timer->reserved = 1;
 345                                goto found;
 346                        }
 347                        break;
 348                default:
 349                        /* REQUEST_ANY */
 350                        timer = t;
 351                        timer->reserved = 1;
 352                        goto found;
 353                }
 354        }
 355found:
 356        spin_unlock_irqrestore(&dm_timer_lock, flags);
 357
 358        if (timer && omap_dm_timer_prepare(timer)) {
 359                timer->reserved = 0;
 360                timer = NULL;
 361        }
 362
 363        if (!timer)
 364                pr_debug("%s: timer request failed!\n", __func__);
 365
 366        return timer;
 367}
 368
 369static struct omap_dm_timer *omap_dm_timer_request(void)
 370{
 371        return _omap_dm_timer_request(REQUEST_ANY, NULL);
 372}
 373
 374static struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 375{
 376        /* Requesting timer by ID is not supported when device tree is used */
 377        if (of_have_populated_dt()) {
 378                pr_warn("%s: Please use omap_dm_timer_request_by_node()\n",
 379                        __func__);
 380                return NULL;
 381        }
 382
 383        return _omap_dm_timer_request(REQUEST_BY_ID, &id);
 384}
 385
 386/**
 387 * omap_dm_timer_request_by_cap - Request a timer by capability
 388 * @cap:        Bit mask of capabilities to match
 389 *
 390 * Find a timer based upon capabilities bit mask. Callers of this function
 391 * should use the definitions found in the plat/dmtimer.h file under the
 392 * comment "timer capabilities used in hwmod database". Returns pointer to
 393 * timer handle on success and a NULL pointer on failure.
 394 */
 395struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
 396{
 397        return _omap_dm_timer_request(REQUEST_BY_CAP, &cap);
 398}
 399
 400/**
 401 * omap_dm_timer_request_by_node - Request a timer by device-tree node
 402 * @np:         Pointer to device-tree timer node
 403 *
 404 * Request a timer based upon a device node pointer. Returns pointer to
 405 * timer handle on success and a NULL pointer on failure.
 406 */
 407static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)
 408{
 409        if (!np)
 410                return NULL;
 411
 412        return _omap_dm_timer_request(REQUEST_BY_NODE, np);
 413}
 414
 415static int omap_dm_timer_free(struct omap_dm_timer *timer)
 416{
 417        if (unlikely(!timer))
 418                return -EINVAL;
 419
 420        clk_put(timer->fclk);
 421
 422        WARN_ON(!timer->reserved);
 423        timer->reserved = 0;
 424        return 0;
 425}
 426
 427int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 428{
 429        if (timer)
 430                return timer->irq;
 431        return -EINVAL;
 432}
 433
 434#if defined(CONFIG_ARCH_OMAP1)
 435#include <mach/hardware.h>
 436
 437static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 438{
 439        return NULL;
 440}
 441
 442/**
 443 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
 444 * @inputmask: current value of idlect mask
 445 */
 446__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 447{
 448        int i = 0;
 449        struct omap_dm_timer *timer = NULL;
 450        unsigned long flags;
 451
 452        /* If ARMXOR cannot be idled this function call is unnecessary */
 453        if (!(inputmask & (1 << 1)))
 454                return inputmask;
 455
 456        /* If any active timer is using ARMXOR return modified mask */
 457        spin_lock_irqsave(&dm_timer_lock, flags);
 458        list_for_each_entry(timer, &omap_timer_list, node) {
 459                u32 l;
 460
 461                l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 462                if (l & OMAP_TIMER_CTRL_ST) {
 463                        if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
 464                                inputmask &= ~(1 << 1);
 465                        else
 466                                inputmask &= ~(1 << 2);
 467                }
 468                i++;
 469        }
 470        spin_unlock_irqrestore(&dm_timer_lock, flags);
 471
 472        return inputmask;
 473}
 474
 475#else
 476
 477static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 478{
 479        if (timer && !IS_ERR(timer->fclk))
 480                return timer->fclk;
 481        return NULL;
 482}
 483
 484__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 485{
 486        BUG();
 487
 488        return 0;
 489}
 490
 491#endif
 492
 493int omap_dm_timer_trigger(struct omap_dm_timer *timer)
 494{
 495        if (unlikely(!timer || !atomic_read(&timer->enabled))) {
 496                pr_err("%s: timer not available or enabled.\n", __func__);
 497                return -EINVAL;
 498        }
 499
 500        omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
 501        return 0;
 502}
 503
 504static int omap_dm_timer_start(struct omap_dm_timer *timer)
 505{
 506        u32 l;
 507
 508        if (unlikely(!timer))
 509                return -EINVAL;
 510
 511        omap_dm_timer_enable(timer);
 512
 513        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 514        if (!(l & OMAP_TIMER_CTRL_ST)) {
 515                l |= OMAP_TIMER_CTRL_ST;
 516                omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 517        }
 518
 519        return 0;
 520}
 521
 522static int omap_dm_timer_stop(struct omap_dm_timer *timer)
 523{
 524        unsigned long rate = 0;
 525
 526        if (unlikely(!timer))
 527                return -EINVAL;
 528
 529        if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
 530                rate = clk_get_rate(timer->fclk);
 531
 532        __omap_dm_timer_stop(timer, timer->posted, rate);
 533
 534        omap_dm_timer_disable(timer);
 535        return 0;
 536}
 537
 538static int omap_dm_timer_set_load(struct omap_dm_timer *timer,
 539                                  unsigned int load)
 540{
 541        if (unlikely(!timer))
 542                return -EINVAL;
 543
 544        omap_dm_timer_enable(timer);
 545        omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 546
 547        omap_dm_timer_disable(timer);
 548        return 0;
 549}
 550
 551static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 552                                   unsigned int match)
 553{
 554        u32 l;
 555
 556        if (unlikely(!timer))
 557                return -EINVAL;
 558
 559        omap_dm_timer_enable(timer);
 560        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 561        if (enable)
 562                l |= OMAP_TIMER_CTRL_CE;
 563        else
 564                l &= ~OMAP_TIMER_CTRL_CE;
 565        omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
 566        omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 567
 568        omap_dm_timer_disable(timer);
 569        return 0;
 570}
 571
 572static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 573                                 int toggle, int trigger, int autoreload)
 574{
 575        u32 l;
 576
 577        if (unlikely(!timer))
 578                return -EINVAL;
 579
 580        omap_dm_timer_enable(timer);
 581        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 582        l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
 583               OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR);
 584        if (def_on)
 585                l |= OMAP_TIMER_CTRL_SCPWM;
 586        if (toggle)
 587                l |= OMAP_TIMER_CTRL_PT;
 588        l |= trigger << 10;
 589        if (autoreload)
 590                l |= OMAP_TIMER_CTRL_AR;
 591        omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 592
 593        omap_dm_timer_disable(timer);
 594        return 0;
 595}
 596
 597static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer)
 598{
 599        u32 l;
 600
 601        if (unlikely(!timer))
 602                return -EINVAL;
 603
 604        omap_dm_timer_enable(timer);
 605        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 606        omap_dm_timer_disable(timer);
 607
 608        return l;
 609}
 610
 611static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
 612                                        int prescaler)
 613{
 614        u32 l;
 615
 616        if (unlikely(!timer) || prescaler < -1 || prescaler > 7)
 617                return -EINVAL;
 618
 619        omap_dm_timer_enable(timer);
 620        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 621        l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
 622        if (prescaler >= 0) {
 623                l |= OMAP_TIMER_CTRL_PRE;
 624                l |= prescaler << 2;
 625        }
 626        omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 627
 628        omap_dm_timer_disable(timer);
 629        return 0;
 630}
 631
 632static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 633                                        unsigned int value)
 634{
 635        if (unlikely(!timer))
 636                return -EINVAL;
 637
 638        omap_dm_timer_enable(timer);
 639        __omap_dm_timer_int_enable(timer, value);
 640
 641        omap_dm_timer_disable(timer);
 642        return 0;
 643}
 644
 645/**
 646 * omap_dm_timer_set_int_disable - disable timer interrupts
 647 * @timer:      pointer to timer handle
 648 * @mask:       bit mask of interrupts to be disabled
 649 *
 650 * Disables the specified timer interrupts for a timer.
 651 */
 652static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
 653{
 654        u32 l = mask;
 655
 656        if (unlikely(!timer))
 657                return -EINVAL;
 658
 659        omap_dm_timer_enable(timer);
 660
 661        if (timer->revision == 1)
 662                l = readl_relaxed(timer->irq_ena) & ~mask;
 663
 664        writel_relaxed(l, timer->irq_dis);
 665        l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
 666        omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
 667
 668        omap_dm_timer_disable(timer);
 669        return 0;
 670}
 671
 672static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 673{
 674        unsigned int l;
 675
 676        if (unlikely(!timer || !atomic_read(&timer->enabled))) {
 677                pr_err("%s: timer not available or enabled.\n", __func__);
 678                return 0;
 679        }
 680
 681        l = readl_relaxed(timer->irq_stat);
 682
 683        return l;
 684}
 685
 686static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 687{
 688        if (unlikely(!timer || !atomic_read(&timer->enabled)))
 689                return -EINVAL;
 690
 691        __omap_dm_timer_write_status(timer, value);
 692
 693        return 0;
 694}
 695
 696static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 697{
 698        if (unlikely(!timer || !atomic_read(&timer->enabled))) {
 699                pr_err("%s: timer not iavailable or enabled.\n", __func__);
 700                return 0;
 701        }
 702
 703        return __omap_dm_timer_read_counter(timer, timer->posted);
 704}
 705
 706static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 707{
 708        if (unlikely(!timer || !atomic_read(&timer->enabled))) {
 709                pr_err("%s: timer not available or enabled.\n", __func__);
 710                return -EINVAL;
 711        }
 712
 713        omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
 714
 715        /* Save the context */
 716        timer->context.tcrr = value;
 717        return 0;
 718}
 719
 720int omap_dm_timers_active(void)
 721{
 722        struct omap_dm_timer *timer;
 723
 724        list_for_each_entry(timer, &omap_timer_list, node) {
 725                if (!timer->reserved)
 726                        continue;
 727
 728                if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
 729                    OMAP_TIMER_CTRL_ST) {
 730                        return 1;
 731                }
 732        }
 733        return 0;
 734}
 735
 736static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
 737{
 738        struct omap_dm_timer *timer = dev_get_drvdata(dev);
 739
 740        atomic_set(&timer->enabled, 0);
 741
 742        if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base)
 743                return 0;
 744
 745        omap_timer_save_context(timer);
 746
 747        return 0;
 748}
 749
 750static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)
 751{
 752        struct omap_dm_timer *timer = dev_get_drvdata(dev);
 753
 754        if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base)
 755                omap_timer_restore_context(timer);
 756
 757        atomic_set(&timer->enabled, 1);
 758
 759        return 0;
 760}
 761
 762static const struct dev_pm_ops omap_dm_timer_pm_ops = {
 763        SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend,
 764                           omap_dm_timer_runtime_resume, NULL)
 765};
 766
 767static const struct of_device_id omap_timer_match[];
 768
 769/**
 770 * omap_dm_timer_probe - probe function called for every registered device
 771 * @pdev:       pointer to current timer platform device
 772 *
 773 * Called by driver framework at the end of device registration for all
 774 * timer devices.
 775 */
 776static int omap_dm_timer_probe(struct platform_device *pdev)
 777{
 778        unsigned long flags;
 779        struct omap_dm_timer *timer;
 780        struct device *dev = &pdev->dev;
 781        const struct dmtimer_platform_data *pdata;
 782        int ret;
 783
 784        pdata = of_device_get_match_data(dev);
 785        if (!pdata)
 786                pdata = dev_get_platdata(dev);
 787        else
 788                dev->platform_data = (void *)pdata;
 789
 790        if (!pdata) {
 791                dev_err(dev, "%s: no platform data.\n", __func__);
 792                return -ENODEV;
 793        }
 794
 795        timer = devm_kzalloc(dev, sizeof(*timer), GFP_KERNEL);
 796        if (!timer)
 797                return  -ENOMEM;
 798
 799        timer->irq = platform_get_irq(pdev, 0);
 800        if (timer->irq < 0)
 801                return timer->irq;
 802
 803        timer->fclk = ERR_PTR(-ENODEV);
 804        timer->io_base = devm_platform_ioremap_resource(pdev, 0);
 805        if (IS_ERR(timer->io_base))
 806                return PTR_ERR(timer->io_base);
 807
 808        platform_set_drvdata(pdev, timer);
 809
 810        if (dev->of_node) {
 811                if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
 812                        timer->capability |= OMAP_TIMER_ALWON;
 813                if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
 814                        timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
 815                if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
 816                        timer->capability |= OMAP_TIMER_HAS_PWM;
 817                if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
 818                        timer->capability |= OMAP_TIMER_SECURE;
 819        } else {
 820                timer->id = pdev->id;
 821                timer->capability = pdata->timer_capability;
 822                timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
 823        }
 824
 825        if (!(timer->capability & OMAP_TIMER_ALWON)) {
 826                timer->nb.notifier_call = omap_timer_context_notifier;
 827                cpu_pm_register_notifier(&timer->nb);
 828        }
 829
 830        if (pdata)
 831                timer->errata = pdata->timer_errata;
 832
 833        timer->pdev = pdev;
 834
 835        pm_runtime_enable(dev);
 836
 837        if (!timer->reserved) {
 838                ret = pm_runtime_get_sync(dev);
 839                if (ret < 0) {
 840                        dev_err(dev, "%s: pm_runtime_get_sync failed!\n",
 841                                __func__);
 842                        goto err_get_sync;
 843                }
 844                __omap_dm_timer_init_regs(timer);
 845                pm_runtime_put(dev);
 846        }
 847
 848        /* add the timer element to the list */
 849        spin_lock_irqsave(&dm_timer_lock, flags);
 850        list_add_tail(&timer->node, &omap_timer_list);
 851        spin_unlock_irqrestore(&dm_timer_lock, flags);
 852
 853        dev_dbg(dev, "Device Probed.\n");
 854
 855        return 0;
 856
 857err_get_sync:
 858        pm_runtime_put_noidle(dev);
 859        pm_runtime_disable(dev);
 860        return ret;
 861}
 862
 863/**
 864 * omap_dm_timer_remove - cleanup a registered timer device
 865 * @pdev:       pointer to current timer platform device
 866 *
 867 * Called by driver framework whenever a timer device is unregistered.
 868 * In addition to freeing platform resources it also deletes the timer
 869 * entry from the local list.
 870 */
 871static int omap_dm_timer_remove(struct platform_device *pdev)
 872{
 873        struct omap_dm_timer *timer;
 874        unsigned long flags;
 875        int ret = -EINVAL;
 876
 877        spin_lock_irqsave(&dm_timer_lock, flags);
 878        list_for_each_entry(timer, &omap_timer_list, node)
 879                if (!strcmp(dev_name(&timer->pdev->dev),
 880                            dev_name(&pdev->dev))) {
 881                        if (!(timer->capability & OMAP_TIMER_ALWON))
 882                                cpu_pm_unregister_notifier(&timer->nb);
 883                        list_del(&timer->node);
 884                        ret = 0;
 885                        break;
 886                }
 887        spin_unlock_irqrestore(&dm_timer_lock, flags);
 888
 889        pm_runtime_disable(&pdev->dev);
 890
 891        return ret;
 892}
 893
 894static const struct omap_dm_timer_ops dmtimer_ops = {
 895        .request_by_node = omap_dm_timer_request_by_node,
 896        .request_specific = omap_dm_timer_request_specific,
 897        .request = omap_dm_timer_request,
 898        .set_source = omap_dm_timer_set_source,
 899        .get_irq = omap_dm_timer_get_irq,
 900        .set_int_enable = omap_dm_timer_set_int_enable,
 901        .set_int_disable = omap_dm_timer_set_int_disable,
 902        .free = omap_dm_timer_free,
 903        .enable = omap_dm_timer_enable,
 904        .disable = omap_dm_timer_disable,
 905        .get_fclk = omap_dm_timer_get_fclk,
 906        .start = omap_dm_timer_start,
 907        .stop = omap_dm_timer_stop,
 908        .set_load = omap_dm_timer_set_load,
 909        .set_match = omap_dm_timer_set_match,
 910        .set_pwm = omap_dm_timer_set_pwm,
 911        .get_pwm_status = omap_dm_timer_get_pwm_status,
 912        .set_prescaler = omap_dm_timer_set_prescaler,
 913        .read_counter = omap_dm_timer_read_counter,
 914        .write_counter = omap_dm_timer_write_counter,
 915        .read_status = omap_dm_timer_read_status,
 916        .write_status = omap_dm_timer_write_status,
 917};
 918
 919static const struct dmtimer_platform_data omap3plus_pdata = {
 920        .timer_errata = OMAP_TIMER_ERRATA_I103_I767,
 921        .timer_ops = &dmtimer_ops,
 922};
 923
 924static const struct of_device_id omap_timer_match[] = {
 925        {
 926                .compatible = "ti,omap2420-timer",
 927        },
 928        {
 929                .compatible = "ti,omap3430-timer",
 930                .data = &omap3plus_pdata,
 931        },
 932        {
 933                .compatible = "ti,omap4430-timer",
 934                .data = &omap3plus_pdata,
 935        },
 936        {
 937                .compatible = "ti,omap5430-timer",
 938                .data = &omap3plus_pdata,
 939        },
 940        {
 941                .compatible = "ti,am335x-timer",
 942                .data = &omap3plus_pdata,
 943        },
 944        {
 945                .compatible = "ti,am335x-timer-1ms",
 946                .data = &omap3plus_pdata,
 947        },
 948        {
 949                .compatible = "ti,dm816-timer",
 950                .data = &omap3plus_pdata,
 951        },
 952        {},
 953};
 954MODULE_DEVICE_TABLE(of, omap_timer_match);
 955
 956static struct platform_driver omap_dm_timer_driver = {
 957        .probe  = omap_dm_timer_probe,
 958        .remove = omap_dm_timer_remove,
 959        .driver = {
 960                .name   = "omap_timer",
 961                .of_match_table = of_match_ptr(omap_timer_match),
 962                .pm = &omap_dm_timer_pm_ops,
 963        },
 964};
 965
 966module_platform_driver(omap_dm_timer_driver);
 967
 968MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
 969MODULE_LICENSE("GPL");
 970MODULE_AUTHOR("Texas Instruments Inc");
 971