Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+23 −18
Original line number Original line Diff line number Diff line
@@ -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);
}
}