diff options
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 810aa1a332e1..8847d6eb2313 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -42,6 +42,7 @@ | |||
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 | 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> |
47 | #include <plat/dmtimer.h> | 48 | #include <plat/dmtimer.h> |
@@ -72,6 +73,11 @@ | |||
72 | #define OMAP3_SECURE_TIMER 1 | 73 | #define OMAP3_SECURE_TIMER 1 |
73 | #endif | 74 | #endif |
74 | 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 | |||
75 | /* Clockevent code */ | 81 | /* Clockevent code */ |
76 | 82 | ||
77 | static struct omap_dm_timer clkev; | 83 | static struct omap_dm_timer clkev; |
@@ -349,6 +355,84 @@ static void __init omap2_clocksource_init(int gptimer_id, | |||
349 | omap2_gptimer_clocksource_init(gptimer_id, fck_source); | 355 | omap2_gptimer_clocksource_init(gptimer_id, fck_source); |
350 | } | 356 | } |
351 | 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 | |||
352 | #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ | 436 | #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ |
353 | clksrc_nr, clksrc_src) \ | 437 | clksrc_nr, clksrc_src) \ |
354 | static void __init omap##name##_timer_init(void) \ | 438 | static void __init omap##name##_timer_init(void) \ |
@@ -410,7 +494,18 @@ OMAP_SYS_TIMER(4) | |||
410 | #endif | 494 | #endif |
411 | 495 | ||
412 | #ifdef CONFIG_SOC_OMAP5 | 496 | #ifdef CONFIG_SOC_OMAP5 |
413 | 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 | } | ||
414 | OMAP_SYS_TIMER(5) | 509 | OMAP_SYS_TIMER(5) |
415 | #endif | 510 | #endif |
416 | 511 | ||