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