]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - arch/arm/plat-omap/dmtimer.c
ARM: OMAP2+: dmtimer: convert to platform devices
[mirror_ubuntu-hirsute-kernel.git] / arch / arm / plat-omap / dmtimer.c
CommitLineData
92105bb7
TL
1/*
2 * linux/arch/arm/plat-omap/dmtimer.c
3 *
4 * OMAP Dual-Mode Timers
5 *
97933d6c
TKD
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 *
92105bb7 12 * Copyright (C) 2005 Nokia Corporation
77900a2f
TT
13 * OMAP2 support by Juha Yrjola
14 * API improvements and OMAP2 clock framework support by Timo Teras
92105bb7 15 *
44169075
SS
16 * Copyright (C) 2009 Texas Instruments
17 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
18 *
92105bb7
TL
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/init.h>
77900a2f
TT
39#include <linux/spinlock.h>
40#include <linux/errno.h>
41#include <linux/list.h>
42#include <linux/clk.h>
43#include <linux/delay.h>
fced80c7 44#include <linux/io.h>
6c366e32 45#include <linux/module.h>
a09e64fb 46#include <mach/hardware.h>
ce491cf8 47#include <plat/dmtimer.h>
a09e64fb 48#include <mach/irqs.h>
92105bb7 49
882c0518 50static int dm_timer_count;
fa4bb626 51
882c0518 52#ifdef CONFIG_ARCH_OMAP2
471b3aa7 53static struct omap_dm_timer omap2_dm_timers[] = {
77900a2f
TT
54 { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
55 { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
56 { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
57 { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
58 { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
59 { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
60 { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
61 { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
62 { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
63 { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
64 { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
65 { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
92105bb7
TL
66};
67
471b3aa7 68static const char *omap2_dm_source_names[] __initdata = {
83379c81
TT
69 "sys_ck",
70 "func_32k_ck",
471b3aa7
SMK
71 "alt_ck",
72 NULL
83379c81
TT
73};
74
aea2a5b0 75static struct clk *omap2_dm_source_clocks[3];
882c0518 76static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
ce2df9ca 77
882c0518 78#else
ce2df9ca 79#define omap2_dm_timers NULL
882c0518 80#define omap2_dm_timer_count 0
ce2df9ca
SMK
81#define omap2_dm_source_names NULL
82#define omap2_dm_source_clocks NULL
882c0518 83#endif /* CONFIG_ARCH_OMAP2 */
ce2df9ca 84
882c0518 85#ifdef CONFIG_ARCH_OMAP3
ce2df9ca
SMK
86static struct omap_dm_timer omap3_dm_timers[] = {
87 { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
88 { .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
89 { .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
90 { .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
91 { .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
92 { .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
93 { .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
94 { .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
95 { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
96 { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
97 { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
9198a406 98 { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
ce2df9ca
SMK
99};
100
101static const char *omap3_dm_source_names[] __initdata = {
102 "sys_ck",
103 "omap_32k_fck",
104 NULL
105};
106
aea2a5b0 107static struct clk *omap3_dm_source_clocks[2];
882c0518 108static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
44169075 109
882c0518 110#else
44169075 111#define omap3_dm_timers NULL
882c0518 112#define omap3_dm_timer_count 0
44169075
SS
113#define omap3_dm_source_names NULL
114#define omap3_dm_source_clocks NULL
882c0518 115#endif /* CONFIG_ARCH_OMAP3 */
44169075 116
882c0518 117#ifdef CONFIG_ARCH_OMAP4
44169075 118static struct omap_dm_timer omap4_dm_timers[] = {
5772ca7d
SS
119 { .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
120 { .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
121 { .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
122 { .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
123 { .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
124 { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
125 { .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
126 { .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
127 { .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
128 { .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
129 { .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
130 { .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
44169075
SS
131};
132static const char *omap4_dm_source_names[] __initdata = {
1dc993b2
RN
133 "sys_clkin_ck",
134 "sys_32k_ck",
44169075
SS
135 NULL
136};
137static struct clk *omap4_dm_source_clocks[2];
882c0518 138static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
44169075 139
77900a2f 140#else
882c0518
TL
141#define omap4_dm_timers NULL
142#define omap4_dm_timer_count 0
143#define omap4_dm_source_names NULL
144#define omap4_dm_source_clocks NULL
145#endif /* CONFIG_ARCH_OMAP4 */
77900a2f 146
471b3aa7 147static struct omap_dm_timer *dm_timers;
aea2a5b0 148static const char **dm_source_names;
471b3aa7
SMK
149static struct clk **dm_source_clocks;
150
92105bb7
TL
151static spinlock_t dm_timer_lock;
152
0f0d0807
RW
153/*
154 * Reads timer registers in posted and non-posted mode. The posted mode bit
155 * is encoded in reg. Note that in posted mode write pending bit must be
156 * checked. Otherwise a read of a non completed write will produce an error.
157 */
158static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
77900a2f 159{
ee17f114
TL
160 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
161 return __omap_dm_timer_read(timer, reg, timer->posted);
77900a2f 162}
92105bb7 163
0f0d0807
RW
164/*
165 * Writes timer registers in posted and non-posted mode. The posted mode bit
166 * is encoded in reg. Note that in posted mode the write pending bit must be
167 * checked. Otherwise a write on a register which has a pending write will be
168 * lost.
169 */
170static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
171 u32 value)
92105bb7 172{
ee17f114
TL
173 WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
174 __omap_dm_timer_write(timer, reg, value, timer->posted);
92105bb7
TL
175}
176
77900a2f 177static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
92105bb7 178{
77900a2f
TT
179 int c;
180
ee17f114
TL
181 if (!timer->sys_stat)
182 return;
183
77900a2f 184 c = 0;
ee17f114 185 while (!(__raw_readl(timer->sys_stat) & 1)) {
77900a2f
TT
186 c++;
187 if (c > 100000) {
188 printk(KERN_ERR "Timer failed to reset\n");
189 return;
190 }
191 }
92105bb7
TL
192}
193
77900a2f
TT
194static void omap_dm_timer_reset(struct omap_dm_timer *timer)
195{
caf64f2f 196 int autoidle = 0, wakeup = 0;
77900a2f 197
39020842 198 if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
e32f7ec2
TT
199 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
200 omap_dm_timer_wait_for_reset(timer);
201 }
12583a70 202 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
77900a2f 203
ba503484
A
204 /* Enable autoidle on OMAP2+ */
205 if (cpu_class_is_omap2())
caf64f2f 206 autoidle = 1;
4ce1e5e1 207
0f0d0807 208 /*
219c5b98 209 * Enable wake-up on OMAP2 CPUs.
0f0d0807 210 */
219c5b98 211 if (cpu_class_is_omap2())
caf64f2f 212 wakeup = 1;
0f0d0807 213
ee17f114 214 __omap_dm_timer_reset(timer, autoidle, wakeup);
0f0d0807 215 timer->posted = 1;
77900a2f
TT
216}
217
caf64f2f 218void omap_dm_timer_prepare(struct omap_dm_timer *timer)
77900a2f 219{
12583a70 220 omap_dm_timer_enable(timer);
77900a2f
TT
221 omap_dm_timer_reset(timer);
222}
223
224struct omap_dm_timer *omap_dm_timer_request(void)
225{
226 struct omap_dm_timer *timer = NULL;
227 unsigned long flags;
228 int i;
229
230 spin_lock_irqsave(&dm_timer_lock, flags);
231 for (i = 0; i < dm_timer_count; i++) {
232 if (dm_timers[i].reserved)
233 continue;
234
235 timer = &dm_timers[i];
83379c81 236 timer->reserved = 1;
77900a2f
TT
237 break;
238 }
239 spin_unlock_irqrestore(&dm_timer_lock, flags);
240
83379c81
TT
241 if (timer != NULL)
242 omap_dm_timer_prepare(timer);
243
77900a2f
TT
244 return timer;
245}
6c366e32 246EXPORT_SYMBOL_GPL(omap_dm_timer_request);
77900a2f
TT
247
248struct omap_dm_timer *omap_dm_timer_request_specific(int id)
92105bb7
TL
249{
250 struct omap_dm_timer *timer;
77900a2f 251 unsigned long flags;
92105bb7 252
77900a2f
TT
253 spin_lock_irqsave(&dm_timer_lock, flags);
254 if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
255 spin_unlock_irqrestore(&dm_timer_lock, flags);
256 printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
8e86f427 257 __FILE__, __LINE__, __func__, id);
77900a2f
TT
258 dump_stack();
259 return NULL;
260 }
92105bb7 261
77900a2f 262 timer = &dm_timers[id-1];
83379c81 263 timer->reserved = 1;
77900a2f
TT
264 spin_unlock_irqrestore(&dm_timer_lock, flags);
265
83379c81
TT
266 omap_dm_timer_prepare(timer);
267
77900a2f 268 return timer;
92105bb7 269}
6c366e32 270EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
92105bb7 271
77900a2f
TT
272void omap_dm_timer_free(struct omap_dm_timer *timer)
273{
12583a70 274 omap_dm_timer_enable(timer);
77900a2f 275 omap_dm_timer_reset(timer);
12583a70 276 omap_dm_timer_disable(timer);
fa4bb626 277
77900a2f
TT
278 WARN_ON(!timer->reserved);
279 timer->reserved = 0;
280}
6c366e32 281EXPORT_SYMBOL_GPL(omap_dm_timer_free);
77900a2f 282
12583a70
TT
283void omap_dm_timer_enable(struct omap_dm_timer *timer)
284{
285 if (timer->enabled)
286 return;
287
882c0518
TL
288#ifdef CONFIG_ARCH_OMAP2PLUS
289 if (cpu_class_is_omap2()) {
290 clk_enable(timer->fclk);
291 clk_enable(timer->iclk);
292 }
293#endif
12583a70
TT
294
295 timer->enabled = 1;
296}
6c366e32 297EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
12583a70
TT
298
299void omap_dm_timer_disable(struct omap_dm_timer *timer)
300{
301 if (!timer->enabled)
302 return;
303
882c0518
TL
304#ifdef CONFIG_ARCH_OMAP2PLUS
305 if (cpu_class_is_omap2()) {
306 clk_disable(timer->iclk);
307 clk_disable(timer->fclk);
308 }
309#endif
12583a70
TT
310
311 timer->enabled = 0;
312}
6c366e32 313EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
12583a70 314
77900a2f
TT
315int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
316{
317 return timer->irq;
318}
6c366e32 319EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
77900a2f
TT
320
321#if defined(CONFIG_ARCH_OMAP1)
322
a569c6ec
TL
323/**
324 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
325 * @inputmask: current value of idlect mask
326 */
327__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
328{
77900a2f 329 int i;
a569c6ec
TL
330
331 /* If ARMXOR cannot be idled this function call is unnecessary */
332 if (!(inputmask & (1 << 1)))
333 return inputmask;
334
335 /* If any active timer is using ARMXOR return modified mask */
77900a2f
TT
336 for (i = 0; i < dm_timer_count; i++) {
337 u32 l;
338
35912c79 339 l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
77900a2f
TT
340 if (l & OMAP_TIMER_CTRL_ST) {
341 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
a569c6ec
TL
342 inputmask &= ~(1 << 1);
343 else
344 inputmask &= ~(1 << 2);
345 }
77900a2f 346 }
a569c6ec
TL
347
348 return inputmask;
349}
6c366e32 350EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
a569c6ec 351
140455fa 352#else
a569c6ec 353
77900a2f 354struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
92105bb7 355{
fa4bb626 356 return timer->fclk;
77900a2f 357}
6c366e32 358EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
92105bb7 359
77900a2f
TT
360__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
361{
362 BUG();
2121880e
DB
363
364 return 0;
92105bb7 365}
6c366e32 366EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
92105bb7 367
77900a2f 368#endif
92105bb7 369
77900a2f 370void omap_dm_timer_trigger(struct omap_dm_timer *timer)
92105bb7 371{
77900a2f 372 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
92105bb7 373}
6c366e32 374EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
92105bb7 375
77900a2f
TT
376void omap_dm_timer_start(struct omap_dm_timer *timer)
377{
378 u32 l;
92105bb7 379
77900a2f
TT
380 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
381 if (!(l & OMAP_TIMER_CTRL_ST)) {
382 l |= OMAP_TIMER_CTRL_ST;
383 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
384 }
385}
6c366e32 386EXPORT_SYMBOL_GPL(omap_dm_timer_start);
92105bb7 387
77900a2f 388void omap_dm_timer_stop(struct omap_dm_timer *timer)
92105bb7 389{
caf64f2f 390 unsigned long rate = 0;
92105bb7 391
140455fa 392#ifdef CONFIG_ARCH_OMAP2PLUS
caf64f2f 393 rate = clk_get_rate(timer->fclk);
5c3db36b 394#endif
caf64f2f 395
ee17f114 396 __omap_dm_timer_stop(timer, timer->posted, rate);
92105bb7 397}
6c366e32 398EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
92105bb7 399
f248076c 400int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
92105bb7 401{
77900a2f 402 if (source < 0 || source >= 3)
f248076c 403 return -EINVAL;
77900a2f 404
97933d6c 405#ifdef CONFIG_ARCH_OMAP2PLUS
caf64f2f
TL
406 return __omap_dm_timer_set_source(timer->fclk,
407 dm_source_clocks[source]);
97933d6c
TKD
408#else
409 return 0;
410#endif
92105bb7 411}
6c366e32 412EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
92105bb7 413
77900a2f
TT
414void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
415 unsigned int load)
92105bb7
TL
416{
417 u32 l;
77900a2f 418
92105bb7 419 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2f
TT
420 if (autoreload)
421 l |= OMAP_TIMER_CTRL_AR;
422 else
423 l &= ~OMAP_TIMER_CTRL_AR;
92105bb7 424 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
77900a2f 425 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
0f0d0807 426
77900a2f 427 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
92105bb7 428}
6c366e32 429EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
92105bb7 430
3fddd09e
RW
431/* Optimized set_load which removes costly spin wait in timer_start */
432void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
433 unsigned int load)
434{
435 u32 l;
436
437 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
64ce2907 438 if (autoreload) {
3fddd09e 439 l |= OMAP_TIMER_CTRL_AR;
64ce2907
PW
440 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
441 } else {
3fddd09e 442 l &= ~OMAP_TIMER_CTRL_AR;
64ce2907 443 }
3fddd09e
RW
444 l |= OMAP_TIMER_CTRL_ST;
445
ee17f114 446 __omap_dm_timer_load_start(timer, l, load, timer->posted);
3fddd09e 447}
6c366e32 448EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
3fddd09e 449
77900a2f
TT
450void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
451 unsigned int match)
92105bb7
TL
452{
453 u32 l;
454
455 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
83379c81 456 if (enable)
77900a2f
TT
457 l |= OMAP_TIMER_CTRL_CE;
458 else
459 l &= ~OMAP_TIMER_CTRL_CE;
92105bb7 460 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
77900a2f 461 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
92105bb7 462}
6c366e32 463EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
92105bb7 464
77900a2f
TT
465void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
466 int toggle, int trigger)
92105bb7
TL
467{
468 u32 l;
469
470 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2f
TT
471 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
472 OMAP_TIMER_CTRL_PT | (0x03 << 10));
473 if (def_on)
474 l |= OMAP_TIMER_CTRL_SCPWM;
475 if (toggle)
476 l |= OMAP_TIMER_CTRL_PT;
477 l |= trigger << 10;
92105bb7
TL
478 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
479}
6c366e32 480EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
92105bb7 481
77900a2f 482void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
92105bb7
TL
483{
484 u32 l;
485
486 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2f
TT
487 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
488 if (prescaler >= 0x00 && prescaler <= 0x07) {
489 l |= OMAP_TIMER_CTRL_PRE;
490 l |= prescaler << 2;
491 }
92105bb7
TL
492 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
493}
6c366e32 494EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
92105bb7 495
77900a2f
TT
496void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
497 unsigned int value)
92105bb7 498{
ee17f114 499 __omap_dm_timer_int_enable(timer, value);
92105bb7 500}
6c366e32 501EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
92105bb7 502
77900a2f 503unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
92105bb7 504{
fa4bb626
TT
505 unsigned int l;
506
ee17f114 507 l = __raw_readl(timer->irq_stat);
fa4bb626
TT
508
509 return l;
92105bb7 510}
6c366e32 511EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
92105bb7 512
77900a2f 513void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
92105bb7 514{
ee17f114 515 __omap_dm_timer_write_status(timer, value);
92105bb7 516}
6c366e32 517EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
92105bb7 518
77900a2f 519unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
92105bb7 520{
ee17f114 521 return __omap_dm_timer_read_counter(timer, timer->posted);
92105bb7 522}
6c366e32 523EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
92105bb7 524
83379c81
TT
525void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
526{
fa4bb626 527 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
83379c81 528}
6c366e32 529EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
83379c81 530
77900a2f 531int omap_dm_timers_active(void)
92105bb7 532{
77900a2f 533 int i;
92105bb7 534
77900a2f
TT
535 for (i = 0; i < dm_timer_count; i++) {
536 struct omap_dm_timer *timer;
92105bb7 537
77900a2f 538 timer = &dm_timers[i];
12583a70
TT
539
540 if (!timer->enabled)
541 continue;
542
77900a2f 543 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
fa4bb626 544 OMAP_TIMER_CTRL_ST) {
77900a2f 545 return 1;
fa4bb626 546 }
77900a2f
TT
547 }
548 return 0;
549}
6c366e32 550EXPORT_SYMBOL_GPL(omap_dm_timers_active);
92105bb7 551
11a0186f 552static int __init omap_dm_timer_init(void)
92105bb7
TL
553{
554 struct omap_dm_timer *timer;
3566fc63 555 int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */
77900a2f 556
97933d6c 557 if (!cpu_class_is_omap2())
77900a2f 558 return -ENODEV;
92105bb7
TL
559
560 spin_lock_init(&dm_timer_lock);
471b3aa7 561
97933d6c 562 if (cpu_is_omap24xx()) {
471b3aa7 563 dm_timers = omap2_dm_timers;
882c0518 564 dm_timer_count = omap2_dm_timer_count;
aea2a5b0
SS
565 dm_source_names = omap2_dm_source_names;
566 dm_source_clocks = omap2_dm_source_clocks;
ce2df9ca
SMK
567 } else if (cpu_is_omap34xx()) {
568 dm_timers = omap3_dm_timers;
882c0518 569 dm_timer_count = omap3_dm_timer_count;
aea2a5b0
SS
570 dm_source_names = omap3_dm_source_names;
571 dm_source_clocks = omap3_dm_source_clocks;
44169075
SS
572 } else if (cpu_is_omap44xx()) {
573 dm_timers = omap4_dm_timers;
882c0518 574 dm_timer_count = omap4_dm_timer_count;
44169075
SS
575 dm_source_names = omap4_dm_source_names;
576 dm_source_clocks = omap4_dm_source_clocks;
ee17f114
TL
577
578 pr_err("dmtimers disabled for omap4 until hwmod conversion\n");
579 return -ENODEV;
83379c81 580 }
471b3aa7
SMK
581
582 if (cpu_class_is_omap2())
583 for (i = 0; dm_source_names[i] != NULL; i++)
584 dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
585
56a25641
SMK
586 if (cpu_is_omap243x())
587 dm_timers[0].phys_base = 0x49018000;
83379c81 588
77900a2f 589 for (i = 0; i < dm_timer_count; i++) {
77900a2f 590 timer = &dm_timers[i];
3566fc63
TL
591
592 /* Static mapping, never released */
593 timer->io_base = ioremap(timer->phys_base, map_size);
594 BUG_ON(!timer->io_base);
595
140455fa 596#ifdef CONFIG_ARCH_OMAP2PLUS
471b3aa7
SMK
597 if (cpu_class_is_omap2()) {
598 char clk_name[16];
599 sprintf(clk_name, "gpt%d_ick", i + 1);
600 timer->iclk = clk_get(NULL, clk_name);
601 sprintf(clk_name, "gpt%d_fck", i + 1);
602 timer->fclk = clk_get(NULL, clk_name);
603 }
11a0186f
TL
604
605 /* One or two timers may be set up early for sys_timer */
606 if (sys_timer_reserved & (1 << i)) {
607 timer->reserved = 1;
608 timer->posted = 1;
ee17f114 609 continue;
11a0186f 610 }
77900a2f 611#endif
ee17f114
TL
612 omap_dm_timer_enable(timer);
613 __omap_dm_timer_init_regs(timer);
614 omap_dm_timer_disable(timer);
92105bb7 615 }
92105bb7 616
92105bb7
TL
617 return 0;
618}
11a0186f
TL
619
620arch_initcall(omap_dm_timer_init);