aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2013-03-19 13:38:15 -0400
committerBenoit Cousson <benoit.cousson@linaro.org>2013-04-08 18:21:29 -0400
commit9cc268d5bbc097ae5a3ae236fb2461ea113274bf (patch)
tree05751016c7bde8b73ee2fbe6564ddb6bd1fb8db0
parent7b3754c63e8d6528002386b313c527a826236d82 (diff)
ARM: OMAP: Simplify dmtimer context-loss handling
The context loss handling in dmtimer appears to assume that omap_dm_timer_set_load_start() or omap_dm_timer_start() and omap_dm_timer_stop() bracket all interactions. Only the first two restore the context and the last updates the context loss counter. However omap_dm_timer_set_load() or omap_dm_timer_set_match() can reasonably be called outside this bracketing, and the fact that they call omap_dm_timer_enable() / omap_dm_timer_disable() suggest that is expected. So if, after a transition into and out of off-mode which would cause the dm timer to loose all state, omap_dm_timer_set_match() is called before omap_dm_timer_start(), the value read from OMAP_TIMER_CTRL_REG will be 'wrong' and this wrong value will be stored context.tclr so a subsequent omap_dm_timer_start() can fail (As the control register is wrong). Simplify this be doing the restore-from-context in omap_dm_timer_enable() so that whenever the timer is enabled, the context is correct. Also update the ctx_loss_count at the same time as we notice it is wrong - these is no value in delaying this until the omap_dm_timer_disable() as it cannot change while the timer is enabled. Signed-off-by: NeilBrown <neilb@suse.de> [jon-hunter@ti.com: minor update to subject and changed variable name] Signed-off-by: Jon Hunter <jon-hunter@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Benoit Cousson <benoit.cousson@linaro.org>
-rw-r--r--arch/arm/plat-omap/dmtimer.c32
1 files changed, 12 insertions, 20 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index a0daa2fb5de6..5cae1dd1f365 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -315,7 +315,19 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free);
315 315
316void omap_dm_timer_enable(struct omap_dm_timer *timer) 316void omap_dm_timer_enable(struct omap_dm_timer *timer)
317{ 317{
318 int c;
319
318 pm_runtime_get_sync(&timer->pdev->dev); 320 pm_runtime_get_sync(&timer->pdev->dev);
321
322 if (!(timer->capability & OMAP_TIMER_ALWON)) {
323 if (timer->get_context_loss_count) {
324 c = timer->get_context_loss_count(&timer->pdev->dev);
325 if (c != timer->ctx_loss_count) {
326 omap_timer_restore_context(timer);
327 timer->ctx_loss_count = c;
328 }
329 }
330 }
319} 331}
320EXPORT_SYMBOL_GPL(omap_dm_timer_enable); 332EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
321 333
@@ -410,13 +422,6 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
410 422
411 omap_dm_timer_enable(timer); 423 omap_dm_timer_enable(timer);
412 424
413 if (!(timer->capability & OMAP_TIMER_ALWON)) {
414 if (timer->get_context_loss_count &&
415 timer->get_context_loss_count(&timer->pdev->dev) !=
416 timer->ctx_loss_count)
417 omap_timer_restore_context(timer);
418 }
419
420 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 425 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
421 if (!(l & OMAP_TIMER_CTRL_ST)) { 426 if (!(l & OMAP_TIMER_CTRL_ST)) {
422 l |= OMAP_TIMER_CTRL_ST; 427 l |= OMAP_TIMER_CTRL_ST;
@@ -441,12 +446,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
441 446
442 __omap_dm_timer_stop(timer, timer->posted, rate); 447 __omap_dm_timer_stop(timer, timer->posted, rate);
443 448
444 if (!(timer->capability & OMAP_TIMER_ALWON)) {
445 if (timer->get_context_loss_count)
446 timer->ctx_loss_count =
447 timer->get_context_loss_count(&timer->pdev->dev);
448 }
449
450 /* 449 /*
451 * Since the register values are computed and written within 450 * Since the register values are computed and written within
452 * __omap_dm_timer_stop, we need to use read to retrieve the 451 * __omap_dm_timer_stop, we need to use read to retrieve the
@@ -553,13 +552,6 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
553 552
554 omap_dm_timer_enable(timer); 553 omap_dm_timer_enable(timer);
555 554
556 if (!(timer->capability & OMAP_TIMER_ALWON)) {
557 if (timer->get_context_loss_count &&
558 timer->get_context_loss_count(&timer->pdev->dev) !=
559 timer->ctx_loss_count)
560 omap_timer_restore_context(timer);
561 }
562
563 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 555 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
564 if (autoreload) { 556 if (autoreload) {
565 l |= OMAP_TIMER_CTRL_AR; 557 l |= OMAP_TIMER_CTRL_AR;