aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2012-08-13 04:54:24 -0400
committerSantosh Shilimkar <santosh.shilimkar@ti.com>2012-09-19 03:30:36 -0400
commitfa6d79d27614223d82418023b7f5300f1a1530d3 (patch)
tree5675ffd08a08f8c15353c05c75c0d66c9c64a573 /arch
parent5698bd757d55b1bb87edd1a9744ab09c142abfc2 (diff)
ARM: OMAP: Add initialisation for the real-time counter.
The real time counter also called master counter, is a free-running counter. 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. The ratio registers needs to be configured based on system clock only onetime. After initialisation, hardware takes care of adjusting the clock in different low power modes to keep counter rate constant. Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/Kconfig4
-rw-r--r--arch/arm/mach-omap2/timer.c90
2 files changed, 93 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 346fd26f3aa6..4b773fd56978 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -24,6 +24,9 @@ config ARCH_OMAP2PLUS_TYPICAL
24config SOC_HAS_OMAP2_SDRC 24config SOC_HAS_OMAP2_SDRC
25 bool "OMAP2 SDRAM Controller support" 25 bool "OMAP2 SDRAM Controller support"
26 26
27config SOC_HAS_REALTIME_COUNTER
28 bool "Real time free running counter"
29
27config ARCH_OMAP2 30config ARCH_OMAP2
28 bool "TI OMAP2" 31 bool "TI OMAP2"
29 depends on ARCH_OMAP2PLUS 32 depends on ARCH_OMAP2PLUS
@@ -70,6 +73,7 @@ config SOC_OMAP5
70 select ARM_GIC 73 select ARM_GIC
71 select HAVE_SMP 74 select HAVE_SMP
72 select ARM_CPU_SUSPEND if PM 75 select ARM_CPU_SUSPEND if PM
76 select SOC_HAS_REALTIME_COUNTER
73 77
74comment "OMAP Core Type" 78comment "OMAP Core Type"
75 depends on ARCH_OMAP2 79 depends on ARCH_OMAP2
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 2ba4f57dda86..026fcfff6698 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -69,6 +69,11 @@
69#define OMAP3_SECURE_TIMER 1 69#define OMAP3_SECURE_TIMER 1
70#endif 70#endif
71 71
72#define REALTIME_COUNTER_BASE 0x48243200
73#define INCREMENTER_NUMERATOR_OFFSET 0x10
74#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14
75#define NUMERATOR_DENUMERATOR_MASK 0xfffff000
76
72/* Clockevent code */ 77/* Clockevent code */
73 78
74static struct omap_dm_timer clkev; 79static struct omap_dm_timer clkev;
@@ -346,6 +351,84 @@ static void __init omap2_clocksource_init(int gptimer_id,
346 omap2_gptimer_clocksource_init(gptimer_id, fck_source); 351 omap2_gptimer_clocksource_init(gptimer_id, fck_source);
347} 352}
348 353
354#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
355/*
356 * The realtime counter also called master counter, is a free-running
357 * counter, which is related to real time. It produces the count used
358 * by the CPU local timer peripherals in the MPU cluster. The timer counts
359 * at a rate of 6.144 MHz. Because the device operates on different clocks
360 * in different power modes, the master counter shifts operation between
361 * clocks, adjusting the increment per clock in hardware accordingly to
362 * maintain a constant count rate.
363 */
364static void __init realtime_counter_init(void)
365{
366 void __iomem *base;
367 static struct clk *sys_clk;
368 unsigned long rate;
369 unsigned int reg, num, den;
370
371 base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
372 if (!base) {
373 pr_err("%s: ioremap failed\n", __func__);
374 return;
375 }
376 sys_clk = clk_get(NULL, "sys_clkin_ck");
377 if (!sys_clk) {
378 pr_err("%s: failed to get system clock handle\n", __func__);
379 iounmap(base);
380 return;
381 }
382
383 rate = clk_get_rate(sys_clk);
384 /* Numerator/denumerator values refer TRM Realtime Counter section */
385 switch (rate) {
386 case 1200000:
387 num = 64;
388 den = 125;
389 break;
390 case 1300000:
391 num = 768;
392 den = 1625;
393 break;
394 case 19200000:
395 num = 8;
396 den = 25;
397 break;
398 case 2600000:
399 num = 384;
400 den = 1625;
401 break;
402 case 2700000:
403 num = 256;
404 den = 1125;
405 break;
406 case 38400000:
407 default:
408 /* Program it for 38.4 MHz */
409 num = 4;
410 den = 25;
411 break;
412 }
413
414 /* Program numerator and denumerator registers */
415 reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) &
416 NUMERATOR_DENUMERATOR_MASK;
417 reg |= num;
418 __raw_writel(reg, base + INCREMENTER_NUMERATOR_OFFSET);
419
420 reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) &
421 NUMERATOR_DENUMERATOR_MASK;
422 reg |= den;
423 __raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
424
425 iounmap(base);
426}
427#else
428static inline void __init realtime_counter_init(void)
429{}
430#endif
431
349#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ 432#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \
350 clksrc_nr, clksrc_src) \ 433 clksrc_nr, clksrc_src) \
351static void __init omap##name##_timer_init(void) \ 434static void __init omap##name##_timer_init(void) \
@@ -403,7 +486,12 @@ OMAP_SYS_TIMER(4)
403#endif 486#endif
404 487
405#ifdef CONFIG_SOC_OMAP5 488#ifdef CONFIG_SOC_OMAP5
406OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE) 489static void __init omap5_timer_init(void)
490{
491 omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
492 omap2_clocksource_init(2, OMAP4_MPU_SOURCE);
493 realtime_counter_init();
494}
407OMAP_SYS_TIMER(5) 495OMAP_SYS_TIMER(5)
408#endif 496#endif
409 497