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