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