diff options
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 125 |
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 | ||
131 | static struct clock_event_device clockevent_gpt = { | 122 | static 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 | ||
216 | static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, | 212 | static 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 | ||
361 | static struct clocksource clocksource_gpt = { | 361 | static 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 | ||
444 | static void __init omap2_gptimer_clocksource_init(int gptimer_id, | 443 | static 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) \ |
548 | void __init omap##name##_gptimer_timer_init(void) \ | 550 | void __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) \ |
557 | void __init omap##name##_sync32k_timer_init(void) \ | 560 | void __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 |
569 | OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon", | 573 | OMAP_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 |
574 | OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon", | 578 | OMAP_SYS_32K_TIMER_INIT(3, 1, "timer_32k_ck", "ti,timer-alwon", |
575 | 2, OMAP3_MPU_SOURCE); | 579 | 2, "timer_sys_ck", NULL); |
576 | OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure", | 580 | OMAP_SYS_32K_TIMER_INIT(3_secure, 12, "secure_32k_fck", "ti,timer-secure", |
577 | 2, OMAP3_MPU_SOURCE); | 581 | 2, "timer_sys_ck", NULL); |
578 | OMAP_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) |
583 | OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", | 585 | OMAP_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) | ||
590 | static 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 |
588 | OMAP_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 |
591 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29); | 596 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29); |
592 | void __init omap4_local_timer_init(void) | 597 | void __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 |
618 | OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon", | ||
619 | 2, OMAP4_MPU_SOURCE); | ||
620 | void __init omap5_realtime_timer_init(void) | 623 | void __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(); |