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>
45 #include <asm/mach/time.h>
46 #include <asm/smp_twd.h>
47 #include <asm/sched_clock.h>
49 #include <asm/arch_timer.h>
50 #include "omap_hwmod.h"
51 #include "omap_device.h"
52 #include <plat/counter-32k.h>
53 #include <plat/dmtimer.h>
54 #include "omap-pm.h"
56 #include "soc.h"
57 #include "common.h"
58 #include "powerdomain.h"
60 /* Parent clocks, eventually these will come from the clock framework */
62 #define OMAP2_MPU_SOURCE "sys_ck"
63 #define OMAP3_MPU_SOURCE OMAP2_MPU_SOURCE
64 #define OMAP4_MPU_SOURCE "sys_clkin_ck"
65 #define OMAP5_MPU_SOURCE "sys_clkin"
66 #define OMAP2_32K_SOURCE "func_32k_ck"
67 #define OMAP3_32K_SOURCE "omap_32k_fck"
68 #define OMAP4_32K_SOURCE "sys_32k_ck"
70 #define REALTIME_COUNTER_BASE 0x48243200
71 #define INCREMENTER_NUMERATOR_OFFSET 0x10
72 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14
73 #define NUMERATOR_DENUMERATOR_MASK 0xfffff000
75 /* Clockevent code */
77 static struct omap_dm_timer clkev;
78 static struct clock_event_device clockevent_gpt;
80 static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
81 {
82 struct clock_event_device *evt = &clockevent_gpt;
84 __omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
86 evt->event_handler(evt);
87 return IRQ_HANDLED;
88 }
90 static struct irqaction omap2_gp_timer_irq = {
91 .name = "gp_timer",
92 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
93 .handler = omap2_gp_timer_interrupt,
94 };
96 static int omap2_gp_timer_set_next_event(unsigned long cycles,
97 struct clock_event_device *evt)
98 {
99 __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
100 0xffffffff - cycles, OMAP_TIMER_POSTED);
102 return 0;
103 }
105 static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
106 struct clock_event_device *evt)
107 {
108 u32 period;
110 __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
112 switch (mode) {
113 case CLOCK_EVT_MODE_PERIODIC:
114 period = clkev.rate / HZ;
115 period -= 1;
116 /* Looks like we need to first set the load value separately */
117 __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
118 0xffffffff - period, OMAP_TIMER_POSTED);
119 __omap_dm_timer_load_start(&clkev,
120 OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
121 0xffffffff - period, OMAP_TIMER_POSTED);
122 break;
123 case CLOCK_EVT_MODE_ONESHOT:
124 break;
125 case CLOCK_EVT_MODE_UNUSED:
126 case CLOCK_EVT_MODE_SHUTDOWN:
127 case CLOCK_EVT_MODE_RESUME:
128 break;
129 }
130 }
132 static void omap_clkevt_suspend(struct clock_event_device *unused)
133 {
134 char name[10];
135 struct omap_hwmod *oh;
137 sprintf(name, "timer%d", clkev.id);
138 oh = omap_hwmod_lookup(name);
139 if (!oh)
140 return;
142 __omap_dm_timer_stop(&clkev, 1, clkev.rate);
143 omap_hwmod_idle(oh);
144 }
146 static void omap_clkevt_resume(struct clock_event_device *unused)
147 {
148 char name[10];
149 struct omap_hwmod *oh;
151 sprintf(name, "timer%d", clkev.id);
152 oh = omap_hwmod_lookup(name);
153 if (!oh)
154 return;
156 omap_hwmod_enable(oh);
157 __omap_dm_timer_load_start(&clkev,
158 OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
159 __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
160 }
162 static struct clock_event_device clockevent_gpt = {
163 .name = "gp_timer",
164 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
165 .shift = 32,
166 .rating = 300,
167 .set_next_event = omap2_gp_timer_set_next_event,
168 .set_mode = omap2_gp_timer_set_mode,
169 .suspend = omap_clkevt_suspend,
170 .resume = omap_clkevt_resume,
171 };
173 static struct property device_disabled = {
174 .name = "status",
175 .length = sizeof("disabled"),
176 .value = "disabled",
177 };
179 static struct of_device_id omap_timer_match[] __initdata = {
180 { .compatible = "ti,omap2-timer", },
181 { }
182 };
184 /**
185 * omap_get_timer_dt - get a timer using device-tree
186 * @match - device-tree match structure for matching a device type
187 * @property - optional timer property to match
188 *
189 * Helper function to get a timer during early boot using device-tree for use
190 * as kernel system timer. Optionally, the property argument can be used to
191 * select a timer with a specific property. Once a timer is found then mark
192 * the timer node in device-tree as disabled, to prevent the kernel from
193 * registering this timer as a platform device and so no one else can use it.
194 */
195 static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
196 const char *property)
197 {
198 struct device_node *np;
200 for_each_matching_node(np, match) {
201 if (!of_device_is_available(np))
202 continue;
204 if (property && !of_get_property(np, property, NULL))
205 continue;
207 of_add_property(np, &device_disabled);
208 return np;
209 }
211 return NULL;
212 }
214 /**
215 * omap_dmtimer_init - initialisation function when device tree is used
216 *
217 * For secure OMAP3 devices, timers with device type "timer-secure" cannot
218 * be used by the kernel as they are reserved. Therefore, to prevent the
219 * kernel registering these devices remove them dynamically from the device
220 * tree on boot.
221 */
222 static void __init omap_dmtimer_init(void)
223 {
224 struct device_node *np;
226 if (!cpu_is_omap34xx())
227 return;
229 /* If we are a secure device, remove any secure timer nodes */
230 if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) {
231 np = omap_get_timer_dt(omap_timer_match, "ti,timer-secure");
232 if (np)
233 of_node_put(np);
234 }
235 }
237 /**
238 * omap_dm_timer_get_errata - get errata flags for a timer
239 *
240 * Get the timer errata flags that are specific to the OMAP device being used.
241 */
242 static u32 __init omap_dm_timer_get_errata(void)
243 {
244 if (cpu_is_omap24xx())
245 return 0;
247 return OMAP_TIMER_ERRATA_I103_I767;
248 }
250 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
251 int gptimer_id,
252 const char *fck_source,
253 const char *property,
254 int posted)
255 {
256 char name[10]; /* 10 = sizeof("gptXX_Xck0") */
257 const char *oh_name;
258 struct device_node *np;
259 struct omap_hwmod *oh;
260 struct resource irq, mem;
261 int r = 0;
263 if (of_have_populated_dt()) {
264 np = omap_get_timer_dt(omap_timer_match, property);
265 if (!np)
266 return -ENODEV;
268 of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
269 if (!oh_name)
270 return -ENODEV;
272 timer->irq = irq_of_parse_and_map(np, 0);
273 if (!timer->irq)
274 return -ENXIO;
276 timer->io_base = of_iomap(np, 0);
278 of_node_put(np);
279 } else {
280 if (omap_dm_timer_reserve_systimer(gptimer_id))
281 return -ENODEV;
283 sprintf(name, "timer%d", gptimer_id);
284 oh_name = name;
285 }
287 oh = omap_hwmod_lookup(oh_name);
288 if (!oh)
289 return -ENODEV;
291 if (!of_have_populated_dt()) {
292 r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL,
293 &irq);
294 if (r)
295 return -ENXIO;
296 timer->irq = irq.start;
298 r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL,
299 &mem);
300 if (r)
301 return -ENXIO;
303 /* Static mapping, never released */
304 timer->io_base = ioremap(mem.start, mem.end - mem.start);
305 }
307 if (!timer->io_base)
308 return -ENXIO;
310 /* After the dmtimer is using hwmod these clocks won't be needed */
311 timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
312 if (IS_ERR(timer->fclk))
313 return -ENODEV;
315 /* FIXME: Need to remove hard-coded test on timer ID */
316 if (gptimer_id != 12) {
317 struct clk *src;
319 src = clk_get(NULL, fck_source);
320 if (IS_ERR(src)) {
321 r = -EINVAL;
322 } else {
323 r = clk_set_parent(timer->fclk, src);
324 if (IS_ERR_VALUE(r))
325 pr_warn("%s: %s cannot set source\n",
326 __func__, oh->name);
327 clk_put(src);
328 }
329 }
331 omap_hwmod_setup_one(oh_name);
332 omap_hwmod_enable(oh);
333 __omap_dm_timer_init_regs(timer);
335 if (posted)
336 __omap_dm_timer_enable_posted(timer);
338 /* Check that the intended posted configuration matches the actual */
339 if (posted != timer->posted)
340 return -EINVAL;
342 timer->rate = clk_get_rate(timer->fclk);
343 timer->reserved = 1;
345 return r;
346 }
348 static void __init omap2_gp_clockevent_init(int gptimer_id,
349 const char *fck_source,
350 const char *property)
351 {
352 int res;
354 clkev.errata = omap_dm_timer_get_errata();
355 clkev.id = gptimer_id;
357 /*
358 * For clock-event timers we never read the timer counter and
359 * so we are not impacted by errata i103 and i767. Therefore,
360 * we can safely ignore this errata for clock-event timers.
361 */
362 __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
364 res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
365 OMAP_TIMER_POSTED);
366 BUG_ON(res);
368 omap2_gp_timer_irq.dev_id = &clkev;
369 setup_irq(clkev.irq, &omap2_gp_timer_irq);
371 __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
373 clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
374 clockevent_gpt.shift);
375 clockevent_gpt.max_delta_ns =
376 clockevent_delta2ns(0xffffffff, &clockevent_gpt);
377 clockevent_gpt.min_delta_ns =
378 clockevent_delta2ns(3, &clockevent_gpt);
379 /* Timer internal resynch latency. */
381 clockevent_gpt.cpumask = cpu_possible_mask;
382 clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev);
383 clockevents_register_device(&clockevent_gpt);
385 pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
386 gptimer_id, clkev.rate);
387 }
389 /* Clocksource code */
390 static struct omap_dm_timer clksrc;
391 static bool use_gptimer_clksrc;
393 /*
394 * clocksource
395 */
396 static cycle_t clocksource_read_cycles(struct clocksource *cs)
397 {
398 return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
399 OMAP_TIMER_NONPOSTED);
400 }
402 static struct clocksource clocksource_gpt = {
403 .name = "gp_timer",
404 .rating = 300,
405 .read = clocksource_read_cycles,
406 .mask = CLOCKSOURCE_MASK(32),
407 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
408 };
410 static u32 notrace dmtimer_read_sched_clock(void)
411 {
412 if (clksrc.reserved)
413 return __omap_dm_timer_read_counter(&clksrc,
414 OMAP_TIMER_NONPOSTED);
416 return 0;
417 }
419 static struct of_device_id omap_counter_match[] __initdata = {
420 { .compatible = "ti,omap-counter32k", },
421 { }
422 };
424 /* Setup free-running counter for clocksource */
425 static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
426 {
427 int ret;
428 struct device_node *np = NULL;
429 struct omap_hwmod *oh;
430 void __iomem *vbase;
431 const char *oh_name = "counter_32k";
433 /*
434 * If device-tree is present, then search the DT blob
435 * to see if the 32kHz counter is supported.
436 */
437 if (of_have_populated_dt()) {
438 np = omap_get_timer_dt(omap_counter_match, NULL);
439 if (!np)
440 return -ENODEV;
442 of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
443 if (!oh_name)
444 return -ENODEV;
445 }
447 /*
448 * First check hwmod data is available for sync32k counter
449 */
450 oh = omap_hwmod_lookup(oh_name);
451 if (!oh || oh->slaves_cnt == 0)
452 return -ENODEV;
454 omap_hwmod_setup_one(oh_name);
456 if (np) {
457 vbase = of_iomap(np, 0);
458 of_node_put(np);
459 } else {
460 vbase = omap_hwmod_get_mpu_rt_va(oh);
461 }
463 if (!vbase) {
464 pr_warn("%s: failed to get counter_32k resource\n", __func__);
465 return -ENXIO;
466 }
468 ret = omap_hwmod_enable(oh);
469 if (ret) {
470 pr_warn("%s: failed to enable counter_32k module (%d)\n",
471 __func__, ret);
472 return ret;
473 }
475 ret = omap_init_clocksource_32k(vbase);
476 if (ret) {
477 pr_warn("%s: failed to initialize counter_32k as a clocksource (%d)\n",
478 __func__, ret);
479 omap_hwmod_idle(oh);
480 }
482 return ret;
483 }
485 static void __init omap2_gptimer_clocksource_init(int gptimer_id,
486 const char *fck_source)
487 {
488 int res;
490 clksrc.errata = omap_dm_timer_get_errata();
492 res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
493 OMAP_TIMER_NONPOSTED);
494 BUG_ON(res);
496 __omap_dm_timer_load_start(&clksrc,
497 OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
498 OMAP_TIMER_NONPOSTED);
499 setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
501 if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
502 pr_err("Could not register clocksource %s\n",
503 clocksource_gpt.name);
504 else
505 pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
506 gptimer_id, clksrc.rate);
507 }
509 #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
510 /*
511 * The realtime counter also called master counter, is a free-running
512 * counter, which is related to real time. It produces the count used
513 * by the CPU local timer peripherals in the MPU cluster. The timer counts
514 * at a rate of 6.144 MHz. Because the device operates on different clocks
515 * in different power modes, the master counter shifts operation between
516 * clocks, adjusting the increment per clock in hardware accordingly to
517 * maintain a constant count rate.
518 */
519 static void __init realtime_counter_init(void)
520 {
521 void __iomem *base;
522 static struct clk *sys_clk;
523 unsigned long rate;
524 unsigned int reg, num, den;
526 base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
527 if (!base) {
528 pr_err("%s: ioremap failed\n", __func__);
529 return;
530 }
531 sys_clk = clk_get(NULL, OMAP5_MPU_SOURCE);
532 if (IS_ERR(sys_clk)) {
533 pr_err("%s: failed to get system clock handle\n", __func__);
534 iounmap(base);
535 return;
536 }
538 rate = clk_get_rate(sys_clk);
539 /* Numerator/denumerator values refer TRM Realtime Counter section */
540 switch (rate) {
541 case 1200000:
542 num = 64;
543 den = 125;
544 break;
545 case 1300000:
546 num = 768;
547 den = 1625;
548 break;
549 case 19200000:
550 num = 8;
551 den = 25;
552 break;
553 case 2600000:
554 num = 384;
555 den = 1625;
556 break;
557 case 2700000:
558 num = 256;
559 den = 1125;
560 break;
561 case 38400000:
562 default:
563 /* Program it for 38.4 MHz */
564 num = 4;
565 den = 25;
566 break;
567 }
569 /* Program numerator and denumerator registers */
570 reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) &
571 NUMERATOR_DENUMERATOR_MASK;
572 reg |= num;
573 __raw_writel(reg, base + INCREMENTER_NUMERATOR_OFFSET);
575 reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) &
576 NUMERATOR_DENUMERATOR_MASK;
577 reg |= den;
578 __raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
580 iounmap(base);
581 }
582 #else
583 static inline void __init realtime_counter_init(void)
584 {}
585 #endif
587 #define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
588 clksrc_nr, clksrc_src) \
589 static void __init omap##name##_gptimer_timer_init(void) \
590 { \
591 omap_dmtimer_init(); \
592 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \
593 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src); \
594 }
596 #define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
597 clksrc_nr, clksrc_src) \
598 static void __init omap##name##_sync32k_timer_init(void) \
599 { \
600 omap_dmtimer_init(); \
601 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \
602 /* Enable the use of clocksource="gp_timer" kernel parameter */ \
603 if (use_gptimer_clksrc) \
604 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);\
605 else \
606 omap2_sync32k_clocksource_init(); \
607 }
609 #define OMAP_SYS_TIMER(name, clksrc) \
610 struct sys_timer omap##name##_timer = { \
611 .init = omap##name##_##clksrc##_timer_init, \
612 };
614 #ifdef CONFIG_ARCH_OMAP2
615 OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon",
616 2, OMAP2_MPU_SOURCE);
617 OMAP_SYS_TIMER(2, sync32k);
618 #endif /* CONFIG_ARCH_OMAP2 */
620 #ifdef CONFIG_ARCH_OMAP3
621 OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon",
622 2, OMAP3_MPU_SOURCE);
623 OMAP_SYS_TIMER(3, sync32k);
624 OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure",
625 2, OMAP3_MPU_SOURCE);
626 OMAP_SYS_TIMER(3_secure, sync32k);
627 OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon",
628 2, OMAP3_MPU_SOURCE);
629 OMAP_SYS_TIMER(3_gp, gptimer);
630 #endif /* CONFIG_ARCH_OMAP3 */
632 #ifdef CONFIG_SOC_AM33XX
633 OMAP_SYS_GP_TIMER_INIT(3_am33xx, 2, OMAP4_MPU_SOURCE, "ti,timer-non-wkup",
634 1, OMAP4_MPU_SOURCE);
635 OMAP_SYS_TIMER(3_am33xx, gptimer);
636 #endif /* CONFIG_SOC_AM33XX */
638 #ifdef CONFIG_ARCH_OMAP4
639 OMAP_SYS_32K_TIMER_INIT(4, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
640 2, OMAP4_MPU_SOURCE);
641 #ifdef CONFIG_LOCAL_TIMERS
642 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
643 static void __init omap4_local_timer_init(void)
644 {
645 omap4_sync32k_timer_init();
646 /* Local timers are not supprted on OMAP4430 ES1.0 */
647 if (omap_rev() != OMAP4430_REV_ES1_0) {
648 int err;
650 if (of_have_populated_dt()) {
651 twd_local_timer_of_register();
652 return;
653 }
655 err = twd_local_timer_register(&twd_local_timer);
656 if (err)
657 pr_err("twd_local_timer_register failed %d\n", err);
658 }
659 }
660 #else /* CONFIG_LOCAL_TIMERS */
661 static void __init omap4_local_timer_init(void)
662 {
663 omap4_sync32k_timer_init();
664 }
665 #endif /* CONFIG_LOCAL_TIMERS */
666 OMAP_SYS_TIMER(4, local);
667 #endif /* CONFIG_ARCH_OMAP4 */
669 #if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
670 OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
671 2, OMAP5_MPU_SOURCE);
672 static void __init omap5_realtime_timer_init(void)
673 {
674 int err;
676 omap5_sync32k_timer_init();
677 realtime_counter_init();
679 err = arch_timer_of_register();
680 if (err)
681 pr_err("%s: arch_timer_register failed %d\n", __func__, err);
682 }
683 OMAP_SYS_TIMER(5, realtime);
684 #endif /* CONFIG_SOC_OMAP5 */
686 /**
687 * omap_timer_init - build and register timer device with an
688 * associated timer hwmod
689 * @oh: timer hwmod pointer to be used to build timer device
690 * @user: parameter that can be passed from calling hwmod API
691 *
692 * Called by omap_hwmod_for_each_by_class to register each of the timer
693 * devices present in the system. The number of timer devices is known
694 * by parsing through the hwmod database for a given class name. At the
695 * end of function call memory is allocated for timer device and it is
696 * registered to the framework ready to be proved by the driver.
697 */
698 static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
699 {
700 int id;
701 int ret = 0;
702 char *name = "omap_timer";
703 struct dmtimer_platform_data *pdata;
704 struct platform_device *pdev;
705 struct omap_timer_capability_dev_attr *timer_dev_attr;
707 pr_debug("%s: %s\n", __func__, oh->name);
709 /* on secure device, do not register secure timer */
710 timer_dev_attr = oh->dev_attr;
711 if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
712 if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
713 return ret;
715 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
716 if (!pdata) {
717 pr_err("%s: No memory for [%s]\n", __func__, oh->name);
718 return -ENOMEM;
719 }
721 /*
722 * Extract the IDs from name field in hwmod database
723 * and use the same for constructing ids' for the
724 * timer devices. In a way, we are avoiding usage of
725 * static variable witin the function to do the same.
726 * CAUTION: We have to be careful and make sure the
727 * name in hwmod database does not change in which case
728 * we might either make corresponding change here or
729 * switch back static variable mechanism.
730 */
731 sscanf(oh->name, "timer%2d", &id);
733 if (timer_dev_attr)
734 pdata->timer_capability = timer_dev_attr->timer_capability;
736 pdata->timer_errata = omap_dm_timer_get_errata();
737 pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
739 pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
740 NULL, 0, 0);
742 if (IS_ERR(pdev)) {
743 pr_err("%s: Can't build omap_device for %s: %s.\n",
744 __func__, name, oh->name);
745 ret = -EINVAL;
746 }
748 kfree(pdata);
750 return ret;
751 }
753 /**
754 * omap2_dm_timer_init - top level regular device initialization
755 *
756 * Uses dedicated hwmod api to parse through hwmod database for
757 * given class name and then build and register the timer device.
758 */
759 static int __init omap2_dm_timer_init(void)
760 {
761 int ret;
763 /* If dtb is there, the devices will be created dynamically */
764 if (of_have_populated_dt())
765 return -ENODEV;
767 ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
768 if (unlikely(ret)) {
769 pr_err("%s: device registration failed.\n", __func__);
770 return -EINVAL;
771 }
773 return 0;
774 }
775 arch_initcall(omap2_dm_timer_init);
777 /**
778 * omap2_override_clocksource - clocksource override with user configuration
779 *
780 * Allows user to override default clocksource, using kernel parameter
781 * clocksource="gp_timer" (For all OMAP2PLUS architectures)
782 *
783 * Note that, here we are using same standard kernel parameter "clocksource=",
784 * and not introducing any OMAP specific interface.
785 */
786 static int __init omap2_override_clocksource(char *str)
787 {
788 if (!str)
789 return 0;
790 /*
791 * For OMAP architecture, we only have two options
792 * - sync_32k (default)
793 * - gp_timer (sys_clk based)
794 */
795 if (!strcmp(str, "gp_timer"))
796 use_gptimer_clksrc = true;
798 return 0;
799 }
800 early_param("clocksource", omap2_override_clocksource);