diff options
| author | Timo Teras <timo.teras@solidboot.com> | 2006-06-26 19:16:23 -0400 |
|---|---|---|
| committer | Tony Lindgren <tony@atomide.com> | 2006-06-26 19:16:23 -0400 |
| commit | 83379c81f6f05a6e80db66ae33378feb4cbca6b3 (patch) | |
| tree | 77d1c1b535ec0708df1325ddb0474aa878aba332 | |
| parent | 7df3450e5c22ba3969e4253dce0d7807dd210bf0 (diff) | |
ARM: OMAP: Update dmtimers
- Initialize timer outside of spinlock to reduce the time the spinlock is held
- Do clk_get to the source clocks during initialization to avoid sleeping later
- New function to set counter register
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>
| -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 | ||
