1306 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * linux/arch/arm/plat-omap/dmtimer.c4 *5 * OMAP Dual-Mode Timers6 *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 Corporation14 * OMAP2 support by Juha Yrjola15 * API improvements and OMAP2 clock framework support by Timo Teras16 *17 * Copyright (C) 2009 Texas Instruments18 * 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/platform_device.h>31#include <linux/platform_data/dmtimer-omap.h>32 33#include <clocksource/timer-ti-dm.h>34 35/*36 * timer errata flags37 *38 * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This39 * errata prevents us from using posted mode on these devices, unless the40 * timer counter register is never read. For more details please refer to41 * the OMAP3/4/5 errata documents.42 */43#define OMAP_TIMER_ERRATA_I103_I767 0x8000000044 45/* posted mode types */46#define OMAP_TIMER_NONPOSTED 0x0047#define OMAP_TIMER_POSTED 0x0148 49/* register offsets with the write pending bit encoded */50#define WPSHIFT 1651 52#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \53 | (WP_NONE << WPSHIFT))54 55#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \56 | (WP_TCLR << WPSHIFT))57 58#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \59 | (WP_TCRR << WPSHIFT))60 61#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \62 | (WP_TLDR << WPSHIFT))63 64#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \65 | (WP_TTGR << WPSHIFT))66 67#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \68 | (WP_NONE << WPSHIFT))69 70#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \71 | (WP_TMAR << WPSHIFT))72 73#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \74 | (WP_NONE << WPSHIFT))75 76#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \77 | (WP_NONE << WPSHIFT))78 79#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \80 | (WP_NONE << WPSHIFT))81 82#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \83 | (WP_TPIR << WPSHIFT))84 85#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \86 | (WP_TNIR << WPSHIFT))87 88#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \89 | (WP_TCVR << WPSHIFT))90 91#define OMAP_TIMER_TICK_INT_MASK_SET_REG \92 (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))93 94#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \95 (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))96 97struct timer_regs {98 u32 ocp_cfg;99 u32 tidr;100 u32 tier;101 u32 twer;102 u32 tclr;103 u32 tcrr;104 u32 tldr;105 u32 ttrg;106 u32 twps;107 u32 tmar;108 u32 tcar1;109 u32 tsicr;110 u32 tcar2;111 u32 tpir;112 u32 tnir;113 u32 tcvr;114 u32 tocr;115 u32 towr;116};117 118struct dmtimer {119 struct omap_dm_timer cookie;120 int id;121 int irq;122 struct clk *fclk;123 124 void __iomem *io_base;125 int irq_stat; /* TISR/IRQSTATUS interrupt status */126 int irq_ena; /* irq enable */127 int irq_dis; /* irq disable, only on v2 ip */128 void __iomem *pend; /* write pending */129 void __iomem *func_base; /* function register base */130 131 atomic_t enabled;132 unsigned reserved:1;133 unsigned posted:1;134 unsigned omap1:1;135 struct timer_regs context;136 int revision;137 u32 capability;138 u32 errata;139 struct platform_device *pdev;140 struct list_head node;141 struct notifier_block nb;142 struct notifier_block fclk_nb;143 unsigned long fclk_rate;144};145 146static u32 omap_reserved_systimers;147static LIST_HEAD(omap_timer_list);148static DEFINE_SPINLOCK(dm_timer_lock);149 150enum {151 REQUEST_ANY = 0,152 REQUEST_BY_ID,153 REQUEST_BY_CAP,154 REQUEST_BY_NODE,155};156 157/**158 * dmtimer_read - read timer registers in posted and non-posted mode159 * @timer: timer pointer over which read operation to perform160 * @reg: lowest byte holds the register offset161 *162 * The posted mode bit is encoded in reg. Note that in posted mode, write163 * pending bit must be checked. Otherwise a read of a non completed write164 * will produce an error.165 */166static inline u32 dmtimer_read(struct dmtimer *timer, u32 reg)167{168 u16 wp, offset;169 170 wp = reg >> WPSHIFT;171 offset = reg & 0xff;172 173 /* Wait for a possible write pending bit in posted mode */174 if (wp && timer->posted)175 while (readl_relaxed(timer->pend) & wp)176 cpu_relax();177 178 return readl_relaxed(timer->func_base + offset);179}180 181/**182 * dmtimer_write - write timer registers in posted and non-posted mode183 * @timer: timer pointer over which write operation is to perform184 * @reg: lowest byte holds the register offset185 * @val: data to write into the register186 *187 * The posted mode bit is encoded in reg. Note that in posted mode, the write188 * pending bit must be checked. Otherwise a write on a register which has a189 * pending write will be lost.190 */191static inline void dmtimer_write(struct dmtimer *timer, u32 reg, u32 val)192{193 u16 wp, offset;194 195 wp = reg >> WPSHIFT;196 offset = reg & 0xff;197 198 /* Wait for a possible write pending bit in posted mode */199 if (wp && timer->posted)200 while (readl_relaxed(timer->pend) & wp)201 cpu_relax();202 203 writel_relaxed(val, timer->func_base + offset);204}205 206static inline void __omap_dm_timer_init_regs(struct dmtimer *timer)207{208 u32 tidr;209 210 /* Assume v1 ip if bits [31:16] are zero */211 tidr = readl_relaxed(timer->io_base);212 if (!(tidr >> 16)) {213 timer->revision = 1;214 timer->irq_stat = OMAP_TIMER_V1_STAT_OFFSET;215 timer->irq_ena = OMAP_TIMER_V1_INT_EN_OFFSET;216 timer->irq_dis = OMAP_TIMER_V1_INT_EN_OFFSET;217 timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;218 timer->func_base = timer->io_base;219 } else {220 timer->revision = 2;221 timer->irq_stat = OMAP_TIMER_V2_IRQSTATUS - OMAP_TIMER_V2_FUNC_OFFSET;222 timer->irq_ena = OMAP_TIMER_V2_IRQENABLE_SET - OMAP_TIMER_V2_FUNC_OFFSET;223 timer->irq_dis = OMAP_TIMER_V2_IRQENABLE_CLR - OMAP_TIMER_V2_FUNC_OFFSET;224 timer->pend = timer->io_base +225 _OMAP_TIMER_WRITE_PEND_OFFSET +226 OMAP_TIMER_V2_FUNC_OFFSET;227 timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;228 }229}230 231/*232 * __omap_dm_timer_enable_posted - enables write posted mode233 * @timer: pointer to timer instance handle234 *235 * Enables the write posted mode for the timer. When posted mode is enabled236 * writes to certain timer registers are immediately acknowledged by the237 * internal bus and hence prevents stalling the CPU waiting for the write to238 * complete. Enabling this feature can improve performance for writing to the239 * timer registers.240 */241static inline void __omap_dm_timer_enable_posted(struct dmtimer *timer)242{243 if (timer->posted)244 return;245 246 if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) {247 timer->posted = OMAP_TIMER_NONPOSTED;248 dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0);249 return;250 }251 252 dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, OMAP_TIMER_CTRL_POSTED);253 timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;254 timer->posted = OMAP_TIMER_POSTED;255}256 257static inline void __omap_dm_timer_stop(struct dmtimer *timer)258{259 u32 l;260 261 l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);262 if (l & OMAP_TIMER_CTRL_ST) {263 l &= ~0x1;264 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);265#ifdef CONFIG_ARCH_OMAP2PLUS266 /* Readback to make sure write has completed */267 dmtimer_read(timer, OMAP_TIMER_CTRL_REG);268 /*269 * Wait for functional clock period x 3.5 to make sure that270 * timer is stopped271 */272 udelay(3500000 / timer->fclk_rate + 1);273#endif274 }275 276 /* Ack possibly pending interrupt */277 dmtimer_write(timer, timer->irq_stat, OMAP_TIMER_INT_OVERFLOW);278}279 280static inline void __omap_dm_timer_int_enable(struct dmtimer *timer,281 unsigned int value)282{283 dmtimer_write(timer, timer->irq_ena, value);284 dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value);285}286 287static inline unsigned int288__omap_dm_timer_read_counter(struct dmtimer *timer)289{290 return dmtimer_read(timer, OMAP_TIMER_COUNTER_REG);291}292 293static inline void __omap_dm_timer_write_status(struct dmtimer *timer,294 unsigned int value)295{296 dmtimer_write(timer, timer->irq_stat, value);297}298 299static void omap_timer_restore_context(struct dmtimer *timer)300{301 dmtimer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, timer->context.ocp_cfg);302 303 dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, timer->context.twer);304 dmtimer_write(timer, OMAP_TIMER_COUNTER_REG, timer->context.tcrr);305 dmtimer_write(timer, OMAP_TIMER_LOAD_REG, timer->context.tldr);306 dmtimer_write(timer, OMAP_TIMER_MATCH_REG, timer->context.tmar);307 dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, timer->context.tsicr);308 dmtimer_write(timer, timer->irq_ena, timer->context.tier);309 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, timer->context.tclr);310}311 312static void omap_timer_save_context(struct dmtimer *timer)313{314 timer->context.ocp_cfg = dmtimer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET);315 316 timer->context.tclr = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);317 timer->context.twer = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG);318 timer->context.tldr = dmtimer_read(timer, OMAP_TIMER_LOAD_REG);319 timer->context.tmar = dmtimer_read(timer, OMAP_TIMER_MATCH_REG);320 timer->context.tier = dmtimer_read(timer, timer->irq_ena);321 timer->context.tsicr = dmtimer_read(timer, OMAP_TIMER_IF_CTRL_REG);322}323 324static int omap_timer_context_notifier(struct notifier_block *nb,325 unsigned long cmd, void *v)326{327 struct dmtimer *timer;328 329 timer = container_of(nb, struct dmtimer, nb);330 331 switch (cmd) {332 case CPU_CLUSTER_PM_ENTER:333 if ((timer->capability & OMAP_TIMER_ALWON) ||334 !atomic_read(&timer->enabled))335 break;336 omap_timer_save_context(timer);337 break;338 case CPU_CLUSTER_PM_ENTER_FAILED: /* No need to restore context */339 break;340 case CPU_CLUSTER_PM_EXIT:341 if ((timer->capability & OMAP_TIMER_ALWON) ||342 !atomic_read(&timer->enabled))343 break;344 omap_timer_restore_context(timer);345 break;346 }347 348 return NOTIFY_OK;349}350 351static int omap_timer_fclk_notifier(struct notifier_block *nb,352 unsigned long event, void *data)353{354 struct clk_notifier_data *clk_data = data;355 struct dmtimer *timer = container_of(nb, struct dmtimer, fclk_nb);356 357 switch (event) {358 case POST_RATE_CHANGE:359 timer->fclk_rate = clk_data->new_rate;360 return NOTIFY_OK;361 default:362 return NOTIFY_DONE;363 }364}365 366static int omap_dm_timer_reset(struct dmtimer *timer)367{368 u32 l, timeout = 100000;369 370 if (timer->revision != 1)371 return -EINVAL;372 373 dmtimer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);374 375 do {376 l = dmtimer_read(timer, OMAP_TIMER_V1_SYS_STAT_OFFSET);377 } while (!l && timeout--);378 379 if (!timeout) {380 dev_err(&timer->pdev->dev, "Timer failed to reset\n");381 return -ETIMEDOUT;382 }383 384 /* Configure timer for smart-idle mode */385 l = dmtimer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET);386 l |= 0x2 << 0x3;387 dmtimer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l);388 389 timer->posted = 0;390 391 return 0;392}393 394/*395 * Functions exposed to PWM and remoteproc drivers via platform_data.396 * Do not use these in the driver, these will get deprecated and will397 * will be replaced by Linux generic framework functions such as398 * chained interrupts and clock framework.399 */400static struct dmtimer *to_dmtimer(struct omap_dm_timer *cookie)401{402 if (!cookie)403 return NULL;404 405 return container_of(cookie, struct dmtimer, cookie);406}407 408static int omap_dm_timer_set_source(struct omap_dm_timer *cookie, int source)409{410 int ret;411 const char *parent_name;412 struct clk *parent;413 struct dmtimer_platform_data *pdata;414 struct dmtimer *timer;415 416 timer = to_dmtimer(cookie);417 if (unlikely(!timer) || IS_ERR(timer->fclk))418 return -EINVAL;419 420 switch (source) {421 case OMAP_TIMER_SRC_SYS_CLK:422 parent_name = "timer_sys_ck";423 break;424 case OMAP_TIMER_SRC_32_KHZ:425 parent_name = "timer_32k_ck";426 break;427 case OMAP_TIMER_SRC_EXT_CLK:428 parent_name = "timer_ext_ck";429 break;430 default:431 return -EINVAL;432 }433 434 pdata = timer->pdev->dev.platform_data;435 436 /*437 * FIXME: Used for OMAP1 devices only because they do not currently438 * use the clock framework to set the parent clock. To be removed439 * once OMAP1 migrated to using clock framework for dmtimers440 */441 if (timer->omap1 && pdata && pdata->set_timer_src)442 return pdata->set_timer_src(timer->pdev, source);443 444#if defined(CONFIG_COMMON_CLK)445 /* Check if the clock has configurable parents */446 if (clk_hw_get_num_parents(__clk_get_hw(timer->fclk)) < 2)447 return 0;448#endif449 450 parent = clk_get(&timer->pdev->dev, parent_name);451 if (IS_ERR(parent)) {452 pr_err("%s: %s not found\n", __func__, parent_name);453 return -EINVAL;454 }455 456 ret = clk_set_parent(timer->fclk, parent);457 if (ret < 0)458 pr_err("%s: failed to set %s as parent\n", __func__,459 parent_name);460 461 clk_put(parent);462 463 return ret;464}465 466static void omap_dm_timer_enable(struct omap_dm_timer *cookie)467{468 struct dmtimer *timer = to_dmtimer(cookie);469 struct device *dev = &timer->pdev->dev;470 int rc;471 472 rc = pm_runtime_resume_and_get(dev);473 if (rc)474 dev_err(dev, "could not enable timer\n");475}476 477static void omap_dm_timer_disable(struct omap_dm_timer *cookie)478{479 struct dmtimer *timer = to_dmtimer(cookie);480 struct device *dev = &timer->pdev->dev;481 482 pm_runtime_put_sync(dev);483}484 485static int omap_dm_timer_prepare(struct dmtimer *timer)486{487 struct device *dev = &timer->pdev->dev;488 int rc;489 490 rc = pm_runtime_resume_and_get(dev);491 if (rc)492 return rc;493 494 if (timer->capability & OMAP_TIMER_NEEDS_RESET) {495 rc = omap_dm_timer_reset(timer);496 if (rc) {497 pm_runtime_put_sync(dev);498 return rc;499 }500 }501 502 __omap_dm_timer_enable_posted(timer);503 pm_runtime_put_sync(dev);504 505 return 0;506}507 508static inline u32 omap_dm_timer_reserved_systimer(int id)509{510 return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;511}512 513static struct dmtimer *_omap_dm_timer_request(int req_type, void *data)514{515 struct dmtimer *timer = NULL, *t;516 struct device_node *np = NULL;517 unsigned long flags;518 u32 cap = 0;519 int id = 0;520 521 switch (req_type) {522 case REQUEST_BY_ID:523 id = *(int *)data;524 break;525 case REQUEST_BY_CAP:526 cap = *(u32 *)data;527 break;528 case REQUEST_BY_NODE:529 np = (struct device_node *)data;530 break;531 default:532 /* REQUEST_ANY */533 break;534 }535 536 spin_lock_irqsave(&dm_timer_lock, flags);537 list_for_each_entry(t, &omap_timer_list, node) {538 if (t->reserved)539 continue;540 541 switch (req_type) {542 case REQUEST_BY_ID:543 if (id == t->pdev->id) {544 timer = t;545 timer->reserved = 1;546 goto found;547 }548 break;549 case REQUEST_BY_CAP:550 if (cap == (t->capability & cap)) {551 /*552 * If timer is not NULL, we have already found553 * one timer. But it was not an exact match554 * because it had more capabilities than what555 * was required. Therefore, unreserve the last556 * timer found and see if this one is a better557 * match.558 */559 if (timer)560 timer->reserved = 0;561 timer = t;562 timer->reserved = 1;563 564 /* Exit loop early if we find an exact match */565 if (t->capability == cap)566 goto found;567 }568 break;569 case REQUEST_BY_NODE:570 if (np == t->pdev->dev.of_node) {571 timer = t;572 timer->reserved = 1;573 goto found;574 }575 break;576 default:577 /* REQUEST_ANY */578 timer = t;579 timer->reserved = 1;580 goto found;581 }582 }583found:584 spin_unlock_irqrestore(&dm_timer_lock, flags);585 586 if (timer && omap_dm_timer_prepare(timer)) {587 timer->reserved = 0;588 timer = NULL;589 }590 591 if (!timer)592 pr_debug("%s: timer request failed!\n", __func__);593 594 return timer;595}596 597static struct omap_dm_timer *omap_dm_timer_request(void)598{599 struct dmtimer *timer;600 601 timer = _omap_dm_timer_request(REQUEST_ANY, NULL);602 if (!timer)603 return NULL;604 605 return &timer->cookie;606}607 608static struct omap_dm_timer *omap_dm_timer_request_specific(int id)609{610 struct dmtimer *timer;611 612 /* Requesting timer by ID is not supported when device tree is used */613 if (of_have_populated_dt()) {614 pr_warn("%s: Please use omap_dm_timer_request_by_node()\n",615 __func__);616 return NULL;617 }618 619 timer = _omap_dm_timer_request(REQUEST_BY_ID, &id);620 if (!timer)621 return NULL;622 623 return &timer->cookie;624}625 626/**627 * omap_dm_timer_request_by_node - Request a timer by device-tree node628 * @np: Pointer to device-tree timer node629 *630 * Request a timer based upon a device node pointer. Returns pointer to631 * timer handle on success and a NULL pointer on failure.632 */633static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)634{635 struct dmtimer *timer;636 637 if (!np)638 return NULL;639 640 timer = _omap_dm_timer_request(REQUEST_BY_NODE, np);641 if (!timer)642 return NULL;643 644 return &timer->cookie;645}646 647static int omap_dm_timer_free(struct omap_dm_timer *cookie)648{649 struct dmtimer *timer;650 struct device *dev;651 int rc;652 653 timer = to_dmtimer(cookie);654 if (unlikely(!timer))655 return -EINVAL;656 657 WARN_ON(!timer->reserved);658 timer->reserved = 0;659 660 dev = &timer->pdev->dev;661 rc = pm_runtime_resume_and_get(dev);662 if (rc)663 return rc;664 665 /* Clear timer configuration */666 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);667 668 pm_runtime_put_sync(dev);669 670 return 0;671}672 673static int omap_dm_timer_get_irq(struct omap_dm_timer *cookie)674{675 struct dmtimer *timer = to_dmtimer(cookie);676 if (timer)677 return timer->irq;678 return -EINVAL;679}680 681#if defined(CONFIG_ARCH_OMAP1)682#include <linux/soc/ti/omap1-io.h>683 684static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *cookie)685{686 return NULL;687}688 689/**690 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR691 * @inputmask: current value of idlect mask692 */693__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)694{695 int i = 0;696 struct dmtimer *timer = NULL;697 unsigned long flags;698 699 /* If ARMXOR cannot be idled this function call is unnecessary */700 if (!(inputmask & (1 << 1)))701 return inputmask;702 703 /* If any active timer is using ARMXOR return modified mask */704 spin_lock_irqsave(&dm_timer_lock, flags);705 list_for_each_entry(timer, &omap_timer_list, node) {706 u32 l;707 708 l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);709 if (l & OMAP_TIMER_CTRL_ST) {710 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)711 inputmask &= ~(1 << 1);712 else713 inputmask &= ~(1 << 2);714 }715 i++;716 }717 spin_unlock_irqrestore(&dm_timer_lock, flags);718 719 return inputmask;720}721 722#else723 724static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *cookie)725{726 struct dmtimer *timer = to_dmtimer(cookie);727 728 if (timer && !IS_ERR(timer->fclk))729 return timer->fclk;730 return NULL;731}732 733__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)734{735 BUG();736 737 return 0;738}739 740#endif741 742static int omap_dm_timer_start(struct omap_dm_timer *cookie)743{744 struct dmtimer *timer;745 struct device *dev;746 int rc;747 u32 l;748 749 timer = to_dmtimer(cookie);750 if (unlikely(!timer))751 return -EINVAL;752 753 dev = &timer->pdev->dev;754 755 rc = pm_runtime_resume_and_get(dev);756 if (rc)757 return rc;758 759 l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);760 if (!(l & OMAP_TIMER_CTRL_ST)) {761 l |= OMAP_TIMER_CTRL_ST;762 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);763 }764 765 return 0;766}767 768static int omap_dm_timer_stop(struct omap_dm_timer *cookie)769{770 struct dmtimer *timer;771 struct device *dev;772 773 timer = to_dmtimer(cookie);774 if (unlikely(!timer))775 return -EINVAL;776 777 dev = &timer->pdev->dev;778 779 __omap_dm_timer_stop(timer);780 781 pm_runtime_put_sync(dev);782 783 return 0;784}785 786static int omap_dm_timer_set_load(struct omap_dm_timer *cookie,787 unsigned int load)788{789 struct dmtimer *timer;790 struct device *dev;791 int rc;792 793 timer = to_dmtimer(cookie);794 if (unlikely(!timer))795 return -EINVAL;796 797 dev = &timer->pdev->dev;798 rc = pm_runtime_resume_and_get(dev);799 if (rc)800 return rc;801 802 dmtimer_write(timer, OMAP_TIMER_LOAD_REG, load);803 804 pm_runtime_put_sync(dev);805 806 return 0;807}808 809static int omap_dm_timer_set_match(struct omap_dm_timer *cookie, int enable,810 unsigned int match)811{812 struct dmtimer *timer;813 struct device *dev;814 int rc;815 u32 l;816 817 timer = to_dmtimer(cookie);818 if (unlikely(!timer))819 return -EINVAL;820 821 dev = &timer->pdev->dev;822 rc = pm_runtime_resume_and_get(dev);823 if (rc)824 return rc;825 826 l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);827 if (enable)828 l |= OMAP_TIMER_CTRL_CE;829 else830 l &= ~OMAP_TIMER_CTRL_CE;831 dmtimer_write(timer, OMAP_TIMER_MATCH_REG, match);832 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);833 834 pm_runtime_put_sync(dev);835 836 return 0;837}838 839static int omap_dm_timer_set_pwm(struct omap_dm_timer *cookie, int def_on,840 int toggle, int trigger, int autoreload)841{842 struct dmtimer *timer;843 struct device *dev;844 int rc;845 u32 l;846 847 timer = to_dmtimer(cookie);848 if (unlikely(!timer))849 return -EINVAL;850 851 dev = &timer->pdev->dev;852 rc = pm_runtime_resume_and_get(dev);853 if (rc)854 return rc;855 856 l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);857 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |858 OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR);859 if (def_on)860 l |= OMAP_TIMER_CTRL_SCPWM;861 if (toggle)862 l |= OMAP_TIMER_CTRL_PT;863 l |= trigger << 10;864 if (autoreload)865 l |= OMAP_TIMER_CTRL_AR;866 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);867 868 pm_runtime_put_sync(dev);869 870 return 0;871}872 873static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *cookie)874{875 struct dmtimer *timer;876 struct device *dev;877 int rc;878 u32 l;879 880 timer = to_dmtimer(cookie);881 if (unlikely(!timer))882 return -EINVAL;883 884 dev = &timer->pdev->dev;885 rc = pm_runtime_resume_and_get(dev);886 if (rc)887 return rc;888 889 l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);890 891 pm_runtime_put_sync(dev);892 893 return l;894}895 896static int omap_dm_timer_set_prescaler(struct omap_dm_timer *cookie,897 int prescaler)898{899 struct dmtimer *timer;900 struct device *dev;901 int rc;902 u32 l;903 904 timer = to_dmtimer(cookie);905 if (unlikely(!timer) || prescaler < -1 || prescaler > 7)906 return -EINVAL;907 908 dev = &timer->pdev->dev;909 rc = pm_runtime_resume_and_get(dev);910 if (rc)911 return rc;912 913 l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG);914 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));915 if (prescaler >= 0) {916 l |= OMAP_TIMER_CTRL_PRE;917 l |= prescaler << 2;918 }919 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l);920 921 pm_runtime_put_sync(dev);922 923 return 0;924}925 926static int omap_dm_timer_set_int_enable(struct omap_dm_timer *cookie,927 unsigned int value)928{929 struct dmtimer *timer;930 struct device *dev;931 int rc;932 933 timer = to_dmtimer(cookie);934 if (unlikely(!timer))935 return -EINVAL;936 937 dev = &timer->pdev->dev;938 rc = pm_runtime_resume_and_get(dev);939 if (rc)940 return rc;941 942 __omap_dm_timer_int_enable(timer, value);943 944 pm_runtime_put_sync(dev);945 946 return 0;947}948 949/**950 * omap_dm_timer_set_int_disable - disable timer interrupts951 * @cookie: pointer to timer cookie952 * @mask: bit mask of interrupts to be disabled953 *954 * Disables the specified timer interrupts for a timer.955 */956static int omap_dm_timer_set_int_disable(struct omap_dm_timer *cookie, u32 mask)957{958 struct dmtimer *timer;959 struct device *dev;960 u32 l = mask;961 int rc;962 963 timer = to_dmtimer(cookie);964 if (unlikely(!timer))965 return -EINVAL;966 967 dev = &timer->pdev->dev;968 rc = pm_runtime_resume_and_get(dev);969 if (rc)970 return rc;971 972 if (timer->revision == 1)973 l = dmtimer_read(timer, timer->irq_ena) & ~mask;974 975 dmtimer_write(timer, timer->irq_dis, l);976 l = dmtimer_read(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;977 dmtimer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, l);978 979 pm_runtime_put_sync(dev);980 981 return 0;982}983 984static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *cookie)985{986 struct dmtimer *timer;987 unsigned int l;988 989 timer = to_dmtimer(cookie);990 if (unlikely(!timer || !atomic_read(&timer->enabled))) {991 pr_err("%s: timer not available or enabled.\n", __func__);992 return 0;993 }994 995 l = dmtimer_read(timer, timer->irq_stat);996 997 return l;998}999 1000static int omap_dm_timer_write_status(struct omap_dm_timer *cookie, unsigned int value)1001{1002 struct dmtimer *timer;1003 1004 timer = to_dmtimer(cookie);1005 if (unlikely(!timer || !atomic_read(&timer->enabled)))1006 return -EINVAL;1007 1008 __omap_dm_timer_write_status(timer, value);1009 1010 return 0;1011}1012 1013static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *cookie)1014{1015 struct dmtimer *timer;1016 1017 timer = to_dmtimer(cookie);1018 if (unlikely(!timer || !atomic_read(&timer->enabled))) {1019 pr_err("%s: timer not iavailable or enabled.\n", __func__);1020 return 0;1021 }1022 1023 return __omap_dm_timer_read_counter(timer);1024}1025 1026static int omap_dm_timer_write_counter(struct omap_dm_timer *cookie, unsigned int value)1027{1028 struct dmtimer *timer;1029 1030 timer = to_dmtimer(cookie);1031 if (unlikely(!timer || !atomic_read(&timer->enabled))) {1032 pr_err("%s: timer not available or enabled.\n", __func__);1033 return -EINVAL;1034 }1035 1036 dmtimer_write(timer, OMAP_TIMER_COUNTER_REG, value);1037 1038 /* Save the context */1039 timer->context.tcrr = value;1040 return 0;1041}1042 1043static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)1044{1045 struct dmtimer *timer = dev_get_drvdata(dev);1046 1047 atomic_set(&timer->enabled, 0);1048 1049 if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base)1050 return 0;1051 1052 omap_timer_save_context(timer);1053 1054 return 0;1055}1056 1057static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)1058{1059 struct dmtimer *timer = dev_get_drvdata(dev);1060 1061 if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base)1062 omap_timer_restore_context(timer);1063 1064 atomic_set(&timer->enabled, 1);1065 1066 return 0;1067}1068 1069static const struct dev_pm_ops omap_dm_timer_pm_ops = {1070 SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend,1071 omap_dm_timer_runtime_resume, NULL)1072};1073 1074static const struct of_device_id omap_timer_match[];1075 1076/**1077 * omap_dm_timer_probe - probe function called for every registered device1078 * @pdev: pointer to current timer platform device1079 *1080 * Called by driver framework at the end of device registration for all1081 * timer devices.1082 */1083static int omap_dm_timer_probe(struct platform_device *pdev)1084{1085 unsigned long flags;1086 struct dmtimer *timer;1087 struct device *dev = &pdev->dev;1088 const struct dmtimer_platform_data *pdata;1089 int ret;1090 1091 pdata = of_device_get_match_data(dev);1092 if (!pdata)1093 pdata = dev_get_platdata(dev);1094 else1095 dev->platform_data = (void *)pdata;1096 1097 if (!pdata) {1098 dev_err(dev, "%s: no platform data.\n", __func__);1099 return -ENODEV;1100 }1101 1102 timer = devm_kzalloc(dev, sizeof(*timer), GFP_KERNEL);1103 if (!timer)1104 return -ENOMEM;1105 1106 timer->irq = platform_get_irq(pdev, 0);1107 if (timer->irq < 0)1108 return timer->irq;1109 1110 timer->io_base = devm_platform_ioremap_resource(pdev, 0);1111 if (IS_ERR(timer->io_base))1112 return PTR_ERR(timer->io_base);1113 1114 platform_set_drvdata(pdev, timer);1115 1116 if (dev->of_node) {1117 if (of_property_read_bool(dev->of_node, "ti,timer-alwon"))1118 timer->capability |= OMAP_TIMER_ALWON;1119 if (of_property_read_bool(dev->of_node, "ti,timer-dsp"))1120 timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;1121 if (of_property_read_bool(dev->of_node, "ti,timer-pwm"))1122 timer->capability |= OMAP_TIMER_HAS_PWM;1123 if (of_property_read_bool(dev->of_node, "ti,timer-secure"))1124 timer->capability |= OMAP_TIMER_SECURE;1125 } else {1126 timer->id = pdev->id;1127 timer->capability = pdata->timer_capability;1128 timer->reserved = omap_dm_timer_reserved_systimer(timer->id);1129 }1130 1131 timer->omap1 = timer->capability & OMAP_TIMER_NEEDS_RESET;1132 1133 /* OMAP1 devices do not yet use the clock framework for dmtimers */1134 if (!timer->omap1) {1135 timer->fclk = devm_clk_get(dev, "fck");1136 if (IS_ERR(timer->fclk))1137 return PTR_ERR(timer->fclk);1138 1139 timer->fclk_nb.notifier_call = omap_timer_fclk_notifier;1140 ret = devm_clk_notifier_register(dev, timer->fclk,1141 &timer->fclk_nb);1142 if (ret)1143 return ret;1144 1145 timer->fclk_rate = clk_get_rate(timer->fclk);1146 } else {1147 timer->fclk = ERR_PTR(-ENODEV);1148 }1149 1150 if (!(timer->capability & OMAP_TIMER_ALWON)) {1151 timer->nb.notifier_call = omap_timer_context_notifier;1152 cpu_pm_register_notifier(&timer->nb);1153 }1154 1155 timer->errata = pdata->timer_errata;1156 1157 timer->pdev = pdev;1158 1159 pm_runtime_enable(dev);1160 1161 if (!timer->reserved) {1162 ret = pm_runtime_resume_and_get(dev);1163 if (ret) {1164 dev_err(dev, "%s: pm_runtime_get_sync failed!\n",1165 __func__);1166 goto err_disable;1167 }1168 __omap_dm_timer_init_regs(timer);1169 1170 /* Clear timer configuration */1171 dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);1172 1173 pm_runtime_put(dev);1174 }1175 1176 /* add the timer element to the list */1177 spin_lock_irqsave(&dm_timer_lock, flags);1178 list_add_tail(&timer->node, &omap_timer_list);1179 spin_unlock_irqrestore(&dm_timer_lock, flags);1180 1181 dev_dbg(dev, "Device Probed.\n");1182 1183 return 0;1184 1185err_disable:1186 pm_runtime_disable(dev);1187 return ret;1188}1189 1190/**1191 * omap_dm_timer_remove - cleanup a registered timer device1192 * @pdev: pointer to current timer platform device1193 *1194 * Called by driver framework whenever a timer device is unregistered.1195 * In addition to freeing platform resources it also deletes the timer1196 * entry from the local list.1197 */1198static void omap_dm_timer_remove(struct platform_device *pdev)1199{1200 struct dmtimer *timer;1201 unsigned long flags;1202 int ret = -EINVAL;1203 1204 spin_lock_irqsave(&dm_timer_lock, flags);1205 list_for_each_entry(timer, &omap_timer_list, node)1206 if (!strcmp(dev_name(&timer->pdev->dev),1207 dev_name(&pdev->dev))) {1208 if (!(timer->capability & OMAP_TIMER_ALWON))1209 cpu_pm_unregister_notifier(&timer->nb);1210 list_del(&timer->node);1211 ret = 0;1212 break;1213 }1214 spin_unlock_irqrestore(&dm_timer_lock, flags);1215 1216 pm_runtime_disable(&pdev->dev);1217 1218 if (ret)1219 dev_err(&pdev->dev, "Unable to determine timer entry in list of drivers on remove\n");1220}1221 1222static const struct omap_dm_timer_ops dmtimer_ops = {1223 .request_by_node = omap_dm_timer_request_by_node,1224 .request_specific = omap_dm_timer_request_specific,1225 .request = omap_dm_timer_request,1226 .set_source = omap_dm_timer_set_source,1227 .get_irq = omap_dm_timer_get_irq,1228 .set_int_enable = omap_dm_timer_set_int_enable,1229 .set_int_disable = omap_dm_timer_set_int_disable,1230 .free = omap_dm_timer_free,1231 .enable = omap_dm_timer_enable,1232 .disable = omap_dm_timer_disable,1233 .get_fclk = omap_dm_timer_get_fclk,1234 .start = omap_dm_timer_start,1235 .stop = omap_dm_timer_stop,1236 .set_load = omap_dm_timer_set_load,1237 .set_match = omap_dm_timer_set_match,1238 .set_pwm = omap_dm_timer_set_pwm,1239 .get_pwm_status = omap_dm_timer_get_pwm_status,1240 .set_prescaler = omap_dm_timer_set_prescaler,1241 .read_counter = omap_dm_timer_read_counter,1242 .write_counter = omap_dm_timer_write_counter,1243 .read_status = omap_dm_timer_read_status,1244 .write_status = omap_dm_timer_write_status,1245};1246 1247static const struct dmtimer_platform_data omap3plus_pdata = {1248 .timer_errata = OMAP_TIMER_ERRATA_I103_I767,1249 .timer_ops = &dmtimer_ops,1250};1251 1252static const struct dmtimer_platform_data am6_pdata = {1253 .timer_ops = &dmtimer_ops,1254};1255 1256static const struct of_device_id omap_timer_match[] = {1257 {1258 .compatible = "ti,omap2420-timer",1259 },1260 {1261 .compatible = "ti,omap3430-timer",1262 .data = &omap3plus_pdata,1263 },1264 {1265 .compatible = "ti,omap4430-timer",1266 .data = &omap3plus_pdata,1267 },1268 {1269 .compatible = "ti,omap5430-timer",1270 .data = &omap3plus_pdata,1271 },1272 {1273 .compatible = "ti,am335x-timer",1274 .data = &omap3plus_pdata,1275 },1276 {1277 .compatible = "ti,am335x-timer-1ms",1278 .data = &omap3plus_pdata,1279 },1280 {1281 .compatible = "ti,dm816-timer",1282 .data = &omap3plus_pdata,1283 },1284 {1285 .compatible = "ti,am654-timer",1286 .data = &am6_pdata,1287 },1288 {},1289};1290MODULE_DEVICE_TABLE(of, omap_timer_match);1291 1292static struct platform_driver omap_dm_timer_driver = {1293 .probe = omap_dm_timer_probe,1294 .remove_new = omap_dm_timer_remove,1295 .driver = {1296 .name = "omap_timer",1297 .of_match_table = omap_timer_match,1298 .pm = &omap_dm_timer_pm_ops,1299 },1300};1301 1302module_platform_driver(omap_dm_timer_driver);1303 1304MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");1305MODULE_AUTHOR("Texas Instruments Inc");1306