diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/msm/timer.txt | 41 | ||||
-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 | 110 |
4 files changed, 86 insertions, 107 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/timer.txt b/Documentation/devicetree/bindings/arm/msm/timer.txt index 8c5907b9cae8..c6ef8f13dc7e 100644 --- a/Documentation/devicetree/bindings/arm/msm/timer.txt +++ b/Documentation/devicetree/bindings/arm/msm/timer.txt | |||
@@ -3,36 +3,35 @@ | |||
3 | Properties: | 3 | Properties: |
4 | 4 | ||
5 | - compatible : Should at least contain "qcom,msm-timer". More specific | 5 | - compatible : Should at least contain "qcom,msm-timer". More specific |
6 | properties such as "qcom,msm-gpt" and "qcom,msm-dgt" specify a general | 6 | properties specify which subsystem the timers are paired with. |
7 | purpose timer and a debug timer respectively. | ||
8 | 7 | ||
9 | - interrupts : Interrupt indicating a match event. | 8 | "qcom,kpss-timer" - krait subsystem |
9 | "qcom,scss-timer" - scorpion subsystem | ||
10 | 10 | ||
11 | - reg : Specifies the base address of the timer registers. The second region | 11 | - interrupts : Interrupts for the the debug timer, the first general purpose |
12 | specifies an optional register used to configure the clock divider. | 12 | timer, and optionally a second general purpose timer in that |
13 | order. | ||
13 | 14 | ||
14 | - clock-frequency : The frequency of the timer in Hz. | 15 | - reg : Specifies the base address of the timer registers. |
16 | |||
17 | - clock-frequency : The frequency of the debug timer and the general purpose | ||
18 | timer(s) in Hz in that order. | ||
15 | 19 | ||
16 | Optional: | 20 | Optional: |
17 | 21 | ||
18 | - cpu-offset : per-cpu offset used when the timer is accessed without the | 22 | - cpu-offset : per-cpu offset used when the timer is accessed without the |
19 | CPU remapping facilities. The offset is cpu-offset * cpu-nr. | 23 | CPU remapping facilities. The offset is |
24 | cpu-offset + (0x10000 * cpu-nr). | ||
20 | 25 | ||
21 | Example: | 26 | Example: |
22 | 27 | ||
23 | timer@200a004 { | 28 | timer@200a000 { |
24 | compatible = "qcom,msm-gpt", "qcom,msm-timer"; | 29 | compatible = "qcom,scss-timer", "qcom,msm-timer"; |
25 | interrupts = <1 2 0x301>; | 30 | interrupts = <1 1 0x301>, |
26 | reg = <0x0200a004 0x10>; | 31 | <1 2 0x301>, |
27 | clock-frequency = <32768>; | 32 | <1 3 0x301>; |
28 | cpu-offset = <0x40000>; | 33 | reg = <0x0200a000 0x100>; |
29 | }; | 34 | clock-frequency = <19200000>, |
30 | 35 | <32768>; | |
31 | timer@200a024 { | ||
32 | compatible = "qcom,msm-dgt", "qcom,msm-timer"; | ||
33 | interrupts = <1 3 0x301>; | ||
34 | reg = <0x0200a024 0x10>, | ||
35 | <0x0200a034 0x4>; | ||
36 | clock-frequency = <6750000>; | ||
37 | cpu-offset = <0x40000>; | 36 | cpu-offset = <0x40000>; |
38 | }; | 37 | }; |
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 f9fd77e8f1f5..284313f3e02c 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c | |||
@@ -30,19 +30,22 @@ | |||
30 | 30 | ||
31 | #include "common.h" | 31 | #include "common.h" |
32 | 32 | ||
33 | #define TIMER_MATCH_VAL 0x0000 | 33 | #define TIMER_MATCH_VAL 0x0000 |
34 | #define TIMER_COUNT_VAL 0x0004 | 34 | #define TIMER_COUNT_VAL 0x0004 |
35 | #define TIMER_ENABLE 0x0008 | 35 | #define TIMER_ENABLE 0x0008 |
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_DIV_4 0x3 | 39 | #define DGT_CLK_CTL 0x10 |
40 | #define DGT_CLK_CTL_DIV_4 0x3 | ||
41 | #define TIMER_STS_GPT0_CLR_PEND BIT(10) | ||
40 | 42 | ||
41 | #define GPT_HZ 32768 | 43 | #define GPT_HZ 32768 |
42 | 44 | ||
43 | #define MSM_DGT_SHIFT 5 | 45 | #define MSM_DGT_SHIFT 5 |
44 | 46 | ||
45 | static void __iomem *event_base; | 47 | static void __iomem *event_base; |
48 | static void __iomem *sts_base; | ||
46 | 49 | ||
47 | static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) | 50 | static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) |
48 | { | 51 | { |
@@ -67,6 +70,11 @@ static int msm_timer_set_next_event(unsigned long cycles, | |||
67 | 70 | ||
68 | writel_relaxed(ctrl, event_base + TIMER_CLEAR); | 71 | writel_relaxed(ctrl, event_base + TIMER_CLEAR); |
69 | writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); | 72 | writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); |
73 | |||
74 | if (sts_base) | ||
75 | while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) | ||
76 | cpu_relax(); | ||
77 | |||
70 | writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); | 78 | writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); |
71 | return 0; | 79 | return 0; |
72 | } | 80 | } |
@@ -137,9 +145,6 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) | |||
137 | if (!smp_processor_id()) | 145 | if (!smp_processor_id()) |
138 | return 0; | 146 | return 0; |
139 | 147 | ||
140 | writel_relaxed(0, event_base + TIMER_ENABLE); | ||
141 | writel_relaxed(0, event_base + TIMER_CLEAR); | ||
142 | writel_relaxed(~0, event_base + TIMER_MATCH_VAL); | ||
143 | evt->irq = msm_clockevent.irq; | 148 | evt->irq = msm_clockevent.irq; |
144 | evt->name = "local_timer"; | 149 | evt->name = "local_timer"; |
145 | evt->features = msm_clockevent.features; | 150 | evt->features = msm_clockevent.features; |
@@ -177,9 +182,6 @@ static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, | |||
177 | struct clocksource *cs = &msm_clocksource; | 182 | struct clocksource *cs = &msm_clocksource; |
178 | int res; | 183 | int res; |
179 | 184 | ||
180 | writel_relaxed(0, event_base + TIMER_ENABLE); | ||
181 | writel_relaxed(0, event_base + TIMER_CLEAR); | ||
182 | writel_relaxed(~0, event_base + TIMER_MATCH_VAL); | ||
183 | ce->cpumask = cpumask_of(0); | 185 | ce->cpumask = cpumask_of(0); |
184 | ce->irq = irq; | 186 | ce->irq = irq; |
185 | 187 | ||
@@ -217,13 +219,9 @@ err: | |||
217 | } | 219 | } |
218 | 220 | ||
219 | #ifdef CONFIG_OF | 221 | #ifdef CONFIG_OF |
220 | static const struct of_device_id msm_dgt_match[] __initconst = { | 222 | static const struct of_device_id msm_timer_match[] __initconst = { |
221 | { .compatible = "qcom,msm-dgt" }, | 223 | { .compatible = "qcom,kpss-timer" }, |
222 | { }, | 224 | { .compatible = "qcom,scss-timer" }, |
223 | }; | ||
224 | |||
225 | static const struct of_device_id msm_gpt_match[] __initconst = { | ||
226 | { .compatible = "qcom,msm-gpt" }, | ||
227 | { }, | 225 | { }, |
228 | }; | 226 | }; |
229 | 227 | ||
@@ -234,33 +232,29 @@ void __init msm_dt_timer_init(void) | |||
234 | int irq; | 232 | int irq; |
235 | struct resource res; | 233 | struct resource res; |
236 | u32 percpu_offset; | 234 | u32 percpu_offset; |
237 | void __iomem *dgt_clk_ctl; | 235 | void __iomem *base; |
236 | void __iomem *cpu0_base; | ||
238 | 237 | ||
239 | np = of_find_matching_node(NULL, msm_gpt_match); | 238 | np = of_find_matching_node(NULL, msm_timer_match); |
240 | if (!np) { | 239 | if (!np) { |
241 | pr_err("Can't find GPT DT node\n"); | 240 | pr_err("Can't find msm timer DT node\n"); |
242 | return; | 241 | return; |
243 | } | 242 | } |
244 | 243 | ||
245 | event_base = of_iomap(np, 0); | 244 | base = of_iomap(np, 0); |
246 | if (!event_base) { | 245 | if (!base) { |
247 | pr_err("Failed to map event base\n"); | 246 | pr_err("Failed to map event base\n"); |
248 | return; | 247 | return; |
249 | } | 248 | } |
250 | 249 | ||
251 | irq = irq_of_parse_and_map(np, 0); | 250 | /* We use GPT0 for the clockevent */ |
251 | irq = irq_of_parse_and_map(np, 1); | ||
252 | if (irq <= 0) { | 252 | if (irq <= 0) { |
253 | pr_err("Can't get irq\n"); | 253 | pr_err("Can't get irq\n"); |
254 | return; | 254 | return; |
255 | } | 255 | } |
256 | of_node_put(np); | ||
257 | |||
258 | np = of_find_matching_node(NULL, msm_dgt_match); | ||
259 | if (!np) { | ||
260 | pr_err("Can't find DGT DT node\n"); | ||
261 | return; | ||
262 | } | ||
263 | 256 | ||
257 | /* We use CPU0's DGT for the clocksource */ | ||
264 | if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) | 258 | if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) |
265 | percpu_offset = 0; | 259 | percpu_offset = 0; |
266 | 260 | ||
@@ -269,45 +263,43 @@ void __init msm_dt_timer_init(void) | |||
269 | return; | 263 | return; |
270 | } | 264 | } |
271 | 265 | ||
272 | source_base = ioremap(res.start + percpu_offset, resource_size(&res)); | 266 | cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); |
273 | if (!source_base) { | 267 | if (!cpu0_base) { |
274 | pr_err("Failed to map source base\n"); | 268 | pr_err("Failed to map source base\n"); |
275 | return; | 269 | return; |
276 | } | 270 | } |
277 | 271 | ||
278 | if (!of_address_to_resource(np, 1, &res)) { | ||
279 | dgt_clk_ctl = ioremap(res.start + percpu_offset, | ||
280 | resource_size(&res)); | ||
281 | if (!dgt_clk_ctl) { | ||
282 | pr_err("Failed to map DGT control base\n"); | ||
283 | return; | ||
284 | } | ||
285 | writel_relaxed(DGT_CLK_CTL_DIV_4, dgt_clk_ctl); | ||
286 | iounmap(dgt_clk_ctl); | ||
287 | } | ||
288 | |||
289 | if (of_property_read_u32(np, "clock-frequency", &freq)) { | 272 | if (of_property_read_u32(np, "clock-frequency", &freq)) { |
290 | pr_err("Unknown frequency\n"); | 273 | pr_err("Unknown frequency\n"); |
291 | return; | 274 | return; |
292 | } | 275 | } |
293 | of_node_put(np); | 276 | of_node_put(np); |
294 | 277 | ||
278 | event_base = base + 0x4; | ||
279 | sts_base = base + 0x88; | ||
280 | source_base = cpu0_base + 0x24; | ||
281 | freq /= 4; | ||
282 | writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); | ||
283 | |||
295 | msm_timer_init(freq, 32, irq, !!percpu_offset); | 284 | msm_timer_init(freq, 32, irq, !!percpu_offset); |
296 | } | 285 | } |
297 | #endif | 286 | #endif |
298 | 287 | ||
299 | static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) | 288 | static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, |
289 | u32 sts) | ||
300 | { | 290 | { |
301 | event_base = ioremap(event, SZ_64); | 291 | void __iomem *base; |
302 | if (!event_base) { | 292 | |
303 | pr_err("Failed to map event base\n"); | 293 | base = ioremap(addr, SZ_256); |
304 | return 1; | 294 | if (!base) { |
305 | } | 295 | pr_err("Failed to map timer base\n"); |
306 | source_base = ioremap(source, SZ_64); | 296 | return -ENOMEM; |
307 | if (!source_base) { | ||
308 | pr_err("Failed to map source base\n"); | ||
309 | return 1; | ||
310 | } | 297 | } |
298 | event_base = base + event; | ||
299 | source_base = base + source; | ||
300 | if (sts) | ||
301 | sts_base = base + sts; | ||
302 | |||
311 | return 0; | 303 | return 0; |
312 | } | 304 | } |
313 | 305 | ||
@@ -315,7 +307,7 @@ void __init msm7x01_timer_init(void) | |||
315 | { | 307 | { |
316 | struct clocksource *cs = &msm_clocksource; | 308 | struct clocksource *cs = &msm_clocksource; |
317 | 309 | ||
318 | if (msm_timer_map(0xc0100000, 0xc0100010)) | 310 | if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0)) |
319 | return; | 311 | return; |
320 | cs->read = msm_read_timer_count_shift; | 312 | cs->read = msm_read_timer_count_shift; |
321 | cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); | 313 | cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); |
@@ -326,14 +318,14 @@ void __init msm7x01_timer_init(void) | |||
326 | 318 | ||
327 | void __init msm7x30_timer_init(void) | 319 | void __init msm7x30_timer_init(void) |
328 | { | 320 | { |
329 | if (msm_timer_map(0xc0100004, 0xc0100024)) | 321 | if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80)) |
330 | return; | 322 | return; |
331 | msm_timer_init(24576000 / 4, 32, 1, false); | 323 | msm_timer_init(24576000 / 4, 32, 1, false); |
332 | } | 324 | } |
333 | 325 | ||
334 | void __init qsd8x50_timer_init(void) | 326 | void __init qsd8x50_timer_init(void) |
335 | { | 327 | { |
336 | if (msm_timer_map(0xAC100000, 0xAC100010)) | 328 | if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34)) |
337 | return; | 329 | return; |
338 | msm_timer_init(19200000 / 4, 32, 7, false); | 330 | msm_timer_init(19200000 / 4, 32, 7, false); |
339 | } | 331 | } |