diff options
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 50524436de63..fb2a23e7c172 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -79,6 +79,9 @@ struct omap_dm_timer { | |||
79 | 79 | ||
80 | #ifdef CONFIG_ARCH_OMAP1 | 80 | #ifdef CONFIG_ARCH_OMAP1 |
81 | 81 | ||
82 | #define omap_dm_clk_enable(x) | ||
83 | #define omap_dm_clk_disable(x) | ||
84 | |||
82 | static struct omap_dm_timer dm_timers[] = { | 85 | static struct omap_dm_timer dm_timers[] = { |
83 | { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, | 86 | { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, |
84 | { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 }, | 87 | { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 }, |
@@ -92,6 +95,9 @@ static struct omap_dm_timer dm_timers[] = { | |||
92 | 95 | ||
93 | #elif defined(CONFIG_ARCH_OMAP2) | 96 | #elif defined(CONFIG_ARCH_OMAP2) |
94 | 97 | ||
98 | #define omap_dm_clk_enable(x) clk_enable(x) | ||
99 | #define omap_dm_clk_disable(x) clk_disable(x) | ||
100 | |||
95 | static struct omap_dm_timer dm_timers[] = { | 101 | static struct omap_dm_timer dm_timers[] = { |
96 | { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, | 102 | { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, |
97 | { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, | 103 | { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, |
@@ -168,11 +174,15 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) | |||
168 | 174 | ||
169 | static void omap_dm_timer_prepare(struct omap_dm_timer *timer) | 175 | static void omap_dm_timer_prepare(struct omap_dm_timer *timer) |
170 | { | 176 | { |
171 | #ifdef CONFIG_ARCH_OMAP2 | 177 | omap_dm_clk_enable(timer->fclk); |
172 | clk_enable(timer->iclk); | 178 | omap_dm_clk_enable(timer->iclk); |
173 | clk_enable(timer->fclk); | 179 | |
174 | #endif | ||
175 | omap_dm_timer_reset(timer); | 180 | omap_dm_timer_reset(timer); |
181 | |||
182 | /* Leave iclk enabled for GPT1 as it is needed for the | ||
183 | * system timer to work properly. */ | ||
184 | if (timer != &dm_timers[0]) | ||
185 | omap_dm_clk_disable(timer->iclk); | ||
176 | } | 186 | } |
177 | 187 | ||
178 | struct omap_dm_timer *omap_dm_timer_request(void) | 188 | struct omap_dm_timer *omap_dm_timer_request(void) |
@@ -223,11 +233,14 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) | |||
223 | 233 | ||
224 | void omap_dm_timer_free(struct omap_dm_timer *timer) | 234 | void omap_dm_timer_free(struct omap_dm_timer *timer) |
225 | { | 235 | { |
236 | omap_dm_clk_enable(timer->iclk); | ||
226 | omap_dm_timer_reset(timer); | 237 | omap_dm_timer_reset(timer); |
227 | #ifdef CONFIG_ARCH_OMAP2 | 238 | omap_dm_clk_disable(timer->iclk); |
228 | clk_disable(timer->iclk); | 239 | |
229 | clk_disable(timer->fclk); | 240 | if (timer == &dm_timers[0]) |
230 | #endif | 241 | omap_dm_clk_disable(timer->iclk); |
242 | omap_dm_clk_disable(timer->fclk); | ||
243 | |||
231 | WARN_ON(!timer->reserved); | 244 | WARN_ON(!timer->reserved); |
232 | timer->reserved = 0; | 245 | timer->reserved = 0; |
233 | } | 246 | } |
@@ -276,7 +289,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | |||
276 | 289 | ||
277 | struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) | 290 | struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) |
278 | { | 291 | { |
279 | return timer->fclk; | 292 | return timer->fclk; |
280 | } | 293 | } |
281 | 294 | ||
282 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | 295 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) |
@@ -288,29 +301,35 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | |||
288 | 301 | ||
289 | void omap_dm_timer_trigger(struct omap_dm_timer *timer) | 302 | void omap_dm_timer_trigger(struct omap_dm_timer *timer) |
290 | { | 303 | { |
304 | omap_dm_clk_enable(timer->iclk); | ||
291 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); | 305 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); |
306 | omap_dm_clk_disable(timer->iclk); | ||
292 | } | 307 | } |
293 | 308 | ||
294 | void omap_dm_timer_start(struct omap_dm_timer *timer) | 309 | void omap_dm_timer_start(struct omap_dm_timer *timer) |
295 | { | 310 | { |
296 | u32 l; | 311 | u32 l; |
297 | 312 | ||
313 | omap_dm_clk_enable(timer->iclk); | ||
298 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 314 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
299 | if (!(l & OMAP_TIMER_CTRL_ST)) { | 315 | if (!(l & OMAP_TIMER_CTRL_ST)) { |
300 | l |= OMAP_TIMER_CTRL_ST; | 316 | l |= OMAP_TIMER_CTRL_ST; |
301 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 317 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
302 | } | 318 | } |
319 | omap_dm_clk_disable(timer->iclk); | ||
303 | } | 320 | } |
304 | 321 | ||
305 | void omap_dm_timer_stop(struct omap_dm_timer *timer) | 322 | void omap_dm_timer_stop(struct omap_dm_timer *timer) |
306 | { | 323 | { |
307 | u32 l; | 324 | u32 l; |
308 | 325 | ||
326 | omap_dm_clk_enable(timer->iclk); | ||
309 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 327 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
310 | if (l & OMAP_TIMER_CTRL_ST) { | 328 | if (l & OMAP_TIMER_CTRL_ST) { |
311 | l &= ~0x1; | 329 | l &= ~0x1; |
312 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 330 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
313 | } | 331 | } |
332 | omap_dm_clk_disable(timer->iclk); | ||
314 | } | 333 | } |
315 | 334 | ||
316 | #ifdef CONFIG_ARCH_OMAP1 | 335 | #ifdef CONFIG_ARCH_OMAP1 |
@@ -348,6 +367,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, | |||
348 | { | 367 | { |
349 | u32 l; | 368 | u32 l; |
350 | 369 | ||
370 | omap_dm_clk_enable(timer->iclk); | ||
351 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 371 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
352 | if (autoreload) | 372 | if (autoreload) |
353 | l |= OMAP_TIMER_CTRL_AR; | 373 | l |= OMAP_TIMER_CTRL_AR; |
@@ -356,6 +376,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, | |||
356 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 376 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
357 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); | 377 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); |
358 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); | 378 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); |
379 | omap_dm_clk_disable(timer->iclk); | ||
359 | } | 380 | } |
360 | 381 | ||
361 | void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, | 382 | void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, |
@@ -363,6 +384,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, | |||
363 | { | 384 | { |
364 | u32 l; | 385 | u32 l; |
365 | 386 | ||
387 | omap_dm_clk_enable(timer->iclk); | ||
366 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 388 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
367 | if (enable) | 389 | if (enable) |
368 | l |= OMAP_TIMER_CTRL_CE; | 390 | l |= OMAP_TIMER_CTRL_CE; |
@@ -370,6 +392,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, | |||
370 | l &= ~OMAP_TIMER_CTRL_CE; | 392 | l &= ~OMAP_TIMER_CTRL_CE; |
371 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 393 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
372 | omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); | 394 | omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); |
395 | omap_dm_clk_disable(timer->iclk); | ||
373 | } | 396 | } |
374 | 397 | ||
375 | 398 | ||
@@ -378,6 +401,7 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, | |||
378 | { | 401 | { |
379 | u32 l; | 402 | u32 l; |
380 | 403 | ||
404 | omap_dm_clk_enable(timer->iclk); | ||
381 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 405 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
382 | l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | | 406 | l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | |
383 | OMAP_TIMER_CTRL_PT | (0x03 << 10)); | 407 | OMAP_TIMER_CTRL_PT | (0x03 << 10)); |
@@ -387,12 +411,14 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, | |||
387 | l |= OMAP_TIMER_CTRL_PT; | 411 | l |= OMAP_TIMER_CTRL_PT; |
388 | l |= trigger << 10; | 412 | l |= trigger << 10; |
389 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 413 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
414 | omap_dm_clk_disable(timer->iclk); | ||
390 | } | 415 | } |
391 | 416 | ||
392 | void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) | 417 | void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) |
393 | { | 418 | { |
394 | u32 l; | 419 | u32 l; |
395 | 420 | ||
421 | omap_dm_clk_enable(timer->iclk); | ||
396 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 422 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
397 | l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); | 423 | l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); |
398 | if (prescaler >= 0x00 && prescaler <= 0x07) { | 424 | if (prescaler >= 0x00 && prescaler <= 0x07) { |
@@ -400,32 +426,51 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) | |||
400 | l |= prescaler << 2; | 426 | l |= prescaler << 2; |
401 | } | 427 | } |
402 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 428 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
429 | omap_dm_clk_disable(timer->iclk); | ||
403 | } | 430 | } |
404 | 431 | ||
405 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, | 432 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, |
406 | unsigned int value) | 433 | unsigned int value) |
407 | { | 434 | { |
435 | omap_dm_clk_enable(timer->iclk); | ||
408 | omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); | 436 | omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); |
437 | omap_dm_clk_disable(timer->iclk); | ||
409 | } | 438 | } |
410 | 439 | ||
411 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) | 440 | unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) |
412 | { | 441 | { |
413 | return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); | 442 | unsigned int l; |
443 | |||
444 | omap_dm_clk_enable(timer->iclk); | ||
445 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); | ||
446 | omap_dm_clk_disable(timer->iclk); | ||
447 | |||
448 | return l; | ||
414 | } | 449 | } |
415 | 450 | ||
416 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) | 451 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) |
417 | { | 452 | { |
453 | omap_dm_clk_enable(timer->iclk); | ||
418 | omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); | 454 | omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); |
455 | omap_dm_clk_disable(timer->iclk); | ||
419 | } | 456 | } |
420 | 457 | ||
421 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) | 458 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) |
422 | { | 459 | { |
423 | return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); | 460 | unsigned int l; |
461 | |||
462 | omap_dm_clk_enable(timer->iclk); | ||
463 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); | ||
464 | omap_dm_clk_disable(timer->iclk); | ||
465 | |||
466 | return l; | ||
424 | } | 467 | } |
425 | 468 | ||
426 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) | 469 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) |
427 | { | 470 | { |
428 | return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); | 471 | omap_dm_clk_enable(timer->iclk); |
472 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); | ||
473 | omap_dm_clk_disable(timer->iclk); | ||
429 | } | 474 | } |
430 | 475 | ||
431 | int omap_dm_timers_active(void) | 476 | int omap_dm_timers_active(void) |
@@ -436,9 +481,13 @@ int omap_dm_timers_active(void) | |||
436 | struct omap_dm_timer *timer; | 481 | struct omap_dm_timer *timer; |
437 | 482 | ||
438 | timer = &dm_timers[i]; | 483 | timer = &dm_timers[i]; |
484 | omap_dm_clk_enable(timer->iclk); | ||
439 | if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & | 485 | if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & |
440 | OMAP_TIMER_CTRL_ST) | 486 | OMAP_TIMER_CTRL_ST) { |
487 | omap_dm_clk_disable(timer->iclk); | ||
441 | return 1; | 488 | return 1; |
489 | } | ||
490 | omap_dm_clk_disable(timer->iclk); | ||
442 | } | 491 | } |
443 | return 0; | 492 | return 0; |
444 | } | 493 | } |