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