diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2013-03-14 23:31:38 -0400 |
---|---|---|
committer | David Brown <davidb@codeaurora.org> | 2013-03-22 13:46:16 -0400 |
commit | eebdb0c1e1d63532399f7cbb65ade5969d63df06 (patch) | |
tree | 0fb67b3ab00115d0e0078f51c721c60f7d4ef9be /arch/arm | |
parent | f6161aa153581da4a3867a2d1a7caf4be19b6ec9 (diff) |
ARM: msm: Rework timer binding to be more general
The msm timer binding I wrote is bad. First off, the clock
frequency in the binding for the dgt is wrong. Software divides
down the input rate by 4 to achieve the rate listed in the
binding. We also treat each individual timer as a separate
hardware component, when in reality there is one timer block
(that may be duplicated per cpu) with multiple timers within it.
Depending on the version of the hardware there can be one or two
general purpose timers, status and divider control registers, and
an entirely different register layout.
In the next patch we'll need to know about the different register
layouts so that we can properly check the status register after
clearing the count. The current binding makes this complicated
because the general purpose timer's reg property doesn't indicate
where that status register is, and in fact it is beyond the size
of the reg property.
Clean all this up by just having one node for the timer hardware,
and describe all the interrupts and clock frequencies supported
while having one reg property that covers the entire timer
register region. We'll use the compatible field in the future to
determine different register layouts and if we should read the
status registers, etc.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: David Brown <davidb@codeaurora.org>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/boot/dts/msm8660-surf.dts | 20 | ||||
-rw-r--r-- | arch/arm/boot/dts/msm8960-cdp.dts | 22 | ||||
-rw-r--r-- | arch/arm/mach-msm/timer.c | 79 |
3 files changed, 48 insertions, 73 deletions
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts index 31f2157cd7d7..743ef42df23e 100644 --- a/arch/arm/boot/dts/msm8660-surf.dts +++ b/arch/arm/boot/dts/msm8660-surf.dts | |||
@@ -16,19 +16,13 @@ | |||
16 | }; | 16 | }; |
17 | 17 | ||
18 | timer@2000004 { | 18 | timer@2000004 { |
19 | compatible = "qcom,msm-gpt", "qcom,msm-timer"; | 19 | compatible = "qcom,scss-timer", "qcom,msm-timer"; |
20 | interrupts = <1 1 0x301>; | 20 | interrupts = <1 0 0x301>, |
21 | reg = <0x02000004 0x10>; | 21 | <1 1 0x301>, |
22 | clock-frequency = <32768>; | 22 | <1 2 0x301>; |
23 | cpu-offset = <0x40000>; | 23 | reg = <0x02000000 0x100>; |
24 | }; | 24 | clock-frequency = <27000000>, |
25 | 25 | <32768>; | |
26 | timer@2000024 { | ||
27 | compatible = "qcom,msm-dgt", "qcom,msm-timer"; | ||
28 | interrupts = <1 0 0x301>; | ||
29 | reg = <0x02000024 0x10>, | ||
30 | <0x02000034 0x4>; | ||
31 | clock-frequency = <6750000>; | ||
32 | cpu-offset = <0x40000>; | 26 | cpu-offset = <0x40000>; |
33 | }; | 27 | }; |
34 | 28 | ||
diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/msm8960-cdp.dts index 9e621b5ad3dd..3ae51fb02e17 100644 --- a/arch/arm/boot/dts/msm8960-cdp.dts +++ b/arch/arm/boot/dts/msm8960-cdp.dts | |||
@@ -15,20 +15,14 @@ | |||
15 | < 0x02002000 0x1000 >; | 15 | < 0x02002000 0x1000 >; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | timer@200a004 { | 18 | timer@200a000 { |
19 | compatible = "qcom,msm-gpt", "qcom,msm-timer"; | 19 | compatible = "qcom,kpss-timer", "qcom,msm-timer"; |
20 | interrupts = <1 2 0x301>; | 20 | interrupts = <1 1 0x301>, |
21 | reg = <0x0200a004 0x10>; | 21 | <1 2 0x301>, |
22 | clock-frequency = <32768>; | 22 | <1 3 0x301>; |
23 | cpu-offset = <0x80000>; | 23 | reg = <0x0200a000 0x100>; |
24 | }; | 24 | clock-frequency = <27000000>, |
25 | 25 | <32768>; | |
26 | timer@200a024 { | ||
27 | compatible = "qcom,msm-dgt", "qcom,msm-timer"; | ||
28 | interrupts = <1 1 0x301>; | ||
29 | reg = <0x0200a024 0x10>, | ||
30 | <0x0200a034 0x4>; | ||
31 | clock-frequency = <6750000>; | ||
32 | cpu-offset = <0x80000>; | 26 | cpu-offset = <0x80000>; |
33 | }; | 27 | }; |
34 | 28 | ||
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 2969027f02fa..165e33b9b1ee 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) | 36 | #define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) |
37 | #define TIMER_ENABLE_EN BIT(0) | 37 | #define TIMER_ENABLE_EN BIT(0) |
38 | #define TIMER_CLEAR 0x000C | 38 | #define TIMER_CLEAR 0x000C |
39 | #define DGT_CLK_CTL 0x10 | ||
39 | #define DGT_CLK_CTL_DIV_4 0x3 | 40 | #define DGT_CLK_CTL_DIV_4 0x3 |
40 | 41 | ||
41 | #define GPT_HZ 32768 | 42 | #define GPT_HZ 32768 |
@@ -214,13 +215,9 @@ err: | |||
214 | } | 215 | } |
215 | 216 | ||
216 | #ifdef CONFIG_OF | 217 | #ifdef CONFIG_OF |
217 | static const struct of_device_id msm_dgt_match[] __initconst = { | 218 | static const struct of_device_id msm_timer_match[] __initconst = { |
218 | { .compatible = "qcom,msm-dgt" }, | 219 | { .compatible = "qcom,kpss-timer" }, |
219 | { }, | 220 | { .compatible = "qcom,scss-timer" }, |
220 | }; | ||
221 | |||
222 | static const struct of_device_id msm_gpt_match[] __initconst = { | ||
223 | { .compatible = "qcom,msm-gpt" }, | ||
224 | { }, | 221 | { }, |
225 | }; | 222 | }; |
226 | 223 | ||
@@ -231,33 +228,29 @@ void __init msm_dt_timer_init(void) | |||
231 | int irq; | 228 | int irq; |
232 | struct resource res; | 229 | struct resource res; |
233 | u32 percpu_offset; | 230 | u32 percpu_offset; |
234 | void __iomem *dgt_clk_ctl; | 231 | void __iomem *base; |
232 | void __iomem *cpu0_base; | ||
235 | 233 | ||
236 | np = of_find_matching_node(NULL, msm_gpt_match); | 234 | np = of_find_matching_node(NULL, msm_timer_match); |
237 | if (!np) { | 235 | if (!np) { |
238 | pr_err("Can't find GPT DT node\n"); | 236 | pr_err("Can't find msm timer DT node\n"); |
239 | return; | 237 | return; |
240 | } | 238 | } |
241 | 239 | ||
242 | event_base = of_iomap(np, 0); | 240 | base = of_iomap(np, 0); |
243 | if (!event_base) { | 241 | if (!base) { |
244 | pr_err("Failed to map event base\n"); | 242 | pr_err("Failed to map event base\n"); |
245 | return; | 243 | return; |
246 | } | 244 | } |
247 | 245 | ||
248 | irq = irq_of_parse_and_map(np, 0); | 246 | /* We use GPT0 for the clockevent */ |
247 | irq = irq_of_parse_and_map(np, 1); | ||
249 | if (irq <= 0) { | 248 | if (irq <= 0) { |
250 | pr_err("Can't get irq\n"); | 249 | pr_err("Can't get irq\n"); |
251 | return; | 250 | return; |
252 | } | 251 | } |
253 | of_node_put(np); | ||
254 | |||
255 | np = of_find_matching_node(NULL, msm_dgt_match); | ||
256 | if (!np) { | ||
257 | pr_err("Can't find DGT DT node\n"); | ||
258 | return; | ||
259 | } | ||
260 | 252 | ||
253 | /* We use CPU0's DGT for the clocksource */ | ||
261 | if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) | 254 | if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) |
262 | percpu_offset = 0; | 255 | percpu_offset = 0; |
263 | 256 | ||
@@ -266,45 +259,39 @@ void __init msm_dt_timer_init(void) | |||
266 | return; | 259 | return; |
267 | } | 260 | } |
268 | 261 | ||
269 | source_base = ioremap(res.start + percpu_offset, resource_size(&res)); | 262 | cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); |
270 | if (!source_base) { | 263 | if (!cpu0_base) { |
271 | pr_err("Failed to map source base\n"); | 264 | pr_err("Failed to map source base\n"); |
272 | return; | 265 | return; |
273 | } | 266 | } |
274 | 267 | ||
275 | if (!of_address_to_resource(np, 1, &res)) { | ||
276 | dgt_clk_ctl = ioremap(res.start + percpu_offset, | ||
277 | resource_size(&res)); | ||
278 | if (!dgt_clk_ctl) { | ||
279 | pr_err("Failed to map DGT control base\n"); | ||
280 | return; | ||
281 | } | ||
282 | writel_relaxed(DGT_CLK_CTL_DIV_4, dgt_clk_ctl); | ||
283 | iounmap(dgt_clk_ctl); | ||
284 | } | ||
285 | |||
286 | if (of_property_read_u32(np, "clock-frequency", &freq)) { | 268 | if (of_property_read_u32(np, "clock-frequency", &freq)) { |
287 | pr_err("Unknown frequency\n"); | 269 | pr_err("Unknown frequency\n"); |
288 | return; | 270 | return; |
289 | } | 271 | } |
290 | of_node_put(np); | 272 | of_node_put(np); |
291 | 273 | ||
274 | event_base = base + 0x4; | ||
275 | source_base = cpu0_base + 0x24; | ||
276 | freq /= 4; | ||
277 | writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); | ||
278 | |||
292 | msm_timer_init(freq, 32, irq, !!percpu_offset); | 279 | msm_timer_init(freq, 32, irq, !!percpu_offset); |
293 | } | 280 | } |
294 | #endif | 281 | #endif |
295 | 282 | ||
296 | static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) | 283 | static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source) |
297 | { | 284 | { |
298 | event_base = ioremap(event, SZ_64); | 285 | void __iomem *base; |
299 | if (!event_base) { | 286 | |
300 | pr_err("Failed to map event base\n"); | 287 | base = ioremap(addr, SZ_256); |
301 | return 1; | 288 | if (!base) { |
302 | } | 289 | pr_err("Failed to map timer base\n"); |
303 | source_base = ioremap(source, SZ_64); | 290 | return -ENOMEM; |
304 | if (!source_base) { | ||
305 | pr_err("Failed to map source base\n"); | ||
306 | return 1; | ||
307 | } | 291 | } |
292 | event_base = base + event; | ||
293 | source_base = base + source; | ||
294 | |||
308 | return 0; | 295 | return 0; |
309 | } | 296 | } |
310 | 297 | ||
@@ -312,7 +299,7 @@ void __init msm7x01_timer_init(void) | |||
312 | { | 299 | { |
313 | struct clocksource *cs = &msm_clocksource; | 300 | struct clocksource *cs = &msm_clocksource; |
314 | 301 | ||
315 | if (msm_timer_map(0xc0100000, 0xc0100010)) | 302 | if (msm_timer_map(0xc0100000, 0x0, 0x10)) |
316 | return; | 303 | return; |
317 | cs->read = msm_read_timer_count_shift; | 304 | cs->read = msm_read_timer_count_shift; |
318 | cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); | 305 | cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); |
@@ -323,14 +310,14 @@ void __init msm7x01_timer_init(void) | |||
323 | 310 | ||
324 | void __init msm7x30_timer_init(void) | 311 | void __init msm7x30_timer_init(void) |
325 | { | 312 | { |
326 | if (msm_timer_map(0xc0100004, 0xc0100024)) | 313 | if (msm_timer_map(0xc0100000, 0x4, 0x24)) |
327 | return; | 314 | return; |
328 | msm_timer_init(24576000 / 4, 32, 1, false); | 315 | msm_timer_init(24576000 / 4, 32, 1, false); |
329 | } | 316 | } |
330 | 317 | ||
331 | void __init qsd8x50_timer_init(void) | 318 | void __init qsd8x50_timer_init(void) |
332 | { | 319 | { |
333 | if (msm_timer_map(0xAC100000, 0xAC100010)) | 320 | if (msm_timer_map(0xAC100000, 0x0, 0x10)) |
334 | return; | 321 | return; |
335 | msm_timer_init(19200000 / 4, 32, 7, false); | 322 | msm_timer_init(19200000 / 4, 32, 7, false); |
336 | } | 323 | } |