2 * linux/arch/arm/plat-omap/dmtimer.c
4 * OMAP Dual-Mode Timers
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>
10 * dmtimer adaptation to platform_driver.
12 * Copyright (C) 2005 Nokia Corporation
13 * OMAP2 support by Juha Yrjola
14 * API improvements and OMAP2 clock framework support by Timo Teras
16 * Copyright (C) 2009 Texas Instruments
17 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
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.
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.
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.
38 #include <linux/module.h>
40 #include <linux/device.h>
41 #include <linux/err.h>
42 #include <linux/pm_runtime.h>
44 #include <plat/dmtimer.h>
45 #include <plat/omap-pm.h>
47 #include <mach/hardware.h>
49 static u32 omap_reserved_systimers;
50 static LIST_HEAD(omap_timer_list);
51 static DEFINE_SPINLOCK(dm_timer_lock);
54 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
55 * @timer: timer pointer over which read operation to perform
56 * @reg: lowest byte holds the register offset
58 * The posted mode bit is encoded in reg. Note that in posted mode write
59 * pending bit must be checked. Otherwise a read of a non completed write
60 * will produce an error.
62 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
64 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
65 return __omap_dm_timer_read(timer, reg, timer->posted);
69 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
70 * @timer: timer pointer over which write operation is to perform
71 * @reg: lowest byte holds the register offset
72 * @value: data to write into the register
74 * The posted mode bit is encoded in reg. Note that in posted mode the write
75 * pending bit must be checked. Otherwise a write on a register which has a
76 * pending write will be lost.
78 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
81 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
82 __omap_dm_timer_write(timer, reg, value, timer->posted);
85 static void omap_timer_restore_context(struct omap_dm_timer *timer)
87 if (timer->revision == 1)
88 __raw_writel(timer->context.tistat, timer->sys_stat);
90 __raw_writel(timer->context.tisr, timer->irq_stat);
91 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
93 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
95 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
97 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
99 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
100 timer->context.tsicr);
101 __raw_writel(timer->context.tier, timer->irq_ena);
102 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
103 timer->context.tclr);
106 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
110 if (!timer->sys_stat)
114 while (!(__raw_readl(timer->sys_stat) & 1)) {
117 printk(KERN_ERR "Timer failed to reset\n");
123 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
125 omap_dm_timer_enable(timer);
126 if (timer->pdev->id != 1) {
127 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
128 omap_dm_timer_wait_for_reset(timer);
131 __omap_dm_timer_reset(timer, 0, 0);
132 omap_dm_timer_disable(timer);
136 int omap_dm_timer_prepare(struct omap_dm_timer *timer)
141 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
142 * do not call clk_get() for these devices.
144 if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
145 timer->fclk = clk_get(&timer->pdev->dev, "fck");
146 if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
148 dev_err(&timer->pdev->dev, ": No fclk handle.\n");
153 if (timer->capability & OMAP_TIMER_NEEDS_RESET)
154 omap_dm_timer_reset(timer);
156 ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
162 static inline u32 omap_dm_timer_reserved_systimer(int id)
164 return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
167 int omap_dm_timer_reserve_systimer(int id)
169 if (omap_dm_timer_reserved_systimer(id))
172 omap_reserved_systimers |= (1 << (id - 1));
177 struct omap_dm_timer *omap_dm_timer_request(void)
179 struct omap_dm_timer *timer = NULL, *t;
183 spin_lock_irqsave(&dm_timer_lock, flags);
184 list_for_each_entry(t, &omap_timer_list, node) {
194 ret = omap_dm_timer_prepare(timer);
200 spin_unlock_irqrestore(&dm_timer_lock, flags);
203 pr_debug("%s: timer request failed!\n", __func__);
207 EXPORT_SYMBOL_GPL(omap_dm_timer_request);
209 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
211 struct omap_dm_timer *timer = NULL, *t;
215 spin_lock_irqsave(&dm_timer_lock, flags);
216 list_for_each_entry(t, &omap_timer_list, node) {
217 if (t->pdev->id == id && !t->reserved) {
225 ret = omap_dm_timer_prepare(timer);
231 spin_unlock_irqrestore(&dm_timer_lock, flags);
234 pr_debug("%s: timer%d request failed!\n", __func__, id);
238 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
240 int omap_dm_timer_free(struct omap_dm_timer *timer)
242 if (unlikely(!timer))
245 clk_put(timer->fclk);
247 WARN_ON(!timer->reserved);
251 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
253 void omap_dm_timer_enable(struct omap_dm_timer *timer)
255 pm_runtime_get_sync(&timer->pdev->dev);
257 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
259 void omap_dm_timer_disable(struct omap_dm_timer *timer)
261 pm_runtime_put(&timer->pdev->dev);
263 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
265 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
271 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
273 #if defined(CONFIG_ARCH_OMAP1)
276 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
277 * @inputmask: current value of idlect mask
279 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
282 struct omap_dm_timer *timer = NULL;
285 /* If ARMXOR cannot be idled this function call is unnecessary */
286 if (!(inputmask & (1 << 1)))
289 /* If any active timer is using ARMXOR return modified mask */
290 spin_lock_irqsave(&dm_timer_lock, flags);
291 list_for_each_entry(timer, &omap_timer_list, node) {
294 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
295 if (l & OMAP_TIMER_CTRL_ST) {
296 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
297 inputmask &= ~(1 << 1);
299 inputmask &= ~(1 << 2);
303 spin_unlock_irqrestore(&dm_timer_lock, flags);
307 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
311 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
317 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
319 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
325 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
329 int omap_dm_timer_trigger(struct omap_dm_timer *timer)
331 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
332 pr_err("%s: timer not available or enabled.\n", __func__);
336 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
339 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
341 int omap_dm_timer_start(struct omap_dm_timer *timer)
345 if (unlikely(!timer))
348 omap_dm_timer_enable(timer);
350 if (!(timer->capability & OMAP_TIMER_ALWON)) {
351 if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
352 timer->ctx_loss_count)
353 omap_timer_restore_context(timer);
356 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
357 if (!(l & OMAP_TIMER_CTRL_ST)) {
358 l |= OMAP_TIMER_CTRL_ST;
359 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
362 /* Save the context */
363 timer->context.tclr = l;
366 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
368 int omap_dm_timer_stop(struct omap_dm_timer *timer)
370 unsigned long rate = 0;
372 if (unlikely(!timer))
375 if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
376 rate = clk_get_rate(timer->fclk);
378 __omap_dm_timer_stop(timer, timer->posted, rate);
380 if (!(timer->capability & OMAP_TIMER_ALWON))
381 timer->ctx_loss_count =
382 omap_pm_get_dev_context_loss_count(&timer->pdev->dev);
385 * Since the register values are computed and written within
386 * __omap_dm_timer_stop, we need to use read to retrieve the
389 timer->context.tclr =
390 omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
391 timer->context.tisr = __raw_readl(timer->irq_stat);
392 omap_dm_timer_disable(timer);
395 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
397 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
400 char *parent_name = NULL;
401 struct clk *fclk, *parent;
402 struct dmtimer_platform_data *pdata;
404 if (unlikely(!timer))
407 pdata = timer->pdev->dev.platform_data;
409 if (source < 0 || source >= 3)
413 * FIXME: Used for OMAP1 devices only because they do not currently
414 * use the clock framework to set the parent clock. To be removed
415 * once OMAP1 migrated to using clock framework for dmtimers
417 if (pdata->set_timer_src)
418 return pdata->set_timer_src(timer->pdev, source);
420 fclk = clk_get(&timer->pdev->dev, "fck");
421 if (IS_ERR_OR_NULL(fclk)) {
422 pr_err("%s: fck not found\n", __func__);
427 case OMAP_TIMER_SRC_SYS_CLK:
428 parent_name = "timer_sys_ck";
431 case OMAP_TIMER_SRC_32_KHZ:
432 parent_name = "timer_32k_ck";
435 case OMAP_TIMER_SRC_EXT_CLK:
436 parent_name = "timer_ext_ck";
440 parent = clk_get(&timer->pdev->dev, parent_name);
441 if (IS_ERR_OR_NULL(parent)) {
442 pr_err("%s: %s not found\n", __func__, parent_name);
447 ret = clk_set_parent(fclk, parent);
448 if (IS_ERR_VALUE(ret))
449 pr_err("%s: failed to set %s as parent\n", __func__,
458 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
460 int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
465 if (unlikely(!timer))
468 omap_dm_timer_enable(timer);
469 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
471 l |= OMAP_TIMER_CTRL_AR;
473 l &= ~OMAP_TIMER_CTRL_AR;
474 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
475 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
477 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
478 /* Save the context */
479 timer->context.tclr = l;
480 timer->context.tldr = load;
481 omap_dm_timer_disable(timer);
484 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
486 /* Optimized set_load which removes costly spin wait in timer_start */
487 int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
492 if (unlikely(!timer))
495 omap_dm_timer_enable(timer);
497 if (!(timer->capability & OMAP_TIMER_ALWON)) {
498 if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
499 timer->ctx_loss_count)
500 omap_timer_restore_context(timer);
503 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
505 l |= OMAP_TIMER_CTRL_AR;
506 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
508 l &= ~OMAP_TIMER_CTRL_AR;
510 l |= OMAP_TIMER_CTRL_ST;
512 __omap_dm_timer_load_start(timer, l, load, timer->posted);
514 /* Save the context */
515 timer->context.tclr = l;
516 timer->context.tldr = load;
517 timer->context.tcrr = load;
520 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
522 int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
527 if (unlikely(!timer))
530 omap_dm_timer_enable(timer);
531 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
533 l |= OMAP_TIMER_CTRL_CE;
535 l &= ~OMAP_TIMER_CTRL_CE;
536 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
537 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
539 /* Save the context */
540 timer->context.tclr = l;
541 timer->context.tmar = match;
542 omap_dm_timer_disable(timer);
545 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
547 int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
548 int toggle, int trigger)
552 if (unlikely(!timer))
555 omap_dm_timer_enable(timer);
556 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
557 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
558 OMAP_TIMER_CTRL_PT | (0x03 << 10));
560 l |= OMAP_TIMER_CTRL_SCPWM;
562 l |= OMAP_TIMER_CTRL_PT;
564 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
566 /* Save the context */
567 timer->context.tclr = l;
568 omap_dm_timer_disable(timer);
571 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
573 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
577 if (unlikely(!timer))
580 omap_dm_timer_enable(timer);
581 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
582 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
583 if (prescaler >= 0x00 && prescaler <= 0x07) {
584 l |= OMAP_TIMER_CTRL_PRE;
587 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
589 /* Save the context */
590 timer->context.tclr = l;
591 omap_dm_timer_disable(timer);
594 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
596 int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
599 if (unlikely(!timer))
602 omap_dm_timer_enable(timer);
603 __omap_dm_timer_int_enable(timer, value);
605 /* Save the context */
606 timer->context.tier = value;
607 timer->context.twer = value;
608 omap_dm_timer_disable(timer);
611 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
613 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
617 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
618 pr_err("%s: timer not available or enabled.\n", __func__);
622 l = __raw_readl(timer->irq_stat);
626 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
628 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
630 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
633 __omap_dm_timer_write_status(timer, value);
634 /* Save the context */
635 timer->context.tisr = value;
638 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
640 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
642 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
643 pr_err("%s: timer not iavailable or enabled.\n", __func__);
647 return __omap_dm_timer_read_counter(timer, timer->posted);
649 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
651 int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
653 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
654 pr_err("%s: timer not available or enabled.\n", __func__);
658 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
660 /* Save the context */
661 timer->context.tcrr = value;
664 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
666 int omap_dm_timers_active(void)
668 struct omap_dm_timer *timer;
670 list_for_each_entry(timer, &omap_timer_list, node) {
671 if (!timer->reserved)
674 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
675 OMAP_TIMER_CTRL_ST) {
681 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
684 * omap_dm_timer_probe - probe function called for every registered device
685 * @pdev: pointer to current timer platform device
687 * Called by driver framework at the end of device registration for all
690 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
693 struct omap_dm_timer *timer;
694 struct resource *mem, *irq;
695 struct device *dev = &pdev->dev;
696 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
699 dev_err(dev, "%s: no platform data.\n", __func__);
703 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
704 if (unlikely(!irq)) {
705 dev_err(dev, "%s: no IRQ resource.\n", __func__);
709 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
710 if (unlikely(!mem)) {
711 dev_err(dev, "%s: no memory resource.\n", __func__);
715 timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
717 dev_err(dev, "%s: memory alloc failed!\n", __func__);
721 timer->io_base = devm_request_and_ioremap(dev, mem);
722 if (!timer->io_base) {
723 dev_err(dev, "%s: region already claimed.\n", __func__);
727 timer->id = pdev->id;
728 timer->irq = irq->start;
729 timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
731 timer->capability = pdata->timer_capability;
733 /* Skip pm_runtime_enable for OMAP1 */
734 if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
735 pm_runtime_enable(dev);
736 pm_runtime_irq_safe(dev);
739 if (!timer->reserved) {
740 pm_runtime_get_sync(dev);
741 __omap_dm_timer_init_regs(timer);
745 /* add the timer element to the list */
746 spin_lock_irqsave(&dm_timer_lock, flags);
747 list_add_tail(&timer->node, &omap_timer_list);
748 spin_unlock_irqrestore(&dm_timer_lock, flags);
750 dev_dbg(dev, "Device Probed.\n");
756 * omap_dm_timer_remove - cleanup a registered timer device
757 * @pdev: pointer to current timer platform device
759 * Called by driver framework whenever a timer device is unregistered.
760 * In addition to freeing platform resources it also deletes the timer
761 * entry from the local list.
763 static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
765 struct omap_dm_timer *timer;
769 spin_lock_irqsave(&dm_timer_lock, flags);
770 list_for_each_entry(timer, &omap_timer_list, node)
771 if (timer->pdev->id == pdev->id) {
772 list_del(&timer->node);
776 spin_unlock_irqrestore(&dm_timer_lock, flags);
781 static struct platform_driver omap_dm_timer_driver = {
782 .probe = omap_dm_timer_probe,
783 .remove = __devexit_p(omap_dm_timer_remove),
785 .name = "omap_timer",
789 static int __init omap_dm_timer_driver_init(void)
791 return platform_driver_register(&omap_dm_timer_driver);
794 static void __exit omap_dm_timer_driver_exit(void)
796 platform_driver_unregister(&omap_dm_timer_driver);
799 early_platform_init("earlytimer", &omap_dm_timer_driver);
800 module_init(omap_dm_timer_driver_init);
801 module_exit(omap_dm_timer_driver_exit);
803 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
804 MODULE_LICENSE("GPL");
805 MODULE_ALIAS("platform:" DRIVER_NAME);
806 MODULE_AUTHOR("Texas Instruments Inc");