mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-21 06:24:12 +00:00
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>
This commit is contained in:
parent
eebdb0c1e1
commit
e25e3d1fef
1 changed files with 23 additions and 18 deletions
|
@ -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,
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
#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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue