aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/dmtimer.c
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@solidboot.com>2006-06-26 19:16:12 -0400
committerTony Lindgren <tony@atomide.com>2006-06-26 19:16:12 -0400
commit77900a2fc3bfb1eb6eaa6d43eef4591e1f7c600d (patch)
tree6d6278f833a6057b1b951e4e9bded234aa6459e2 /arch/arm/plat-omap/dmtimer.c
parent6e711ec6d249c0d3f8bc225066738d064ed90032 (diff)
ARM: OMAP: Port dmtimers to OMAP2 and implement PWM support
Port dmtimer framework to OMAP2. Modify the dmtimers API to support setting of PWM configuration and prescaler. Convert 32 kHz timer and GP timer to use the dmtimer framework. Signed-off-by: Timo Teras <timo.teras@solidboot.com> Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
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);