Merge branch 'sh-latest' of git://github.com/pmundt/linux-sh
[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/io.h>
39 #include <linux/slab.h>
40 #include <linux/err.h>
41 #include <linux/pm_runtime.h>
42
43 #include <plat/dmtimer.h>
44
45 static LIST_HEAD(omap_timer_list);
46 static DEFINE_SPINLOCK(dm_timer_lock);
47
48 /**
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
52  *
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.
56  */
57 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
58 {
59         WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
60         return __omap_dm_timer_read(timer, reg, timer->posted);
61 }
62
63 /**
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
68  *
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.
72  */
73 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
74                                                 u32 value)
75 {
76         WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
77         __omap_dm_timer_write(timer, reg, value, timer->posted);
78 }
79
80 static void omap_timer_restore_context(struct omap_dm_timer *timer)
81 {
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);
86
87         __raw_writel(timer->context.tisr, timer->irq_stat);
88         omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
89                                 timer->context.twer);
90         omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
91                                 timer->context.tcrr);
92         omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
93                                 timer->context.tldr);
94         omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
95                                 timer->context.tmar);
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);
101 }
102
103 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
104 {
105         int c;
106
107         if (!timer->sys_stat)
108                 return;
109
110         c = 0;
111         while (!(__raw_readl(timer->sys_stat) & 1)) {
112                 c++;
113                 if (c > 100000) {
114                         printk(KERN_ERR "Timer failed to reset\n");
115                         return;
116                 }
117         }
118 }
119
120 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
121 {
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);
126         }
127
128         __omap_dm_timer_reset(timer, 0, 0);
129         omap_dm_timer_disable(timer);
130         timer->posted = 1;
131 }
132
133 int omap_dm_timer_prepare(struct omap_dm_timer *timer)
134 {
135         struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
136         int ret;
137
138         timer->fclk = clk_get(&timer->pdev->dev, "fck");
139         if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
140                 timer->fclk = NULL;
141                 dev_err(&timer->pdev->dev, ": No fclk handle.\n");
142                 return -EINVAL;
143         }
144
145         if (pdata->needs_manual_reset)
146                 omap_dm_timer_reset(timer);
147
148         ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
149
150         timer->posted = 1;
151         return ret;
152 }
153
154 struct omap_dm_timer *omap_dm_timer_request(void)
155 {
156         struct omap_dm_timer *timer = NULL, *t;
157         unsigned long flags;
158         int ret = 0;
159
160         spin_lock_irqsave(&dm_timer_lock, flags);
161         list_for_each_entry(t, &omap_timer_list, node) {
162                 if (t->reserved)
163                         continue;
164
165                 timer = t;
166                 timer->reserved = 1;
167                 break;
168         }
169
170         if (timer) {
171                 ret = omap_dm_timer_prepare(timer);
172                 if (ret) {
173                         timer->reserved = 0;
174                         timer = NULL;
175                 }
176         }
177         spin_unlock_irqrestore(&dm_timer_lock, flags);
178
179         if (!timer)
180                 pr_debug("%s: timer request failed!\n", __func__);
181
182         return timer;
183 }
184 EXPORT_SYMBOL_GPL(omap_dm_timer_request);
185
186 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
187 {
188         struct omap_dm_timer *timer = NULL, *t;
189         unsigned long flags;
190         int ret = 0;
191
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) {
195                         timer = t;
196                         timer->reserved = 1;
197                         break;
198                 }
199         }
200
201         if (timer) {
202                 ret = omap_dm_timer_prepare(timer);
203                 if (ret) {
204                         timer->reserved = 0;
205                         timer = NULL;
206                 }
207         }
208         spin_unlock_irqrestore(&dm_timer_lock, flags);
209
210         if (!timer)
211                 pr_debug("%s: timer%d request failed!\n", __func__, id);
212
213         return timer;
214 }
215 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
216
217 int omap_dm_timer_free(struct omap_dm_timer *timer)
218 {
219         if (unlikely(!timer))
220                 return -EINVAL;
221
222         clk_put(timer->fclk);
223
224         WARN_ON(!timer->reserved);
225         timer->reserved = 0;
226         return 0;
227 }
228 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
229
230 void omap_dm_timer_enable(struct omap_dm_timer *timer)
231 {
232         pm_runtime_get_sync(&timer->pdev->dev);
233 }
234 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
235
236 void omap_dm_timer_disable(struct omap_dm_timer *timer)
237 {
238         pm_runtime_put(&timer->pdev->dev);
239 }
240 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
241
242 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
243 {
244         if (timer)
245                 return timer->irq;
246         return -EINVAL;
247 }
248 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
249
250 #if defined(CONFIG_ARCH_OMAP1)
251
252 /**
253  * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
254  * @inputmask: current value of idlect mask
255  */
256 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
257 {
258         int i = 0;
259         struct omap_dm_timer *timer = NULL;
260         unsigned long flags;
261
262         /* If ARMXOR cannot be idled this function call is unnecessary */
263         if (!(inputmask & (1 << 1)))
264                 return inputmask;
265
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) {
269                 u32 l;
270
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);
275                         else
276                                 inputmask &= ~(1 << 2);
277                 }
278                 i++;
279         }
280         spin_unlock_irqrestore(&dm_timer_lock, flags);
281
282         return inputmask;
283 }
284 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
285
286 #else
287
288 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
289 {
290         if (timer)
291                 return timer->fclk;
292         return NULL;
293 }
294 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
295
296 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
297 {
298         BUG();
299
300         return 0;
301 }
302 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
303
304 #endif
305
306 int omap_dm_timer_trigger(struct omap_dm_timer *timer)
307 {
308         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
309                 pr_err("%s: timer not available or enabled.\n", __func__);
310                 return -EINVAL;
311         }
312
313         omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
314         return 0;
315 }
316 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
317
318 int omap_dm_timer_start(struct omap_dm_timer *timer)
319 {
320         u32 l;
321
322         if (unlikely(!timer))
323                 return -EINVAL;
324
325         omap_dm_timer_enable(timer);
326
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);
332         }
333
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);
338         }
339
340         /* Save the context */
341         timer->context.tclr = l;
342         return 0;
343 }
344 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
345
346 int omap_dm_timer_stop(struct omap_dm_timer *timer)
347 {
348         unsigned long rate = 0;
349         struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
350
351         if (unlikely(!timer))
352                 return -EINVAL;
353
354         if (!pdata->needs_manual_reset)
355                 rate = clk_get_rate(timer->fclk);
356
357         __omap_dm_timer_stop(timer, timer->posted, rate);
358
359         return 0;
360 }
361 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
362
363 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
364 {
365         int ret;
366         struct dmtimer_platform_data *pdata;
367
368         if (unlikely(!timer))
369                 return -EINVAL;
370
371         pdata = timer->pdev->dev.platform_data;
372
373         if (source < 0 || source >= 3)
374                 return -EINVAL;
375
376         ret = pdata->set_timer_src(timer->pdev, source);
377
378         return ret;
379 }
380 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
381
382 int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
383                             unsigned int load)
384 {
385         u32 l;
386
387         if (unlikely(!timer))
388                 return -EINVAL;
389
390         omap_dm_timer_enable(timer);
391         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
392         if (autoreload)
393                 l |= OMAP_TIMER_CTRL_AR;
394         else
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);
398
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);
404         return 0;
405 }
406 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
407
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,
410                             unsigned int load)
411 {
412         u32 l;
413
414         if (unlikely(!timer))
415                 return -EINVAL;
416
417         omap_dm_timer_enable(timer);
418
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);
424         }
425
426         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
427         if (autoreload) {
428                 l |= OMAP_TIMER_CTRL_AR;
429                 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
430         } else {
431                 l &= ~OMAP_TIMER_CTRL_AR;
432         }
433         l |= OMAP_TIMER_CTRL_ST;
434
435         __omap_dm_timer_load_start(timer, l, load, timer->posted);
436
437         /* Save the context */
438         timer->context.tclr = l;
439         timer->context.tldr = load;
440         timer->context.tcrr = load;
441         return 0;
442 }
443 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
444
445 int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
446                              unsigned int match)
447 {
448         u32 l;
449
450         if (unlikely(!timer))
451                 return -EINVAL;
452
453         omap_dm_timer_enable(timer);
454         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
455         if (enable)
456                 l |= OMAP_TIMER_CTRL_CE;
457         else
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);
461
462         /* Save the context */
463         timer->context.tclr = l;
464         timer->context.tmar = match;
465         omap_dm_timer_disable(timer);
466         return 0;
467 }
468 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
469
470 int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
471                            int toggle, int trigger)
472 {
473         u32 l;
474
475         if (unlikely(!timer))
476                 return -EINVAL;
477
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));
482         if (def_on)
483                 l |= OMAP_TIMER_CTRL_SCPWM;
484         if (toggle)
485                 l |= OMAP_TIMER_CTRL_PT;
486         l |= trigger << 10;
487         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
488
489         /* Save the context */
490         timer->context.tclr = l;
491         omap_dm_timer_disable(timer);
492         return 0;
493 }
494 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
495
496 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
497 {
498         u32 l;
499
500         if (unlikely(!timer))
501                 return -EINVAL;
502
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;
508                 l |= prescaler << 2;
509         }
510         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
511
512         /* Save the context */
513         timer->context.tclr = l;
514         omap_dm_timer_disable(timer);
515         return 0;
516 }
517 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
518
519 int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
520                                   unsigned int value)
521 {
522         if (unlikely(!timer))
523                 return -EINVAL;
524
525         omap_dm_timer_enable(timer);
526         __omap_dm_timer_int_enable(timer, value);
527
528         /* Save the context */
529         timer->context.tier = value;
530         timer->context.twer = value;
531         omap_dm_timer_disable(timer);
532         return 0;
533 }
534 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
535
536 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
537 {
538         unsigned int l;
539
540         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
541                 pr_err("%s: timer not available or enabled.\n", __func__);
542                 return 0;
543         }
544
545         l = __raw_readl(timer->irq_stat);
546
547         return l;
548 }
549 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
550
551 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
552 {
553         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
554                 return -EINVAL;
555
556         __omap_dm_timer_write_status(timer, value);
557         /* Save the context */
558         timer->context.tisr = value;
559         return 0;
560 }
561 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
562
563 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
564 {
565         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
566                 pr_err("%s: timer not iavailable or enabled.\n", __func__);
567                 return 0;
568         }
569
570         return __omap_dm_timer_read_counter(timer, timer->posted);
571 }
572 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
573
574 int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
575 {
576         if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
577                 pr_err("%s: timer not available or enabled.\n", __func__);
578                 return -EINVAL;
579         }
580
581         omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
582
583         /* Save the context */
584         timer->context.tcrr = value;
585         return 0;
586 }
587 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
588
589 int omap_dm_timers_active(void)
590 {
591         struct omap_dm_timer *timer;
592
593         list_for_each_entry(timer, &omap_timer_list, node) {
594                 if (!timer->reserved)
595                         continue;
596
597                 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
598                     OMAP_TIMER_CTRL_ST) {
599                         return 1;
600                 }
601         }
602         return 0;
603 }
604 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
605
606 /**
607  * omap_dm_timer_probe - probe function called for every registered device
608  * @pdev:       pointer to current timer platform device
609  *
610  * Called by driver framework at the end of device registration for all
611  * timer devices.
612  */
613 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
614 {
615         int ret;
616         unsigned long flags;
617         struct omap_dm_timer *timer;
618         struct resource *mem, *irq, *ioarea;
619         struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
620
621         if (!pdata) {
622                 dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
623                 return -ENODEV;
624         }
625
626         irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
627         if (unlikely(!irq)) {
628                 dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
629                 return -ENODEV;
630         }
631
632         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
633         if (unlikely(!mem)) {
634                 dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
635                 return -ENODEV;
636         }
637
638         ioarea = request_mem_region(mem->start, resource_size(mem),
639                         pdev->name);
640         if (!ioarea) {
641                 dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
642                 return -EBUSY;
643         }
644
645         timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
646         if (!timer) {
647                 dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
648                         __func__);
649                 ret = -ENOMEM;
650                 goto err_free_ioregion;
651         }
652
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__);
656                 ret = -ENOMEM;
657                 goto err_free_mem;
658         }
659
660         timer->id = pdev->id;
661         timer->irq = irq->start;
662         timer->reserved = pdata->reserved;
663         timer->pdev = pdev;
664         timer->loses_context = pdata->loses_context;
665         timer->get_context_loss_count = pdata->get_context_loss_count;
666
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);
671         }
672
673         if (!timer->reserved) {
674                 pm_runtime_get_sync(&pdev->dev);
675                 __omap_dm_timer_init_regs(timer);
676                 pm_runtime_put(&pdev->dev);
677         }
678
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);
683
684         dev_dbg(&pdev->dev, "Device Probed.\n");
685
686         return 0;
687
688 err_free_mem:
689         kfree(timer);
690
691 err_free_ioregion:
692         release_mem_region(mem->start, resource_size(mem));
693
694         return ret;
695 }
696
697 /**
698  * omap_dm_timer_remove - cleanup a registered timer device
699  * @pdev:       pointer to current timer platform device
700  *
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.
704  */
705 static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
706 {
707         struct omap_dm_timer *timer;
708         unsigned long flags;
709         int ret = -EINVAL;
710
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);
715                         kfree(timer);
716                         ret = 0;
717                         break;
718                 }
719         spin_unlock_irqrestore(&dm_timer_lock, flags);
720
721         return ret;
722 }
723
724 static struct platform_driver omap_dm_timer_driver = {
725         .probe  = omap_dm_timer_probe,
726         .remove = __devexit_p(omap_dm_timer_remove),
727         .driver = {
728                 .name   = "omap_timer",
729         },
730 };
731
732 static int __init omap_dm_timer_driver_init(void)
733 {
734         return platform_driver_register(&omap_dm_timer_driver);
735 }
736
737 static void __exit omap_dm_timer_driver_exit(void)
738 {
739         platform_driver_unregister(&omap_dm_timer_driver);
740 }
741
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);
745
746 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
747 MODULE_LICENSE("GPL");
748 MODULE_ALIAS("platform:" DRIVER_NAME);
749 MODULE_AUTHOR("Texas Instruments Inc");