Commit e25e3d1f authored by Stephen Boyd's avatar Stephen Boyd Committed by David Brown

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: default avatarStephen Boyd <sboyd@codeaurora.org>
Signed-off-by: default avatarDavid Brown <davidb@codeaurora.org>
parent eebdb0c1
...@@ -38,12 +38,14 @@ ...@@ -38,12 +38,14 @@
#define TIMER_CLEAR 0x000C #define TIMER_CLEAR 0x000C
#define DGT_CLK_CTL 0x10 #define DGT_CLK_CTL 0x10
#define DGT_CLK_CTL_DIV_4 0x3 #define DGT_CLK_CTL_DIV_4 0x3
#define TIMER_STS_GPT0_CLR_PEND BIT(10)
#define GPT_HZ 32768 #define GPT_HZ 32768
#define MSM_DGT_SHIFT 5 #define MSM_DGT_SHIFT 5
static void __iomem *event_base; static void __iomem *event_base;
static void __iomem *sts_base;
static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
{ {
...@@ -65,6 +67,11 @@ static int msm_timer_set_next_event(unsigned long cycles, ...@@ -65,6 +67,11 @@ static int msm_timer_set_next_event(unsigned long cycles,
writel_relaxed(0, event_base + TIMER_CLEAR); writel_relaxed(0, event_base + TIMER_CLEAR);
writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
if (sts_base)
while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
cpu_relax();
writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
return 0; return 0;
} }
...@@ -135,9 +142,6 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) ...@@ -135,9 +142,6 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
if (!smp_processor_id()) if (!smp_processor_id())
return 0; return 0;
writel_relaxed(0, event_base + TIMER_ENABLE);
writel_relaxed(0, event_base + TIMER_CLEAR);
writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
evt->irq = msm_clockevent.irq; evt->irq = msm_clockevent.irq;
evt->name = "local_timer"; evt->name = "local_timer";
evt->features = msm_clockevent.features; evt->features = msm_clockevent.features;
...@@ -175,9 +179,6 @@ static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, ...@@ -175,9 +179,6 @@ static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
struct clocksource *cs = &msm_clocksource; struct clocksource *cs = &msm_clocksource;
int res; int res;
writel_relaxed(0, event_base + TIMER_ENABLE);
writel_relaxed(0, event_base + TIMER_CLEAR);
writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
ce->cpumask = cpumask_of(0); ce->cpumask = cpumask_of(0);
ce->irq = irq; ce->irq = irq;
...@@ -272,6 +273,7 @@ void __init msm_dt_timer_init(void) ...@@ -272,6 +273,7 @@ void __init msm_dt_timer_init(void)
of_node_put(np); of_node_put(np);
event_base = base + 0x4; event_base = base + 0x4;
sts_base = base + 0x88;
source_base = cpu0_base + 0x24; source_base = cpu0_base + 0x24;
freq /= 4; freq /= 4;
writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
...@@ -280,7 +282,8 @@ void __init msm_dt_timer_init(void) ...@@ -280,7 +282,8 @@ void __init msm_dt_timer_init(void)
} }
#endif #endif
static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source) static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
u32 sts)
{ {
void __iomem *base; void __iomem *base;
...@@ -291,6 +294,8 @@ static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source) ...@@ -291,6 +294,8 @@ static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source)
} }
event_base = base + event; event_base = base + event;
source_base = base + source; source_base = base + source;
if (sts)
sts_base = base + sts;
return 0; return 0;
} }
...@@ -299,7 +304,7 @@ void __init msm7x01_timer_init(void) ...@@ -299,7 +304,7 @@ void __init msm7x01_timer_init(void)
{ {
struct clocksource *cs = &msm_clocksource; struct clocksource *cs = &msm_clocksource;
if (msm_timer_map(0xc0100000, 0x0, 0x10)) if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
return; return;
cs->read = msm_read_timer_count_shift; cs->read = msm_read_timer_count_shift;
cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
...@@ -310,14 +315,14 @@ void __init msm7x01_timer_init(void) ...@@ -310,14 +315,14 @@ void __init msm7x01_timer_init(void)
void __init msm7x30_timer_init(void) void __init msm7x30_timer_init(void)
{ {
if (msm_timer_map(0xc0100000, 0x4, 0x24)) if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
return; return;
msm_timer_init(24576000 / 4, 32, 1, false); msm_timer_init(24576000 / 4, 32, 1, false);
} }
void __init qsd8x50_timer_init(void) void __init qsd8x50_timer_init(void)
{ {
if (msm_timer_map(0xAC100000, 0x0, 0x10)) if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
return; return;
msm_timer_init(19200000 / 4, 32, 7, false); msm_timer_init(19200000 / 4, 32, 7, false);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment