diff options
Diffstat (limited to 'arch/arm/mach-msm')
| -rw-r--r-- | arch/arm/mach-msm/timer.c | 110 | 
1 files changed, 51 insertions, 59 deletions
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index f9fd77e8f1f..284313f3e02 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -30,19 +30,22 @@  #include "common.h" -#define TIMER_MATCH_VAL         0x0000 -#define TIMER_COUNT_VAL         0x0004 -#define TIMER_ENABLE            0x0008 -#define TIMER_ENABLE_CLR_ON_MATCH_EN    BIT(1) -#define TIMER_ENABLE_EN                 BIT(0) -#define TIMER_CLEAR             0x000C -#define DGT_CLK_CTL_DIV_4	0x3 +#define TIMER_MATCH_VAL			0x0000 +#define TIMER_COUNT_VAL			0x0004 +#define TIMER_ENABLE			0x0008 +#define TIMER_ENABLE_CLR_ON_MATCH_EN	BIT(1) +#define TIMER_ENABLE_EN			BIT(0) +#define TIMER_CLEAR			0x000C +#define DGT_CLK_CTL			0x10 +#define DGT_CLK_CTL_DIV_4		0x3 +#define TIMER_STS_GPT0_CLR_PEND		BIT(10)  #define GPT_HZ 32768  #define MSM_DGT_SHIFT 5  static void __iomem *event_base; +static void __iomem *sts_base;  static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)  { @@ -67,6 +70,11 @@ static int msm_timer_set_next_event(unsigned long cycles,  	writel_relaxed(ctrl, event_base + TIMER_CLEAR);  	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);  	return 0;  } @@ -137,9 +145,6 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)  	if (!smp_processor_id())  		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->name = "local_timer";  	evt->features = msm_clockevent.features; @@ -177,9 +182,6 @@ static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,  	struct clocksource *cs = &msm_clocksource;  	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->irq = irq; @@ -217,13 +219,9 @@ err:  }  #ifdef CONFIG_OF -static const struct of_device_id msm_dgt_match[] __initconst = { -	{ .compatible = "qcom,msm-dgt" }, -	{ }, -}; - -static const struct of_device_id msm_gpt_match[] __initconst = { -	{ .compatible = "qcom,msm-gpt" }, +static const struct of_device_id msm_timer_match[] __initconst = { +	{ .compatible = "qcom,kpss-timer" }, +	{ .compatible = "qcom,scss-timer" },  	{ },  }; @@ -234,33 +232,29 @@ void __init msm_dt_timer_init(void)  	int irq;  	struct resource res;  	u32 percpu_offset; -	void __iomem *dgt_clk_ctl; +	void __iomem *base; +	void __iomem *cpu0_base; -	np = of_find_matching_node(NULL, msm_gpt_match); +	np = of_find_matching_node(NULL, msm_timer_match);  	if (!np) { -		pr_err("Can't find GPT DT node\n"); +		pr_err("Can't find msm timer DT node\n");  		return;  	} -	event_base = of_iomap(np, 0); -	if (!event_base) { +	base = of_iomap(np, 0); +	if (!base) {  		pr_err("Failed to map event base\n");  		return;  	} -	irq = irq_of_parse_and_map(np, 0); +	/* We use GPT0 for the clockevent */ +	irq = irq_of_parse_and_map(np, 1);  	if (irq <= 0) {  		pr_err("Can't get irq\n");  		return;  	} -	of_node_put(np); - -	np = of_find_matching_node(NULL, msm_dgt_match); -	if (!np) { -		pr_err("Can't find DGT DT node\n"); -		return; -	} +	/* We use CPU0's DGT for the clocksource */  	if (of_property_read_u32(np, "cpu-offset", &percpu_offset))  		percpu_offset = 0; @@ -269,45 +263,43 @@ void __init msm_dt_timer_init(void)  		return;  	} -	source_base = ioremap(res.start + percpu_offset, resource_size(&res)); -	if (!source_base) { +	cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); +	if (!cpu0_base) {  		pr_err("Failed to map source base\n");  		return;  	} -	if (!of_address_to_resource(np, 1, &res)) { -		dgt_clk_ctl = ioremap(res.start + percpu_offset, -				      resource_size(&res)); -		if (!dgt_clk_ctl) { -			pr_err("Failed to map DGT control base\n"); -			return; -		} -		writel_relaxed(DGT_CLK_CTL_DIV_4, dgt_clk_ctl); -		iounmap(dgt_clk_ctl); -	} -  	if (of_property_read_u32(np, "clock-frequency", &freq)) {  		pr_err("Unknown frequency\n");  		return;  	}  	of_node_put(np); +	event_base = base + 0x4; +	sts_base = base + 0x88; +	source_base = cpu0_base + 0x24; +	freq /= 4; +	writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); +  	msm_timer_init(freq, 32, irq, !!percpu_offset);  }  #endif -static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) +static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, +				u32 sts)  { -	event_base = ioremap(event, SZ_64); -	if (!event_base) { -		pr_err("Failed to map event base\n"); -		return 1; -	} -	source_base = ioremap(source, SZ_64); -	if (!source_base) { -		pr_err("Failed to map source base\n"); -		return 1; +	void __iomem *base; + +	base = ioremap(addr, SZ_256); +	if (!base) { +		pr_err("Failed to map timer base\n"); +		return -ENOMEM;  	} +	event_base = base + event; +	source_base = base + source; +	if (sts) +		sts_base = base + sts; +  	return 0;  } @@ -315,7 +307,7 @@ void __init msm7x01_timer_init(void)  {  	struct clocksource *cs = &msm_clocksource; -	if (msm_timer_map(0xc0100000, 0xc0100010)) +	if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))  		return;  	cs->read = msm_read_timer_count_shift;  	cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); @@ -326,14 +318,14 @@ void __init msm7x01_timer_init(void)  void __init msm7x30_timer_init(void)  { -	if (msm_timer_map(0xc0100004, 0xc0100024)) +	if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))  		return;  	msm_timer_init(24576000 / 4, 32, 1, false);  }  void __init qsd8x50_timer_init(void)  { -	if (msm_timer_map(0xAC100000, 0xAC100010)) +	if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))  		return;  	msm_timer_init(19200000 / 4, 32, 7, false);  }  |