ipq806x: Add support for IPQ806x chip family
[openwrt/staging/wigyori.git] / target / linux / ipq806x / patches / 0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch
1 From 00009eabeb2074bef5c89e576a7a6d827c12c3d9 Mon Sep 17 00:00:00 2001
2 From: Kumar Gala <galak@codeaurora.org>
3 Date: Wed, 29 Jan 2014 16:17:30 -0600
4 Subject: [PATCH 004/182] clocksource: qcom: Move clocksource code out of
5 mach-msm
6
7 We intend to share the clocksource code for MSM platforms between legacy
8 and multiplatform supported qcom SoCs.
9
10 Acked-by: Olof Johansson <olof@lixom.net>
11 Signed-off-by: Kumar Gala <galak@codeaurora.org>
12 ---
13 arch/arm/mach-msm/Kconfig | 13 +-
14 arch/arm/mach-msm/Makefile | 1 -
15 arch/arm/mach-msm/timer.c | 333 --------------------------------------
16 drivers/clocksource/Kconfig | 3 +
17 drivers/clocksource/Makefile | 1 +
18 drivers/clocksource/qcom-timer.c | 329 +++++++++++++++++++++++++++++++++++++
19 6 files changed, 338 insertions(+), 342 deletions(-)
20 delete mode 100644 arch/arm/mach-msm/timer.c
21 create mode 100644 drivers/clocksource/qcom-timer.c
22
23 diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
24 index 9625cf3..3c4eca7 100644
25 --- a/arch/arm/mach-msm/Kconfig
26 +++ b/arch/arm/mach-msm/Kconfig
27 @@ -21,7 +21,7 @@ config ARCH_MSM8X60
28 select CPU_V7
29 select HAVE_SMP
30 select MSM_SCM if SMP
31 - select MSM_TIMER
32 + select CLKSRC_QCOM
33
34 config ARCH_MSM8960
35 bool "Enable support for MSM8960"
36 @@ -29,7 +29,7 @@ config ARCH_MSM8960
37 select CPU_V7
38 select HAVE_SMP
39 select MSM_SCM if SMP
40 - select MSM_TIMER
41 + select CLKSRC_QCOM
42
43 config ARCH_MSM8974
44 bool "Enable support for MSM8974"
45 @@ -54,7 +54,7 @@ config ARCH_MSM7X00A
46 select MACH_TROUT if !MACH_HALIBUT
47 select MSM_PROC_COMM
48 select MSM_SMD
49 - select MSM_TIMER
50 + select CLKSRC_QCOM
51 select MSM_SMD_PKG3
52
53 config ARCH_MSM7X30
54 @@ -66,7 +66,7 @@ config ARCH_MSM7X30
55 select MSM_GPIOMUX
56 select MSM_PROC_COMM
57 select MSM_SMD
58 - select MSM_TIMER
59 + select CLKSRC_QCOM
60 select MSM_VIC
61
62 config ARCH_QSD8X50
63 @@ -78,7 +78,7 @@ config ARCH_QSD8X50
64 select MSM_GPIOMUX
65 select MSM_PROC_COMM
66 select MSM_SMD
67 - select MSM_TIMER
68 + select CLKSRC_QCOM
69 select MSM_VIC
70
71 endchoice
72 @@ -153,7 +153,4 @@ config MSM_GPIOMUX
73 config MSM_SCM
74 bool
75
76 -config MSM_TIMER
77 - bool
78 -
79 endif
80 diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
81 index 8327f60..04b1bee 100644
82 --- a/arch/arm/mach-msm/Makefile
83 +++ b/arch/arm/mach-msm/Makefile
84 @@ -1,4 +1,3 @@
85 -obj-$(CONFIG_MSM_TIMER) += timer.o
86 obj-$(CONFIG_MSM_PROC_COMM) += clock.o
87
88 obj-$(CONFIG_MSM_VIC) += irq-vic.o
89 diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
90 deleted file mode 100644
91 index fd16449..0000000
92 --- a/arch/arm/mach-msm/timer.c
93 +++ /dev/null
94 @@ -1,333 +0,0 @@
95 -/*
96 - *
97 - * Copyright (C) 2007 Google, Inc.
98 - * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
99 - *
100 - * This software is licensed under the terms of the GNU General Public
101 - * License version 2, as published by the Free Software Foundation, and
102 - * may be copied, distributed, and modified under those terms.
103 - *
104 - * This program is distributed in the hope that it will be useful,
105 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
106 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107 - * GNU General Public License for more details.
108 - *
109 - */
110 -
111 -#include <linux/clocksource.h>
112 -#include <linux/clockchips.h>
113 -#include <linux/cpu.h>
114 -#include <linux/init.h>
115 -#include <linux/interrupt.h>
116 -#include <linux/irq.h>
117 -#include <linux/io.h>
118 -#include <linux/of.h>
119 -#include <linux/of_address.h>
120 -#include <linux/of_irq.h>
121 -#include <linux/sched_clock.h>
122 -
123 -#include <asm/mach/time.h>
124 -
125 -#include "common.h"
126 -
127 -#define TIMER_MATCH_VAL 0x0000
128 -#define TIMER_COUNT_VAL 0x0004
129 -#define TIMER_ENABLE 0x0008
130 -#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1)
131 -#define TIMER_ENABLE_EN BIT(0)
132 -#define TIMER_CLEAR 0x000C
133 -#define DGT_CLK_CTL 0x10
134 -#define DGT_CLK_CTL_DIV_4 0x3
135 -#define TIMER_STS_GPT0_CLR_PEND BIT(10)
136 -
137 -#define GPT_HZ 32768
138 -
139 -#define MSM_DGT_SHIFT 5
140 -
141 -static void __iomem *event_base;
142 -static void __iomem *sts_base;
143 -
144 -static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
145 -{
146 - struct clock_event_device *evt = dev_id;
147 - /* Stop the timer tick */
148 - if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
149 - u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
150 - ctrl &= ~TIMER_ENABLE_EN;
151 - writel_relaxed(ctrl, event_base + TIMER_ENABLE);
152 - }
153 - evt->event_handler(evt);
154 - return IRQ_HANDLED;
155 -}
156 -
157 -static int msm_timer_set_next_event(unsigned long cycles,
158 - struct clock_event_device *evt)
159 -{
160 - u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
161 -
162 - ctrl &= ~TIMER_ENABLE_EN;
163 - writel_relaxed(ctrl, event_base + TIMER_ENABLE);
164 -
165 - writel_relaxed(ctrl, event_base + TIMER_CLEAR);
166 - writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
167 -
168 - if (sts_base)
169 - while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
170 - cpu_relax();
171 -
172 - writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
173 - return 0;
174 -}
175 -
176 -static void msm_timer_set_mode(enum clock_event_mode mode,
177 - struct clock_event_device *evt)
178 -{
179 - u32 ctrl;
180 -
181 - ctrl = readl_relaxed(event_base + TIMER_ENABLE);
182 - ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
183 -
184 - switch (mode) {
185 - case CLOCK_EVT_MODE_RESUME:
186 - case CLOCK_EVT_MODE_PERIODIC:
187 - break;
188 - case CLOCK_EVT_MODE_ONESHOT:
189 - /* Timer is enabled in set_next_event */
190 - break;
191 - case CLOCK_EVT_MODE_UNUSED:
192 - case CLOCK_EVT_MODE_SHUTDOWN:
193 - break;
194 - }
195 - writel_relaxed(ctrl, event_base + TIMER_ENABLE);
196 -}
197 -
198 -static struct clock_event_device __percpu *msm_evt;
199 -
200 -static void __iomem *source_base;
201 -
202 -static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
203 -{
204 - return readl_relaxed(source_base + TIMER_COUNT_VAL);
205 -}
206 -
207 -static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
208 -{
209 - /*
210 - * Shift timer count down by a constant due to unreliable lower bits
211 - * on some targets.
212 - */
213 - return msm_read_timer_count(cs) >> MSM_DGT_SHIFT;
214 -}
215 -
216 -static struct clocksource msm_clocksource = {
217 - .name = "dg_timer",
218 - .rating = 300,
219 - .read = msm_read_timer_count,
220 - .mask = CLOCKSOURCE_MASK(32),
221 - .flags = CLOCK_SOURCE_IS_CONTINUOUS,
222 -};
223 -
224 -static int msm_timer_irq;
225 -static int msm_timer_has_ppi;
226 -
227 -static int msm_local_timer_setup(struct clock_event_device *evt)
228 -{
229 - int cpu = smp_processor_id();
230 - int err;
231 -
232 - evt->irq = msm_timer_irq;
233 - evt->name = "msm_timer";
234 - evt->features = CLOCK_EVT_FEAT_ONESHOT;
235 - evt->rating = 200;
236 - evt->set_mode = msm_timer_set_mode;
237 - evt->set_next_event = msm_timer_set_next_event;
238 - evt->cpumask = cpumask_of(cpu);
239 -
240 - clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff);
241 -
242 - if (msm_timer_has_ppi) {
243 - enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
244 - } else {
245 - err = request_irq(evt->irq, msm_timer_interrupt,
246 - IRQF_TIMER | IRQF_NOBALANCING |
247 - IRQF_TRIGGER_RISING, "gp_timer", evt);
248 - if (err)
249 - pr_err("request_irq failed\n");
250 - }
251 -
252 - return 0;
253 -}
254 -
255 -static void msm_local_timer_stop(struct clock_event_device *evt)
256 -{
257 - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
258 - disable_percpu_irq(evt->irq);
259 -}
260 -
261 -static int msm_timer_cpu_notify(struct notifier_block *self,
262 - unsigned long action, void *hcpu)
263 -{
264 - /*
265 - * Grab cpu pointer in each case to avoid spurious
266 - * preemptible warnings
267 - */
268 - switch (action & ~CPU_TASKS_FROZEN) {
269 - case CPU_STARTING:
270 - msm_local_timer_setup(this_cpu_ptr(msm_evt));
271 - break;
272 - case CPU_DYING:
273 - msm_local_timer_stop(this_cpu_ptr(msm_evt));
274 - break;
275 - }
276 -
277 - return NOTIFY_OK;
278 -}
279 -
280 -static struct notifier_block msm_timer_cpu_nb = {
281 - .notifier_call = msm_timer_cpu_notify,
282 -};
283 -
284 -static u64 notrace msm_sched_clock_read(void)
285 -{
286 - return msm_clocksource.read(&msm_clocksource);
287 -}
288 -
289 -static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
290 - bool percpu)
291 -{
292 - struct clocksource *cs = &msm_clocksource;
293 - int res = 0;
294 -
295 - msm_timer_irq = irq;
296 - msm_timer_has_ppi = percpu;
297 -
298 - msm_evt = alloc_percpu(struct clock_event_device);
299 - if (!msm_evt) {
300 - pr_err("memory allocation failed for clockevents\n");
301 - goto err;
302 - }
303 -
304 - if (percpu)
305 - res = request_percpu_irq(irq, msm_timer_interrupt,
306 - "gp_timer", msm_evt);
307 -
308 - if (res) {
309 - pr_err("request_percpu_irq failed\n");
310 - } else {
311 - res = register_cpu_notifier(&msm_timer_cpu_nb);
312 - if (res) {
313 - free_percpu_irq(irq, msm_evt);
314 - goto err;
315 - }
316 -
317 - /* Immediately configure the timer on the boot CPU */
318 - msm_local_timer_setup(__this_cpu_ptr(msm_evt));
319 - }
320 -
321 -err:
322 - writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE);
323 - res = clocksource_register_hz(cs, dgt_hz);
324 - if (res)
325 - pr_err("clocksource_register failed\n");
326 - sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
327 -}
328 -
329 -#ifdef CONFIG_OF
330 -static void __init msm_dt_timer_init(struct device_node *np)
331 -{
332 - u32 freq;
333 - int irq;
334 - struct resource res;
335 - u32 percpu_offset;
336 - void __iomem *base;
337 - void __iomem *cpu0_base;
338 -
339 - base = of_iomap(np, 0);
340 - if (!base) {
341 - pr_err("Failed to map event base\n");
342 - return;
343 - }
344 -
345 - /* We use GPT0 for the clockevent */
346 - irq = irq_of_parse_and_map(np, 1);
347 - if (irq <= 0) {
348 - pr_err("Can't get irq\n");
349 - return;
350 - }
351 -
352 - /* We use CPU0's DGT for the clocksource */
353 - if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
354 - percpu_offset = 0;
355 -
356 - if (of_address_to_resource(np, 0, &res)) {
357 - pr_err("Failed to parse DGT resource\n");
358 - return;
359 - }
360 -
361 - cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res));
362 - if (!cpu0_base) {
363 - pr_err("Failed to map source base\n");
364 - return;
365 - }
366 -
367 - if (of_property_read_u32(np, "clock-frequency", &freq)) {
368 - pr_err("Unknown frequency\n");
369 - return;
370 - }
371 -
372 - event_base = base + 0x4;
373 - sts_base = base + 0x88;
374 - source_base = cpu0_base + 0x24;
375 - freq /= 4;
376 - writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
377 -
378 - msm_timer_init(freq, 32, irq, !!percpu_offset);
379 -}
380 -CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
381 -CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
382 -#endif
383 -
384 -static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
385 - u32 sts)
386 -{
387 - void __iomem *base;
388 -
389 - base = ioremap(addr, SZ_256);
390 - if (!base) {
391 - pr_err("Failed to map timer base\n");
392 - return -ENOMEM;
393 - }
394 - event_base = base + event;
395 - source_base = base + source;
396 - if (sts)
397 - sts_base = base + sts;
398 -
399 - return 0;
400 -}
401 -
402 -void __init msm7x01_timer_init(void)
403 -{
404 - struct clocksource *cs = &msm_clocksource;
405 -
406 - if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
407 - return;
408 - cs->read = msm_read_timer_count_shift;
409 - cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
410 - /* 600 KHz */
411 - msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7,
412 - false);
413 -}
414 -
415 -void __init msm7x30_timer_init(void)
416 -{
417 - if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
418 - return;
419 - msm_timer_init(24576000 / 4, 32, 1, false);
420 -}
421 -
422 -void __init qsd8x50_timer_init(void)
423 -{
424 - if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
425 - return;
426 - msm_timer_init(19200000 / 4, 32, 7, false);
427 -}
428 diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
429 index cd6950f..6510ec4 100644
430 --- a/drivers/clocksource/Kconfig
431 +++ b/drivers/clocksource/Kconfig
432 @@ -140,3 +140,6 @@ config VF_PIT_TIMER
433 bool
434 help
435 Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
436 +
437 +config CLKSRC_QCOM
438 + bool
439 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
440 index c7ca50a..2e0c0cc 100644
441 --- a/drivers/clocksource/Makefile
442 +++ b/drivers/clocksource/Makefile
443 @@ -32,6 +32,7 @@ obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o
444 obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
445 obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o
446 obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o
447 +obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o
448
449 obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
450 obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
451 diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c
452 new file mode 100644
453 index 0000000..dca829e
454 --- /dev/null
455 +++ b/drivers/clocksource/qcom-timer.c
456 @@ -0,0 +1,329 @@
457 +/*
458 + *
459 + * Copyright (C) 2007 Google, Inc.
460 + * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved.
461 + *
462 + * This software is licensed under the terms of the GNU General Public
463 + * License version 2, as published by the Free Software Foundation, and
464 + * may be copied, distributed, and modified under those terms.
465 + *
466 + * This program is distributed in the hope that it will be useful,
467 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
468 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
469 + * GNU General Public License for more details.
470 + *
471 + */
472 +
473 +#include <linux/clocksource.h>
474 +#include <linux/clockchips.h>
475 +#include <linux/cpu.h>
476 +#include <linux/init.h>
477 +#include <linux/interrupt.h>
478 +#include <linux/irq.h>
479 +#include <linux/io.h>
480 +#include <linux/of.h>
481 +#include <linux/of_address.h>
482 +#include <linux/of_irq.h>
483 +#include <linux/sched_clock.h>
484 +
485 +#define TIMER_MATCH_VAL 0x0000
486 +#define TIMER_COUNT_VAL 0x0004
487 +#define TIMER_ENABLE 0x0008
488 +#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1)
489 +#define TIMER_ENABLE_EN BIT(0)
490 +#define TIMER_CLEAR 0x000C
491 +#define DGT_CLK_CTL 0x10
492 +#define DGT_CLK_CTL_DIV_4 0x3
493 +#define TIMER_STS_GPT0_CLR_PEND BIT(10)
494 +
495 +#define GPT_HZ 32768
496 +
497 +#define MSM_DGT_SHIFT 5
498 +
499 +static void __iomem *event_base;
500 +static void __iomem *sts_base;
501 +
502 +static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
503 +{
504 + struct clock_event_device *evt = dev_id;
505 + /* Stop the timer tick */
506 + if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
507 + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
508 + ctrl &= ~TIMER_ENABLE_EN;
509 + writel_relaxed(ctrl, event_base + TIMER_ENABLE);
510 + }
511 + evt->event_handler(evt);
512 + return IRQ_HANDLED;
513 +}
514 +
515 +static int msm_timer_set_next_event(unsigned long cycles,
516 + struct clock_event_device *evt)
517 +{
518 + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
519 +
520 + ctrl &= ~TIMER_ENABLE_EN;
521 + writel_relaxed(ctrl, event_base + TIMER_ENABLE);
522 +
523 + writel_relaxed(ctrl, event_base + TIMER_CLEAR);
524 + writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
525 +
526 + if (sts_base)
527 + while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
528 + cpu_relax();
529 +
530 + writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
531 + return 0;
532 +}
533 +
534 +static void msm_timer_set_mode(enum clock_event_mode mode,
535 + struct clock_event_device *evt)
536 +{
537 + u32 ctrl;
538 +
539 + ctrl = readl_relaxed(event_base + TIMER_ENABLE);
540 + ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
541 +
542 + switch (mode) {
543 + case CLOCK_EVT_MODE_RESUME:
544 + case CLOCK_EVT_MODE_PERIODIC:
545 + break;
546 + case CLOCK_EVT_MODE_ONESHOT:
547 + /* Timer is enabled in set_next_event */
548 + break;
549 + case CLOCK_EVT_MODE_UNUSED:
550 + case CLOCK_EVT_MODE_SHUTDOWN:
551 + break;
552 + }
553 + writel_relaxed(ctrl, event_base + TIMER_ENABLE);
554 +}
555 +
556 +static struct clock_event_device __percpu *msm_evt;
557 +
558 +static void __iomem *source_base;
559 +
560 +static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
561 +{
562 + return readl_relaxed(source_base + TIMER_COUNT_VAL);
563 +}
564 +
565 +static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
566 +{
567 + /*
568 + * Shift timer count down by a constant due to unreliable lower bits
569 + * on some targets.
570 + */
571 + return msm_read_timer_count(cs) >> MSM_DGT_SHIFT;
572 +}
573 +
574 +static struct clocksource msm_clocksource = {
575 + .name = "dg_timer",
576 + .rating = 300,
577 + .read = msm_read_timer_count,
578 + .mask = CLOCKSOURCE_MASK(32),
579 + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
580 +};
581 +
582 +static int msm_timer_irq;
583 +static int msm_timer_has_ppi;
584 +
585 +static int msm_local_timer_setup(struct clock_event_device *evt)
586 +{
587 + int cpu = smp_processor_id();
588 + int err;
589 +
590 + evt->irq = msm_timer_irq;
591 + evt->name = "msm_timer";
592 + evt->features = CLOCK_EVT_FEAT_ONESHOT;
593 + evt->rating = 200;
594 + evt->set_mode = msm_timer_set_mode;
595 + evt->set_next_event = msm_timer_set_next_event;
596 + evt->cpumask = cpumask_of(cpu);
597 +
598 + clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff);
599 +
600 + if (msm_timer_has_ppi) {
601 + enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
602 + } else {
603 + err = request_irq(evt->irq, msm_timer_interrupt,
604 + IRQF_TIMER | IRQF_NOBALANCING |
605 + IRQF_TRIGGER_RISING, "gp_timer", evt);
606 + if (err)
607 + pr_err("request_irq failed\n");
608 + }
609 +
610 + return 0;
611 +}
612 +
613 +static void msm_local_timer_stop(struct clock_event_device *evt)
614 +{
615 + evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
616 + disable_percpu_irq(evt->irq);
617 +}
618 +
619 +static int msm_timer_cpu_notify(struct notifier_block *self,
620 + unsigned long action, void *hcpu)
621 +{
622 + /*
623 + * Grab cpu pointer in each case to avoid spurious
624 + * preemptible warnings
625 + */
626 + switch (action & ~CPU_TASKS_FROZEN) {
627 + case CPU_STARTING:
628 + msm_local_timer_setup(this_cpu_ptr(msm_evt));
629 + break;
630 + case CPU_DYING:
631 + msm_local_timer_stop(this_cpu_ptr(msm_evt));
632 + break;
633 + }
634 +
635 + return NOTIFY_OK;
636 +}
637 +
638 +static struct notifier_block msm_timer_cpu_nb = {
639 + .notifier_call = msm_timer_cpu_notify,
640 +};
641 +
642 +static u64 notrace msm_sched_clock_read(void)
643 +{
644 + return msm_clocksource.read(&msm_clocksource);
645 +}
646 +
647 +static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
648 + bool percpu)
649 +{
650 + struct clocksource *cs = &msm_clocksource;
651 + int res = 0;
652 +
653 + msm_timer_irq = irq;
654 + msm_timer_has_ppi = percpu;
655 +
656 + msm_evt = alloc_percpu(struct clock_event_device);
657 + if (!msm_evt) {
658 + pr_err("memory allocation failed for clockevents\n");
659 + goto err;
660 + }
661 +
662 + if (percpu)
663 + res = request_percpu_irq(irq, msm_timer_interrupt,
664 + "gp_timer", msm_evt);
665 +
666 + if (res) {
667 + pr_err("request_percpu_irq failed\n");
668 + } else {
669 + res = register_cpu_notifier(&msm_timer_cpu_nb);
670 + if (res) {
671 + free_percpu_irq(irq, msm_evt);
672 + goto err;
673 + }
674 +
675 + /* Immediately configure the timer on the boot CPU */
676 + msm_local_timer_setup(__this_cpu_ptr(msm_evt));
677 + }
678 +
679 +err:
680 + writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE);
681 + res = clocksource_register_hz(cs, dgt_hz);
682 + if (res)
683 + pr_err("clocksource_register failed\n");
684 + sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
685 +}
686 +
687 +#ifdef CONFIG_OF
688 +static void __init msm_dt_timer_init(struct device_node *np)
689 +{
690 + u32 freq;
691 + int irq;
692 + struct resource res;
693 + u32 percpu_offset;
694 + void __iomem *base;
695 + void __iomem *cpu0_base;
696 +
697 + base = of_iomap(np, 0);
698 + if (!base) {
699 + pr_err("Failed to map event base\n");
700 + return;
701 + }
702 +
703 + /* We use GPT0 for the clockevent */
704 + irq = irq_of_parse_and_map(np, 1);
705 + if (irq <= 0) {
706 + pr_err("Can't get irq\n");
707 + return;
708 + }
709 +
710 + /* We use CPU0's DGT for the clocksource */
711 + if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
712 + percpu_offset = 0;
713 +
714 + if (of_address_to_resource(np, 0, &res)) {
715 + pr_err("Failed to parse DGT resource\n");
716 + return;
717 + }
718 +
719 + cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res));
720 + if (!cpu0_base) {
721 + pr_err("Failed to map source base\n");
722 + return;
723 + }
724 +
725 + if (of_property_read_u32(np, "clock-frequency", &freq)) {
726 + pr_err("Unknown frequency\n");
727 + return;
728 + }
729 +
730 + event_base = base + 0x4;
731 + sts_base = base + 0x88;
732 + source_base = cpu0_base + 0x24;
733 + freq /= 4;
734 + writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
735 +
736 + msm_timer_init(freq, 32, irq, !!percpu_offset);
737 +}
738 +CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
739 +CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
740 +#endif
741 +
742 +static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
743 + u32 sts)
744 +{
745 + void __iomem *base;
746 +
747 + base = ioremap(addr, SZ_256);
748 + if (!base) {
749 + pr_err("Failed to map timer base\n");
750 + return -ENOMEM;
751 + }
752 + event_base = base + event;
753 + source_base = base + source;
754 + if (sts)
755 + sts_base = base + sts;
756 +
757 + return 0;
758 +}
759 +
760 +void __init msm7x01_timer_init(void)
761 +{
762 + struct clocksource *cs = &msm_clocksource;
763 +
764 + if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0))
765 + return;
766 + cs->read = msm_read_timer_count_shift;
767 + cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
768 + /* 600 KHz */
769 + msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7,
770 + false);
771 +}
772 +
773 +void __init msm7x30_timer_init(void)
774 +{
775 + if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
776 + return;
777 + msm_timer_init(24576000 / 4, 32, 1, false);
778 +}
779 +
780 +void __init qsd8x50_timer_init(void)
781 +{
782 + if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
783 + return;
784 + msm_timer_init(19200000 / 4, 32, 7, false);
785 +}
786 --
787 1.7.10.4
788