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/clk.h>
39 #include <linux/module.h>
41 #include <linux/device.h>
42 #include <linux/err.h>
43 #include <linux/pm_runtime.h>
45 #include <linux/of_device.h>
46 #include <linux/platform_device.h>
47 #include <linux/platform_data/dmtimer-omap.h>
49 #include <plat/dmtimer.h>
51 static u32 omap_reserved_systimers
;
52 static LIST_HEAD(omap_timer_list
);
53 static DEFINE_SPINLOCK(dm_timer_lock
);
56 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
57 * @timer: timer pointer over which read operation to perform
58 * @reg: lowest byte holds the register offset
60 * The posted mode bit is encoded in reg. Note that in posted mode write
61 * pending bit must be checked. Otherwise a read of a non completed write
62 * will produce an error.
64 static inline u32
omap_dm_timer_read_reg(struct omap_dm_timer
*timer
, u32 reg
)
66 WARN_ON((reg
& 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET
);
67 return __omap_dm_timer_read(timer
, reg
, timer
->posted
);
71 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
72 * @timer: timer pointer over which write operation is to perform
73 * @reg: lowest byte holds the register offset
74 * @value: data to write into the register
76 * The posted mode bit is encoded in reg. Note that in posted mode the write
77 * pending bit must be checked. Otherwise a write on a register which has a
78 * pending write will be lost.
80 static void omap_dm_timer_write_reg(struct omap_dm_timer
*timer
, u32 reg
,
83 WARN_ON((reg
& 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET
);
84 __omap_dm_timer_write(timer
, reg
, value
, timer
->posted
);
87 static void omap_timer_restore_context(struct omap_dm_timer
*timer
)
89 omap_dm_timer_write_reg(timer
, OMAP_TIMER_WAKEUP_EN_REG
,
91 omap_dm_timer_write_reg(timer
, OMAP_TIMER_COUNTER_REG
,
93 omap_dm_timer_write_reg(timer
, OMAP_TIMER_LOAD_REG
,
95 omap_dm_timer_write_reg(timer
, OMAP_TIMER_MATCH_REG
,
97 omap_dm_timer_write_reg(timer
, OMAP_TIMER_IF_CTRL_REG
,
98 timer
->context
.tsicr
);
99 __raw_writel(timer
->context
.tier
, timer
->irq_ena
);
100 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
,
101 timer
->context
.tclr
);
104 static int omap_dm_timer_reset(struct omap_dm_timer
*timer
)
106 u32 l
, timeout
= 100000;
108 if (timer
->revision
!= 1)
111 omap_dm_timer_write_reg(timer
, OMAP_TIMER_IF_CTRL_REG
, 0x06);
114 l
= __omap_dm_timer_read(timer
,
115 OMAP_TIMER_V1_SYS_STAT_OFFSET
, 0);
116 } while (!l
&& timeout
--);
119 dev_err(&timer
->pdev
->dev
, "Timer failed to reset\n");
123 /* Configure timer for smart-idle mode */
124 l
= __omap_dm_timer_read(timer
, OMAP_TIMER_OCP_CFG_OFFSET
, 0);
126 __omap_dm_timer_write(timer
, OMAP_TIMER_OCP_CFG_OFFSET
, l
, 0);
133 static int omap_dm_timer_prepare(struct omap_dm_timer
*timer
)
138 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
139 * do not call clk_get() for these devices.
141 if (!(timer
->capability
& OMAP_TIMER_NEEDS_RESET
)) {
142 timer
->fclk
= clk_get(&timer
->pdev
->dev
, "fck");
143 if (WARN_ON_ONCE(IS_ERR(timer
->fclk
))) {
144 dev_err(&timer
->pdev
->dev
, ": No fclk handle.\n");
149 omap_dm_timer_enable(timer
);
151 if (timer
->capability
& OMAP_TIMER_NEEDS_RESET
) {
152 rc
= omap_dm_timer_reset(timer
);
154 omap_dm_timer_disable(timer
);
159 __omap_dm_timer_enable_posted(timer
);
160 omap_dm_timer_disable(timer
);
162 return omap_dm_timer_set_source(timer
, OMAP_TIMER_SRC_32_KHZ
);
165 static inline u32
omap_dm_timer_reserved_systimer(int id
)
167 return (omap_reserved_systimers
& (1 << (id
- 1))) ? 1 : 0;
170 int omap_dm_timer_reserve_systimer(int id
)
172 if (omap_dm_timer_reserved_systimer(id
))
175 omap_reserved_systimers
|= (1 << (id
- 1));
180 struct omap_dm_timer
*omap_dm_timer_request(void)
182 struct omap_dm_timer
*timer
= NULL
, *t
;
186 spin_lock_irqsave(&dm_timer_lock
, flags
);
187 list_for_each_entry(t
, &omap_timer_list
, node
) {
195 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
198 ret
= omap_dm_timer_prepare(timer
);
206 pr_debug("%s: timer request failed!\n", __func__
);
210 EXPORT_SYMBOL_GPL(omap_dm_timer_request
);
212 struct omap_dm_timer
*omap_dm_timer_request_specific(int id
)
214 struct omap_dm_timer
*timer
= NULL
, *t
;
218 /* Requesting timer by ID is not supported when device tree is used */
219 if (of_have_populated_dt()) {
220 pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n",
225 spin_lock_irqsave(&dm_timer_lock
, flags
);
226 list_for_each_entry(t
, &omap_timer_list
, node
) {
227 if (t
->pdev
->id
== id
&& !t
->reserved
) {
233 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
236 ret
= omap_dm_timer_prepare(timer
);
244 pr_debug("%s: timer%d request failed!\n", __func__
, id
);
248 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific
);
251 * omap_dm_timer_request_by_cap - Request a timer by capability
252 * @cap: Bit mask of capabilities to match
254 * Find a timer based upon capabilities bit mask. Callers of this function
255 * should use the definitions found in the plat/dmtimer.h file under the
256 * comment "timer capabilities used in hwmod database". Returns pointer to
257 * timer handle on success and a NULL pointer on failure.
259 struct omap_dm_timer
*omap_dm_timer_request_by_cap(u32 cap
)
261 struct omap_dm_timer
*timer
= NULL
, *t
;
267 spin_lock_irqsave(&dm_timer_lock
, flags
);
268 list_for_each_entry(t
, &omap_timer_list
, node
) {
269 if ((!t
->reserved
) && ((t
->capability
& cap
) == cap
)) {
271 * If timer is not NULL, we have already found one timer
272 * but it was not an exact match because it had more
273 * capabilites that what was required. Therefore,
274 * unreserve the last timer found and see if this one
283 /* Exit loop early if we find an exact match */
284 if (t
->capability
== cap
)
288 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
290 if (timer
&& omap_dm_timer_prepare(timer
)) {
296 pr_debug("%s: timer request failed!\n", __func__
);
300 EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap
);
302 int omap_dm_timer_free(struct omap_dm_timer
*timer
)
304 if (unlikely(!timer
))
307 clk_put(timer
->fclk
);
309 WARN_ON(!timer
->reserved
);
313 EXPORT_SYMBOL_GPL(omap_dm_timer_free
);
315 void omap_dm_timer_enable(struct omap_dm_timer
*timer
)
317 pm_runtime_get_sync(&timer
->pdev
->dev
);
319 EXPORT_SYMBOL_GPL(omap_dm_timer_enable
);
321 void omap_dm_timer_disable(struct omap_dm_timer
*timer
)
323 pm_runtime_put_sync(&timer
->pdev
->dev
);
325 EXPORT_SYMBOL_GPL(omap_dm_timer_disable
);
327 int omap_dm_timer_get_irq(struct omap_dm_timer
*timer
)
333 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq
);
335 #if defined(CONFIG_ARCH_OMAP1)
336 #include <mach/hardware.h>
338 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
339 * @inputmask: current value of idlect mask
341 __u32
omap_dm_timer_modify_idlect_mask(__u32 inputmask
)
344 struct omap_dm_timer
*timer
= NULL
;
347 /* If ARMXOR cannot be idled this function call is unnecessary */
348 if (!(inputmask
& (1 << 1)))
351 /* If any active timer is using ARMXOR return modified mask */
352 spin_lock_irqsave(&dm_timer_lock
, flags
);
353 list_for_each_entry(timer
, &omap_timer_list
, node
) {
356 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
357 if (l
& OMAP_TIMER_CTRL_ST
) {
358 if (((omap_readl(MOD_CONF_CTRL_1
) >> (i
* 2)) & 0x03) == 0)
359 inputmask
&= ~(1 << 1);
361 inputmask
&= ~(1 << 2);
365 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
369 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask
);
373 struct clk
*omap_dm_timer_get_fclk(struct omap_dm_timer
*timer
)
375 if (timer
&& !IS_ERR(timer
->fclk
))
379 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk
);
381 __u32
omap_dm_timer_modify_idlect_mask(__u32 inputmask
)
387 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask
);
391 int omap_dm_timer_trigger(struct omap_dm_timer
*timer
)
393 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
394 pr_err("%s: timer not available or enabled.\n", __func__
);
398 omap_dm_timer_write_reg(timer
, OMAP_TIMER_TRIGGER_REG
, 0);
401 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger
);
403 int omap_dm_timer_start(struct omap_dm_timer
*timer
)
407 if (unlikely(!timer
))
410 omap_dm_timer_enable(timer
);
412 if (!(timer
->capability
& OMAP_TIMER_ALWON
)) {
413 if (timer
->get_context_loss_count
&&
414 timer
->get_context_loss_count(&timer
->pdev
->dev
) !=
415 timer
->ctx_loss_count
)
416 omap_timer_restore_context(timer
);
419 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
420 if (!(l
& OMAP_TIMER_CTRL_ST
)) {
421 l
|= OMAP_TIMER_CTRL_ST
;
422 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
425 /* Save the context */
426 timer
->context
.tclr
= l
;
429 EXPORT_SYMBOL_GPL(omap_dm_timer_start
);
431 int omap_dm_timer_stop(struct omap_dm_timer
*timer
)
433 unsigned long rate
= 0;
435 if (unlikely(!timer
))
438 if (!(timer
->capability
& OMAP_TIMER_NEEDS_RESET
))
439 rate
= clk_get_rate(timer
->fclk
);
441 __omap_dm_timer_stop(timer
, timer
->posted
, rate
);
443 if (!(timer
->capability
& OMAP_TIMER_ALWON
)) {
444 if (timer
->get_context_loss_count
)
445 timer
->ctx_loss_count
=
446 timer
->get_context_loss_count(&timer
->pdev
->dev
);
450 * Since the register values are computed and written within
451 * __omap_dm_timer_stop, we need to use read to retrieve the
454 timer
->context
.tclr
=
455 omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
456 omap_dm_timer_disable(timer
);
459 EXPORT_SYMBOL_GPL(omap_dm_timer_stop
);
461 int omap_dm_timer_set_source(struct omap_dm_timer
*timer
, int source
)
464 char *parent_name
= NULL
;
466 struct dmtimer_platform_data
*pdata
;
468 if (unlikely(!timer
))
471 pdata
= timer
->pdev
->dev
.platform_data
;
473 if (source
< 0 || source
>= 3)
477 * FIXME: Used for OMAP1 devices only because they do not currently
478 * use the clock framework to set the parent clock. To be removed
479 * once OMAP1 migrated to using clock framework for dmtimers
481 if (pdata
&& pdata
->set_timer_src
)
482 return pdata
->set_timer_src(timer
->pdev
, source
);
484 if (IS_ERR(timer
->fclk
))
488 case OMAP_TIMER_SRC_SYS_CLK
:
489 parent_name
= "timer_sys_ck";
492 case OMAP_TIMER_SRC_32_KHZ
:
493 parent_name
= "timer_32k_ck";
496 case OMAP_TIMER_SRC_EXT_CLK
:
497 parent_name
= "timer_ext_ck";
501 parent
= clk_get(&timer
->pdev
->dev
, parent_name
);
502 if (IS_ERR(parent
)) {
503 pr_err("%s: %s not found\n", __func__
, parent_name
);
507 ret
= clk_set_parent(timer
->fclk
, parent
);
509 pr_err("%s: failed to set %s as parent\n", __func__
,
516 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source
);
518 int omap_dm_timer_set_load(struct omap_dm_timer
*timer
, int autoreload
,
523 if (unlikely(!timer
))
526 omap_dm_timer_enable(timer
);
527 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
529 l
|= OMAP_TIMER_CTRL_AR
;
531 l
&= ~OMAP_TIMER_CTRL_AR
;
532 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
533 omap_dm_timer_write_reg(timer
, OMAP_TIMER_LOAD_REG
, load
);
535 omap_dm_timer_write_reg(timer
, OMAP_TIMER_TRIGGER_REG
, 0);
536 /* Save the context */
537 timer
->context
.tclr
= l
;
538 timer
->context
.tldr
= load
;
539 omap_dm_timer_disable(timer
);
542 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load
);
544 /* Optimized set_load which removes costly spin wait in timer_start */
545 int omap_dm_timer_set_load_start(struct omap_dm_timer
*timer
, int autoreload
,
550 if (unlikely(!timer
))
553 omap_dm_timer_enable(timer
);
555 if (!(timer
->capability
& OMAP_TIMER_ALWON
)) {
556 if (timer
->get_context_loss_count
&&
557 timer
->get_context_loss_count(&timer
->pdev
->dev
) !=
558 timer
->ctx_loss_count
)
559 omap_timer_restore_context(timer
);
562 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
564 l
|= OMAP_TIMER_CTRL_AR
;
565 omap_dm_timer_write_reg(timer
, OMAP_TIMER_LOAD_REG
, load
);
567 l
&= ~OMAP_TIMER_CTRL_AR
;
569 l
|= OMAP_TIMER_CTRL_ST
;
571 __omap_dm_timer_load_start(timer
, l
, load
, timer
->posted
);
573 /* Save the context */
574 timer
->context
.tclr
= l
;
575 timer
->context
.tldr
= load
;
576 timer
->context
.tcrr
= load
;
579 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start
);
581 int omap_dm_timer_set_match(struct omap_dm_timer
*timer
, int enable
,
586 if (unlikely(!timer
))
589 omap_dm_timer_enable(timer
);
590 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
592 l
|= OMAP_TIMER_CTRL_CE
;
594 l
&= ~OMAP_TIMER_CTRL_CE
;
595 omap_dm_timer_write_reg(timer
, OMAP_TIMER_MATCH_REG
, match
);
596 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
598 /* Save the context */
599 timer
->context
.tclr
= l
;
600 timer
->context
.tmar
= match
;
601 omap_dm_timer_disable(timer
);
604 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match
);
606 int omap_dm_timer_set_pwm(struct omap_dm_timer
*timer
, int def_on
,
607 int toggle
, int trigger
)
611 if (unlikely(!timer
))
614 omap_dm_timer_enable(timer
);
615 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
616 l
&= ~(OMAP_TIMER_CTRL_GPOCFG
| OMAP_TIMER_CTRL_SCPWM
|
617 OMAP_TIMER_CTRL_PT
| (0x03 << 10));
619 l
|= OMAP_TIMER_CTRL_SCPWM
;
621 l
|= OMAP_TIMER_CTRL_PT
;
623 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
625 /* Save the context */
626 timer
->context
.tclr
= l
;
627 omap_dm_timer_disable(timer
);
630 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm
);
632 int omap_dm_timer_set_prescaler(struct omap_dm_timer
*timer
, int prescaler
)
636 if (unlikely(!timer
))
639 omap_dm_timer_enable(timer
);
640 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
641 l
&= ~(OMAP_TIMER_CTRL_PRE
| (0x07 << 2));
642 if (prescaler
>= 0x00 && prescaler
<= 0x07) {
643 l
|= OMAP_TIMER_CTRL_PRE
;
646 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
648 /* Save the context */
649 timer
->context
.tclr
= l
;
650 omap_dm_timer_disable(timer
);
653 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler
);
655 int omap_dm_timer_set_int_enable(struct omap_dm_timer
*timer
,
658 if (unlikely(!timer
))
661 omap_dm_timer_enable(timer
);
662 __omap_dm_timer_int_enable(timer
, value
);
664 /* Save the context */
665 timer
->context
.tier
= value
;
666 timer
->context
.twer
= value
;
667 omap_dm_timer_disable(timer
);
670 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable
);
673 * omap_dm_timer_set_int_disable - disable timer interrupts
674 * @timer: pointer to timer handle
675 * @mask: bit mask of interrupts to be disabled
677 * Disables the specified timer interrupts for a timer.
679 int omap_dm_timer_set_int_disable(struct omap_dm_timer
*timer
, u32 mask
)
683 if (unlikely(!timer
))
686 omap_dm_timer_enable(timer
);
688 if (timer
->revision
== 1)
689 l
= __raw_readl(timer
->irq_ena
) & ~mask
;
691 __raw_writel(l
, timer
->irq_dis
);
692 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_WAKEUP_EN_REG
) & ~mask
;
693 omap_dm_timer_write_reg(timer
, OMAP_TIMER_WAKEUP_EN_REG
, l
);
695 /* Save the context */
696 timer
->context
.tier
&= ~mask
;
697 timer
->context
.twer
&= ~mask
;
698 omap_dm_timer_disable(timer
);
701 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable
);
703 unsigned int omap_dm_timer_read_status(struct omap_dm_timer
*timer
)
707 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
708 pr_err("%s: timer not available or enabled.\n", __func__
);
712 l
= __raw_readl(timer
->irq_stat
);
716 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status
);
718 int omap_dm_timer_write_status(struct omap_dm_timer
*timer
, unsigned int value
)
720 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
)))
723 __omap_dm_timer_write_status(timer
, value
);
727 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status
);
729 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer
*timer
)
731 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
732 pr_err("%s: timer not iavailable or enabled.\n", __func__
);
736 return __omap_dm_timer_read_counter(timer
, timer
->posted
);
738 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter
);
740 int omap_dm_timer_write_counter(struct omap_dm_timer
*timer
, unsigned int value
)
742 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
743 pr_err("%s: timer not available or enabled.\n", __func__
);
747 omap_dm_timer_write_reg(timer
, OMAP_TIMER_COUNTER_REG
, value
);
749 /* Save the context */
750 timer
->context
.tcrr
= value
;
753 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter
);
755 int omap_dm_timers_active(void)
757 struct omap_dm_timer
*timer
;
759 list_for_each_entry(timer
, &omap_timer_list
, node
) {
760 if (!timer
->reserved
)
763 if (omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
) &
764 OMAP_TIMER_CTRL_ST
) {
770 EXPORT_SYMBOL_GPL(omap_dm_timers_active
);
773 * omap_dm_timer_probe - probe function called for every registered device
774 * @pdev: pointer to current timer platform device
776 * Called by driver framework at the end of device registration for all
779 static int omap_dm_timer_probe(struct platform_device
*pdev
)
782 struct omap_dm_timer
*timer
;
783 struct resource
*mem
, *irq
;
784 struct device
*dev
= &pdev
->dev
;
785 struct dmtimer_platform_data
*pdata
= pdev
->dev
.platform_data
;
787 if (!pdata
&& !dev
->of_node
) {
788 dev_err(dev
, "%s: no platform data.\n", __func__
);
792 irq
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
793 if (unlikely(!irq
)) {
794 dev_err(dev
, "%s: no IRQ resource.\n", __func__
);
798 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
799 if (unlikely(!mem
)) {
800 dev_err(dev
, "%s: no memory resource.\n", __func__
);
804 timer
= devm_kzalloc(dev
, sizeof(struct omap_dm_timer
), GFP_KERNEL
);
806 dev_err(dev
, "%s: memory alloc failed!\n", __func__
);
810 timer
->fclk
= ERR_PTR(-ENODEV
);
811 timer
->io_base
= devm_request_and_ioremap(dev
, mem
);
812 if (!timer
->io_base
) {
813 dev_err(dev
, "%s: region already claimed.\n", __func__
);
818 if (of_find_property(dev
->of_node
, "ti,timer-alwon", NULL
))
819 timer
->capability
|= OMAP_TIMER_ALWON
;
820 if (of_find_property(dev
->of_node
, "ti,timer-dsp", NULL
))
821 timer
->capability
|= OMAP_TIMER_HAS_DSP_IRQ
;
822 if (of_find_property(dev
->of_node
, "ti,timer-pwm", NULL
))
823 timer
->capability
|= OMAP_TIMER_HAS_PWM
;
824 if (of_find_property(dev
->of_node
, "ti,timer-secure", NULL
))
825 timer
->capability
|= OMAP_TIMER_SECURE
;
827 timer
->id
= pdev
->id
;
828 timer
->errata
= pdata
->timer_errata
;
829 timer
->capability
= pdata
->timer_capability
;
830 timer
->reserved
= omap_dm_timer_reserved_systimer(timer
->id
);
831 timer
->get_context_loss_count
= pdata
->get_context_loss_count
;
834 timer
->irq
= irq
->start
;
837 /* Skip pm_runtime_enable for OMAP1 */
838 if (!(timer
->capability
& OMAP_TIMER_NEEDS_RESET
)) {
839 pm_runtime_enable(dev
);
840 pm_runtime_irq_safe(dev
);
843 if (!timer
->reserved
) {
844 pm_runtime_get_sync(dev
);
845 __omap_dm_timer_init_regs(timer
);
849 /* add the timer element to the list */
850 spin_lock_irqsave(&dm_timer_lock
, flags
);
851 list_add_tail(&timer
->node
, &omap_timer_list
);
852 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
854 dev_dbg(dev
, "Device Probed.\n");
860 * omap_dm_timer_remove - cleanup a registered timer device
861 * @pdev: pointer to current timer platform device
863 * Called by driver framework whenever a timer device is unregistered.
864 * In addition to freeing platform resources it also deletes the timer
865 * entry from the local list.
867 static int omap_dm_timer_remove(struct platform_device
*pdev
)
869 struct omap_dm_timer
*timer
;
873 spin_lock_irqsave(&dm_timer_lock
, flags
);
874 list_for_each_entry(timer
, &omap_timer_list
, node
)
875 if (!strcmp(dev_name(&timer
->pdev
->dev
),
876 dev_name(&pdev
->dev
))) {
877 list_del(&timer
->node
);
881 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
886 static const struct of_device_id omap_timer_match
[] = {
887 { .compatible
= "ti,omap2-timer", },
890 MODULE_DEVICE_TABLE(of
, omap_timer_match
);
892 static struct platform_driver omap_dm_timer_driver
= {
893 .probe
= omap_dm_timer_probe
,
894 .remove
= omap_dm_timer_remove
,
896 .name
= "omap_timer",
897 .of_match_table
= of_match_ptr(omap_timer_match
),
901 early_platform_init("earlytimer", &omap_dm_timer_driver
);
902 module_platform_driver(omap_dm_timer_driver
);
904 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
905 MODULE_LICENSE("GPL");
906 MODULE_ALIAS("platform:" DRIVER_NAME
);
907 MODULE_AUTHOR("Texas Instruments Inc");