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