aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/dmtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/dmtimer.c')
-rw-r--r--arch/arm/plat-omap/dmtimer.c413
1 files changed, 295 insertions, 118 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index eba3cb52ad87..c25a1a6d2b03 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -4,7 +4,8 @@
4 * OMAP Dual-Mode Timers 4 * OMAP Dual-Mode Timers
5 * 5 *
6 * Copyright (C) 2005 Nokia Corporation 6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com> 7 * OMAP2 support by Juha Yrjola
8 * API improvements and OMAP2 clock framework support by Timo Teras
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
@@ -26,15 +27,17 @@
26 */ 27 */
27 28
28#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/spinlock.h>
31#include <linux/errno.h>
32#include <linux/list.h>
33#include <linux/clk.h>
34#include <linux/delay.h>
29#include <asm/hardware.h> 35#include <asm/hardware.h>
30#include <asm/arch/dmtimer.h> 36#include <asm/arch/dmtimer.h>
31#include <asm/io.h> 37#include <asm/io.h>
32#include <asm/arch/irqs.h> 38#include <asm/arch/irqs.h>
33#include <linux/spinlock.h>
34#include <linux/list.h>
35
36#define OMAP_TIMER_COUNT 8
37 39
40/* register offsets */
38#define OMAP_TIMER_ID_REG 0x00 41#define OMAP_TIMER_ID_REG 0x00
39#define OMAP_TIMER_OCP_CFG_REG 0x10 42#define OMAP_TIMER_OCP_CFG_REG 0x10
40#define OMAP_TIMER_SYS_STAT_REG 0x14 43#define OMAP_TIMER_SYS_STAT_REG 0x14
@@ -50,52 +53,184 @@
50#define OMAP_TIMER_CAPTURE_REG 0x3c 53#define OMAP_TIMER_CAPTURE_REG 0x3c
51#define OMAP_TIMER_IF_CTRL_REG 0x40 54#define OMAP_TIMER_IF_CTRL_REG 0x40
52 55
56/* timer control reg bits */
57#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
58#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
59#define OMAP_TIMER_CTRL_PT (1 << 12)
60#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
61#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
62#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
63#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
64#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
65#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
66#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */
67#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
68#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
69
70struct omap_dm_timer {
71 unsigned long phys_base;
72 int irq;
73#ifdef CONFIG_ARCH_OMAP2
74 struct clk *iclk, *fclk;
75#endif
76 void __iomem *io_base;
77 unsigned reserved:1;
78};
79
80#ifdef CONFIG_ARCH_OMAP1
81
82static struct omap_dm_timer dm_timers[] = {
83 { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
84 { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
85 { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
86 { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
87 { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
88 { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
89 { .phys_base = 0xfffb4400, .irq = INT_1610_GPTIMER7 },
90 { .phys_base = 0xfffb4c00, .irq = INT_1610_GPTIMER8 },
91};
53 92
54static struct dmtimer_info_struct { 93#elif defined(CONFIG_ARCH_OMAP2)
55 struct list_head unused_timers;
56 struct list_head reserved_timers;
57} dm_timer_info;
58 94
59static struct omap_dm_timer dm_timers[] = { 95static struct omap_dm_timer dm_timers[] = {
60 { .base=0xfffb1400, .irq=INT_1610_GPTIMER1 }, 96 { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
61 { .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 }, 97 { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
62 { .base=0xfffb2400, .irq=INT_1610_GPTIMER3 }, 98 { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
63 { .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 }, 99 { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
64 { .base=0xfffb3400, .irq=INT_1610_GPTIMER5 }, 100 { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
65 { .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 }, 101 { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
66 { .base=0xfffb4400, .irq=INT_1610_GPTIMER7 }, 102 { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
67 { .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 }, 103 { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
68 { .base=0x0 }, 104 { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
105 { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
106 { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
107 { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
69}; 108};
70 109
110#else
111
112#error OMAP architecture not supported!
113
114#endif
115
116static const int dm_timer_count = ARRAY_SIZE(dm_timers);
71 117
72static spinlock_t dm_timer_lock; 118static spinlock_t dm_timer_lock;
73 119
120static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
121{
122 return readl(timer->io_base + reg);
123}
74 124
75inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value) 125static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
76{ 126{
77 omap_writel(value, timer->base + reg); 127 writel(value, timer->io_base + reg);
78 while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG)) 128 while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
79 ; 129 ;
80} 130}
81 131
82u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) 132static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
83{ 133{
84 return omap_readl(timer->base + reg); 134 int c;
135
136 c = 0;
137 while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
138 c++;
139 if (c > 100000) {
140 printk(KERN_ERR "Timer failed to reset\n");
141 return;
142 }
143 }
85} 144}
86 145
87int omap_dm_timers_active(void) 146static void omap_dm_timer_reset(struct omap_dm_timer *timer)
147{
148 u32 l;
149
150 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
151 omap_dm_timer_wait_for_reset(timer);
152
153 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK);
154
155 /* Set to smart-idle mode */
156 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
157 l |= 0x02 << 3;
158 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
159}
160
161static void omap_dm_timer_reserve(struct omap_dm_timer *timer)
162{
163 timer->reserved = 1;
164#ifdef CONFIG_ARCH_OMAP2
165 clk_enable(timer->iclk);
166 clk_enable(timer->fclk);
167#endif
168 omap_dm_timer_reset(timer);
169}
170
171struct omap_dm_timer *omap_dm_timer_request(void)
172{
173 struct omap_dm_timer *timer = NULL;
174 unsigned long flags;
175 int i;
176
177 spin_lock_irqsave(&dm_timer_lock, flags);
178 for (i = 0; i < dm_timer_count; i++) {
179 if (dm_timers[i].reserved)
180 continue;
181
182 timer = &dm_timers[i];
183 omap_dm_timer_reserve(timer);
184 break;
185 }
186 spin_unlock_irqrestore(&dm_timer_lock, flags);
187
188 return timer;
189}
190
191struct omap_dm_timer *omap_dm_timer_request_specific(int id)
88{ 192{
89 struct omap_dm_timer *timer; 193 struct omap_dm_timer *timer;
194 unsigned long flags;
90 195
91 for (timer = &dm_timers[0]; timer->base; ++timer) 196 spin_lock_irqsave(&dm_timer_lock, flags);
92 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & 197 if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
93 OMAP_TIMER_CTRL_ST) 198 spin_unlock_irqrestore(&dm_timer_lock, flags);
94 return 1; 199 printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
200 __FILE__, __LINE__, __FUNCTION__, id);
201 dump_stack();
202 return NULL;
203 }
95 204
96 return 0; 205 timer = &dm_timers[id-1];
206 omap_dm_timer_reserve(timer);
207 spin_unlock_irqrestore(&dm_timer_lock, flags);
208
209 return timer;
97} 210}
98 211
212void omap_dm_timer_free(struct omap_dm_timer *timer)
213{
214 omap_dm_timer_reset(timer);
215#ifdef CONFIG_ARCH_OMAP2
216 clk_disable(timer->iclk);
217 clk_disable(timer->fclk);
218#endif
219 WARN_ON(!timer->reserved);
220 timer->reserved = 0;
221}
222
223int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
224{
225 return timer->irq;
226}
227
228#if defined(CONFIG_ARCH_OMAP1)
229
230struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
231{
232 BUG();
233}
99 234
100/** 235/**
101 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR 236 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
@@ -103,184 +238,226 @@ int omap_dm_timers_active(void)
103 */ 238 */
104__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) 239__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
105{ 240{
106 int n; 241 int i;
107 242
108 /* If ARMXOR cannot be idled this function call is unnecessary */ 243 /* If ARMXOR cannot be idled this function call is unnecessary */
109 if (!(inputmask & (1 << 1))) 244 if (!(inputmask & (1 << 1)))
110 return inputmask; 245 return inputmask;
111 246
112 /* If any active timer is using ARMXOR return modified mask */ 247 /* If any active timer is using ARMXOR return modified mask */
113 for (n = 0; dm_timers[n].base; ++n) 248 for (i = 0; i < dm_timer_count; i++) {
114 if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)& 249 u32 l;
115 OMAP_TIMER_CTRL_ST) { 250
116 if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0) 251 l = omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG);
252 if (l & OMAP_TIMER_CTRL_ST) {
253 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
117 inputmask &= ~(1 << 1); 254 inputmask &= ~(1 << 1);
118 else 255 else
119 inputmask &= ~(1 << 2); 256 inputmask &= ~(1 << 2);
120 } 257 }
258 }
121 259
122 return inputmask; 260 return inputmask;
123} 261}
124 262
263#elif defined(CONFIG_ARCH_OMAP2)
125 264
126void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) 265struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
127{ 266{
128 int n = (timer - dm_timers) << 1; 267 return timer->fclk;
129 u32 l; 268}
130 269
131 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); 270__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
132 l |= source << n; 271{
133 omap_writel(l, MOD_CONF_CTRL_1); 272 BUG();
134} 273}
135 274
275#endif
136 276
137static void omap_dm_timer_reset(struct omap_dm_timer *timer) 277void omap_dm_timer_trigger(struct omap_dm_timer *timer)
138{ 278{
139 /* Reset and set posted mode */ 279 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
140 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
141 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
142
143 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
144} 280}
145 281
282void omap_dm_timer_start(struct omap_dm_timer *timer)
283{
284 u32 l;
146 285
286 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
287 if (!(l & OMAP_TIMER_CTRL_ST)) {
288 l |= OMAP_TIMER_CTRL_ST;
289 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
290 }
291}
147 292
148struct omap_dm_timer * omap_dm_timer_request(void) 293void omap_dm_timer_stop(struct omap_dm_timer *timer)
149{ 294{
150 struct omap_dm_timer *timer = NULL; 295 u32 l;
151 unsigned long flags;
152 296
153 spin_lock_irqsave(&dm_timer_lock, flags); 297 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
154 if (!list_empty(&dm_timer_info.unused_timers)) { 298 if (l & OMAP_TIMER_CTRL_ST) {
155 timer = (struct omap_dm_timer *) 299 l &= ~0x1;
156 dm_timer_info.unused_timers.next; 300 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
157 list_move_tail((struct list_head *)timer,
158 &dm_timer_info.reserved_timers);
159 } 301 }
160 spin_unlock_irqrestore(&dm_timer_lock, flags);
161
162 return timer;
163} 302}
164 303
304#ifdef CONFIG_ARCH_OMAP1
165 305
166void omap_dm_timer_free(struct omap_dm_timer *timer) 306void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
167{ 307{
168 unsigned long flags; 308 int n = (timer - dm_timers) << 1;
169 309 u32 l;
170 omap_dm_timer_reset(timer);
171 310
172 spin_lock_irqsave(&dm_timer_lock, flags); 311 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
173 list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers); 312 l |= source << n;
174 spin_unlock_irqrestore(&dm_timer_lock, flags); 313 omap_writel(l, MOD_CONF_CTRL_1);
175} 314}
176 315
177void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, 316#else
178 unsigned int value)
179{
180 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
181}
182 317
183unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) 318void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
184{ 319{
185 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); 320 static const char *source_timers[] = {
321 "sys_ck",
322 "func_32k_ck",
323 "alt_ck"
324 };
325 struct clk *parent;
326
327 if (source < 0 || source >= 3)
328 return;
329
330 parent = clk_get(NULL, source_timers[source]);
331 clk_disable(timer->fclk);
332 clk_set_parent(timer->fclk, parent);
333 clk_enable(timer->fclk);
334 clk_put(parent);
335
336 /* When the functional clock disappears, too quick writes seem to
337 * cause an abort. */
338 udelay(50);
186} 339}
187 340
188void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) 341#endif
189{
190 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
191}
192 342
193void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer) 343void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
344 unsigned int load)
194{ 345{
195 u32 l; 346 u32 l;
347
196 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 348 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
197 l |= OMAP_TIMER_CTRL_AR; 349 if (autoreload)
350 l |= OMAP_TIMER_CTRL_AR;
351 else
352 l &= ~OMAP_TIMER_CTRL_AR;
198 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 353 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
354 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
355 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
199} 356}
200 357
201void omap_dm_timer_trigger(struct omap_dm_timer *timer) 358void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
202{ 359 unsigned int match)
203 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
204}
205
206void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
207{ 360{
208 u32 l; 361 u32 l;
209 362
210 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 363 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
211 l |= value & 0x3; 364 if (enable)
365 l |= OMAP_TIMER_CTRL_CE;
366 else
367 l &= ~OMAP_TIMER_CTRL_CE;
212 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 368 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
369 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
213} 370}
214 371
215void omap_dm_timer_start(struct omap_dm_timer *timer) 372
373void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
374 int toggle, int trigger)
216{ 375{
217 u32 l; 376 u32 l;
218 377
219 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 378 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
220 l |= OMAP_TIMER_CTRL_ST; 379 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
380 OMAP_TIMER_CTRL_PT | (0x03 << 10));
381 if (def_on)
382 l |= OMAP_TIMER_CTRL_SCPWM;
383 if (toggle)
384 l |= OMAP_TIMER_CTRL_PT;
385 l |= trigger << 10;
221 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 386 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
222} 387}
223 388
224void omap_dm_timer_stop(struct omap_dm_timer *timer) 389void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
225{ 390{
226 u32 l; 391 u32 l;
227 392
228 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 393 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
229 l &= ~0x1; 394 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
395 if (prescaler >= 0x00 && prescaler <= 0x07) {
396 l |= OMAP_TIMER_CTRL_PRE;
397 l |= prescaler << 2;
398 }
230 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 399 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
231} 400}
232 401
233unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) 402void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
403 unsigned int value)
234{ 404{
235 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); 405 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
236} 406}
237 407
238void omap_dm_timer_reset_counter(struct omap_dm_timer *timer) 408unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
239{ 409{
240 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0); 410 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
241} 411}
242 412
243void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load) 413void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
244{ 414{
245 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); 415 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
246} 416}
247 417
248void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match) 418unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
249{ 419{
250 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); 420 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
251} 421}
252 422
253void omap_dm_timer_enable_compare(struct omap_dm_timer *timer) 423int omap_dm_timers_active(void)
254{ 424{
255 u32 l; 425 int i;
256 426
257 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 427 for (i = 0; i < dm_timer_count; i++) {
258 l |= OMAP_TIMER_CTRL_CE; 428 struct omap_dm_timer *timer;
259 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
260}
261 429
430 timer = &dm_timers[i];
431 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
432 OMAP_TIMER_CTRL_ST)
433 return 1;
434 }
435 return 0;
436}
262 437
263static inline void __dm_timer_init(void) 438int omap_dm_timer_init(void)
264{ 439{
265 struct omap_dm_timer *timer; 440 struct omap_dm_timer *timer;
441 int i;
442
443 if (!(cpu_is_omap16xx() || cpu_is_omap24xx()))
444 return -ENODEV;
266 445
267 spin_lock_init(&dm_timer_lock); 446 spin_lock_init(&dm_timer_lock);
268 INIT_LIST_HEAD(&dm_timer_info.unused_timers); 447 for (i = 0; i < dm_timer_count; i++) {
269 INIT_LIST_HEAD(&dm_timer_info.reserved_timers); 448#ifdef CONFIG_ARCH_OMAP2
270 449 char clk_name[16];
271 timer = &dm_timers[0]; 450#endif
272 while (timer->base) { 451
273 list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers); 452 timer = &dm_timers[i];
274 omap_dm_timer_reset(timer); 453 timer->io_base = (void __iomem *) io_p2v(timer->phys_base);
275 timer++; 454#ifdef CONFIG_ARCH_OMAP2
455 sprintf(clk_name, "gpt%d_ick", i + 1);
456 timer->iclk = clk_get(NULL, clk_name);
457 sprintf(clk_name, "gpt%d_fck", i + 1);
458 timer->fclk = clk_get(NULL, clk_name);
459#endif
276 } 460 }
277}
278 461
279static int __init omap_dm_timer_init(void)
280{
281 if (cpu_is_omap16xx())
282 __dm_timer_init();
283 return 0; 462 return 0;
284} 463}
285
286arch_initcall(omap_dm_timer_init);