OMAP: CLK: CLKSRC: Add suspend resume hooks
[sfrench/cifs-2.6.git] / arch / arm / mach-omap2 / timer.c
1 /*
2  * linux/arch/arm/mach-omap2/timer.c
3  *
4  * OMAP2 GP timer support.
5  *
6  * Copyright (C) 2009 Nokia Corporation
7  *
8  * Update to use new clocksource/clockevent layers
9  * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
10  * Copyright (C) 2007 MontaVista Software, Inc.
11  *
12  * Original driver:
13  * Copyright (C) 2005 Nokia Corporation
14  * Author: Paul Mundt <paul.mundt@nokia.com>
15  *         Juha Yrjölä <juha.yrjola@nokia.com>
16  * OMAP Dual-mode timer framework support by Timo Teras
17  *
18  * Some parts based off of TI's 24xx code:
19  *
20  * Copyright (C) 2004-2009 Texas Instruments, Inc.
21  *
22  * Roughly modelled after the OMAP1 MPU timer code.
23  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
24  *
25  * This file is subject to the terms and conditions of the GNU General Public
26  * License. See the file "COPYING" in the main directory of this archive
27  * for more details.
28  */
29 #include <linux/init.h>
30 #include <linux/time.h>
31 #include <linux/interrupt.h>
32 #include <linux/err.h>
33 #include <linux/clk.h>
34 #include <linux/delay.h>
35 #include <linux/irq.h>
36 #include <linux/clocksource.h>
37 #include <linux/clockchips.h>
38 #include <linux/slab.h>
39 #include <linux/of.h>
40 #include <linux/of_address.h>
41 #include <linux/of_irq.h>
42 #include <linux/platform_device.h>
43 #include <linux/platform_data/dmtimer-omap.h>
44 #include <linux/sched_clock.h>
45
46 #include <asm/mach/time.h>
47 #include <asm/smp_twd.h>
48
49 #include "omap_hwmod.h"
50 #include "omap_device.h"
51 #include <plat/counter-32k.h>
52 #include <clocksource/timer-ti-dm.h>
53 #include "omap-pm.h"
54
55 #include "soc.h"
56 #include "common.h"
57 #include "control.h"
58 #include "powerdomain.h"
59 #include "omap-secure.h"
60
61 #define REALTIME_COUNTER_BASE                           0x48243200
62 #define INCREMENTER_NUMERATOR_OFFSET                    0x10
63 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET           0x14
64 #define NUMERATOR_DENUMERATOR_MASK                      0xfffff000
65
66 /* Clockevent code */
67
68 static struct omap_dm_timer clkev;
69 static struct clock_event_device clockevent_gpt;
70
71 /* Clockevent hwmod for am335x and am437x suspend */
72 static struct omap_hwmod *clockevent_gpt_hwmod;
73
74 /* Clockesource hwmod for am437x suspend */
75 static struct omap_hwmod *clocksource_gpt_hwmod;
76
77 #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
78 static unsigned long arch_timer_freq;
79
80 void set_cntfreq(void)
81 {
82         omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
83 }
84 #endif
85
86 static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
87 {
88         struct clock_event_device *evt = &clockevent_gpt;
89
90         __omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
91
92         evt->event_handler(evt);
93         return IRQ_HANDLED;
94 }
95
96 static struct irqaction omap2_gp_timer_irq = {
97         .name           = "gp_timer",
98         .flags          = IRQF_TIMER | IRQF_IRQPOLL,
99         .handler        = omap2_gp_timer_interrupt,
100 };
101
102 static int omap2_gp_timer_set_next_event(unsigned long cycles,
103                                          struct clock_event_device *evt)
104 {
105         __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
106                                    0xffffffff - cycles, OMAP_TIMER_POSTED);
107
108         return 0;
109 }
110
111 static int omap2_gp_timer_shutdown(struct clock_event_device *evt)
112 {
113         __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
114         return 0;
115 }
116
117 static int omap2_gp_timer_set_periodic(struct clock_event_device *evt)
118 {
119         u32 period;
120
121         __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
122
123         period = clkev.rate / HZ;
124         period -= 1;
125         /* Looks like we need to first set the load value separately */
126         __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, 0xffffffff - period,
127                               OMAP_TIMER_POSTED);
128         __omap_dm_timer_load_start(&clkev,
129                                    OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
130                                    0xffffffff - period, OMAP_TIMER_POSTED);
131         return 0;
132 }
133
134 static void omap_clkevt_idle(struct clock_event_device *unused)
135 {
136         if (!clockevent_gpt_hwmod)
137                 return;
138
139         omap_hwmod_idle(clockevent_gpt_hwmod);
140 }
141
142 static void omap_clkevt_unidle(struct clock_event_device *unused)
143 {
144         if (!clockevent_gpt_hwmod)
145                 return;
146
147         omap_hwmod_enable(clockevent_gpt_hwmod);
148         __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
149 }
150
151 static struct clock_event_device clockevent_gpt = {
152         .features               = CLOCK_EVT_FEAT_PERIODIC |
153                                   CLOCK_EVT_FEAT_ONESHOT,
154         .rating                 = 300,
155         .set_next_event         = omap2_gp_timer_set_next_event,
156         .set_state_shutdown     = omap2_gp_timer_shutdown,
157         .set_state_periodic     = omap2_gp_timer_set_periodic,
158         .set_state_oneshot      = omap2_gp_timer_shutdown,
159         .tick_resume            = omap2_gp_timer_shutdown,
160 };
161
162 static const struct of_device_id omap_timer_match[] __initconst = {
163         { .compatible = "ti,omap2420-timer", },
164         { .compatible = "ti,omap3430-timer", },
165         { .compatible = "ti,omap4430-timer", },
166         { .compatible = "ti,omap5430-timer", },
167         { .compatible = "ti,dm814-timer", },
168         { .compatible = "ti,dm816-timer", },
169         { .compatible = "ti,am335x-timer", },
170         { .compatible = "ti,am335x-timer-1ms", },
171         { }
172 };
173
174 /**
175  * omap_get_timer_dt - get a timer using device-tree
176  * @match       - device-tree match structure for matching a device type
177  * @property    - optional timer property to match
178  *
179  * Helper function to get a timer during early boot using device-tree for use
180  * as kernel system timer. Optionally, the property argument can be used to
181  * select a timer with a specific property. Once a timer is found then mark
182  * the timer node in device-tree as disabled, to prevent the kernel from
183  * registering this timer as a platform device and so no one else can use it.
184  */
185 static struct device_node * __init omap_get_timer_dt(const struct of_device_id *match,
186                                                      const char *property)
187 {
188         struct device_node *np;
189
190         for_each_matching_node(np, match) {
191                 if (!of_device_is_available(np))
192                         continue;
193
194                 if (property && !of_get_property(np, property, NULL))
195                         continue;
196
197                 if (!property && (of_get_property(np, "ti,timer-alwon", NULL) ||
198                                   of_get_property(np, "ti,timer-dsp", NULL) ||
199                                   of_get_property(np, "ti,timer-pwm", NULL) ||
200                                   of_get_property(np, "ti,timer-secure", NULL)))
201                         continue;
202
203                 if (!of_device_is_compatible(np, "ti,omap-counter32k")) {
204                         struct property *prop;
205
206                         prop = kzalloc(sizeof(*prop), GFP_KERNEL);
207                         if (!prop)
208                                 return NULL;
209                         prop->name = "status";
210                         prop->value = "disabled";
211                         prop->length = strlen(prop->value);
212                         of_add_property(np, prop);
213                 }
214                 return np;
215         }
216
217         return NULL;
218 }
219
220 /**
221  * omap_dmtimer_init - initialisation function when device tree is used
222  *
223  * For secure OMAP3/DRA7xx devices, timers with device type "timer-secure"
224  * cannot be used by the kernel as they are reserved. Therefore, to prevent the
225  * kernel registering these devices remove them dynamically from the device
226  * tree on boot.
227  */
228 static void __init omap_dmtimer_init(void)
229 {
230         struct device_node *np;
231
232         if (!cpu_is_omap34xx() && !soc_is_dra7xx())
233                 return;
234
235         /* If we are a secure device, remove any secure timer nodes */
236         if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) {
237                 np = omap_get_timer_dt(omap_timer_match, "ti,timer-secure");
238                 of_node_put(np);
239         }
240 }
241
242 /**
243  * omap_dm_timer_get_errata - get errata flags for a timer
244  *
245  * Get the timer errata flags that are specific to the OMAP device being used.
246  */
247 static u32 __init omap_dm_timer_get_errata(void)
248 {
249         if (cpu_is_omap24xx())
250                 return 0;
251
252         return OMAP_TIMER_ERRATA_I103_I767;
253 }
254
255 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
256                                          const char *fck_source,
257                                          const char *property,
258                                          const char **timer_name,
259                                          int posted)
260 {
261         const char *oh_name = NULL;
262         struct device_node *np;
263         struct omap_hwmod *oh;
264         struct clk *src;
265         int r = 0;
266
267         np = omap_get_timer_dt(omap_timer_match, property);
268         if (!np)
269                 return -ENODEV;
270
271         of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
272         if (!oh_name)
273                 return -ENODEV;
274
275         timer->irq = irq_of_parse_and_map(np, 0);
276         if (!timer->irq)
277                 return -ENXIO;
278
279         timer->io_base = of_iomap(np, 0);
280
281         timer->fclk = of_clk_get_by_name(np, "fck");
282
283         of_node_put(np);
284
285         oh = omap_hwmod_lookup(oh_name);
286         if (!oh)
287                 return -ENODEV;
288
289         *timer_name = oh->name;
290
291         if (!timer->io_base)
292                 return -ENXIO;
293
294         omap_hwmod_setup_one(oh_name);
295
296         /* After the dmtimer is using hwmod these clocks won't be needed */
297         if (IS_ERR_OR_NULL(timer->fclk))
298                 timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
299         if (IS_ERR(timer->fclk))
300                 return PTR_ERR(timer->fclk);
301
302         src = clk_get(NULL, fck_source);
303         if (IS_ERR(src))
304                 return PTR_ERR(src);
305
306         WARN(clk_set_parent(timer->fclk, src) < 0,
307              "Cannot set timer parent clock, no PLL clock driver?");
308
309         clk_put(src);
310
311         omap_hwmod_enable(oh);
312         __omap_dm_timer_init_regs(timer);
313
314         if (posted)
315                 __omap_dm_timer_enable_posted(timer);
316
317         /* Check that the intended posted configuration matches the actual */
318         if (posted != timer->posted)
319                 return -EINVAL;
320
321         timer->rate = clk_get_rate(timer->fclk);
322         timer->reserved = 1;
323
324         return r;
325 }
326
327 #if !defined(CONFIG_SMP) && defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
328 void tick_broadcast(const struct cpumask *mask)
329 {
330 }
331 #endif
332
333 static void __init omap2_gp_clockevent_init(int gptimer_id,
334                                                 const char *fck_source,
335                                                 const char *property)
336 {
337         int res;
338
339         clkev.id = gptimer_id;
340         clkev.errata = omap_dm_timer_get_errata();
341
342         /*
343          * For clock-event timers we never read the timer counter and
344          * so we are not impacted by errata i103 and i767. Therefore,
345          * we can safely ignore this errata for clock-event timers.
346          */
347         __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
348
349         res = omap_dm_timer_init_one(&clkev, fck_source, property,
350                                      &clockevent_gpt.name, OMAP_TIMER_POSTED);
351         BUG_ON(res);
352
353         omap2_gp_timer_irq.dev_id = &clkev;
354         setup_irq(clkev.irq, &omap2_gp_timer_irq);
355
356         __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
357
358         clockevent_gpt.cpumask = cpu_possible_mask;
359         clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev);
360         clockevents_config_and_register(&clockevent_gpt, clkev.rate,
361                                         3, /* Timer internal resynch latency */
362                                         0xffffffff);
363
364         if (soc_is_am33xx() || soc_is_am43xx()) {
365                 clockevent_gpt.suspend = omap_clkevt_idle;
366                 clockevent_gpt.resume = omap_clkevt_unidle;
367
368                 clockevent_gpt_hwmod =
369                         omap_hwmod_lookup(clockevent_gpt.name);
370         }
371
372         pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,
373                 clkev.rate);
374 }
375
376 /* Clocksource code */
377 static struct omap_dm_timer clksrc;
378 static bool use_gptimer_clksrc __initdata;
379
380 /*
381  * clocksource
382  */
383 static u64 clocksource_read_cycles(struct clocksource *cs)
384 {
385         return (u64)__omap_dm_timer_read_counter(&clksrc,
386                                                      OMAP_TIMER_NONPOSTED);
387 }
388
389 static struct clocksource clocksource_gpt = {
390         .rating         = 300,
391         .read           = clocksource_read_cycles,
392         .mask           = CLOCKSOURCE_MASK(32),
393         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
394 };
395
396 static u64 notrace dmtimer_read_sched_clock(void)
397 {
398         if (clksrc.reserved)
399                 return __omap_dm_timer_read_counter(&clksrc,
400                                                     OMAP_TIMER_NONPOSTED);
401
402         return 0;
403 }
404
405 static const struct of_device_id omap_counter_match[] __initconst = {
406         { .compatible = "ti,omap-counter32k", },
407         { }
408 };
409
410 /* Setup free-running counter for clocksource */
411 static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
412 {
413         int ret;
414         struct device_node *np = NULL;
415         struct omap_hwmod *oh;
416         const char *oh_name = "counter_32k";
417
418         /*
419          * See if the 32kHz counter is supported.
420          */
421         np = omap_get_timer_dt(omap_counter_match, NULL);
422         if (!np)
423                 return -ENODEV;
424
425         of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
426         if (!oh_name)
427                 return -ENODEV;
428
429         /*
430          * First check hwmod data is available for sync32k counter
431          */
432         oh = omap_hwmod_lookup(oh_name);
433         if (!oh || oh->slaves_cnt == 0)
434                 return -ENODEV;
435
436         omap_hwmod_setup_one(oh_name);
437
438         ret = omap_hwmod_enable(oh);
439         if (ret) {
440                 pr_warn("%s: failed to enable counter_32k module (%d)\n",
441                                                         __func__, ret);
442                 return ret;
443         }
444
445         return ret;
446 }
447
448 static unsigned int omap2_gptimer_clksrc_load;
449
450 static void omap2_gptimer_clksrc_suspend(struct clocksource *unused)
451 {
452         omap2_gptimer_clksrc_load =
453                 __omap_dm_timer_read_counter(&clksrc, OMAP_TIMER_NONPOSTED);
454
455         omap_hwmod_idle(clocksource_gpt_hwmod);
456 }
457
458 static void omap2_gptimer_clksrc_resume(struct clocksource *unused)
459 {
460         omap_hwmod_enable(clocksource_gpt_hwmod);
461
462         __omap_dm_timer_load_start(&clksrc,
463                                    OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
464                                    omap2_gptimer_clksrc_load,
465                                    OMAP_TIMER_NONPOSTED);
466 }
467
468 static void __init omap2_gptimer_clocksource_init(int gptimer_id,
469                                                   const char *fck_source,
470                                                   const char *property)
471 {
472         int res;
473
474         clksrc.id = gptimer_id;
475         clksrc.errata = omap_dm_timer_get_errata();
476
477         res = omap_dm_timer_init_one(&clksrc, fck_source, property,
478                                      &clocksource_gpt.name,
479                                      OMAP_TIMER_NONPOSTED);
480
481         if (soc_is_am43xx()) {
482                 clocksource_gpt.suspend = omap2_gptimer_clksrc_suspend;
483                 clocksource_gpt.resume = omap2_gptimer_clksrc_resume;
484
485                 clocksource_gpt_hwmod =
486                         omap_hwmod_lookup(clocksource_gpt.name);
487         }
488
489         BUG_ON(res);
490
491         __omap_dm_timer_load_start(&clksrc,
492                                    OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
493                                    OMAP_TIMER_NONPOSTED);
494         sched_clock_register(dmtimer_read_sched_clock, 32, clksrc.rate);
495
496         if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
497                 pr_err("Could not register clocksource %s\n",
498                         clocksource_gpt.name);
499         else
500                 pr_info("OMAP clocksource: %s at %lu Hz\n",
501                         clocksource_gpt.name, clksrc.rate);
502 }
503
504 static void __init __omap_sync32k_timer_init(int clkev_nr, const char *clkev_src,
505                 const char *clkev_prop, int clksrc_nr, const char *clksrc_src,
506                 const char *clksrc_prop, bool gptimer)
507 {
508         omap_clk_init();
509         omap_dmtimer_init();
510         omap2_gp_clockevent_init(clkev_nr, clkev_src, clkev_prop);
511
512         /* Enable the use of clocksource="gp_timer" kernel parameter */
513         if (use_gptimer_clksrc || gptimer)
514                 omap2_gptimer_clocksource_init(clksrc_nr, clksrc_src,
515                                                 clksrc_prop);
516         else
517                 omap2_sync32k_clocksource_init();
518 }
519
520 void __init omap_init_time(void)
521 {
522         __omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
523                         2, "timer_sys_ck", NULL, false);
524
525         timer_probe();
526 }
527
528 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX)
529 void __init omap3_secure_sync32k_timer_init(void)
530 {
531         __omap_sync32k_timer_init(12, "secure_32k_fck", "ti,timer-secure",
532                         2, "timer_sys_ck", NULL, false);
533
534         timer_probe();
535 }
536 #endif /* CONFIG_ARCH_OMAP3 */
537
538 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
539         defined(CONFIG_SOC_AM43XX)
540 void __init omap3_gptimer_timer_init(void)
541 {
542         __omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
543                         1, "timer_sys_ck", "ti,timer-alwon", true);
544         if (of_have_populated_dt())
545                 timer_probe();
546 }
547 #endif
548
549 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) ||          \
550         defined(CONFIG_SOC_DRA7XX)
551 static void __init omap4_sync32k_timer_init(void)
552 {
553         __omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
554                         2, "sys_clkin_ck", NULL, false);
555 }
556
557 void __init omap4_local_timer_init(void)
558 {
559         omap4_sync32k_timer_init();
560         timer_probe();
561 }
562 #endif
563
564 #if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
565
566 /*
567  * The realtime counter also called master counter, is a free-running
568  * counter, which is related to real time. It produces the count used
569  * by the CPU local timer peripherals in the MPU cluster. The timer counts
570  * at a rate of 6.144 MHz. Because the device operates on different clocks
571  * in different power modes, the master counter shifts operation between
572  * clocks, adjusting the increment per clock in hardware accordingly to
573  * maintain a constant count rate.
574  */
575 static void __init realtime_counter_init(void)
576 {
577 #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
578         void __iomem *base;
579         static struct clk *sys_clk;
580         unsigned long rate;
581         unsigned int reg;
582         unsigned long long num, den;
583
584         base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
585         if (!base) {
586                 pr_err("%s: ioremap failed\n", __func__);
587                 return;
588         }
589         sys_clk = clk_get(NULL, "sys_clkin");
590         if (IS_ERR(sys_clk)) {
591                 pr_err("%s: failed to get system clock handle\n", __func__);
592                 iounmap(base);
593                 return;
594         }
595
596         rate = clk_get_rate(sys_clk);
597
598         if (soc_is_dra7xx()) {
599                 /*
600                  * Errata i856 says the 32.768KHz crystal does not start at
601                  * power on, so the CPU falls back to an emulated 32KHz clock
602                  * based on sysclk / 610 instead. This causes the master counter
603                  * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
604                  * (OR sysclk * 75 / 244)
605                  *
606                  * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
607                  * Of course any board built without a populated 32.768KHz
608                  * crystal would also need this fix even if the CPU is fixed
609                  * later.
610                  *
611                  * Either case can be detected by using the two speedselect bits
612                  * If they are not 0, then the 32.768KHz clock driving the
613                  * coarse counter that corrects the fine counter every time it
614                  * ticks is actually rate/610 rather than 32.768KHz and we
615                  * should compensate to avoid the 570ppm (at 20MHz, much worse
616                  * at other rates) too fast system time.
617                  */
618                 reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
619                 if (reg & DRA7_SPEEDSELECT_MASK) {
620                         num = 75;
621                         den = 244;
622                         goto sysclk1_based;
623                 }
624         }
625
626         /* Numerator/denumerator values refer TRM Realtime Counter section */
627         switch (rate) {
628         case 12000000:
629                 num = 64;
630                 den = 125;
631                 break;
632         case 13000000:
633                 num = 768;
634                 den = 1625;
635                 break;
636         case 19200000:
637                 num = 8;
638                 den = 25;
639                 break;
640         case 20000000:
641                 num = 192;
642                 den = 625;
643                 break;
644         case 26000000:
645                 num = 384;
646                 den = 1625;
647                 break;
648         case 27000000:
649                 num = 256;
650                 den = 1125;
651                 break;
652         case 38400000:
653         default:
654                 /* Program it for 38.4 MHz */
655                 num = 4;
656                 den = 25;
657                 break;
658         }
659
660 sysclk1_based:
661         /* Program numerator and denumerator registers */
662         reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
663                         NUMERATOR_DENUMERATOR_MASK;
664         reg |= num;
665         writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
666
667         reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
668                         NUMERATOR_DENUMERATOR_MASK;
669         reg |= den;
670         writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
671
672         arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
673         set_cntfreq();
674
675         iounmap(base);
676 #endif
677 }
678
679 void __init omap5_realtime_timer_init(void)
680 {
681         omap4_sync32k_timer_init();
682         realtime_counter_init();
683
684         timer_probe();
685 }
686 #endif /* CONFIG_SOC_OMAP5 || CONFIG_SOC_DRA7XX */
687
688 /**
689  * omap2_override_clocksource - clocksource override with user configuration
690  *
691  * Allows user to override default clocksource, using kernel parameter
692  *   clocksource="gp_timer"     (For all OMAP2PLUS architectures)
693  *
694  * Note that, here we are using same standard kernel parameter "clocksource=",
695  * and not introducing any OMAP specific interface.
696  */
697 static int __init omap2_override_clocksource(char *str)
698 {
699         if (!str)
700                 return 0;
701         /*
702          * For OMAP architecture, we only have two options
703          *    - sync_32k (default)
704          *    - gp_timer (sys_clk based)
705          */
706         if (!strcmp(str, "gp_timer"))
707                 use_gptimer_clksrc = true;
708
709         return 0;
710 }
711 early_param("clocksource", omap2_override_clocksource);