diff options
| -rw-r--r-- | arch/arm/boot/dts/omap5.dtsi | 12 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/Kconfig | 5 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/timer.c | 97 |
3 files changed, 113 insertions, 1 deletions
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 9ac75b37c992..5db33f481a33 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi | |||
| @@ -33,9 +33,21 @@ | |||
| 33 | cpus { | 33 | cpus { |
| 34 | cpu@0 { | 34 | cpu@0 { |
| 35 | compatible = "arm,cortex-a15"; | 35 | compatible = "arm,cortex-a15"; |
| 36 | timer { | ||
| 37 | compatible = "arm,armv7-timer"; | ||
| 38 | /* 14th PPI IRQ, active low level-sensitive */ | ||
| 39 | interrupts = <1 14 0x308>; | ||
| 40 | clock-frequency = <6144000>; | ||
| 41 | }; | ||
| 36 | }; | 42 | }; |
| 37 | cpu@1 { | 43 | cpu@1 { |
| 38 | compatible = "arm,cortex-a15"; | 44 | compatible = "arm,cortex-a15"; |
| 45 | timer { | ||
| 46 | compatible = "arm,armv7-timer"; | ||
| 47 | /* 14th PPI IRQ, active low level-sensitive */ | ||
| 48 | interrupts = <1 14 0x308>; | ||
| 49 | clock-frequency = <6144000>; | ||
| 50 | }; | ||
| 39 | }; | 51 | }; |
| 40 | }; | 52 | }; |
| 41 | 53 | ||
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index eef99b77c40b..edc30b8b77ed 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
| @@ -25,6 +25,9 @@ config ARCH_OMAP2PLUS_TYPICAL | |||
| 25 | config SOC_HAS_OMAP2_SDRC | 25 | config SOC_HAS_OMAP2_SDRC |
| 26 | bool "OMAP2 SDRAM Controller support" | 26 | bool "OMAP2 SDRAM Controller support" |
| 27 | 27 | ||
| 28 | config SOC_HAS_REALTIME_COUNTER | ||
| 29 | bool "Real time free running counter" | ||
| 30 | |||
| 28 | config ARCH_OMAP2 | 31 | config ARCH_OMAP2 |
| 29 | bool "TI OMAP2" | 32 | bool "TI OMAP2" |
| 30 | depends on ARCH_OMAP2PLUS | 33 | depends on ARCH_OMAP2PLUS |
| @@ -71,6 +74,8 @@ config SOC_OMAP5 | |||
| 71 | select ARM_GIC | 74 | select ARM_GIC |
| 72 | select HAVE_SMP | 75 | select HAVE_SMP |
| 73 | select ARM_CPU_SUSPEND if PM | 76 | select ARM_CPU_SUSPEND if PM |
| 77 | select SOC_HAS_REALTIME_COUNTER | ||
| 78 | select ARM_ARCH_TIMER | ||
| 74 | 79 | ||
| 75 | comment "OMAP Core Type" | 80 | comment "OMAP Core Type" |
| 76 | depends on ARCH_OMAP2 | 81 | depends on ARCH_OMAP2 |
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 8f4525047200..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; |
| @@ -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 | ||
