diff options
author | Tony Lindgren <tony@atomide.com> | 2012-09-21 16:48:01 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2012-09-21 16:48:01 -0400 |
commit | 0c9de3c52d2baed6bc2ee44885adb418152c71c4 (patch) | |
tree | e19ab2c41ae47250fd614418022b32aa783aa563 /arch/arm/mach-omap2/timer.c | |
parent | 6bfc82ff589a00e5fbc12b958c649d703d273c86 (diff) | |
parent | 3c7c5dab44d6c8861bc86dab924353d8d40344f8 (diff) |
Merge branch 'for_3.7/omap5_arch_timer' of git://github.com/SantoshShilimkar/linux into devel-dt-arch-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.c | 104 |
1 files changed, 103 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index e2084facca59..a9c9b3dbc82c 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; |
@@ -263,6 +269,7 @@ static u32 notrace dmtimer_read_sched_clock(void) | |||
263 | return 0; | 269 | return 0; |
264 | } | 270 | } |
265 | 271 | ||
272 | #ifdef CONFIG_OMAP_32K_TIMER | ||
266 | /* Setup free-running counter for clocksource */ | 273 | /* Setup free-running counter for clocksource */ |
267 | static int __init omap2_sync32k_clocksource_init(void) | 274 | static int __init omap2_sync32k_clocksource_init(void) |
268 | { | 275 | { |
@@ -302,6 +309,12 @@ static int __init omap2_sync32k_clocksource_init(void) | |||
302 | 309 | ||
303 | return ret; | 310 | return ret; |
304 | } | 311 | } |
312 | #else | ||
313 | static inline int omap2_sync32k_clocksource_init(void) | ||
314 | { | ||
315 | return -ENODEV; | ||
316 | } | ||
317 | #endif | ||
305 | 318 | ||
306 | static void __init omap2_gptimer_clocksource_init(int gptimer_id, | 319 | static void __init omap2_gptimer_clocksource_init(int gptimer_id, |
307 | const char *fck_source) | 320 | const char *fck_source) |
@@ -342,6 +355,84 @@ static void __init omap2_clocksource_init(int gptimer_id, | |||
342 | omap2_gptimer_clocksource_init(gptimer_id, fck_source); | 355 | omap2_gptimer_clocksource_init(gptimer_id, fck_source); |
343 | } | 356 | } |
344 | 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 | |||
345 | #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ | 436 | #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ |
346 | clksrc_nr, clksrc_src) \ | 437 | clksrc_nr, clksrc_src) \ |
347 | static void __init omap##name##_timer_init(void) \ | 438 | static void __init omap##name##_timer_init(void) \ |
@@ -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 | ||