omap: Move dmtimer defines to dmtimer.h
[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         if (timer->posted)
174                 while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
175                                 & (reg >> WPSHIFT))
176                         cpu_relax();
177         return readl(timer->io_base + (reg & 0xff));
178 }
179
180 /*
181  * Writes timer registers in posted and non-posted mode. The posted mode bit
182  * is encoded in reg. Note that in posted mode the write pending bit must be
183  * checked. Otherwise a write on a register which has a pending write will be
184  * lost.
185  */
186 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
187                                                 u32 value)
188 {
189         if (timer->posted)
190                 while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
191                                 & (reg >> WPSHIFT))
192                         cpu_relax();
193         writel(value, timer->io_base + (reg & 0xff));
194 }
195
196 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
197 {
198         int c;
199
200         c = 0;
201         while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
202                 c++;
203                 if (c > 100000) {
204                         printk(KERN_ERR "Timer failed to reset\n");
205                         return;
206                 }
207         }
208 }
209
210 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
211 {
212         u32 l;
213
214         if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
215                 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
216                 omap_dm_timer_wait_for_reset(timer);
217         }
218         omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
219
220         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
221         l |= 0x02 << 3;  /* Set to smart-idle mode */
222         l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
223
224         /* Enable autoidle on OMAP2 / OMAP3 */
225         if (cpu_is_omap24xx() || cpu_is_omap34xx())
226                 l |= 0x1 << 0;
227
228         /*
229          * Enable wake-up on OMAP2 CPUs.
230          */
231         if (cpu_class_is_omap2())
232                 l |= 1 << 2;
233         omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
234
235         /* Match hardware reset default of posted mode */
236         omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
237                         OMAP_TIMER_CTRL_POSTED);
238         timer->posted = 1;
239 }
240
241 static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
242 {
243         omap_dm_timer_enable(timer);
244         omap_dm_timer_reset(timer);
245 }
246
247 struct omap_dm_timer *omap_dm_timer_request(void)
248 {
249         struct omap_dm_timer *timer = NULL;
250         unsigned long flags;
251         int i;
252
253         spin_lock_irqsave(&dm_timer_lock, flags);
254         for (i = 0; i < dm_timer_count; i++) {
255                 if (dm_timers[i].reserved)
256                         continue;
257
258                 timer = &dm_timers[i];
259                 timer->reserved = 1;
260                 break;
261         }
262         spin_unlock_irqrestore(&dm_timer_lock, flags);
263
264         if (timer != NULL)
265                 omap_dm_timer_prepare(timer);
266
267         return timer;
268 }
269 EXPORT_SYMBOL_GPL(omap_dm_timer_request);
270
271 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
272 {
273         struct omap_dm_timer *timer;
274         unsigned long flags;
275
276         spin_lock_irqsave(&dm_timer_lock, flags);
277         if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
278                 spin_unlock_irqrestore(&dm_timer_lock, flags);
279                 printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
280                        __FILE__, __LINE__, __func__, id);
281                 dump_stack();
282                 return NULL;
283         }
284
285         timer = &dm_timers[id-1];
286         timer->reserved = 1;
287         spin_unlock_irqrestore(&dm_timer_lock, flags);
288
289         omap_dm_timer_prepare(timer);
290
291         return timer;
292 }
293 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
294
295 void omap_dm_timer_free(struct omap_dm_timer *timer)
296 {
297         omap_dm_timer_enable(timer);
298         omap_dm_timer_reset(timer);
299         omap_dm_timer_disable(timer);
300
301         WARN_ON(!timer->reserved);
302         timer->reserved = 0;
303 }
304 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
305
306 void omap_dm_timer_enable(struct omap_dm_timer *timer)
307 {
308         if (timer->enabled)
309                 return;
310
311 #ifdef CONFIG_ARCH_OMAP2PLUS
312         if (cpu_class_is_omap2()) {
313                 clk_enable(timer->fclk);
314                 clk_enable(timer->iclk);
315         }
316 #endif
317
318         timer->enabled = 1;
319 }
320 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
321
322 void omap_dm_timer_disable(struct omap_dm_timer *timer)
323 {
324         if (!timer->enabled)
325                 return;
326
327 #ifdef CONFIG_ARCH_OMAP2PLUS
328         if (cpu_class_is_omap2()) {
329                 clk_disable(timer->iclk);
330                 clk_disable(timer->fclk);
331         }
332 #endif
333
334         timer->enabled = 0;
335 }
336 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
337
338 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
339 {
340         return timer->irq;
341 }
342 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
343
344 #if defined(CONFIG_ARCH_OMAP1)
345
346 /**
347  * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
348  * @inputmask: current value of idlect mask
349  */
350 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
351 {
352         int i;
353
354         /* If ARMXOR cannot be idled this function call is unnecessary */
355         if (!(inputmask & (1 << 1)))
356                 return inputmask;
357
358         /* If any active timer is using ARMXOR return modified mask */
359         for (i = 0; i < dm_timer_count; i++) {
360                 u32 l;
361
362                 l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
363                 if (l & OMAP_TIMER_CTRL_ST) {
364                         if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
365                                 inputmask &= ~(1 << 1);
366                         else
367                                 inputmask &= ~(1 << 2);
368                 }
369         }
370
371         return inputmask;
372 }
373 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
374
375 #else
376
377 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
378 {
379         return timer->fclk;
380 }
381 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
382
383 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
384 {
385         BUG();
386
387         return 0;
388 }
389 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
390
391 #endif
392
393 void omap_dm_timer_trigger(struct omap_dm_timer *timer)
394 {
395         omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
396 }
397 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
398
399 void omap_dm_timer_start(struct omap_dm_timer *timer)
400 {
401         u32 l;
402
403         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
404         if (!(l & OMAP_TIMER_CTRL_ST)) {
405                 l |= OMAP_TIMER_CTRL_ST;
406                 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
407         }
408 }
409 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
410
411 void omap_dm_timer_stop(struct omap_dm_timer *timer)
412 {
413         u32 l;
414
415         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
416         if (l & OMAP_TIMER_CTRL_ST) {
417                 l &= ~0x1;
418                 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
419 #ifdef CONFIG_ARCH_OMAP2PLUS
420                 /* Readback to make sure write has completed */
421                 omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
422                  /*
423                   * Wait for functional clock period x 3.5 to make sure that
424                   * timer is stopped
425                   */
426                 udelay(3500000 / clk_get_rate(timer->fclk) + 1);
427 #endif
428         }
429         /* Ack possibly pending interrupt */
430         omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
431                         OMAP_TIMER_INT_OVERFLOW);
432 }
433 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
434
435 #ifdef CONFIG_ARCH_OMAP1
436
437 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
438 {
439         int n = (timer - dm_timers) << 1;
440         u32 l;
441
442         l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
443         l |= source << n;
444         omap_writel(l, MOD_CONF_CTRL_1);
445
446         return 0;
447 }
448 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
449
450 #else
451
452 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
453 {
454         int ret = -EINVAL;
455
456         if (source < 0 || source >= 3)
457                 return -EINVAL;
458
459         clk_disable(timer->fclk);
460         ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
461         clk_enable(timer->fclk);
462
463         /*
464          * When the functional clock disappears, too quick writes seem
465          * to cause an abort. XXX Is this still necessary?
466          */
467         __delay(300000);
468
469         return ret;
470 }
471 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
472
473 #endif
474
475 void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
476                             unsigned int load)
477 {
478         u32 l;
479
480         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
481         if (autoreload)
482                 l |= OMAP_TIMER_CTRL_AR;
483         else
484                 l &= ~OMAP_TIMER_CTRL_AR;
485         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
486         omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
487
488         omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
489 }
490 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
491
492 /* Optimized set_load which removes costly spin wait in timer_start */
493 void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
494                             unsigned int load)
495 {
496         u32 l;
497
498         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
499         if (autoreload) {
500                 l |= OMAP_TIMER_CTRL_AR;
501                 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
502         } else {
503                 l &= ~OMAP_TIMER_CTRL_AR;
504         }
505         l |= OMAP_TIMER_CTRL_ST;
506
507         omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
508         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
509 }
510 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
511
512 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
513                              unsigned int match)
514 {
515         u32 l;
516
517         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
518         if (enable)
519                 l |= OMAP_TIMER_CTRL_CE;
520         else
521                 l &= ~OMAP_TIMER_CTRL_CE;
522         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
523         omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
524 }
525 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
526
527 void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
528                            int toggle, int trigger)
529 {
530         u32 l;
531
532         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
533         l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
534                OMAP_TIMER_CTRL_PT | (0x03 << 10));
535         if (def_on)
536                 l |= OMAP_TIMER_CTRL_SCPWM;
537         if (toggle)
538                 l |= OMAP_TIMER_CTRL_PT;
539         l |= trigger << 10;
540         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
541 }
542 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
543
544 void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
545 {
546         u32 l;
547
548         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
549         l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
550         if (prescaler >= 0x00 && prescaler <= 0x07) {
551                 l |= OMAP_TIMER_CTRL_PRE;
552                 l |= prescaler << 2;
553         }
554         omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
555 }
556 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
557
558 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
559                                   unsigned int value)
560 {
561         omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
562         omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
563 }
564 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
565
566 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
567 {
568         unsigned int l;
569
570         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
571
572         return l;
573 }
574 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
575
576 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
577 {
578         omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
579 }
580 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
581
582 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
583 {
584         unsigned int l;
585
586         l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
587
588         return l;
589 }
590 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
591
592 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
593 {
594         omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
595 }
596 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
597
598 int omap_dm_timers_active(void)
599 {
600         int i;
601
602         for (i = 0; i < dm_timer_count; i++) {
603                 struct omap_dm_timer *timer;
604
605                 timer = &dm_timers[i];
606
607                 if (!timer->enabled)
608                         continue;
609
610                 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
611                     OMAP_TIMER_CTRL_ST) {
612                         return 1;
613                 }
614         }
615         return 0;
616 }
617 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
618
619 int __init omap_dm_timer_init(void)
620 {
621         struct omap_dm_timer *timer;
622         int i, map_size = SZ_8K;        /* Module 4KB + L4 4KB except on omap1 */
623
624         if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
625                 return -ENODEV;
626
627         spin_lock_init(&dm_timer_lock);
628
629         if (cpu_class_is_omap1()) {
630                 dm_timers = omap1_dm_timers;
631                 dm_timer_count = omap1_dm_timer_count;
632                 map_size = SZ_2K;
633         } else if (cpu_is_omap24xx()) {
634                 dm_timers = omap2_dm_timers;
635                 dm_timer_count = omap2_dm_timer_count;
636                 dm_source_names = omap2_dm_source_names;
637                 dm_source_clocks = omap2_dm_source_clocks;
638         } else if (cpu_is_omap34xx()) {
639                 dm_timers = omap3_dm_timers;
640                 dm_timer_count = omap3_dm_timer_count;
641                 dm_source_names = omap3_dm_source_names;
642                 dm_source_clocks = omap3_dm_source_clocks;
643         } else if (cpu_is_omap44xx()) {
644                 dm_timers = omap4_dm_timers;
645                 dm_timer_count = omap4_dm_timer_count;
646                 dm_source_names = omap4_dm_source_names;
647                 dm_source_clocks = omap4_dm_source_clocks;
648         }
649
650         if (cpu_class_is_omap2())
651                 for (i = 0; dm_source_names[i] != NULL; i++)
652                         dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
653
654         if (cpu_is_omap243x())
655                 dm_timers[0].phys_base = 0x49018000;
656
657         for (i = 0; i < dm_timer_count; i++) {
658                 timer = &dm_timers[i];
659
660                 /* Static mapping, never released */
661                 timer->io_base = ioremap(timer->phys_base, map_size);
662                 BUG_ON(!timer->io_base);
663
664 #ifdef CONFIG_ARCH_OMAP2PLUS
665                 if (cpu_class_is_omap2()) {
666                         char clk_name[16];
667                         sprintf(clk_name, "gpt%d_ick", i + 1);
668                         timer->iclk = clk_get(NULL, clk_name);
669                         sprintf(clk_name, "gpt%d_fck", i + 1);
670                         timer->fclk = clk_get(NULL, clk_name);
671                 }
672 #endif
673         }
674
675         return 0;
676 }