diff options
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 114 |
1 files changed, 108 insertions, 6 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 2ba4f57dda86..8847d6eb2313 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -36,16 +36,20 @@ | |||
36 | #include <linux/clocksource.h> | 36 | #include <linux/clocksource.h> |
37 | #include <linux/clockchips.h> | 37 | #include <linux/clockchips.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/of.h> | ||
39 | 40 | ||
40 | #include <asm/mach/time.h> | 41 | #include <asm/mach/time.h> |
41 | #include <plat/dmtimer.h> | ||
42 | #include <asm/smp_twd.h> | 42 | #include <asm/smp_twd.h> |
43 | #include <asm/sched_clock.h> | 43 | #include <asm/sched_clock.h> |
44 | #include "common.h" | 44 | |
45 | #include <asm/arch_timer.h> | ||
45 | #include <plat/omap_hwmod.h> | 46 | #include <plat/omap_hwmod.h> |
46 | #include <plat/omap_device.h> | 47 | #include <plat/omap_device.h> |
48 | #include <plat/dmtimer.h> | ||
47 | #include <plat/omap-pm.h> | 49 | #include <plat/omap-pm.h> |
48 | 50 | ||
51 | #include "soc.h" | ||
52 | #include "common.h" | ||
49 | #include "powerdomain.h" | 53 | #include "powerdomain.h" |
50 | 54 | ||
51 | /* Parent clocks, eventually these will come from the clock framework */ | 55 | /* Parent clocks, eventually these will come from the clock framework */ |
@@ -69,6 +73,11 @@ | |||
69 | #define OMAP3_SECURE_TIMER 1 | 73 | #define OMAP3_SECURE_TIMER 1 |
70 | #endif | 74 | #endif |
71 | 75 | ||
76 | #define REALTIME_COUNTER_BASE 0x48243200 | ||
77 | #define INCREMENTER_NUMERATOR_OFFSET 0x10 | ||
78 | #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14 | ||
79 | #define NUMERATOR_DENUMERATOR_MASK 0xfffff000 | ||
80 | |||
72 | /* Clockevent code */ | 81 | /* Clockevent code */ |
73 | 82 | ||
74 | static struct omap_dm_timer clkev; | 83 | static struct omap_dm_timer clkev; |
@@ -211,7 +220,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id, | |||
211 | res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source); | 220 | res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source); |
212 | BUG_ON(res); | 221 | BUG_ON(res); |
213 | 222 | ||
214 | omap2_gp_timer_irq.dev_id = (void *)&clkev; | 223 | omap2_gp_timer_irq.dev_id = &clkev; |
215 | setup_irq(clkev.irq, &omap2_gp_timer_irq); | 224 | setup_irq(clkev.irq, &omap2_gp_timer_irq); |
216 | 225 | ||
217 | __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW); | 226 | __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW); |
@@ -346,6 +355,84 @@ static void __init omap2_clocksource_init(int gptimer_id, | |||
346 | omap2_gptimer_clocksource_init(gptimer_id, fck_source); | 355 | omap2_gptimer_clocksource_init(gptimer_id, fck_source); |
347 | } | 356 | } |
348 | 357 | ||
358 | #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER | ||
359 | /* | ||
360 | * The realtime counter also called master counter, is a free-running | ||
361 | * counter, which is related to real time. It produces the count used | ||
362 | * by the CPU local timer peripherals in the MPU cluster. The timer counts | ||
363 | * at a rate of 6.144 MHz. Because the device operates on different clocks | ||
364 | * in different power modes, the master counter shifts operation between | ||
365 | * clocks, adjusting the increment per clock in hardware accordingly to | ||
366 | * maintain a constant count rate. | ||
367 | */ | ||
368 | static void __init realtime_counter_init(void) | ||
369 | { | ||
370 | void __iomem *base; | ||
371 | static struct clk *sys_clk; | ||
372 | unsigned long rate; | ||
373 | unsigned int reg, num, den; | ||
374 | |||
375 | base = ioremap(REALTIME_COUNTER_BASE, SZ_32); | ||
376 | if (!base) { | ||
377 | pr_err("%s: ioremap failed\n", __func__); | ||
378 | return; | ||
379 | } | ||
380 | sys_clk = clk_get(NULL, "sys_clkin_ck"); | ||
381 | if (!sys_clk) { | ||
382 | pr_err("%s: failed to get system clock handle\n", __func__); | ||
383 | iounmap(base); | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | rate = clk_get_rate(sys_clk); | ||
388 | /* Numerator/denumerator values refer TRM Realtime Counter section */ | ||
389 | switch (rate) { | ||
390 | case 1200000: | ||
391 | num = 64; | ||
392 | den = 125; | ||
393 | break; | ||
394 | case 1300000: | ||
395 | num = 768; | ||
396 | den = 1625; | ||
397 | break; | ||
398 | case 19200000: | ||
399 | num = 8; | ||
400 | den = 25; | ||
401 | break; | ||
402 | case 2600000: | ||
403 | num = 384; | ||
404 | den = 1625; | ||
405 | break; | ||
406 | case 2700000: | ||
407 | num = 256; | ||
408 | den = 1125; | ||
409 | break; | ||
410 | case 38400000: | ||
411 | default: | ||
412 | /* Program it for 38.4 MHz */ | ||
413 | num = 4; | ||
414 | den = 25; | ||
415 | break; | ||
416 | } | ||
417 | |||
418 | /* Program numerator and denumerator registers */ | ||
419 | reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) & | ||
420 | NUMERATOR_DENUMERATOR_MASK; | ||
421 | reg |= num; | ||
422 | __raw_writel(reg, base + INCREMENTER_NUMERATOR_OFFSET); | ||
423 | |||
424 | reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) & | ||
425 | NUMERATOR_DENUMERATOR_MASK; | ||
426 | reg |= den; | ||
427 | __raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); | ||
428 | |||
429 | iounmap(base); | ||
430 | } | ||
431 | #else | ||
432 | static inline void __init realtime_counter_init(void) | ||
433 | {} | ||
434 | #endif | ||
435 | |||
349 | #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ | 436 | #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ |
350 | clksrc_nr, clksrc_src) \ | 437 | clksrc_nr, clksrc_src) \ |
351 | static void __init omap##name##_timer_init(void) \ | 438 | static void __init omap##name##_timer_init(void) \ |
@@ -380,8 +467,7 @@ OMAP_SYS_TIMER(3_am33xx) | |||
380 | #ifdef CONFIG_ARCH_OMAP4 | 467 | #ifdef CONFIG_ARCH_OMAP4 |
381 | #ifdef CONFIG_LOCAL_TIMERS | 468 | #ifdef CONFIG_LOCAL_TIMERS |
382 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, | 469 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, |
383 | OMAP44XX_LOCAL_TWD_BASE, | 470 | OMAP44XX_LOCAL_TWD_BASE, 29 + OMAP_INTC_START); |
384 | OMAP44XX_IRQ_LOCALTIMER); | ||
385 | #endif | 471 | #endif |
386 | 472 | ||
387 | static void __init omap4_timer_init(void) | 473 | static void __init omap4_timer_init(void) |
@@ -393,6 +479,11 @@ static void __init omap4_timer_init(void) | |||
393 | if (omap_rev() != OMAP4430_REV_ES1_0) { | 479 | if (omap_rev() != OMAP4430_REV_ES1_0) { |
394 | int err; | 480 | int err; |
395 | 481 | ||
482 | if (of_have_populated_dt()) { | ||
483 | twd_local_timer_of_register(); | ||
484 | return; | ||
485 | } | ||
486 | |||
396 | err = twd_local_timer_register(&twd_local_timer); | 487 | err = twd_local_timer_register(&twd_local_timer); |
397 | if (err) | 488 | if (err) |
398 | pr_err("twd_local_timer_register failed %d\n", err); | 489 | pr_err("twd_local_timer_register failed %d\n", err); |
@@ -403,7 +494,18 @@ OMAP_SYS_TIMER(4) | |||
403 | #endif | 494 | #endif |
404 | 495 | ||
405 | #ifdef CONFIG_SOC_OMAP5 | 496 | #ifdef CONFIG_SOC_OMAP5 |
406 | OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE) | 497 | static void __init omap5_timer_init(void) |
498 | { | ||
499 | int err; | ||
500 | |||
501 | omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); | ||
502 | omap2_clocksource_init(2, OMAP4_MPU_SOURCE); | ||
503 | realtime_counter_init(); | ||
504 | |||
505 | err = arch_timer_of_register(); | ||
506 | if (err) | ||
507 | pr_err("%s: arch_timer_register failed %d\n", __func__, err); | ||
508 | } | ||
407 | OMAP_SYS_TIMER(5) | 509 | OMAP_SYS_TIMER(5) |
408 | #endif | 510 | #endif |
409 | 511 | ||