diff options
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 46 | ||||
-rw-r--r-- | include/asm-arm/arch-omap/dmtimer.h | 1 |
2 files changed, 31 insertions, 16 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index bfccebc77515..804a53534370 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -107,6 +107,14 @@ static struct omap_dm_timer dm_timers[] = { | |||
107 | { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 }, | 107 | { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 }, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | static const char *dm_source_names[] = { | ||
111 | "sys_ck", | ||
112 | "func_32k_ck", | ||
113 | "alt_ck" | ||
114 | }; | ||
115 | |||
116 | static struct clk *dm_source_clocks[3]; | ||
117 | |||
110 | #else | 118 | #else |
111 | 119 | ||
112 | #error OMAP architecture not supported! | 120 | #error OMAP architecture not supported! |
@@ -114,7 +122,6 @@ static struct omap_dm_timer dm_timers[] = { | |||
114 | #endif | 122 | #endif |
115 | 123 | ||
116 | static const int dm_timer_count = ARRAY_SIZE(dm_timers); | 124 | static const int dm_timer_count = ARRAY_SIZE(dm_timers); |
117 | |||
118 | static spinlock_t dm_timer_lock; | 125 | static spinlock_t dm_timer_lock; |
119 | 126 | ||
120 | static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) | 127 | static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) |
@@ -159,9 +166,8 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) | |||
159 | omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); | 166 | omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); |
160 | } | 167 | } |
161 | 168 | ||
162 | static void omap_dm_timer_reserve(struct omap_dm_timer *timer) | 169 | static void omap_dm_timer_prepare(struct omap_dm_timer *timer) |
163 | { | 170 | { |
164 | timer->reserved = 1; | ||
165 | #ifdef CONFIG_ARCH_OMAP2 | 171 | #ifdef CONFIG_ARCH_OMAP2 |
166 | clk_enable(timer->iclk); | 172 | clk_enable(timer->iclk); |
167 | clk_enable(timer->fclk); | 173 | clk_enable(timer->fclk); |
@@ -181,11 +187,14 @@ struct omap_dm_timer *omap_dm_timer_request(void) | |||
181 | continue; | 187 | continue; |
182 | 188 | ||
183 | timer = &dm_timers[i]; | 189 | timer = &dm_timers[i]; |
184 | omap_dm_timer_reserve(timer); | 190 | timer->reserved = 1; |
185 | break; | 191 | break; |
186 | } | 192 | } |
187 | spin_unlock_irqrestore(&dm_timer_lock, flags); | 193 | spin_unlock_irqrestore(&dm_timer_lock, flags); |
188 | 194 | ||
195 | if (timer != NULL) | ||
196 | omap_dm_timer_prepare(timer); | ||
197 | |||
189 | return timer; | 198 | return timer; |
190 | } | 199 | } |
191 | 200 | ||
@@ -204,9 +213,11 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) | |||
204 | } | 213 | } |
205 | 214 | ||
206 | timer = &dm_timers[id-1]; | 215 | timer = &dm_timers[id-1]; |
207 | omap_dm_timer_reserve(timer); | 216 | timer->reserved = 1; |
208 | spin_unlock_irqrestore(&dm_timer_lock, flags); | 217 | spin_unlock_irqrestore(&dm_timer_lock, flags); |
209 | 218 | ||
219 | omap_dm_timer_prepare(timer); | ||
220 | |||
210 | return timer; | 221 | return timer; |
211 | } | 222 | } |
212 | 223 | ||
@@ -318,21 +329,12 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | |||
318 | 329 | ||
319 | void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | 330 | void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) |
320 | { | 331 | { |
321 | static const char *source_timers[] = { | ||
322 | "sys_ck", | ||
323 | "func_32k_ck", | ||
324 | "alt_ck" | ||
325 | }; | ||
326 | struct clk *parent; | ||
327 | |||
328 | if (source < 0 || source >= 3) | 332 | if (source < 0 || source >= 3) |
329 | return; | 333 | return; |
330 | 334 | ||
331 | parent = clk_get(NULL, source_timers[source]); | ||
332 | clk_disable(timer->fclk); | 335 | clk_disable(timer->fclk); |
333 | clk_set_parent(timer->fclk, parent); | 336 | clk_set_parent(timer->fclk, dm_source_clocks[source]); |
334 | clk_enable(timer->fclk); | 337 | clk_enable(timer->fclk); |
335 | clk_put(parent); | ||
336 | 338 | ||
337 | /* When the functional clock disappears, too quick writes seem to | 339 | /* When the functional clock disappears, too quick writes seem to |
338 | * cause an abort. */ | 340 | * cause an abort. */ |
@@ -362,7 +364,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, | |||
362 | u32 l; | 364 | u32 l; |
363 | 365 | ||
364 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 366 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
365 | if (enable) | 367 | if (enable) |
366 | l |= OMAP_TIMER_CTRL_CE; | 368 | l |= OMAP_TIMER_CTRL_CE; |
367 | else | 369 | else |
368 | l &= ~OMAP_TIMER_CTRL_CE; | 370 | l &= ~OMAP_TIMER_CTRL_CE; |
@@ -421,6 +423,11 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) | |||
421 | return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); | 423 | return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); |
422 | } | 424 | } |
423 | 425 | ||
426 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) | ||
427 | { | ||
428 | return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); | ||
429 | } | ||
430 | |||
424 | int omap_dm_timers_active(void) | 431 | int omap_dm_timers_active(void) |
425 | { | 432 | { |
426 | int i; | 433 | int i; |
@@ -445,6 +452,13 @@ int omap_dm_timer_init(void) | |||
445 | return -ENODEV; | 452 | return -ENODEV; |
446 | 453 | ||
447 | spin_lock_init(&dm_timer_lock); | 454 | spin_lock_init(&dm_timer_lock); |
455 | #ifdef CONFIG_ARCH_OMAP2 | ||
456 | for (i = 0; i < ARRAY_SIZE(dm_source_names); i++) { | ||
457 | dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]); | ||
458 | BUG_ON(dm_source_clocks[i] == NULL); | ||
459 | } | ||
460 | #endif | ||
461 | |||
448 | for (i = 0; i < dm_timer_count; i++) { | 462 | for (i = 0; i < dm_timer_count; i++) { |
449 | #ifdef CONFIG_ARCH_OMAP2 | 463 | #ifdef CONFIG_ARCH_OMAP2 |
450 | char clk_name[16]; | 464 | char clk_name[16]; |
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h index 5b58e3d62742..7a289ff07404 100644 --- a/include/asm-arm/arch-omap/dmtimer.h +++ b/include/asm-arm/arch-omap/dmtimer.h | |||
@@ -73,6 +73,7 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int valu | |||
73 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); | 73 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); |
74 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); | 74 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); |
75 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); | 75 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); |
76 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value); | ||
76 | 77 | ||
77 | int omap_dm_timers_active(void); | 78 | int omap_dm_timers_active(void); |
78 | 79 | ||