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