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.
39 #include <linux/slab.h>
40 #include <linux/err.h>
41 #include <linux/pm_runtime.h>
43 #include <plat/dmtimer.h>
45 static LIST_HEAD(omap_timer_list);
46 static DEFINE_SPINLOCK(dm_timer_lock);
49 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
50 * @timer: timer pointer over which read operation to perform
51 * @reg: lowest byte holds the register offset
53 * The posted mode bit is encoded in reg. Note that in posted mode write
54 * pending bit must be checked. Otherwise a read of a non completed write
55 * will produce an error.
57 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
59 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
60 return __omap_dm_timer_read(timer, reg, timer->posted);
64 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
65 * @timer: timer pointer over which write operation is to perform
66 * @reg: lowest byte holds the register offset
67 * @value: data to write into the register
69 * The posted mode bit is encoded in reg. Note that in posted mode the write
70 * pending bit must be checked. Otherwise a write on a register which has a
71 * pending write will be lost.
73 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
76 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
77 __omap_dm_timer_write(timer, reg, value, timer->posted);
80 static void omap_timer_restore_context(struct omap_dm_timer *timer)
82 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_OFFSET,
83 timer->context.tiocp_cfg);
84 if (timer->revision > 1)
85 __raw_writel(timer->context.tistat, timer->sys_stat);
87 __raw_writel(timer->context.tisr, timer->irq_stat);
88 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
90 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
92 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
94 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
96 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
97 timer->context.tsicr);
98 __raw_writel(timer->context.tier, timer->irq_ena);
99 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
100 timer->context.tclr);
103 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
107 if (!timer->sys_stat)
111 while (!(__raw_readl(timer->sys_stat) & 1)) {
114 printk(KERN_ERR "Timer failed to reset\n");
120 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
122 omap_dm_timer_enable(timer);
123 if (timer->pdev->id != 1) {
124 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
125 omap_dm_timer_wait_for_reset(timer);
128 __omap_dm_timer_reset(timer, 0, 0);
129 omap_dm_timer_disable(timer);
133 int omap_dm_timer_prepare(struct omap_dm_timer *timer)
135 struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
138 timer->fclk = clk_get(&timer->pdev->dev, "fck");
139 if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
141 dev_err(&timer->pdev->dev, ": No fclk handle.\n");
145 if (pdata->needs_manual_reset)
146 omap_dm_timer_reset(timer);
148 ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
154 struct omap_dm_timer *omap_dm_timer_request(void)
156 struct omap_dm_timer *timer = NULL, *t;
160 spin_lock_irqsave(&dm_timer_lock, flags);
161 list_for_each_entry(t, &omap_timer_list, node) {
171 ret = omap_dm_timer_prepare(timer);
177 spin_unlock_irqrestore(&dm_timer_lock, flags);
180 pr_debug("%s: timer request failed!\n", __func__);
184 EXPORT_SYMBOL_GPL(omap_dm_timer_request);
186 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
188 struct omap_dm_timer *timer = NULL, *t;
192 spin_lock_irqsave(&dm_timer_lock, flags);
193 list_for_each_entry(t, &omap_timer_list, node) {
194 if (t->pdev->id == id && !t->reserved) {
202 ret = omap_dm_timer_prepare(timer);
208 spin_unlock_irqrestore(&dm_timer_lock, flags);
211 pr_debug("%s: timer%d request failed!\n", __func__, id);
215 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
217 int omap_dm_timer_free(struct omap_dm_timer *timer)
219 if (unlikely(!timer))
222 clk_put(timer->fclk);
224 WARN_ON(!timer->reserved);
228 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
230 void omap_dm_timer_enable(struct omap_dm_timer *timer)
232 pm_runtime_get_sync(&timer->pdev->dev);
234 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
236 void omap_dm_timer_disable(struct omap_dm_timer *timer)
238 pm_runtime_put(&timer->pdev->dev);
240 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
242 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
248 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
250 #if defined(CONFIG_ARCH_OMAP1)
253 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
254 * @inputmask: current value of idlect mask
256 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
259 struct omap_dm_timer *timer = NULL;
262 /* If ARMXOR cannot be idled this function call is unnecessary */
263 if (!(inputmask & (1 << 1)))
266 /* If any active timer is using ARMXOR return modified mask */
267 spin_lock_irqsave(&dm_timer_lock, flags);
268 list_for_each_entry(timer, &omap_timer_list, node) {
271 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
272 if (l & OMAP_TIMER_CTRL_ST) {
273 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
274 inputmask &= ~(1 << 1);
276 inputmask &= ~(1 << 2);
280 spin_unlock_irqrestore(&dm_timer_lock, flags);
284 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
288 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
294 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
296 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
302 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
306 int omap_dm_timer_trigger(struct omap_dm_timer *timer)
308 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
309 pr_err("%s: timer not available or enabled.\n", __func__);
313 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
316 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
318 int omap_dm_timer_start(struct omap_dm_timer *timer)
322 if (unlikely(!timer))
325 omap_dm_timer_enable(timer);
327 if (timer->loses_context) {
328 u32 ctx_loss_cnt_after =
329 timer->get_context_loss_count(&timer->pdev->dev);
330 if (ctx_loss_cnt_after != timer->ctx_loss_count)
331 omap_timer_restore_context(timer);
334 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
335 if (!(l & OMAP_TIMER_CTRL_ST)) {
336 l |= OMAP_TIMER_CTRL_ST;
337 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
340 /* Save the context */
341 timer->context.tclr = l;
344 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
346 int omap_dm_timer_stop(struct omap_dm_timer *timer)
348 unsigned long rate = 0;
349 struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
351 if (unlikely(!timer))
354 if (!pdata->needs_manual_reset)
355 rate = clk_get_rate(timer->fclk);
357 __omap_dm_timer_stop(timer, timer->posted, rate);
361 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
363 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
366 struct dmtimer_platform_data *pdata;
368 if (unlikely(!timer))
371 pdata = timer->pdev->dev.platform_data;
373 if (source < 0 || source >= 3)
376 ret = pdata->set_timer_src(timer->pdev, source);
380 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
382 int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
387 if (unlikely(!timer))
390 omap_dm_timer_enable(timer);
391 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
393 l |= OMAP_TIMER_CTRL_AR;
395 l &= ~OMAP_TIMER_CTRL_AR;
396 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
397 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
399 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
400 /* Save the context */
401 timer->context.tclr = l;
402 timer->context.tldr = load;
403 omap_dm_timer_disable(timer);
406 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
408 /* Optimized set_load which removes costly spin wait in timer_start */
409 int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
414 if (unlikely(!timer))
417 omap_dm_timer_enable(timer);
419 if (timer->loses_context) {
420 u32 ctx_loss_cnt_after =
421 timer->get_context_loss_count(&timer->pdev->dev);
422 if (ctx_loss_cnt_after != timer->ctx_loss_count)
423 omap_timer_restore_context(timer);
426 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
428 l |= OMAP_TIMER_CTRL_AR;
429 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
431 l &= ~OMAP_TIMER_CTRL_AR;
433 l |= OMAP_TIMER_CTRL_ST;
435 __omap_dm_timer_load_start(timer, l, load, timer->posted);
437 /* Save the context */
438 timer->context.tclr = l;
439 timer->context.tldr = load;
440 timer->context.tcrr = load;
443 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
445 int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
450 if (unlikely(!timer))
453 omap_dm_timer_enable(timer);
454 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
456 l |= OMAP_TIMER_CTRL_CE;
458 l &= ~OMAP_TIMER_CTRL_CE;
459 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
460 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
462 /* Save the context */
463 timer->context.tclr = l;
464 timer->context.tmar = match;
465 omap_dm_timer_disable(timer);
468 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
470 int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
471 int toggle, int trigger)
475 if (unlikely(!timer))
478 omap_dm_timer_enable(timer);
479 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
480 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
481 OMAP_TIMER_CTRL_PT | (0x03 << 10));
483 l |= OMAP_TIMER_CTRL_SCPWM;
485 l |= OMAP_TIMER_CTRL_PT;
487 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
489 /* Save the context */
490 timer->context.tclr = l;
491 omap_dm_timer_disable(timer);
494 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
496 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
500 if (unlikely(!timer))
503 omap_dm_timer_enable(timer);
504 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
505 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
506 if (prescaler >= 0x00 && prescaler <= 0x07) {
507 l |= OMAP_TIMER_CTRL_PRE;
510 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
512 /* Save the context */
513 timer->context.tclr = l;
514 omap_dm_timer_disable(timer);
517 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
519 int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
522 if (unlikely(!timer))
525 omap_dm_timer_enable(timer);
526 __omap_dm_timer_int_enable(timer, value);
528 /* Save the context */
529 timer->context.tier = value;
530 timer->context.twer = value;
531 omap_dm_timer_disable(timer);
534 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
536 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
540 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
541 pr_err("%s: timer not available or enabled.\n", __func__);
545 l = __raw_readl(timer->irq_stat);
549 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
551 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
553 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
556 __omap_dm_timer_write_status(timer, value);
557 /* Save the context */
558 timer->context.tisr = value;
561 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
563 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
565 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
566 pr_err("%s: timer not iavailable or enabled.\n", __func__);
570 return __omap_dm_timer_read_counter(timer, timer->posted);
572 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
574 int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
576 if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
577 pr_err("%s: timer not available or enabled.\n", __func__);
581 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
583 /* Save the context */
584 timer->context.tcrr = value;
587 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
589 int omap_dm_timers_active(void)
591 struct omap_dm_timer *timer;
593 list_for_each_entry(timer, &omap_timer_list, node) {
594 if (!timer->reserved)
597 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
598 OMAP_TIMER_CTRL_ST) {
604 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
607 * omap_dm_timer_probe - probe function called for every registered device
608 * @pdev: pointer to current timer platform device
610 * Called by driver framework at the end of device registration for all
613 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
617 struct omap_dm_timer *timer;
618 struct resource *mem, *irq, *ioarea;
619 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
622 dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
626 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
627 if (unlikely(!irq)) {
628 dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
632 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
633 if (unlikely(!mem)) {
634 dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
638 ioarea = request_mem_region(mem->start, resource_size(mem),
641 dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
645 timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
647 dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
650 goto err_free_ioregion;
653 timer->io_base = ioremap(mem->start, resource_size(mem));
654 if (!timer->io_base) {
655 dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
660 timer->id = pdev->id;
661 timer->irq = irq->start;
662 timer->reserved = pdata->reserved;
664 timer->loses_context = pdata->loses_context;
665 timer->get_context_loss_count = pdata->get_context_loss_count;
667 /* Skip pm_runtime_enable for OMAP1 */
668 if (!pdata->needs_manual_reset) {
669 pm_runtime_enable(&pdev->dev);
670 pm_runtime_irq_safe(&pdev->dev);
673 if (!timer->reserved) {
674 pm_runtime_get_sync(&pdev->dev);
675 __omap_dm_timer_init_regs(timer);
676 pm_runtime_put(&pdev->dev);
679 /* add the timer element to the list */
680 spin_lock_irqsave(&dm_timer_lock, flags);
681 list_add_tail(&timer->node, &omap_timer_list);
682 spin_unlock_irqrestore(&dm_timer_lock, flags);
684 dev_dbg(&pdev->dev, "Device Probed.\n");
692 release_mem_region(mem->start, resource_size(mem));
698 * omap_dm_timer_remove - cleanup a registered timer device
699 * @pdev: pointer to current timer platform device
701 * Called by driver framework whenever a timer device is unregistered.
702 * In addition to freeing platform resources it also deletes the timer
703 * entry from the local list.
705 static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
707 struct omap_dm_timer *timer;
711 spin_lock_irqsave(&dm_timer_lock, flags);
712 list_for_each_entry(timer, &omap_timer_list, node)
713 if (timer->pdev->id == pdev->id) {
714 list_del(&timer->node);
719 spin_unlock_irqrestore(&dm_timer_lock, flags);
724 static struct platform_driver omap_dm_timer_driver = {
725 .probe = omap_dm_timer_probe,
726 .remove = omap_dm_timer_remove,
728 .name = "omap_timer",
732 static int __init omap_dm_timer_driver_init(void)
734 return platform_driver_register(&omap_dm_timer_driver);
737 static void __exit omap_dm_timer_driver_exit(void)
739 platform_driver_unregister(&omap_dm_timer_driver);
742 early_platform_init("earlytimer", &omap_dm_timer_driver);
743 module_init(omap_dm_timer_driver_init);
744 module_exit(omap_dm_timer_driver_exit);
746 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
747 MODULE_LICENSE("GPL");
748 MODULE_ALIAS("platform:" DRIVER_NAME);
749 MODULE_AUTHOR("Texas Instruments Inc");