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