aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r--arch/arm/mach-omap2/timer.c103
1 files changed, 102 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 5214d5bfba27..8847d6eb2313 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -36,11 +36,13 @@
36#include <linux/clocksource.h> 36#include <linux/clocksource.h>
37#include <linux/clockchips.h> 37#include <linux/clockchips.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/of.h>
39 40
40#include <asm/mach/time.h> 41#include <asm/mach/time.h>
41#include <asm/smp_twd.h> 42#include <asm/smp_twd.h>
42#include <asm/sched_clock.h> 43#include <asm/sched_clock.h>
43 44
45#include <asm/arch_timer.h>
44#include <plat/omap_hwmod.h> 46#include <plat/omap_hwmod.h>
45#include <plat/omap_device.h> 47#include <plat/omap_device.h>
46#include <plat/dmtimer.h> 48#include <plat/dmtimer.h>
@@ -71,6 +73,11 @@
71#define OMAP3_SECURE_TIMER 1 73#define OMAP3_SECURE_TIMER 1
72#endif 74#endif
73 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
74/* Clockevent code */ 81/* Clockevent code */
75 82
76static struct omap_dm_timer clkev; 83static struct omap_dm_timer clkev;
@@ -348,6 +355,84 @@ static void __init omap2_clocksource_init(int gptimer_id,
348 omap2_gptimer_clocksource_init(gptimer_id, fck_source); 355 omap2_gptimer_clocksource_init(gptimer_id, fck_source);
349} 356}
350 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 */
368static 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
432static inline void __init realtime_counter_init(void)
433{}
434#endif
435
351#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \ 436#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, \
352 clksrc_nr, clksrc_src) \ 437 clksrc_nr, clksrc_src) \
353static void __init omap##name##_timer_init(void) \ 438static void __init omap##name##_timer_init(void) \
@@ -394,6 +479,11 @@ static void __init omap4_timer_init(void)
394 if (omap_rev() != OMAP4430_REV_ES1_0) { 479 if (omap_rev() != OMAP4430_REV_ES1_0) {
395 int err; 480 int err;
396 481
482 if (of_have_populated_dt()) {
483 twd_local_timer_of_register();
484 return;
485 }
486
397 err = twd_local_timer_register(&twd_local_timer); 487 err = twd_local_timer_register(&twd_local_timer);
398 if (err) 488 if (err)
399 pr_err("twd_local_timer_register failed %d\n", err); 489 pr_err("twd_local_timer_register failed %d\n", err);
@@ -404,7 +494,18 @@ OMAP_SYS_TIMER(4)
404#endif 494#endif
405 495
406#ifdef CONFIG_SOC_OMAP5 496#ifdef CONFIG_SOC_OMAP5
407OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE) 497static 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}
408OMAP_SYS_TIMER(5) 509OMAP_SYS_TIMER(5)
409#endif 510#endif
410 511