diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2012-09-05 15:28:53 -0400 |
---|---|---|
committer | David Brown <davidb@codeaurora.org> | 2012-09-13 14:14:46 -0400 |
commit | 6e3321631ac2eca99b3289b83ea1f290b1a8bd92 (patch) | |
tree | 8a899b8f63562d4479c3cd008ea6c32bd391b7ca /arch/arm/mach-msm | |
parent | 4312a7ef9cd744849e16ef4bdeb7ca6beec9ec76 (diff) |
ARM: msm: Add DT support to msm_timer
Add support to setup the MSM timer via information obtained from
the devicetree.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
[davidb@codeaurora.org: Remove leading zeros]
Signed-off-by: David Brown <davidb@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r-- | arch/arm/mach-msm/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-msm/timer.c | 87 |
2 files changed, 88 insertions, 0 deletions
diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h index 4c2dd16e659b..7d57fb076193 100644 --- a/arch/arm/mach-msm/common.h +++ b/arch/arm/mach-msm/common.h | |||
@@ -16,6 +16,7 @@ extern struct sys_timer msm7x01_timer; | |||
16 | extern struct sys_timer msm7x30_timer; | 16 | extern struct sys_timer msm7x30_timer; |
17 | extern struct sys_timer msm8x60_timer; | 17 | extern struct sys_timer msm8x60_timer; |
18 | extern struct sys_timer msm8960_timer; | 18 | extern struct sys_timer msm8960_timer; |
19 | extern struct sys_timer msm_dt_timer; | ||
19 | extern struct sys_timer qsd8x50_timer; | 20 | extern struct sys_timer qsd8x50_timer; |
20 | 21 | ||
21 | #endif | 22 | #endif |
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index ddb870117659..b17a39db991e 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_address.h> | ||
25 | #include <linux/of_irq.h> | ||
23 | 26 | ||
24 | #include <asm/mach/time.h> | 27 | #include <asm/mach/time.h> |
25 | #include <asm/hardware/gic.h> | 28 | #include <asm/hardware/gic.h> |
@@ -216,6 +219,90 @@ err: | |||
216 | setup_sched_clock(msm_sched_clock_read, sched_bits, dgt_hz); | 219 | setup_sched_clock(msm_sched_clock_read, sched_bits, dgt_hz); |
217 | } | 220 | } |
218 | 221 | ||
222 | #ifdef CONFIG_OF | ||
223 | static const struct of_device_id msm_dgt_match[] __initconst = { | ||
224 | { .compatible = "qcom,msm-dgt" }, | ||
225 | { }, | ||
226 | }; | ||
227 | |||
228 | static const struct of_device_id msm_gpt_match[] __initconst = { | ||
229 | { .compatible = "qcom,msm-gpt" }, | ||
230 | { }, | ||
231 | }; | ||
232 | |||
233 | static void __init msm_dt_timer_init(void) | ||
234 | { | ||
235 | struct device_node *np; | ||
236 | u32 freq; | ||
237 | int irq; | ||
238 | struct resource res; | ||
239 | u32 percpu_offset; | ||
240 | void __iomem *dgt_clk_ctl; | ||
241 | |||
242 | np = of_find_matching_node(NULL, msm_gpt_match); | ||
243 | if (!np) { | ||
244 | pr_err("Can't find GPT DT node\n"); | ||
245 | return; | ||
246 | } | ||
247 | |||
248 | event_base = of_iomap(np, 0); | ||
249 | if (!event_base) { | ||
250 | pr_err("Failed to map event base\n"); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | irq = irq_of_parse_and_map(np, 0); | ||
255 | if (irq <= 0) { | ||
256 | pr_err("Can't get irq\n"); | ||
257 | return; | ||
258 | } | ||
259 | of_node_put(np); | ||
260 | |||
261 | np = of_find_matching_node(NULL, msm_dgt_match); | ||
262 | if (!np) { | ||
263 | pr_err("Can't find DGT DT node\n"); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) | ||
268 | percpu_offset = 0; | ||
269 | |||
270 | if (of_address_to_resource(np, 0, &res)) { | ||
271 | pr_err("Failed to parse DGT resource\n"); | ||
272 | return; | ||
273 | } | ||
274 | |||
275 | source_base = ioremap(res.start + percpu_offset, resource_size(&res)); | ||
276 | if (!source_base) { | ||
277 | pr_err("Failed to map source base\n"); | ||
278 | return; | ||
279 | } | ||
280 | |||
281 | if (!of_address_to_resource(np, 1, &res)) { | ||
282 | dgt_clk_ctl = ioremap(res.start + percpu_offset, | ||
283 | resource_size(&res)); | ||
284 | if (!dgt_clk_ctl) { | ||
285 | pr_err("Failed to map DGT control base\n"); | ||
286 | return; | ||
287 | } | ||
288 | writel_relaxed(DGT_CLK_CTL_DIV_4, dgt_clk_ctl); | ||
289 | iounmap(dgt_clk_ctl); | ||
290 | } | ||
291 | |||
292 | if (of_property_read_u32(np, "clock-frequency", &freq)) { | ||
293 | pr_err("Unknown frequency\n"); | ||
294 | return; | ||
295 | } | ||
296 | of_node_put(np); | ||
297 | |||
298 | msm_timer_init(freq, 32, irq, !!percpu_offset); | ||
299 | } | ||
300 | |||
301 | struct sys_timer msm_dt_timer = { | ||
302 | .init = msm_dt_timer_init | ||
303 | }; | ||
304 | #endif | ||
305 | |||
219 | static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) | 306 | static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) |
220 | { | 307 | { |
221 | event_base = ioremap(event, SZ_64); | 308 | event_base = ioremap(event, SZ_64); |