Loading arch/arm/boot/dts/omap5.dtsi +12 −0 Original line number Original line Diff line number Diff line Loading @@ -33,9 +33,21 @@ cpus { cpus { cpu@0 { cpu@0 { compatible = "arm,cortex-a15"; compatible = "arm,cortex-a15"; timer { compatible = "arm,armv7-timer"; /* 14th PPI IRQ, active low level-sensitive */ interrupts = <1 14 0x308>; clock-frequency = <6144000>; }; }; }; cpu@1 { cpu@1 { compatible = "arm,cortex-a15"; compatible = "arm,cortex-a15"; timer { compatible = "arm,armv7-timer"; /* 14th PPI IRQ, active low level-sensitive */ interrupts = <1 14 0x308>; clock-frequency = <6144000>; }; }; }; }; }; Loading arch/arm/mach-omap2/Kconfig +5 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,9 @@ config ARCH_OMAP2PLUS_TYPICAL config SOC_HAS_OMAP2_SDRC config SOC_HAS_OMAP2_SDRC bool "OMAP2 SDRAM Controller support" bool "OMAP2 SDRAM Controller support" config SOC_HAS_REALTIME_COUNTER bool "Real time free running counter" config ARCH_OMAP2 config ARCH_OMAP2 bool "TI OMAP2" bool "TI OMAP2" depends on ARCH_OMAP2PLUS depends on ARCH_OMAP2PLUS Loading Loading @@ -71,6 +74,8 @@ config SOC_OMAP5 select ARM_GIC select ARM_GIC select HAVE_SMP select HAVE_SMP select ARM_CPU_SUSPEND if PM select ARM_CPU_SUSPEND if PM select SOC_HAS_REALTIME_COUNTER select ARM_ARCH_TIMER comment "OMAP Core Type" comment "OMAP Core Type" depends on ARCH_OMAP2 depends on ARCH_OMAP2 Loading arch/arm/mach-omap2/timer.c +96 −1 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <asm/smp_twd.h> #include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <asm/sched_clock.h> #include <asm/arch_timer.h> #include <plat/omap_hwmod.h> #include <plat/omap_hwmod.h> #include <plat/omap_device.h> #include <plat/omap_device.h> #include <plat/dmtimer.h> #include <plat/dmtimer.h> Loading Loading @@ -72,6 +73,11 @@ #define OMAP3_SECURE_TIMER 1 #define OMAP3_SECURE_TIMER 1 #endif #endif #define REALTIME_COUNTER_BASE 0x48243200 #define INCREMENTER_NUMERATOR_OFFSET 0x10 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14 #define NUMERATOR_DENUMERATOR_MASK 0xfffff000 /* Clockevent code */ /* Clockevent code */ static struct omap_dm_timer clkev; static struct omap_dm_timer clkev; Loading Loading @@ -349,6 +355,84 @@ static void __init omap2_clocksource_init(int gptimer_id, omap2_gptimer_clocksource_init(gptimer_id, fck_source); omap2_gptimer_clocksource_init(gptimer_id, fck_source); } } #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER /* * The realtime counter also called master counter, is a free-running * counter, which is related to real time. It produces the count used * by the CPU local timer peripherals in the MPU cluster. The timer counts * at a rate of 6.144 MHz. Because the device operates on different clocks * in different power modes, the master counter shifts operation between * clocks, adjusting the increment per clock in hardware accordingly to * maintain a constant count rate. */ static void __init realtime_counter_init(void) { void __iomem *base; static struct clk *sys_clk; unsigned long rate; unsigned int reg, num, den; base = ioremap(REALTIME_COUNTER_BASE, SZ_32); if (!base) { pr_err("%s: ioremap failed\n", __func__); return; } sys_clk = clk_get(NULL, "sys_clkin_ck"); if (!sys_clk) { pr_err("%s: failed to get system clock handle\n", __func__); iounmap(base); return; } rate = clk_get_rate(sys_clk); /* Numerator/denumerator values refer TRM Realtime Counter section */ switch (rate) { case 1200000: num = 64; den = 125; break; case 1300000: num = 768; den = 1625; break; case 19200000: num = 8; den = 25; break; case 2600000: num = 384; den = 1625; break; case 2700000: num = 256; den = 1125; break; case 38400000: default: /* Program it for 38.4 MHz */ num = 4; den = 25; break; } /* Program numerator and denumerator registers */ reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) & NUMERATOR_DENUMERATOR_MASK; reg |= num; __raw_writel(reg, base + INCREMENTER_NUMERATOR_OFFSET); reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) & NUMERATOR_DENUMERATOR_MASK; reg |= den; __raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); iounmap(base); } #else static inline void __init realtime_counter_init(void) {} #endif #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ clksrc_nr, clksrc_src) \ clksrc_nr, clksrc_src) \ static void __init omap##name##_timer_init(void) \ static void __init omap##name##_timer_init(void) \ Loading Loading @@ -410,7 +494,18 @@ OMAP_SYS_TIMER(4) #endif #endif #ifdef CONFIG_SOC_OMAP5 #ifdef CONFIG_SOC_OMAP5 OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE) static void __init omap5_timer_init(void) { int err; omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); omap2_clocksource_init(2, OMAP4_MPU_SOURCE); realtime_counter_init(); err = arch_timer_of_register(); if (err) pr_err("%s: arch_timer_register failed %d\n", __func__, err); } OMAP_SYS_TIMER(5) OMAP_SYS_TIMER(5) #endif #endif Loading Loading
arch/arm/boot/dts/omap5.dtsi +12 −0 Original line number Original line Diff line number Diff line Loading @@ -33,9 +33,21 @@ cpus { cpus { cpu@0 { cpu@0 { compatible = "arm,cortex-a15"; compatible = "arm,cortex-a15"; timer { compatible = "arm,armv7-timer"; /* 14th PPI IRQ, active low level-sensitive */ interrupts = <1 14 0x308>; clock-frequency = <6144000>; }; }; }; cpu@1 { cpu@1 { compatible = "arm,cortex-a15"; compatible = "arm,cortex-a15"; timer { compatible = "arm,armv7-timer"; /* 14th PPI IRQ, active low level-sensitive */ interrupts = <1 14 0x308>; clock-frequency = <6144000>; }; }; }; }; }; Loading
arch/arm/mach-omap2/Kconfig +5 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,9 @@ config ARCH_OMAP2PLUS_TYPICAL config SOC_HAS_OMAP2_SDRC config SOC_HAS_OMAP2_SDRC bool "OMAP2 SDRAM Controller support" bool "OMAP2 SDRAM Controller support" config SOC_HAS_REALTIME_COUNTER bool "Real time free running counter" config ARCH_OMAP2 config ARCH_OMAP2 bool "TI OMAP2" bool "TI OMAP2" depends on ARCH_OMAP2PLUS depends on ARCH_OMAP2PLUS Loading Loading @@ -71,6 +74,8 @@ config SOC_OMAP5 select ARM_GIC select ARM_GIC select HAVE_SMP select HAVE_SMP select ARM_CPU_SUSPEND if PM select ARM_CPU_SUSPEND if PM select SOC_HAS_REALTIME_COUNTER select ARM_ARCH_TIMER comment "OMAP Core Type" comment "OMAP Core Type" depends on ARCH_OMAP2 depends on ARCH_OMAP2 Loading
arch/arm/mach-omap2/timer.c +96 −1 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <asm/smp_twd.h> #include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <asm/sched_clock.h> #include <asm/arch_timer.h> #include <plat/omap_hwmod.h> #include <plat/omap_hwmod.h> #include <plat/omap_device.h> #include <plat/omap_device.h> #include <plat/dmtimer.h> #include <plat/dmtimer.h> Loading Loading @@ -72,6 +73,11 @@ #define OMAP3_SECURE_TIMER 1 #define OMAP3_SECURE_TIMER 1 #endif #endif #define REALTIME_COUNTER_BASE 0x48243200 #define INCREMENTER_NUMERATOR_OFFSET 0x10 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14 #define NUMERATOR_DENUMERATOR_MASK 0xfffff000 /* Clockevent code */ /* Clockevent code */ static struct omap_dm_timer clkev; static struct omap_dm_timer clkev; Loading Loading @@ -349,6 +355,84 @@ static void __init omap2_clocksource_init(int gptimer_id, omap2_gptimer_clocksource_init(gptimer_id, fck_source); omap2_gptimer_clocksource_init(gptimer_id, fck_source); } } #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER /* * The realtime counter also called master counter, is a free-running * counter, which is related to real time. It produces the count used * by the CPU local timer peripherals in the MPU cluster. The timer counts * at a rate of 6.144 MHz. Because the device operates on different clocks * in different power modes, the master counter shifts operation between * clocks, adjusting the increment per clock in hardware accordingly to * maintain a constant count rate. */ static void __init realtime_counter_init(void) { void __iomem *base; static struct clk *sys_clk; unsigned long rate; unsigned int reg, num, den; base = ioremap(REALTIME_COUNTER_BASE, SZ_32); if (!base) { pr_err("%s: ioremap failed\n", __func__); return; } sys_clk = clk_get(NULL, "sys_clkin_ck"); if (!sys_clk) { pr_err("%s: failed to get system clock handle\n", __func__); iounmap(base); return; } rate = clk_get_rate(sys_clk); /* Numerator/denumerator values refer TRM Realtime Counter section */ switch (rate) { case 1200000: num = 64; den = 125; break; case 1300000: num = 768; den = 1625; break; case 19200000: num = 8; den = 25; break; case 2600000: num = 384; den = 1625; break; case 2700000: num = 256; den = 1125; break; case 38400000: default: /* Program it for 38.4 MHz */ num = 4; den = 25; break; } /* Program numerator and denumerator registers */ reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) & NUMERATOR_DENUMERATOR_MASK; reg |= num; __raw_writel(reg, base + INCREMENTER_NUMERATOR_OFFSET); reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) & NUMERATOR_DENUMERATOR_MASK; reg |= den; __raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); iounmap(base); } #else static inline void __init realtime_counter_init(void) {} #endif #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ clksrc_nr, clksrc_src) \ clksrc_nr, clksrc_src) \ static void __init omap##name##_timer_init(void) \ static void __init omap##name##_timer_init(void) \ Loading Loading @@ -410,7 +494,18 @@ OMAP_SYS_TIMER(4) #endif #endif #ifdef CONFIG_SOC_OMAP5 #ifdef CONFIG_SOC_OMAP5 OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE) static void __init omap5_timer_init(void) { int err; omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); omap2_clocksource_init(2, OMAP4_MPU_SOURCE); realtime_counter_init(); err = arch_timer_of_register(); if (err) pr_err("%s: arch_timer_register failed %d\n", __func__, err); } OMAP_SYS_TIMER(5) OMAP_SYS_TIMER(5) #endif #endif Loading