fd730c1e470494eb3500f8dd0b62fda5a54aed48
[openwrt.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