aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r--arch/arm/mach-omap2/timer.c125
1 files changed, 64 insertions, 61 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 2bdd4cf17a8f..f12aa6c15da4 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -57,15 +57,6 @@
57#include "common.h" 57#include "common.h"
58#include "powerdomain.h" 58#include "powerdomain.h"
59 59
60/* Parent clocks, eventually these will come from the clock framework */
61
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 OMAP2_32K_SOURCE "func_32k_ck"
66#define OMAP3_32K_SOURCE "omap_32k_fck"
67#define OMAP4_32K_SOURCE "sys_32k_ck"
68
69#define REALTIME_COUNTER_BASE 0x48243200 60#define REALTIME_COUNTER_BASE 0x48243200
70#define INCREMENTER_NUMERATOR_OFFSET 0x10 61#define INCREMENTER_NUMERATOR_OFFSET 0x10
71#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14 62#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14
@@ -129,7 +120,6 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
129} 120}
130 121
131static struct clock_event_device clockevent_gpt = { 122static struct clock_event_device clockevent_gpt = {
132 .name = "gp_timer",
133 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 123 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
134 .rating = 300, 124 .rating = 300,
135 .set_next_event = omap2_gp_timer_set_next_event, 125 .set_next_event = omap2_gp_timer_set_next_event,
@@ -170,6 +160,12 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
170 if (property && !of_get_property(np, property, NULL)) 160 if (property && !of_get_property(np, property, NULL))
171 continue; 161 continue;
172 162
163 if (!property && (of_get_property(np, "ti,timer-alwon", NULL) ||
164 of_get_property(np, "ti,timer-dsp", NULL) ||
165 of_get_property(np, "ti,timer-pwm", NULL) ||
166 of_get_property(np, "ti,timer-secure", NULL)))
167 continue;
168
173 of_add_property(np, &device_disabled); 169 of_add_property(np, &device_disabled);
174 return np; 170 return np;
175 } 171 }
@@ -214,16 +210,17 @@ static u32 __init omap_dm_timer_get_errata(void)
214} 210}
215 211
216static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, 212static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
217 int gptimer_id, 213 const char *fck_source,
218 const char *fck_source, 214 const char *property,
219 const char *property, 215 const char **timer_name,
220 int posted) 216 int posted)
221{ 217{
222 char name[10]; /* 10 = sizeof("gptXX_Xck0") */ 218 char name[10]; /* 10 = sizeof("gptXX_Xck0") */
223 const char *oh_name; 219 const char *oh_name;
224 struct device_node *np; 220 struct device_node *np;
225 struct omap_hwmod *oh; 221 struct omap_hwmod *oh;
226 struct resource irq, mem; 222 struct resource irq, mem;
223 struct clk *src;
227 int r = 0; 224 int r = 0;
228 225
229 if (of_have_populated_dt()) { 226 if (of_have_populated_dt()) {
@@ -243,10 +240,10 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
243 240
244 of_node_put(np); 241 of_node_put(np);
245 } else { 242 } else {
246 if (omap_dm_timer_reserve_systimer(gptimer_id)) 243 if (omap_dm_timer_reserve_systimer(timer->id))
247 return -ENODEV; 244 return -ENODEV;
248 245
249 sprintf(name, "timer%d", gptimer_id); 246 sprintf(name, "timer%d", timer->id);
250 oh_name = name; 247 oh_name = name;
251 } 248 }
252 249
@@ -254,6 +251,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
254 if (!oh) 251 if (!oh)
255 return -ENODEV; 252 return -ENODEV;
256 253
254 *timer_name = oh->name;
255
257 if (!of_have_populated_dt()) { 256 if (!of_have_populated_dt()) {
258 r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, 257 r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL,
259 &irq); 258 &irq);
@@ -276,24 +275,24 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
276 /* After the dmtimer is using hwmod these clocks won't be needed */ 275 /* After the dmtimer is using hwmod these clocks won't be needed */
277 timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh)); 276 timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
278 if (IS_ERR(timer->fclk)) 277 if (IS_ERR(timer->fclk))
279 return -ENODEV; 278 return PTR_ERR(timer->fclk);
280 279
281 /* FIXME: Need to remove hard-coded test on timer ID */ 280 src = clk_get(NULL, fck_source);
282 if (gptimer_id != 12) { 281 if (IS_ERR(src))
283 struct clk *src; 282 return PTR_ERR(src);
284 283
285 src = clk_get(NULL, fck_source); 284 if (clk_get_parent(timer->fclk) != src) {
286 if (IS_ERR(src)) { 285 r = clk_set_parent(timer->fclk, src);
287 r = -EINVAL; 286 if (r < 0) {
288 } else { 287 pr_warn("%s: %s cannot set source\n", __func__,
289 r = clk_set_parent(timer->fclk, src); 288 oh->name);
290 if (IS_ERR_VALUE(r))
291 pr_warn("%s: %s cannot set source\n",
292 __func__, oh->name);
293 clk_put(src); 289 clk_put(src);
290 return r;
294 } 291 }
295 } 292 }
296 293
294 clk_put(src);
295
297 omap_hwmod_setup_one(oh_name); 296 omap_hwmod_setup_one(oh_name);
298 omap_hwmod_enable(oh); 297 omap_hwmod_enable(oh);
299 __omap_dm_timer_init_regs(timer); 298 __omap_dm_timer_init_regs(timer);
@@ -317,6 +316,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
317{ 316{
318 int res; 317 int res;
319 318
319 clkev.id = gptimer_id;
320 clkev.errata = omap_dm_timer_get_errata(); 320 clkev.errata = omap_dm_timer_get_errata();
321 321
322 /* 322 /*
@@ -326,8 +326,8 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
326 */ 326 */
327 __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767); 327 __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
328 328
329 res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property, 329 res = omap_dm_timer_init_one(&clkev, fck_source, property,
330 OMAP_TIMER_POSTED); 330 &clockevent_gpt.name, OMAP_TIMER_POSTED);
331 BUG_ON(res); 331 BUG_ON(res);
332 332
333 omap2_gp_timer_irq.dev_id = &clkev; 333 omap2_gp_timer_irq.dev_id = &clkev;
@@ -341,8 +341,8 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
341 3, /* Timer internal resynch latency */ 341 3, /* Timer internal resynch latency */
342 0xffffffff); 342 0xffffffff);
343 343
344 pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n", 344 pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,
345 gptimer_id, clkev.rate); 345 clkev.rate);
346} 346}
347 347
348/* Clocksource code */ 348/* Clocksource code */
@@ -359,7 +359,6 @@ static cycle_t clocksource_read_cycles(struct clocksource *cs)
359} 359}
360 360
361static struct clocksource clocksource_gpt = { 361static struct clocksource clocksource_gpt = {
362 .name = "gp_timer",
363 .rating = 300, 362 .rating = 300,
364 .read = clocksource_read_cycles, 363 .read = clocksource_read_cycles,
365 .mask = CLOCKSOURCE_MASK(32), 364 .mask = CLOCKSOURCE_MASK(32),
@@ -442,13 +441,16 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
442} 441}
443 442
444static void __init omap2_gptimer_clocksource_init(int gptimer_id, 443static void __init omap2_gptimer_clocksource_init(int gptimer_id,
445 const char *fck_source) 444 const char *fck_source,
445 const char *property)
446{ 446{
447 int res; 447 int res;
448 448
449 clksrc.id = gptimer_id;
449 clksrc.errata = omap_dm_timer_get_errata(); 450 clksrc.errata = omap_dm_timer_get_errata();
450 451
451 res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL, 452 res = omap_dm_timer_init_one(&clksrc, fck_source, property,
453 &clocksource_gpt.name,
452 OMAP_TIMER_NONPOSTED); 454 OMAP_TIMER_NONPOSTED);
453 BUG_ON(res); 455 BUG_ON(res);
454 456
@@ -461,8 +463,8 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
461 pr_err("Could not register clocksource %s\n", 463 pr_err("Could not register clocksource %s\n",
462 clocksource_gpt.name); 464 clocksource_gpt.name);
463 else 465 else
464 pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n", 466 pr_info("OMAP clocksource: %s at %lu Hz\n",
465 gptimer_id, clksrc.rate); 467 clocksource_gpt.name, clksrc.rate);
466} 468}
467 469
468#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER 470#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
@@ -487,7 +489,7 @@ static void __init realtime_counter_init(void)
487 pr_err("%s: ioremap failed\n", __func__); 489 pr_err("%s: ioremap failed\n", __func__);
488 return; 490 return;
489 } 491 }
490 sys_clk = clk_get(NULL, "sys_clkin_ck"); 492 sys_clk = clk_get(NULL, "sys_clkin");
491 if (IS_ERR(sys_clk)) { 493 if (IS_ERR(sys_clk)) {
492 pr_err("%s: failed to get system clock handle\n", __func__); 494 pr_err("%s: failed to get system clock handle\n", __func__);
493 iounmap(base); 495 iounmap(base);
@@ -544,49 +546,52 @@ static inline void __init realtime_counter_init(void)
544#endif 546#endif
545 547
546#define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \ 548#define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
547 clksrc_nr, clksrc_src) \ 549 clksrc_nr, clksrc_src, clksrc_prop) \
548void __init omap##name##_gptimer_timer_init(void) \ 550void __init omap##name##_gptimer_timer_init(void) \
549{ \ 551{ \
550 omap_dmtimer_init(); \ 552 omap_dmtimer_init(); \
551 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ 553 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \
552 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src); \ 554 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src, \
555 clksrc_prop); \
553} 556}
554 557
555#define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \ 558#define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
556 clksrc_nr, clksrc_src) \ 559 clksrc_nr, clksrc_src, clksrc_prop) \
557void __init omap##name##_sync32k_timer_init(void) \ 560void __init omap##name##_sync32k_timer_init(void) \
558{ \ 561{ \
559 omap_dmtimer_init(); \ 562 omap_dmtimer_init(); \
560 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ 563 omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \
561 /* Enable the use of clocksource="gp_timer" kernel parameter */ \ 564 /* Enable the use of clocksource="gp_timer" kernel parameter */ \
562 if (use_gptimer_clksrc) \ 565 if (use_gptimer_clksrc) \
563 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);\ 566 omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src, \
567 clksrc_prop); \
564 else \ 568 else \
565 omap2_sync32k_clocksource_init(); \ 569 omap2_sync32k_clocksource_init(); \
566} 570}
567 571
568#ifdef CONFIG_ARCH_OMAP2 572#ifdef CONFIG_ARCH_OMAP2
569OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon", 573OMAP_SYS_32K_TIMER_INIT(2, 1, "timer_32k_ck", "ti,timer-alwon",
570 2, OMAP2_MPU_SOURCE); 574 2, "timer_sys_ck", NULL);
571#endif /* CONFIG_ARCH_OMAP2 */ 575#endif /* CONFIG_ARCH_OMAP2 */
572 576
573#ifdef CONFIG_ARCH_OMAP3 577#ifdef CONFIG_ARCH_OMAP3
574OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon", 578OMAP_SYS_32K_TIMER_INIT(3, 1, "timer_32k_ck", "ti,timer-alwon",
575 2, OMAP3_MPU_SOURCE); 579 2, "timer_sys_ck", NULL);
576OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure", 580OMAP_SYS_32K_TIMER_INIT(3_secure, 12, "secure_32k_fck", "ti,timer-secure",
577 2, OMAP3_MPU_SOURCE); 581 2, "timer_sys_ck", NULL);
578OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon",
579 2, OMAP3_MPU_SOURCE);
580#endif /* CONFIG_ARCH_OMAP3 */ 582#endif /* CONFIG_ARCH_OMAP3 */
581 583
582#ifdef CONFIG_SOC_AM33XX 584#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
583OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", 585OMAP_SYS_GP_TIMER_INIT(3, 2, "timer_sys_ck", NULL,
584 2, OMAP4_MPU_SOURCE); 586 1, "timer_sys_ck", "ti,timer-alwon");
585#endif /* CONFIG_SOC_AM33XX */ 587#endif
588
589#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
590static OMAP_SYS_32K_TIMER_INIT(4, 1, "timer_32k_ck", "ti,timer-alwon",
591 2, "sys_clkin_ck", NULL);
592#endif
586 593
587#ifdef CONFIG_ARCH_OMAP4 594#ifdef CONFIG_ARCH_OMAP4
588OMAP_SYS_32K_TIMER_INIT(4, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
589 2, OMAP4_MPU_SOURCE);
590#ifdef CONFIG_LOCAL_TIMERS 595#ifdef CONFIG_LOCAL_TIMERS
591static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29); 596static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
592void __init omap4_local_timer_init(void) 597void __init omap4_local_timer_init(void)
@@ -597,7 +602,7 @@ void __init omap4_local_timer_init(void)
597 int err; 602 int err;
598 603
599 if (of_have_populated_dt()) { 604 if (of_have_populated_dt()) {
600 twd_local_timer_of_register(); 605 clocksource_of_init();
601 return; 606 return;
602 } 607 }
603 608
@@ -615,13 +620,11 @@ void __init omap4_local_timer_init(void)
615#endif /* CONFIG_ARCH_OMAP4 */ 620#endif /* CONFIG_ARCH_OMAP4 */
616 621
617#ifdef CONFIG_SOC_OMAP5 622#ifdef CONFIG_SOC_OMAP5
618OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
619 2, OMAP4_MPU_SOURCE);
620void __init omap5_realtime_timer_init(void) 623void __init omap5_realtime_timer_init(void)
621{ 624{
622 int err; 625 int err;
623 626
624 omap5_sync32k_timer_init(); 627 omap4_sync32k_timer_init();
625 realtime_counter_init(); 628 realtime_counter_init();
626 629
627 err = arch_timer_of_register(); 630 err = arch_timer_of_register();