Commit fa6d79d27614223d82418023b7f5300f1a1530d3

Authored by Santosh Shilimkar
1 parent 5698bd757d

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>

Showing 2 changed files with 93 additions and 1 deletions Side-by-side Diff

arch/arm/mach-omap2/Kconfig
... ... @@ -24,6 +24,9 @@
24 24 config SOC_HAS_OMAP2_SDRC
25 25 bool "OMAP2 SDRAM Controller support"
26 26  
  27 +config SOC_HAS_REALTIME_COUNTER
  28 + bool "Real time free running counter"
  29 +
27 30 config ARCH_OMAP2
28 31 bool "TI OMAP2"
29 32 depends on ARCH_OMAP2PLUS
... ... @@ -70,6 +73,7 @@
70 73 select ARM_GIC
71 74 select HAVE_SMP
72 75 select ARM_CPU_SUSPEND if PM
  76 + select SOC_HAS_REALTIME_COUNTER
73 77  
74 78 comment "OMAP Core Type"
75 79 depends on ARCH_OMAP2
arch/arm/mach-omap2/timer.c
... ... @@ -69,6 +69,11 @@
69 69 #define OMAP3_SECURE_TIMER 1
70 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 77 /* Clockevent code */
73 78  
74 79 static struct omap_dm_timer clkev;
... ... @@ -346,6 +351,84 @@
346 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 + */
  364 +static 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
  428 +static inline void __init realtime_counter_init(void)
  429 +{}
  430 +#endif
  431 +
349 432 #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \
350 433 clksrc_nr, clksrc_src) \
351 434 static void __init omap##name##_timer_init(void) \
... ... @@ -403,7 +486,12 @@
403 486 #endif
404 487  
405 488 #ifdef CONFIG_SOC_OMAP5
406   -OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE)
  489 +static 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 +}
407 495 OMAP_SYS_TIMER(5)
408 496 #endif
409 497