aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2009-04-28 04:17:54 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-04-28 05:01:21 -0400
commit5b644c7a218702668d7b610994e7dcbc3d4705d3 (patch)
tree67418dc01db1e5abccbe5b526232eaf6811217e8 /drivers/clocksource
parentc2e0090c668fc99f5be65fd9907da781cb6a2ef5 (diff)
clocksource: improve sh_cmt clocksource overflow handling
This patch improves the sh_cmt clocksource handling. Currently the counter value is ignored in the case of overflow. With this patch the overflow flag is read before and after reading the counter, removing any counter value and overflow flag mismatch issues. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/sh_cmt.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index c24756489612..d607ac2d516b 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -111,16 +111,21 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
111 int *has_wrapped) 111 int *has_wrapped)
112{ 112{
113 unsigned long v1, v2, v3; 113 unsigned long v1, v2, v3;
114 int o1, o2;
115
116 o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
114 117
115 /* Make sure the timer value is stable. Stolen from acpi_pm.c */ 118 /* Make sure the timer value is stable. Stolen from acpi_pm.c */
116 do { 119 do {
120 o2 = o1;
117 v1 = sh_cmt_read(p, CMCNT); 121 v1 = sh_cmt_read(p, CMCNT);
118 v2 = sh_cmt_read(p, CMCNT); 122 v2 = sh_cmt_read(p, CMCNT);
119 v3 = sh_cmt_read(p, CMCNT); 123 v3 = sh_cmt_read(p, CMCNT);
120 } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) 124 o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
121 || (v3 > v1 && v3 < v2))); 125 } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
126 || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
122 127
123 *has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit; 128 *has_wrapped = o1;
124 return v2; 129 return v2;
125} 130}
126 131
@@ -394,7 +399,7 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
394 raw = sh_cmt_get_counter(p, &has_wrapped); 399 raw = sh_cmt_get_counter(p, &has_wrapped);
395 400
396 if (unlikely(has_wrapped)) 401 if (unlikely(has_wrapped))
397 raw = p->match_value; 402 raw += p->match_value;
398 spin_unlock_irqrestore(&p->lock, flags); 403 spin_unlock_irqrestore(&p->lock, flags);
399 404
400 return value + raw; 405 return value + raw;