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
);
63 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
64 * @timer: timer pointer over which read operation to perform
65 * @reg: lowest byte holds the register offset
67 * The posted mode bit is encoded in reg. Note that in posted mode write
68 * pending bit must be checked. Otherwise a read of a non completed write
69 * will produce an error.
71 static inline u32
omap_dm_timer_read_reg(struct omap_dm_timer
*timer
, u32 reg
)
73 WARN_ON((reg
& 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET
);
74 return __omap_dm_timer_read(timer
, reg
, timer
->posted
);
78 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
79 * @timer: timer pointer over which write operation is to perform
80 * @reg: lowest byte holds the register offset
81 * @value: data to write into the register
83 * The posted mode bit is encoded in reg. Note that in posted mode the write
84 * pending bit must be checked. Otherwise a write on a register which has a
85 * pending write will be lost.
87 static void omap_dm_timer_write_reg(struct omap_dm_timer
*timer
, u32 reg
,
90 WARN_ON((reg
& 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET
);
91 __omap_dm_timer_write(timer
, reg
, value
, timer
->posted
);
94 static void omap_timer_restore_context(struct omap_dm_timer
*timer
)
96 omap_dm_timer_write_reg(timer
, OMAP_TIMER_WAKEUP_EN_REG
,
98 omap_dm_timer_write_reg(timer
, OMAP_TIMER_COUNTER_REG
,
100 omap_dm_timer_write_reg(timer
, OMAP_TIMER_LOAD_REG
,
101 timer
->context
.tldr
);
102 omap_dm_timer_write_reg(timer
, OMAP_TIMER_MATCH_REG
,
103 timer
->context
.tmar
);
104 omap_dm_timer_write_reg(timer
, OMAP_TIMER_IF_CTRL_REG
,
105 timer
->context
.tsicr
);
106 writel_relaxed(timer
->context
.tier
, timer
->irq_ena
);
107 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
,
108 timer
->context
.tclr
);
111 static int omap_dm_timer_reset(struct omap_dm_timer
*timer
)
113 u32 l
, timeout
= 100000;
115 if (timer
->revision
!= 1)
118 omap_dm_timer_write_reg(timer
, OMAP_TIMER_IF_CTRL_REG
, 0x06);
121 l
= __omap_dm_timer_read(timer
,
122 OMAP_TIMER_V1_SYS_STAT_OFFSET
, 0);
123 } while (!l
&& timeout
--);
126 dev_err(&timer
->pdev
->dev
, "Timer failed to reset\n");
130 /* Configure timer for smart-idle mode */
131 l
= __omap_dm_timer_read(timer
, OMAP_TIMER_OCP_CFG_OFFSET
, 0);
133 __omap_dm_timer_write(timer
, OMAP_TIMER_OCP_CFG_OFFSET
, l
, 0);
140 static int omap_dm_timer_prepare(struct omap_dm_timer
*timer
)
145 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
146 * do not call clk_get() for these devices.
148 if (!(timer
->capability
& OMAP_TIMER_NEEDS_RESET
)) {
149 timer
->fclk
= clk_get(&timer
->pdev
->dev
, "fck");
150 if (WARN_ON_ONCE(IS_ERR(timer
->fclk
))) {
151 dev_err(&timer
->pdev
->dev
, ": No fclk handle.\n");
156 omap_dm_timer_enable(timer
);
158 if (timer
->capability
& OMAP_TIMER_NEEDS_RESET
) {
159 rc
= omap_dm_timer_reset(timer
);
161 omap_dm_timer_disable(timer
);
166 __omap_dm_timer_enable_posted(timer
);
167 omap_dm_timer_disable(timer
);
169 return omap_dm_timer_set_source(timer
, OMAP_TIMER_SRC_32_KHZ
);
172 static inline u32
omap_dm_timer_reserved_systimer(int id
)
174 return (omap_reserved_systimers
& (1 << (id
- 1))) ? 1 : 0;
177 int omap_dm_timer_reserve_systimer(int id
)
179 if (omap_dm_timer_reserved_systimer(id
))
182 omap_reserved_systimers
|= (1 << (id
- 1));
187 static struct omap_dm_timer
*_omap_dm_timer_request(int req_type
, void *data
)
189 struct omap_dm_timer
*timer
= NULL
, *t
;
190 struct device_node
*np
= NULL
;
202 case REQUEST_BY_NODE
:
203 np
= (struct device_node
*)data
;
210 spin_lock_irqsave(&dm_timer_lock
, flags
);
211 list_for_each_entry(t
, &omap_timer_list
, node
) {
217 if (id
== t
->pdev
->id
) {
224 if (cap
== (t
->capability
& cap
)) {
226 * If timer is not NULL, we have already found
227 * one timer but it was not an exact match
228 * because it had more capabilites that what
229 * was required. Therefore, unreserve the last
230 * timer found and see if this one is a better
238 /* Exit loop early if we find an exact match */
239 if (t
->capability
== cap
)
243 case REQUEST_BY_NODE
:
244 if (np
== t
->pdev
->dev
.of_node
) {
258 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
260 if (timer
&& omap_dm_timer_prepare(timer
)) {
266 pr_debug("%s: timer request failed!\n", __func__
);
271 struct omap_dm_timer
*omap_dm_timer_request(void)
273 return _omap_dm_timer_request(REQUEST_ANY
, NULL
);
275 EXPORT_SYMBOL_GPL(omap_dm_timer_request
);
277 struct omap_dm_timer
*omap_dm_timer_request_specific(int id
)
279 /* Requesting timer by ID is not supported when device tree is used */
280 if (of_have_populated_dt()) {
281 pr_warn("%s: Please use omap_dm_timer_request_by_cap/node()\n",
286 return _omap_dm_timer_request(REQUEST_BY_ID
, &id
);
288 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific
);
291 * omap_dm_timer_request_by_cap - Request a timer by capability
292 * @cap: Bit mask of capabilities to match
294 * Find a timer based upon capabilities bit mask. Callers of this function
295 * should use the definitions found in the plat/dmtimer.h file under the
296 * comment "timer capabilities used in hwmod database". Returns pointer to
297 * timer handle on success and a NULL pointer on failure.
299 struct omap_dm_timer
*omap_dm_timer_request_by_cap(u32 cap
)
301 return _omap_dm_timer_request(REQUEST_BY_CAP
, &cap
);
303 EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap
);
306 * omap_dm_timer_request_by_node - Request a timer by device-tree node
307 * @np: Pointer to device-tree timer node
309 * Request a timer based upon a device node pointer. Returns pointer to
310 * timer handle on success and a NULL pointer on failure.
312 struct omap_dm_timer
*omap_dm_timer_request_by_node(struct device_node
*np
)
317 return _omap_dm_timer_request(REQUEST_BY_NODE
, np
);
319 EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node
);
321 int omap_dm_timer_free(struct omap_dm_timer
*timer
)
323 if (unlikely(!timer
))
326 clk_put(timer
->fclk
);
328 WARN_ON(!timer
->reserved
);
332 EXPORT_SYMBOL_GPL(omap_dm_timer_free
);
334 void omap_dm_timer_enable(struct omap_dm_timer
*timer
)
338 pm_runtime_get_sync(&timer
->pdev
->dev
);
340 if (!(timer
->capability
& OMAP_TIMER_ALWON
)) {
341 if (timer
->get_context_loss_count
) {
342 c
= timer
->get_context_loss_count(&timer
->pdev
->dev
);
343 if (c
!= timer
->ctx_loss_count
) {
344 omap_timer_restore_context(timer
);
345 timer
->ctx_loss_count
= c
;
348 omap_timer_restore_context(timer
);
352 EXPORT_SYMBOL_GPL(omap_dm_timer_enable
);
354 void omap_dm_timer_disable(struct omap_dm_timer
*timer
)
356 pm_runtime_put_sync(&timer
->pdev
->dev
);
358 EXPORT_SYMBOL_GPL(omap_dm_timer_disable
);
360 int omap_dm_timer_get_irq(struct omap_dm_timer
*timer
)
366 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq
);
368 #if defined(CONFIG_ARCH_OMAP1)
369 #include <mach/hardware.h>
371 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
372 * @inputmask: current value of idlect mask
374 __u32
omap_dm_timer_modify_idlect_mask(__u32 inputmask
)
377 struct omap_dm_timer
*timer
= NULL
;
380 /* If ARMXOR cannot be idled this function call is unnecessary */
381 if (!(inputmask
& (1 << 1)))
384 /* If any active timer is using ARMXOR return modified mask */
385 spin_lock_irqsave(&dm_timer_lock
, flags
);
386 list_for_each_entry(timer
, &omap_timer_list
, node
) {
389 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
390 if (l
& OMAP_TIMER_CTRL_ST
) {
391 if (((omap_readl(MOD_CONF_CTRL_1
) >> (i
* 2)) & 0x03) == 0)
392 inputmask
&= ~(1 << 1);
394 inputmask
&= ~(1 << 2);
398 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
402 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask
);
406 struct clk
*omap_dm_timer_get_fclk(struct omap_dm_timer
*timer
)
408 if (timer
&& !IS_ERR(timer
->fclk
))
412 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk
);
414 __u32
omap_dm_timer_modify_idlect_mask(__u32 inputmask
)
420 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask
);
424 int omap_dm_timer_trigger(struct omap_dm_timer
*timer
)
426 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
427 pr_err("%s: timer not available or enabled.\n", __func__
);
431 omap_dm_timer_write_reg(timer
, OMAP_TIMER_TRIGGER_REG
, 0);
434 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger
);
436 int omap_dm_timer_start(struct omap_dm_timer
*timer
)
440 if (unlikely(!timer
))
443 omap_dm_timer_enable(timer
);
445 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
446 if (!(l
& OMAP_TIMER_CTRL_ST
)) {
447 l
|= OMAP_TIMER_CTRL_ST
;
448 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
451 /* Save the context */
452 timer
->context
.tclr
= l
;
455 EXPORT_SYMBOL_GPL(omap_dm_timer_start
);
457 int omap_dm_timer_stop(struct omap_dm_timer
*timer
)
459 unsigned long rate
= 0;
461 if (unlikely(!timer
))
464 if (!(timer
->capability
& OMAP_TIMER_NEEDS_RESET
))
465 rate
= clk_get_rate(timer
->fclk
);
467 __omap_dm_timer_stop(timer
, timer
->posted
, rate
);
470 * Since the register values are computed and written within
471 * __omap_dm_timer_stop, we need to use read to retrieve the
474 timer
->context
.tclr
=
475 omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
476 omap_dm_timer_disable(timer
);
479 EXPORT_SYMBOL_GPL(omap_dm_timer_stop
);
481 int omap_dm_timer_set_source(struct omap_dm_timer
*timer
, int source
)
484 char *parent_name
= NULL
;
486 struct dmtimer_platform_data
*pdata
;
488 if (unlikely(!timer
))
491 pdata
= timer
->pdev
->dev
.platform_data
;
493 if (source
< 0 || source
>= 3)
497 * FIXME: Used for OMAP1 devices only because they do not currently
498 * use the clock framework to set the parent clock. To be removed
499 * once OMAP1 migrated to using clock framework for dmtimers
501 if (pdata
&& pdata
->set_timer_src
)
502 return pdata
->set_timer_src(timer
->pdev
, source
);
504 if (IS_ERR(timer
->fclk
))
508 case OMAP_TIMER_SRC_SYS_CLK
:
509 parent_name
= "timer_sys_ck";
512 case OMAP_TIMER_SRC_32_KHZ
:
513 parent_name
= "timer_32k_ck";
516 case OMAP_TIMER_SRC_EXT_CLK
:
517 parent_name
= "timer_ext_ck";
521 parent
= clk_get(&timer
->pdev
->dev
, parent_name
);
522 if (IS_ERR(parent
)) {
523 pr_err("%s: %s not found\n", __func__
, parent_name
);
527 ret
= clk_set_parent(timer
->fclk
, parent
);
529 pr_err("%s: failed to set %s as parent\n", __func__
,
536 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source
);
538 int omap_dm_timer_set_load(struct omap_dm_timer
*timer
, int autoreload
,
543 if (unlikely(!timer
))
546 omap_dm_timer_enable(timer
);
547 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
549 l
|= OMAP_TIMER_CTRL_AR
;
551 l
&= ~OMAP_TIMER_CTRL_AR
;
552 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
553 omap_dm_timer_write_reg(timer
, OMAP_TIMER_LOAD_REG
, load
);
555 omap_dm_timer_write_reg(timer
, OMAP_TIMER_TRIGGER_REG
, 0);
556 /* Save the context */
557 timer
->context
.tclr
= l
;
558 timer
->context
.tldr
= load
;
559 omap_dm_timer_disable(timer
);
562 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load
);
564 /* Optimized set_load which removes costly spin wait in timer_start */
565 int omap_dm_timer_set_load_start(struct omap_dm_timer
*timer
, int autoreload
,
570 if (unlikely(!timer
))
573 omap_dm_timer_enable(timer
);
575 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
577 l
|= OMAP_TIMER_CTRL_AR
;
578 omap_dm_timer_write_reg(timer
, OMAP_TIMER_LOAD_REG
, load
);
580 l
&= ~OMAP_TIMER_CTRL_AR
;
582 l
|= OMAP_TIMER_CTRL_ST
;
584 __omap_dm_timer_load_start(timer
, l
, load
, timer
->posted
);
586 /* Save the context */
587 timer
->context
.tclr
= l
;
588 timer
->context
.tldr
= load
;
589 timer
->context
.tcrr
= load
;
592 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start
);
594 int omap_dm_timer_set_match(struct omap_dm_timer
*timer
, int enable
,
599 if (unlikely(!timer
))
602 omap_dm_timer_enable(timer
);
603 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
605 l
|= OMAP_TIMER_CTRL_CE
;
607 l
&= ~OMAP_TIMER_CTRL_CE
;
608 omap_dm_timer_write_reg(timer
, OMAP_TIMER_MATCH_REG
, match
);
609 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
611 /* Save the context */
612 timer
->context
.tclr
= l
;
613 timer
->context
.tmar
= match
;
614 omap_dm_timer_disable(timer
);
617 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match
);
619 int omap_dm_timer_set_pwm(struct omap_dm_timer
*timer
, int def_on
,
620 int toggle
, int trigger
)
624 if (unlikely(!timer
))
627 omap_dm_timer_enable(timer
);
628 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
629 l
&= ~(OMAP_TIMER_CTRL_GPOCFG
| OMAP_TIMER_CTRL_SCPWM
|
630 OMAP_TIMER_CTRL_PT
| (0x03 << 10));
632 l
|= OMAP_TIMER_CTRL_SCPWM
;
634 l
|= OMAP_TIMER_CTRL_PT
;
636 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
638 /* Save the context */
639 timer
->context
.tclr
= l
;
640 omap_dm_timer_disable(timer
);
643 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm
);
645 int omap_dm_timer_set_prescaler(struct omap_dm_timer
*timer
, int prescaler
)
649 if (unlikely(!timer
))
652 omap_dm_timer_enable(timer
);
653 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
);
654 l
&= ~(OMAP_TIMER_CTRL_PRE
| (0x07 << 2));
655 if (prescaler
>= 0x00 && prescaler
<= 0x07) {
656 l
|= OMAP_TIMER_CTRL_PRE
;
659 omap_dm_timer_write_reg(timer
, OMAP_TIMER_CTRL_REG
, l
);
661 /* Save the context */
662 timer
->context
.tclr
= l
;
663 omap_dm_timer_disable(timer
);
666 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler
);
668 int omap_dm_timer_set_int_enable(struct omap_dm_timer
*timer
,
671 if (unlikely(!timer
))
674 omap_dm_timer_enable(timer
);
675 __omap_dm_timer_int_enable(timer
, value
);
677 /* Save the context */
678 timer
->context
.tier
= value
;
679 timer
->context
.twer
= value
;
680 omap_dm_timer_disable(timer
);
683 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable
);
686 * omap_dm_timer_set_int_disable - disable timer interrupts
687 * @timer: pointer to timer handle
688 * @mask: bit mask of interrupts to be disabled
690 * Disables the specified timer interrupts for a timer.
692 int omap_dm_timer_set_int_disable(struct omap_dm_timer
*timer
, u32 mask
)
696 if (unlikely(!timer
))
699 omap_dm_timer_enable(timer
);
701 if (timer
->revision
== 1)
702 l
= readl_relaxed(timer
->irq_ena
) & ~mask
;
704 writel_relaxed(l
, timer
->irq_dis
);
705 l
= omap_dm_timer_read_reg(timer
, OMAP_TIMER_WAKEUP_EN_REG
) & ~mask
;
706 omap_dm_timer_write_reg(timer
, OMAP_TIMER_WAKEUP_EN_REG
, l
);
708 /* Save the context */
709 timer
->context
.tier
&= ~mask
;
710 timer
->context
.twer
&= ~mask
;
711 omap_dm_timer_disable(timer
);
714 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable
);
716 unsigned int omap_dm_timer_read_status(struct omap_dm_timer
*timer
)
720 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
721 pr_err("%s: timer not available or enabled.\n", __func__
);
725 l
= readl_relaxed(timer
->irq_stat
);
729 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status
);
731 int omap_dm_timer_write_status(struct omap_dm_timer
*timer
, unsigned int value
)
733 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
)))
736 __omap_dm_timer_write_status(timer
, value
);
740 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status
);
742 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer
*timer
)
744 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
745 pr_err("%s: timer not iavailable or enabled.\n", __func__
);
749 return __omap_dm_timer_read_counter(timer
, timer
->posted
);
751 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter
);
753 int omap_dm_timer_write_counter(struct omap_dm_timer
*timer
, unsigned int value
)
755 if (unlikely(!timer
|| pm_runtime_suspended(&timer
->pdev
->dev
))) {
756 pr_err("%s: timer not available or enabled.\n", __func__
);
760 omap_dm_timer_write_reg(timer
, OMAP_TIMER_COUNTER_REG
, value
);
762 /* Save the context */
763 timer
->context
.tcrr
= value
;
766 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter
);
768 int omap_dm_timers_active(void)
770 struct omap_dm_timer
*timer
;
772 list_for_each_entry(timer
, &omap_timer_list
, node
) {
773 if (!timer
->reserved
)
776 if (omap_dm_timer_read_reg(timer
, OMAP_TIMER_CTRL_REG
) &
777 OMAP_TIMER_CTRL_ST
) {
783 EXPORT_SYMBOL_GPL(omap_dm_timers_active
);
785 static const struct of_device_id omap_timer_match
[];
788 * omap_dm_timer_probe - probe function called for every registered device
789 * @pdev: pointer to current timer platform device
791 * Called by driver framework at the end of device registration for all
794 static int omap_dm_timer_probe(struct platform_device
*pdev
)
797 struct omap_dm_timer
*timer
;
798 struct resource
*mem
, *irq
;
799 struct device
*dev
= &pdev
->dev
;
800 const struct of_device_id
*match
;
801 const struct dmtimer_platform_data
*pdata
;
803 match
= of_match_device(of_match_ptr(omap_timer_match
), dev
);
804 pdata
= match
? match
->data
: dev
->platform_data
;
806 if (!pdata
&& !dev
->of_node
) {
807 dev_err(dev
, "%s: no platform data.\n", __func__
);
811 irq
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
812 if (unlikely(!irq
)) {
813 dev_err(dev
, "%s: no IRQ resource.\n", __func__
);
817 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
818 if (unlikely(!mem
)) {
819 dev_err(dev
, "%s: no memory resource.\n", __func__
);
823 timer
= devm_kzalloc(dev
, sizeof(struct omap_dm_timer
), GFP_KERNEL
);
825 dev_err(dev
, "%s: memory alloc failed!\n", __func__
);
829 timer
->fclk
= ERR_PTR(-ENODEV
);
830 timer
->io_base
= devm_ioremap_resource(dev
, mem
);
831 if (IS_ERR(timer
->io_base
))
832 return PTR_ERR(timer
->io_base
);
835 if (of_find_property(dev
->of_node
, "ti,timer-alwon", NULL
))
836 timer
->capability
|= OMAP_TIMER_ALWON
;
837 if (of_find_property(dev
->of_node
, "ti,timer-dsp", NULL
))
838 timer
->capability
|= OMAP_TIMER_HAS_DSP_IRQ
;
839 if (of_find_property(dev
->of_node
, "ti,timer-pwm", NULL
))
840 timer
->capability
|= OMAP_TIMER_HAS_PWM
;
841 if (of_find_property(dev
->of_node
, "ti,timer-secure", NULL
))
842 timer
->capability
|= OMAP_TIMER_SECURE
;
844 timer
->id
= pdev
->id
;
845 timer
->capability
= pdata
->timer_capability
;
846 timer
->reserved
= omap_dm_timer_reserved_systimer(timer
->id
);
847 timer
->get_context_loss_count
= pdata
->get_context_loss_count
;
851 timer
->errata
= pdata
->timer_errata
;
853 timer
->irq
= irq
->start
;
856 /* Skip pm_runtime_enable for OMAP1 */
857 if (!(timer
->capability
& OMAP_TIMER_NEEDS_RESET
)) {
858 pm_runtime_enable(dev
);
859 pm_runtime_irq_safe(dev
);
862 if (!timer
->reserved
) {
863 pm_runtime_get_sync(dev
);
864 __omap_dm_timer_init_regs(timer
);
868 /* add the timer element to the list */
869 spin_lock_irqsave(&dm_timer_lock
, flags
);
870 list_add_tail(&timer
->node
, &omap_timer_list
);
871 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
873 dev_dbg(dev
, "Device Probed.\n");
879 * omap_dm_timer_remove - cleanup a registered timer device
880 * @pdev: pointer to current timer platform device
882 * Called by driver framework whenever a timer device is unregistered.
883 * In addition to freeing platform resources it also deletes the timer
884 * entry from the local list.
886 static int omap_dm_timer_remove(struct platform_device
*pdev
)
888 struct omap_dm_timer
*timer
;
892 spin_lock_irqsave(&dm_timer_lock
, flags
);
893 list_for_each_entry(timer
, &omap_timer_list
, node
)
894 if (!strcmp(dev_name(&timer
->pdev
->dev
),
895 dev_name(&pdev
->dev
))) {
896 list_del(&timer
->node
);
900 spin_unlock_irqrestore(&dm_timer_lock
, flags
);
905 static const struct dmtimer_platform_data omap3plus_pdata
= {
906 .timer_errata
= OMAP_TIMER_ERRATA_I103_I767
,
909 static const struct of_device_id omap_timer_match
[] = {
911 .compatible
= "ti,omap2420-timer",
914 .compatible
= "ti,omap3430-timer",
915 .data
= &omap3plus_pdata
,
918 .compatible
= "ti,omap4430-timer",
919 .data
= &omap3plus_pdata
,
922 .compatible
= "ti,omap5430-timer",
923 .data
= &omap3plus_pdata
,
926 .compatible
= "ti,am335x-timer",
927 .data
= &omap3plus_pdata
,
930 .compatible
= "ti,am335x-timer-1ms",
931 .data
= &omap3plus_pdata
,
935 MODULE_DEVICE_TABLE(of
, omap_timer_match
);
937 static struct platform_driver omap_dm_timer_driver
= {
938 .probe
= omap_dm_timer_probe
,
939 .remove
= omap_dm_timer_remove
,
941 .name
= "omap_timer",
942 .of_match_table
= of_match_ptr(omap_timer_match
),
946 early_platform_init("earlytimer", &omap_dm_timer_driver
);
947 module_platform_driver(omap_dm_timer_driver
);
949 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
950 MODULE_LICENSE("GPL");
951 MODULE_ALIAS("platform:" DRIVER_NAME
);
952 MODULE_AUTHOR("Texas Instruments Inc");