aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2013-03-14 23:31:39 -0400
committerDavid Brown <davidb@codeaurora.org>2013-03-22 13:46:16 -0400
commite25e3d1fef2c57e49aef64535341c15fe2b29b4a (patch)
treeb5ae984efc823a9eb256e10c98f5b339f10e0712 /arch/arm/mach-msm
parenteebdb0c1e1d63532399f7cbb65ade5969d63df06 (diff)
ARM: msm: Wait for timer clear to complete
Without looping on the status bit, there is no way to guarantee that a clear of the timer has actually completed. This can cause us to enable the timer before the count has cleared and miss a timer interrupt. To simplify this patch, remove the timer register setup done during timer init, since it's duplicate work that is eventually done in the set_next_event() callback. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: David Brown <davidb@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r--arch/arm/mach-msm/timer.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 165e33b9b1ee..b4b0d79476a8 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -30,20 +30,22 @@
30 30
31#include "common.h" 31#include "common.h"
32 32
33#define TIMER_MATCH_VAL 0x0000 33#define TIMER_MATCH_VAL 0x0000
34#define TIMER_COUNT_VAL 0x0004 34#define TIMER_COUNT_VAL 0x0004
35#define TIMER_ENABLE 0x0008 35#define TIMER_ENABLE 0x0008
36#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) 36#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1)
37#define TIMER_ENABLE_EN BIT(0) 37#define TIMER_ENABLE_EN BIT(0)
38#define TIMER_CLEAR 0x000C 38#define TIMER_CLEAR 0x000C
39#define DGT_CLK_CTL 0x10 39#define DGT_CLK_CTL 0x10
40#define DGT_CLK_CTL_DIV_4 0x3 40#define DGT_CLK_CTL_DIV_4 0x3
41#define TIMER_STS_GPT0_CLR_PEND BIT(10)
41 42
42#define GPT_HZ 32768 43#define GPT_HZ 32768
43 44
44#define MSM_DGT_SHIFT 5 45#define MSM_DGT_SHIFT 5
45 46
46static void __iomem *event_base; 47static void __iomem *event_base;
48static void __iomem *sts_base;
47 49
48static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) 50static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
49{ 51{
@@ -65,6 +67,11 @@ static int msm_timer_set_next_event(unsigned long cycles,
65 67
66 writel_relaxed(0, event_base + TIMER_CLEAR); 68 writel_relaxed(0, event_base + TIMER_CLEAR);
67 writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); 69 writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
70
71 if (sts_base)
72 while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
73 cpu_relax();
74
68 writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); 75 writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
69 return 0; 76 return 0;
70} 77}
@@ -135,9 +142,6 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
135 if (!smp_processor_id()) 142 if (!smp_processor_id())
136 return 0; 143 return 0;
137 144
138 writel_relaxed(0, event_base + TIMER_ENABLE);
139 writel_relaxed(0, event_base + TIMER_CLEAR);
140 writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
141 evt->irq = msm_clockevent.irq; 145 evt->irq = msm_clockevent.irq;
142 evt->name = "local_timer"; 146 evt->name = "local_timer";
143 evt->features = msm_clockevent.features; 147 evt->features = msm_clockevent.features;
@@ -175,9 +179,6 @@ static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
175 struct clocksource *cs = &msm_clocksource; 179 struct clocksource *cs = &msm_clocksource;
176 int res; 180 int res;
177 181
178 writel_relaxed(0, event_base + TIMER_ENABLE);
179 writel_relaxed(0, event_base + TIMER_CLEAR);
180 writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
181 ce->cpumask = cpumask_of(0); 182 ce->cpumask = cpumask_of(0);
182 ce->irq = irq; 183 ce->irq = irq;
183 184
@@ -272,6 +273,7 @@ void __init msm_dt_timer_init(void)
272 of_node_put(np); 273 of_node_put(np);
273 274
274 event_base = base + 0x4; 275 event_base = base + 0x4;
276 sts_base = base + 0x88;
275 source_base = cpu0_base + 0x24; 277 source_base = cpu0_base + 0x24;
276 freq /= 4; 278 freq /= 4;
277 writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); 279 writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
@@ -280,7 +282,8 @@ void __init msm_dt_timer_init(void)
280} 282}
281#endif 283#endif
282 284
283static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source) 285static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
286 u32 sts)
284{ 287{
285 void __iomem *base; 288 void __iomem *base;
286 289
@@ -291,6 +294,8 @@ static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source)
291 } 294 }
292 event_base = base + event; 295 event_base = base + event;
293 source_base = base + source; 296 source_base = base + source;
297 if (sts)
298 sts_base = base + sts;
294 299
295 return 0; 300 return 0;
296} 301}
@@ -299,7 +304,7 @@ void __init msm7x01_timer_init(void)
299{ 304{
300 struct clocksource *cs = &msm_clocksource; 305 struct clocksource *cs = &msm_clocksource;
301 306
302 if (msm_timer_map(0xc0100000, 0x0, 0x10)) 307 if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
303 return; 308 return;
304 cs->read = msm_read_timer_count_shift; 309 cs->read = msm_read_timer_count_shift;
305 cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); 310 cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
@@ -310,14 +315,14 @@ void __init msm7x01_timer_init(void)
310 315
311void __init msm7x30_timer_init(void) 316void __init msm7x30_timer_init(void)
312{ 317{
313 if (msm_timer_map(0xc0100000, 0x4, 0x24)) 318 if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
314 return; 319 return;
315 msm_timer_init(24576000 / 4, 32, 1, false); 320 msm_timer_init(24576000 / 4, 32, 1, false);
316} 321}
317 322
318void __init qsd8x50_timer_init(void) 323void __init qsd8x50_timer_init(void)
319{ 324{
320 if (msm_timer_map(0xAC100000, 0x0, 0x10)) 325 if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
321 return; 326 return;
322 msm_timer_init(19200000 / 4, 32, 7, false); 327 msm_timer_init(19200000 / 4, 32, 7, false);
323} 328}