Merge branch 'stable/bug.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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) 2005 Nokia Corporation
7  * OMAP2 support by Juha Yrjola
8  * API improvements and OMAP2 clock framework support by Timo Teras
9  *
10  * Copyright (C) 2009 Texas Instruments
11  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation; either version 2 of the License, or (at your
16  * option) any later version.
17  *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * You should have received a copy of the  GNU General Public License along
28  * with this program; if not, write  to the Free Software Foundation, Inc.,
29  * 675 Mass Ave, Cambridge, MA 02139, USA.
30  */
31
32 #include <linux/init.h>
33 #include <linux/spinlock.h>
34 #include <linux/errno.h>
35 #include <linux/list.h>
36 #include <linux/clk.h>
37 #include <linux/delay.h>
38 #include <linux/io.h>
39 #include <linux/module.h>
40 #include <mach/hardware.h>
41 #include <plat/dmtimer.h>
42 #include <mach/irqs.h>
43
44 static int dm_timer_count;
45
46 #ifdef CONFIG_ARCH_OMAP1
47 static struct omap_dm_timer omap1_dm_timers[] = {
48         { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
49         { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
50         { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
51         { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
52         { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
53         { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
54         { .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
55         { .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
56 };
57
58 static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
59
60 #else
61 #define omap1_dm_timers                 NULL
62 #define omap1_dm_timer_count            0
63 #endif  /* CONFIG_ARCH_OMAP1 */
64
65 #ifdef CONFIG_ARCH_OMAP2
66 static struct omap_dm_timer omap2_dm_timers[] = {
67         { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
68         { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
69         { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
70         { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
71         { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
72         { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
73         { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
74         { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
75         { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
76         { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
77         { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
78         { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
79 };
80
81 static const char *omap2_dm_source_names[] __initdata = {
82         "sys_ck",
83         "func_32k_ck",
84         "alt_ck",
85         NULL
86 };
87
88 static struct clk *omap2_dm_source_clocks[3];
89 static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
90
91 #else
92 #define omap2_dm_timers                 NULL
93 #define omap2_dm_timer_count            0
94 #define omap2_dm_source_names           NULL
95 #define omap2_dm_source_clocks          NULL
96 #endif  /* CONFIG_ARCH_OMAP2 */
97
98 #ifdef CONFIG_ARCH_OMAP3
99 static struct omap_dm_timer omap3_dm_timers[] = {
100         { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
101         { .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
102         { .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
103         { .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
104         { .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
105         { .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
106         { .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
107         { .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
108         { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
109         { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
110         { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
111         { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
112 };
113
114 static const char *omap3_dm_source_names[] __initdata = {
115         "sys_ck",
116         "omap_32k_fck",
117         NULL
118 };
119
120 static struct clk *omap3_dm_source_clocks[2];
121 static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
122
123 #else
124 #define omap3_dm_timers                 NULL
125 #define omap3_dm_timer_count            0
126 #define omap3_dm_source_names           NULL
127 #define omap3_dm_source_clocks          NULL
128 #endif  /* CONFIG_ARCH_OMAP3 */
129
130 #ifdef CONFIG_ARCH_OMAP4
131 static struct omap_dm_timer omap4_dm_timers[] = {
132         { .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
133         { .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
134         { .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
135         { .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
136         { .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
137         { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
138         { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
139         { .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
140         { .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
141         { .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
142         { .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
143         { .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
144 };
145 static const char *omap4_dm_source_names[] __initdata = {
146         "sys_clkin_ck",
147         "sys_32k_ck",
148         NULL
149 };
150 static struct clk *omap4_dm_source_clocks[2];
151 static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
152
153 #else
154 #define omap4_dm_timers                 NULL
155 #define omap4_dm_timer_count            0
156 #define omap4_dm_source_names           NULL
157 #define omap4_dm_source_clocks          NULL
158 #endif  /* CONFIG_ARCH_OMAP4 */
159
160 static struct omap_dm_timer *dm_timers;
161 static const char **dm_source_names;
162 static struct clk **dm_source_clocks;
163
164 static spinlock_t dm_timer_lock;
165
166 /*
167  * Reads timer registers in posted and non-posted mode. The posted mode bit
168  * is encoded in reg. Note that in posted mode write pending bit must be
169  * checked. Otherwise a read of a non completed write will produce an error.
170  */
171 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
172 {
173         return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
174 }
175
176 /*
177  * Writes timer registers in posted and non-posted mode. The posted mode bit
178  * is encoded in reg. Note that in posted mode the write pending bit must be
179  * checked. Otherwise a write on a register which has a pending write will be
180  * lost.
181  */
182 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
183                                                 u32 value)
184 {
185         __omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
186 }
187
188 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
189 {
190         int c;
191
192         c = 0;
193         while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
194                 c++;
195                 if (c > 100000) {
196                         printk(KERN_ERR "Timer failed to reset\n");
197                         return;
198                 }
199         }
200 }
201
202 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
203 {
204         int autoidle = 0, wakeup = 0;
205
206         if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
207                 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
208                 omap_dm_timer_wait_for_reset(timer);
209         }
210         omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
211
212         /* Enable autoidle on OMAP2+ */
213         if (cpu_class_is_omap2())
214                 autoidle = 1;
215
216         /*
217          * Enable wake-up on OMAP2 CPUs.
218          */
219         if (cpu_class_is_omap2())
220                 wakeup = 1;
221
222         __omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
223         timer->posted = 1;
224 }
225
226 void omap_dm_timer_prepare(struct omap_dm_timer *timer)
227 {
228         omap_dm_timer_enable(timer);
229         omap_dm_timer_reset(timer);
230 }
231
232 struct omap_dm_timer *omap_dm_timer_request(void)
233 {
234         struct omap_dm_timer *timer = NULL;
235         unsigned long flags;
236         int i;
237
238         spin_lock_irqsave(&dm_timer_lock, flags);
239         for (i = 0; i < dm_timer_count; i++) {
240                 if (dm_timers[i].reserved)
241                         continue;
242
243                 timer = &dm_timers[i];
244                 timer->reserved = 1;
245                 break;
246         }
247         spin_unlock_irqrestore(&dm_timer_lock, flags);
248
249         if (timer != NULL)
250                 omap_dm_timer_prepare(timer);
251
252         return timer;
253 }
254 EXPORT_SYMBOL_GPL(omap_dm_timer_request);
255
256 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
257 {
258         struct omap_dm_timer *timer;
259         unsigned long flags;
260
261         spin_lock_irqsave(&dm_timer_lock, flags);
262         if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
263                 spin_unlock_irqrestore(&dm_timer_lock, flags);
264                 printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
265                        __FILE__, __LINE__, __func__, id);
266                 dump_stack();
267                 return NULL;
268         }
269
270         timer = &dm_timers[id-1];
271         timer->reserved = 1;
272         spin_unlock_irqrestore(&dm_timer_lock, flags);
273
274         omap_dm_timer_prepare(timer);
275
276         return timer;
277 }
278 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
279
280 void omap_dm_timer_free(struct omap_dm_timer *timer)
281 {
282         omap_dm_timer_enable(timer);
283         omap_dm_timer_reset(timer);
284         omap_dm_timer_disable(timer);
285
286         WARN_ON(!timer->reserved);
287         timer->reserved = 0;
288 }
289 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
290
291 void omap_dm_timer_enable(struct omap_dm_timer *timer)
292 {
293         if (timer->enabled)
294                 return;
295
296 #ifdef CONFIG_ARCH_OMAP2PLUS
297         if (cpu_class_is_omap2()) {
298                 clk_enable(timer->fclk);
299                 clk_enable(timer->iclk);
300         }
301 #endif
302
303         timer->enabled = 1;
304 }
305 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
306
307 void omap_dm_timer_disable(struct omap_dm_timer *timer)
308 {
309         if (!timer->enabled)
310                 return;
311
312 #ifdef CONFIG_ARCH_OMAP2PLUS
313         if (cpu_class_is_omap2()) {
314                 clk_disable(timer->iclk);
315                 clk_disable(timer->fclk);
316         }
317 #endif
318
319         timer->enabled = 0;
320 }
321 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
322
323 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
324 {
325         return timer->irq;
326 }
327 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
328
329 #if defined(CONFIG_ARCH_OMAP1)
330
331 /**
332  * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
333  * @inputmask: current value of idlect mask
334  */
335 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
336 {
337         int i;
338
339         /* If ARMXOR cannot be idled this function call is unnecessary */
340         if (!(inputmask & (1 << 1)))
341                 return inputmask;
342
343         /* If any active timer is using ARMXOR return modified mask */
344         for (i = 0; i < dm_timer_count; i++) {
345                 u32 l;
346
347                 l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
348                 if (l & OMAP_TIMER_CTRL_ST) {
349                         if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
350                                 inputmask &= ~(1 << 1);
351                         else
352                                 inputmask &= ~(1 << 2);
353                 }
354         }
355
356         return inputmask;
357 }
358 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
359
360 #else
361
362 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
363 {
364         return timer->fclk;
365 }
366 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
367
368 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
369 {
370         BUG();
371
372         return 0;
373 }
374 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
375
376 #endif
377
378 void omap_dm_timer_trigger(struct omap_dm_timer *timer)
379 {
380         omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
381 }
382 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
383
384 void omap_dm_timer_start(struct omap_dm_timer *timer)
385 {
386         u32 l;
387
388         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
389         if (!(l & OMAP_TIMER_CTRL_ST)) {
390                 l |= OMAP_TIMER_CTRL_ST;
391                 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
392         }
393 }
394 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
395
396 void omap_dm_timer_stop(struct omap_dm_timer *timer)
397 {
398         unsigned long rate = 0;
399
400 #ifdef CONFIG_ARCH_OMAP2PLUS
401         rate = clk_get_rate(timer->fclk);
402 #endif
403
404         __omap_dm_timer_stop(timer->io_base, timer->posted, rate);
405 }
406 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
407
408 #ifdef CONFIG_ARCH_OMAP1
409
410 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
411 {
412         int n = (timer - dm_timers) << 1;
413         u32 l;
414
415         l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
416         l |= source << n;
417         omap_writel(l, MOD_CONF_CTRL_1);
418
419         return 0;
420 }
421 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
422
423 #else
424
425 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
426 {
427         if (source < 0 || source >= 3)
428                 return -EINVAL;
429
430         return __omap_dm_timer_set_source(timer->fclk,
431                                                 dm_source_clocks[source]);
432 }
433 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
434
435 #endif
436
437 void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
438                             unsigned int load)
439 {
440         u32 l;
441
442         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
443         if (autoreload)
444                 l |= OMAP_TIMER_CTRL_AR;
445         else
446                 l &= ~OMAP_TIMER_CTRL_AR;
447         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
448         omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
449
450         omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
451 }
452 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
453
454 /* Optimized set_load which removes costly spin wait in timer_start */
455 void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
456                             unsigned int load)
457 {
458         u32 l;
459
460         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
461         if (autoreload) {
462                 l |= OMAP_TIMER_CTRL_AR;
463                 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
464         } else {
465                 l &= ~OMAP_TIMER_CTRL_AR;
466         }
467         l |= OMAP_TIMER_CTRL_ST;
468
469         __omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
470 }
471 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
472
473 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
474                              unsigned int match)
475 {
476         u32 l;
477
478         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
479         if (enable)
480                 l |= OMAP_TIMER_CTRL_CE;
481         else
482                 l &= ~OMAP_TIMER_CTRL_CE;
483         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
484         omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
485 }
486 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
487
488 void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
489                            int toggle, int trigger)
490 {
491         u32 l;
492
493         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
494         l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
495                OMAP_TIMER_CTRL_PT | (0x03 << 10));
496         if (def_on)
497                 l |= OMAP_TIMER_CTRL_SCPWM;
498         if (toggle)
499                 l |= OMAP_TIMER_CTRL_PT;
500         l |= trigger << 10;
501         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
502 }
503 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
504
505 void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
506 {
507         u32 l;
508
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 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
518
519 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
520                                   unsigned int value)
521 {
522         __omap_dm_timer_int_enable(timer->io_base, value);
523 }
524 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
525
526 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
527 {
528         unsigned int l;
529
530         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
531
532         return l;
533 }
534 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
535
536 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
537 {
538         __omap_dm_timer_write_status(timer->io_base, value);
539 }
540 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
541
542 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
543 {
544         return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
545 }
546 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
547
548 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
549 {
550         omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
551 }
552 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
553
554 int omap_dm_timers_active(void)
555 {
556         int i;
557
558         for (i = 0; i < dm_timer_count; i++) {
559                 struct omap_dm_timer *timer;
560
561                 timer = &dm_timers[i];
562
563                 if (!timer->enabled)
564                         continue;
565
566                 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
567                     OMAP_TIMER_CTRL_ST) {
568                         return 1;
569                 }
570         }
571         return 0;
572 }
573 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
574
575 static int __init omap_dm_timer_init(void)
576 {
577         struct omap_dm_timer *timer;
578         int i, map_size = SZ_8K;        /* Module 4KB + L4 4KB except on omap1 */
579
580         if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
581                 return -ENODEV;
582
583         spin_lock_init(&dm_timer_lock);
584
585         if (cpu_class_is_omap1()) {
586                 dm_timers = omap1_dm_timers;
587                 dm_timer_count = omap1_dm_timer_count;
588                 map_size = SZ_2K;
589         } else if (cpu_is_omap24xx()) {
590                 dm_timers = omap2_dm_timers;
591                 dm_timer_count = omap2_dm_timer_count;
592                 dm_source_names = omap2_dm_source_names;
593                 dm_source_clocks = omap2_dm_source_clocks;
594         } else if (cpu_is_omap34xx()) {
595                 dm_timers = omap3_dm_timers;
596                 dm_timer_count = omap3_dm_timer_count;
597                 dm_source_names = omap3_dm_source_names;
598                 dm_source_clocks = omap3_dm_source_clocks;
599         } else if (cpu_is_omap44xx()) {
600                 dm_timers = omap4_dm_timers;
601                 dm_timer_count = omap4_dm_timer_count;
602                 dm_source_names = omap4_dm_source_names;
603                 dm_source_clocks = omap4_dm_source_clocks;
604         }
605
606         if (cpu_class_is_omap2())
607                 for (i = 0; dm_source_names[i] != NULL; i++)
608                         dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
609
610         if (cpu_is_omap243x())
611                 dm_timers[0].phys_base = 0x49018000;
612
613         for (i = 0; i < dm_timer_count; i++) {
614                 timer = &dm_timers[i];
615
616                 /* Static mapping, never released */
617                 timer->io_base = ioremap(timer->phys_base, map_size);
618                 BUG_ON(!timer->io_base);
619
620 #ifdef CONFIG_ARCH_OMAP2PLUS
621                 if (cpu_class_is_omap2()) {
622                         char clk_name[16];
623                         sprintf(clk_name, "gpt%d_ick", i + 1);
624                         timer->iclk = clk_get(NULL, clk_name);
625                         sprintf(clk_name, "gpt%d_fck", i + 1);
626                         timer->fclk = clk_get(NULL, clk_name);
627                 }
628
629                 /* One or two timers may be set up early for sys_timer */
630                 if (sys_timer_reserved & (1  << i)) {
631                         timer->reserved = 1;
632                         timer->posted = 1;
633                 }
634 #endif
635         }
636
637         return 0;
638 }
639
640 arch_initcall(omap_dm_timer_init);