Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck...
[pandora-kernel.git] / arch / arm / plat-omap / dmtimer.c
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/module.h>
39 #include <linux/io.h>
40 #include <linux/device.h>
41 #include <linux/err.h>
42 #include <linux/pm_runtime.h>
43
44 #include <plat/dmtimer.h>
45 #include <plat/omap-pm.h>
46
47 #include <mach/hardware.h>
48
49 static u32 omap_reserved_systimers;
50 static LIST_HEAD(omap_timer_list);
51 static DEFINE_SPINLOCK(dm_timer_lock);
52
53 /**
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
57  *
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.
61  */
62 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
63 {
64         WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
65         return __omap_dm_timer_read(timer, reg, timer->posted);
66 }
67
68 /**
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
73  *
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.
77  */
78 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
79                                                 u32 value)
80 {
81         WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
82         __omap_dm_timer_write(timer, reg, value, timer->posted);
83 }
84
85 static void omap_timer_restore_context(struct omap_dm_timer *timer)
86 {
87         if (timer->revision == 1)
88                 __raw_writel(timer->context.tistat, timer->sys_stat);
89
90         __raw_writel(timer->context.tisr, timer->irq_stat);
91         omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
92                                 timer->context.twer);
93         omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
94                                 timer->context.tcrr);
95         omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
96                                 timer->context.tldr);
97         omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
98                                 timer->context.tmar);
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);
104 }
105
106 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
107 {
108         int c;
109
110         if (!timer->sys_stat)
111                 return;
112
113         c = 0;
114         while (!(__raw_readl(timer->sys_stat) & 1)) {
115                 c++;
116                 if (c > 100000) {
117                         printk(KERN_ERR "Timer failed to reset\n");
118                         return;
119                 }
120         }
121 }
122
123 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
124 {
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);
129         }
130
131         __omap_dm_timer_reset(timer, 0, 0);
132         omap_dm_timer_disable(timer);
133         timer->posted = 1;
134 }
135
136 int omap_dm_timer_prepare(struct omap_dm_timer *timer)
137 {
138         int ret;
139
140         /*
141          * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
142          * do not call clk_get() for these devices.
143          */
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))) {
147                         timer->fclk = NULL;
148                         dev_err(&timer->pdev->dev, ": No fclk handle.\n");
149                         return -EINVAL;
150                 }
151         }
152
153         if (timer->capability & OMAP_TIMER_NEEDS_RESET)
154                 omap_dm_timer_reset(timer);
155
156         ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
157
158         timer->posted = 1;
159         return ret;
160 }
161
162 static inline u32 omap_dm_timer_reserved_systimer(int id)
163 {
164         return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
165 }
166
167 int omap_dm_timer_reserve_systimer(int id)
168 {
169         if (omap_dm_timer_reserved_systimer(id))
170                 return -ENODEV;
171
172         omap_reserved_systimers |= (1 << (id - 1));
173
174         return 0;
175 }
176
177 struct omap_dm_timer *omap_dm_timer_request(void)
178 {
179         struct omap_dm_timer *timer = NULL, *t;
180         unsigned long flags;
181         int ret = 0;
182
183         spin_lock_irqsave(&dm_timer_lock, flags);
184         list_for_each_entry(t, &omap_timer_list, node) {
185                 if (t->reserved)
186                         continue;
187
188                 timer = t;
189                 timer->reserved = 1;
190                 break;
191         }
192
193         if (timer) {
194                 ret = omap_dm_timer_prepare(timer);
195                 if (ret) {
196                         timer->reserved = 0;
197                         timer = NULL;
198                 }
199         }
200         spin_unlock_irqrestore(&dm_timer_lock, flags);
201
202         if (!timer)
203                 pr_debug("%s: timer request failed!\n", __func__);
204
205         return timer;
206 }
207 EXPORT_SYMBOL_GPL(omap_dm_timer_request);
208
209 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
210 {
211         struct omap_dm_timer *timer = NULL, *t;
212         unsigned long flags;
213         int ret = 0;
214
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) {
218                         timer = t;
219                         timer->reserved = 1;
220                         break;
221                 }
222         }
223
224         if (timer) {
225                 ret = omap_dm_timer_prepare(timer);
226                 if (ret) {
227                         timer->reserved = 0;
228                         timer = NULL;
229                 }
230         }
231         spin_unlock_irqrestore(&dm_timer_lock, flags);
232
233         if (!timer)
234                 pr_debug("%s: timer%d request failed!\n", __func__, id);
235
236         return timer;
237 }
238 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
239
240 int omap_dm_timer_free(struct omap_dm_timer *timer)
241 {
242         if (unlikely(!timer))
243                 return -EINVAL;
244
245         clk_put(timer->fclk);
246
247         WARN_ON(!timer->reserved);
248         timer->reserved = 0;
249         return 0;
250 }
251 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
252
253 void omap_dm_timer_enable(struct omap_dm_timer *timer)
254 {
255         pm_runtime_get_sync(&timer->pdev->dev);
256 }
257 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
258
259 void omap_dm_timer_disable(struct omap_dm_timer *timer)
260 {
261         pm_runtime_put(&timer->pdev->dev);
262 }
263 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
264
265 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
266 {
267         if (timer)
268                 return timer->irq;
269         return -EINVAL;
270 }
271 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
272
273 #if defined(CONFIG_ARCH_OMAP1)
274
275 /**
276  * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
277  * @inputmask: current value of idlect mask
278  */
279 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
280 {
281         int i = 0;
282         struct omap_dm_timer *timer = NULL;
283         unsigned long flags;
284
285         /* If ARMXOR cannot be idled this function call is unnecessary */
286         if (!(inputmask & (1 << 1)))
287                 return inputmask;
288
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) {
292                 u32 l;
293
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);
298                         else
299                                 inputmask &= ~(1 << 2);
300                 }
301                 i++;
302         }
303         spin_unlock_irqrestore(&dm_timer_lock, flags);
304
305         return inputmask;
306 }
307 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
308
309 #else
310
311 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
312 {
313         if (timer)
314                 return timer->fclk;
315         return NULL;
316 }
317 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
318
319 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
320 {
321         BUG();
322
323         return 0;
324 }
325 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
326
327 #endif
328
329 int omap_dm_timer_trigger(struct omap_dm_timer *timer)
330 {
331         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
332                 pr_err("%s: timer not available or enabled.\n", __func__);
333                 return -EINVAL;
334         }
335
336         omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
337         return 0;
338 }
339 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
340
341 int omap_dm_timer_start(struct omap_dm_timer *timer)
342 {
343         u32 l;
344
345         if (unlikely(!timer))
346                 return -EINVAL;
347
348         omap_dm_timer_enable(timer);
349
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);
354         }
355
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);
360         }
361
362         /* Save the context */
363         timer->context.tclr = l;
364         return 0;
365 }
366 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
367
368 int omap_dm_timer_stop(struct omap_dm_timer *timer)
369 {
370         unsigned long rate = 0;
371
372         if (unlikely(!timer))
373                 return -EINVAL;
374
375         if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
376                 rate = clk_get_rate(timer->fclk);
377
378         __omap_dm_timer_stop(timer, timer->posted, rate);
379
380         if (!(timer->capability & OMAP_TIMER_ALWON))
381                 timer->ctx_loss_count =
382                         omap_pm_get_dev_context_loss_count(&timer->pdev->dev);
383
384         /*
385          * Since the register values are computed and written within
386          * __omap_dm_timer_stop, we need to use read to retrieve the
387          * context.
388          */
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);
393         return 0;
394 }
395 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
396
397 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
398 {
399         int ret;
400         char *parent_name = NULL;
401         struct clk *fclk, *parent;
402         struct dmtimer_platform_data *pdata;
403
404         if (unlikely(!timer))
405                 return -EINVAL;
406
407         pdata = timer->pdev->dev.platform_data;
408
409         if (source < 0 || source >= 3)
410                 return -EINVAL;
411
412         /*
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
416          */
417         if (pdata->set_timer_src)
418                 return pdata->set_timer_src(timer->pdev, source);
419
420         fclk = clk_get(&timer->pdev->dev, "fck");
421         if (IS_ERR_OR_NULL(fclk)) {
422                 pr_err("%s: fck not found\n", __func__);
423                 return -EINVAL;
424         }
425
426         switch (source) {
427         case OMAP_TIMER_SRC_SYS_CLK:
428                 parent_name = "timer_sys_ck";
429                 break;
430
431         case OMAP_TIMER_SRC_32_KHZ:
432                 parent_name = "timer_32k_ck";
433                 break;
434
435         case OMAP_TIMER_SRC_EXT_CLK:
436                 parent_name = "timer_ext_ck";
437                 break;
438         }
439
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);
443                 ret = -EINVAL;
444                 goto out;
445         }
446
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__,
450                         parent_name);
451
452         clk_put(parent);
453 out:
454         clk_put(fclk);
455
456         return ret;
457 }
458 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
459
460 int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
461                             unsigned int load)
462 {
463         u32 l;
464
465         if (unlikely(!timer))
466                 return -EINVAL;
467
468         omap_dm_timer_enable(timer);
469         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
470         if (autoreload)
471                 l |= OMAP_TIMER_CTRL_AR;
472         else
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);
476
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);
482         return 0;
483 }
484 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
485
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,
488                             unsigned int load)
489 {
490         u32 l;
491
492         if (unlikely(!timer))
493                 return -EINVAL;
494
495         omap_dm_timer_enable(timer);
496
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);
501         }
502
503         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
504         if (autoreload) {
505                 l |= OMAP_TIMER_CTRL_AR;
506                 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
507         } else {
508                 l &= ~OMAP_TIMER_CTRL_AR;
509         }
510         l |= OMAP_TIMER_CTRL_ST;
511
512         __omap_dm_timer_load_start(timer, l, load, timer->posted);
513
514         /* Save the context */
515         timer->context.tclr = l;
516         timer->context.tldr = load;
517         timer->context.tcrr = load;
518         return 0;
519 }
520 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
521
522 int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
523                              unsigned int match)
524 {
525         u32 l;
526
527         if (unlikely(!timer))
528                 return -EINVAL;
529
530         omap_dm_timer_enable(timer);
531         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
532         if (enable)
533                 l |= OMAP_TIMER_CTRL_CE;
534         else
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);
538
539         /* Save the context */
540         timer->context.tclr = l;
541         timer->context.tmar = match;
542         omap_dm_timer_disable(timer);
543         return 0;
544 }
545 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
546
547 int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
548                            int toggle, int trigger)
549 {
550         u32 l;
551
552         if (unlikely(!timer))
553                 return -EINVAL;
554
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));
559         if (def_on)
560                 l |= OMAP_TIMER_CTRL_SCPWM;
561         if (toggle)
562                 l |= OMAP_TIMER_CTRL_PT;
563         l |= trigger << 10;
564         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
565
566         /* Save the context */
567         timer->context.tclr = l;
568         omap_dm_timer_disable(timer);
569         return 0;
570 }
571 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
572
573 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
574 {
575         u32 l;
576
577         if (unlikely(!timer))
578                 return -EINVAL;
579
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;
585                 l |= prescaler << 2;
586         }
587         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
588
589         /* Save the context */
590         timer->context.tclr = l;
591         omap_dm_timer_disable(timer);
592         return 0;
593 }
594 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
595
596 int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
597                                   unsigned int value)
598 {
599         if (unlikely(!timer))
600                 return -EINVAL;
601
602         omap_dm_timer_enable(timer);
603         __omap_dm_timer_int_enable(timer, value);
604
605         /* Save the context */
606         timer->context.tier = value;
607         timer->context.twer = value;
608         omap_dm_timer_disable(timer);
609         return 0;
610 }
611 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
612
613 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
614 {
615         unsigned int l;
616
617         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
618                 pr_err("%s: timer not available or enabled.\n", __func__);
619                 return 0;
620         }
621
622         l = __raw_readl(timer->irq_stat);
623
624         return l;
625 }
626 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
627
628 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
629 {
630         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
631                 return -EINVAL;
632
633         __omap_dm_timer_write_status(timer, value);
634         /* Save the context */
635         timer->context.tisr = value;
636         return 0;
637 }
638 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
639
640 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
641 {
642         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
643                 pr_err("%s: timer not iavailable or enabled.\n", __func__);
644                 return 0;
645         }
646
647         return __omap_dm_timer_read_counter(timer, timer->posted);
648 }
649 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
650
651 int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
652 {
653         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
654                 pr_err("%s: timer not available or enabled.\n", __func__);
655                 return -EINVAL;
656         }
657
658         omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
659
660         /* Save the context */
661         timer->context.tcrr = value;
662         return 0;
663 }
664 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
665
666 int omap_dm_timers_active(void)
667 {
668         struct omap_dm_timer *timer;
669
670         list_for_each_entry(timer, &omap_timer_list, node) {
671                 if (!timer->reserved)
672                         continue;
673
674                 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
675                     OMAP_TIMER_CTRL_ST) {
676                         return 1;
677                 }
678         }
679         return 0;
680 }
681 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
682
683 /**
684  * omap_dm_timer_probe - probe function called for every registered device
685  * @pdev:       pointer to current timer platform device
686  *
687  * Called by driver framework at the end of device registration for all
688  * timer devices.
689  */
690 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
691 {
692         unsigned long flags;
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;
697
698         if (!pdata) {
699                 dev_err(dev, "%s: no platform data.\n", __func__);
700                 return -ENODEV;
701         }
702
703         irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
704         if (unlikely(!irq)) {
705                 dev_err(dev, "%s: no IRQ resource.\n", __func__);
706                 return -ENODEV;
707         }
708
709         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
710         if (unlikely(!mem)) {
711                 dev_err(dev, "%s: no memory resource.\n", __func__);
712                 return -ENODEV;
713         }
714
715         timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
716         if (!timer) {
717                 dev_err(dev, "%s: memory alloc failed!\n", __func__);
718                 return  -ENOMEM;
719         }
720
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__);
724                 return -ENOMEM;
725         }
726
727         timer->id = pdev->id;
728         timer->irq = irq->start;
729         timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
730         timer->pdev = pdev;
731         timer->capability = pdata->timer_capability;
732
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);
737         }
738
739         if (!timer->reserved) {
740                 pm_runtime_get_sync(dev);
741                 __omap_dm_timer_init_regs(timer);
742                 pm_runtime_put(dev);
743         }
744
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);
749
750         dev_dbg(dev, "Device Probed.\n");
751
752         return 0;
753 }
754
755 /**
756  * omap_dm_timer_remove - cleanup a registered timer device
757  * @pdev:       pointer to current timer platform device
758  *
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.
762  */
763 static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
764 {
765         struct omap_dm_timer *timer;
766         unsigned long flags;
767         int ret = -EINVAL;
768
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);
773                         ret = 0;
774                         break;
775                 }
776         spin_unlock_irqrestore(&dm_timer_lock, flags);
777
778         return ret;
779 }
780
781 static struct platform_driver omap_dm_timer_driver = {
782         .probe  = omap_dm_timer_probe,
783         .remove = __devexit_p(omap_dm_timer_remove),
784         .driver = {
785                 .name   = "omap_timer",
786         },
787 };
788
789 static int __init omap_dm_timer_driver_init(void)
790 {
791         return platform_driver_register(&omap_dm_timer_driver);
792 }
793
794 static void __exit omap_dm_timer_driver_exit(void)
795 {
796         platform_driver_unregister(&omap_dm_timer_driver);
797 }
798
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);
802
803 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
804 MODULE_LICENSE("GPL");
805 MODULE_ALIAS("platform:" DRIVER_NAME);
806 MODULE_AUTHOR("Texas Instruments Inc");