aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/msm/timer.txt41
-rw-r--r--arch/arm/boot/dts/msm8660-surf.dts20
-rw-r--r--arch/arm/boot/dts/msm8960-cdp.dts22
-rw-r--r--arch/arm/mach-msm/timer.c110
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 @@
3Properties: 3Properties:
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
16Optional: 20Optional:
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
21Example: 26Example:
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
45static void __iomem *event_base; 47static void __iomem *event_base;
48static void __iomem *sts_base;
46 49
47static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) 50static 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
220static const struct of_device_id msm_dgt_match[] __initconst = { 222static 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
225static 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
299static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) 288static 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
327void __init msm7x30_timer_init(void) 319void __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
334void __init qsd8x50_timer_init(void) 326void __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}