10f622e8cSTony Lindgren /*
20f622e8cSTony Lindgren * linux/arch/arm/mach-omap2/timer.c
30f622e8cSTony Lindgren *
40f622e8cSTony Lindgren * OMAP2 GP timer support.
50f622e8cSTony Lindgren *
60f622e8cSTony Lindgren * Copyright (C) 2009 Nokia Corporation
70f622e8cSTony Lindgren *
80f622e8cSTony Lindgren * Update to use new clocksource/clockevent layers
90f622e8cSTony Lindgren * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
100f622e8cSTony Lindgren * Copyright (C) 2007 MontaVista Software, Inc.
110f622e8cSTony Lindgren *
120f622e8cSTony Lindgren * Original driver:
130f622e8cSTony Lindgren * Copyright (C) 2005 Nokia Corporation
140f622e8cSTony Lindgren * Author: Paul Mundt <paul.mundt@nokia.com>
150f622e8cSTony Lindgren * Juha Yrjölä <juha.yrjola@nokia.com>
160f622e8cSTony Lindgren * OMAP Dual-mode timer framework support by Timo Teras
170f622e8cSTony Lindgren *
180f622e8cSTony Lindgren * Some parts based off of TI's 24xx code:
190f622e8cSTony Lindgren *
200f622e8cSTony Lindgren * Copyright (C) 2004-2009 Texas Instruments, Inc.
210f622e8cSTony Lindgren *
220f622e8cSTony Lindgren * Roughly modelled after the OMAP1 MPU timer code.
230f622e8cSTony Lindgren * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
240f622e8cSTony Lindgren *
250f622e8cSTony Lindgren * This file is subject to the terms and conditions of the GNU General Public
260f622e8cSTony Lindgren * License. See the file "COPYING" in the main directory of this archive
270f622e8cSTony Lindgren * for more details.
280f622e8cSTony Lindgren */
290f622e8cSTony Lindgren #include <linux/clk.h>
300f622e8cSTony Lindgren #include <linux/clocksource.h>
31b481113aSTarun Kanti DebBarma
32dbc04161STony Lindgren #include "soc.h"
337d7e1ebaSTony Lindgren #include "common.h"
34afc9d590SLennart Sorensen #include "control.h"
355523e409SR Sricharan #include "omap-secure.h"
360f622e8cSTony Lindgren
37fa6d79d2SSantosh Shilimkar #define REALTIME_COUNTER_BASE 0x48243200
38fa6d79d2SSantosh Shilimkar #define INCREMENTER_NUMERATOR_OFFSET 0x10
39fa6d79d2SSantosh Shilimkar #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14
40fa6d79d2SSantosh Shilimkar #define NUMERATOR_DENUMERATOR_MASK 0xfffff000
41fa6d79d2SSantosh Shilimkar
425523e409SR Sricharan static unsigned long arch_timer_freq;
435523e409SR Sricharan
set_cntfreq(void)445523e409SR Sricharan void set_cntfreq(void)
455523e409SR Sricharan {
465523e409SR Sricharan omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
475523e409SR Sricharan }
480f622e8cSTony Lindgren
49fa6d79d2SSantosh Shilimkar /*
50fa6d79d2SSantosh Shilimkar * The realtime counter also called master counter, is a free-running
51fa6d79d2SSantosh Shilimkar * counter, which is related to real time. It produces the count used
52fa6d79d2SSantosh Shilimkar * by the CPU local timer peripherals in the MPU cluster. The timer counts
53fa6d79d2SSantosh Shilimkar * at a rate of 6.144 MHz. Because the device operates on different clocks
54fa6d79d2SSantosh Shilimkar * in different power modes, the master counter shifts operation between
55fa6d79d2SSantosh Shilimkar * clocks, adjusting the increment per clock in hardware accordingly to
56fa6d79d2SSantosh Shilimkar * maintain a constant count rate.
57fa6d79d2SSantosh Shilimkar */
realtime_counter_init(void)58fa6d79d2SSantosh Shilimkar static void __init realtime_counter_init(void)
59fa6d79d2SSantosh Shilimkar {
60fa6d79d2SSantosh Shilimkar void __iomem *base;
61fa6d79d2SSantosh Shilimkar static struct clk *sys_clk;
62fa6d79d2SSantosh Shilimkar unsigned long rate;
63afc9d590SLennart Sorensen unsigned int reg;
64afc9d590SLennart Sorensen unsigned long long num, den;
65fa6d79d2SSantosh Shilimkar
66fa6d79d2SSantosh Shilimkar base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
67fa6d79d2SSantosh Shilimkar if (!base) {
68fa6d79d2SSantosh Shilimkar pr_err("%s: ioremap failed\n", __func__);
69fa6d79d2SSantosh Shilimkar return;
70fa6d79d2SSantosh Shilimkar }
717f585bbfSTony Lindgren sys_clk = clk_get(NULL, "sys_clkin");
72533b2981SWei Yongjun if (IS_ERR(sys_clk)) {
73fa6d79d2SSantosh Shilimkar pr_err("%s: failed to get system clock handle\n", __func__);
74fa6d79d2SSantosh Shilimkar iounmap(base);
75fa6d79d2SSantosh Shilimkar return;
76fa6d79d2SSantosh Shilimkar }
77fa6d79d2SSantosh Shilimkar
78fa6d79d2SSantosh Shilimkar rate = clk_get_rate(sys_clk);
79*ed8167cbSChen Hui clk_put(sys_clk);
80afc9d590SLennart Sorensen
81afc9d590SLennart Sorensen if (soc_is_dra7xx()) {
82afc9d590SLennart Sorensen /*
83afc9d590SLennart Sorensen * Errata i856 says the 32.768KHz crystal does not start at
84afc9d590SLennart Sorensen * power on, so the CPU falls back to an emulated 32KHz clock
85afc9d590SLennart Sorensen * based on sysclk / 610 instead. This causes the master counter
86afc9d590SLennart Sorensen * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
87afc9d590SLennart Sorensen * (OR sysclk * 75 / 244)
88afc9d590SLennart Sorensen *
89afc9d590SLennart Sorensen * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
90afc9d590SLennart Sorensen * Of course any board built without a populated 32.768KHz
91afc9d590SLennart Sorensen * crystal would also need this fix even if the CPU is fixed
92afc9d590SLennart Sorensen * later.
93afc9d590SLennart Sorensen *
94afc9d590SLennart Sorensen * Either case can be detected by using the two speedselect bits
95afc9d590SLennart Sorensen * If they are not 0, then the 32.768KHz clock driving the
96afc9d590SLennart Sorensen * coarse counter that corrects the fine counter every time it
97afc9d590SLennart Sorensen * ticks is actually rate/610 rather than 32.768KHz and we
98afc9d590SLennart Sorensen * should compensate to avoid the 570ppm (at 20MHz, much worse
99afc9d590SLennart Sorensen * at other rates) too fast system time.
100afc9d590SLennart Sorensen */
101afc9d590SLennart Sorensen reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
102afc9d590SLennart Sorensen if (reg & DRA7_SPEEDSELECT_MASK) {
103afc9d590SLennart Sorensen num = 75;
104afc9d590SLennart Sorensen den = 244;
105afc9d590SLennart Sorensen goto sysclk1_based;
106afc9d590SLennart Sorensen }
107afc9d590SLennart Sorensen }
108afc9d590SLennart Sorensen
109fa6d79d2SSantosh Shilimkar /* Numerator/denumerator values refer TRM Realtime Counter section */
110fa6d79d2SSantosh Shilimkar switch (rate) {
111572b24e6SLennart Sorensen case 12000000:
112fa6d79d2SSantosh Shilimkar num = 64;
113fa6d79d2SSantosh Shilimkar den = 125;
114fa6d79d2SSantosh Shilimkar break;
115572b24e6SLennart Sorensen case 13000000:
116fa6d79d2SSantosh Shilimkar num = 768;
117fa6d79d2SSantosh Shilimkar den = 1625;
118fa6d79d2SSantosh Shilimkar break;
119fa6d79d2SSantosh Shilimkar case 19200000:
120fa6d79d2SSantosh Shilimkar num = 8;
121fa6d79d2SSantosh Shilimkar den = 25;
122fa6d79d2SSantosh Shilimkar break;
12338a1981cSSricharan R case 20000000:
12438a1981cSSricharan R num = 192;
12538a1981cSSricharan R den = 625;
12638a1981cSSricharan R break;
127572b24e6SLennart Sorensen case 26000000:
128fa6d79d2SSantosh Shilimkar num = 384;
129fa6d79d2SSantosh Shilimkar den = 1625;
130fa6d79d2SSantosh Shilimkar break;
131572b24e6SLennart Sorensen case 27000000:
132fa6d79d2SSantosh Shilimkar num = 256;
133fa6d79d2SSantosh Shilimkar den = 1125;
134fa6d79d2SSantosh Shilimkar break;
135fa6d79d2SSantosh Shilimkar case 38400000:
136fa6d79d2SSantosh Shilimkar default:
137fa6d79d2SSantosh Shilimkar /* Program it for 38.4 MHz */
138fa6d79d2SSantosh Shilimkar num = 4;
139fa6d79d2SSantosh Shilimkar den = 25;
140fa6d79d2SSantosh Shilimkar break;
141fa6d79d2SSantosh Shilimkar }
142fa6d79d2SSantosh Shilimkar
143afc9d590SLennart Sorensen sysclk1_based:
144fa6d79d2SSantosh Shilimkar /* Program numerator and denumerator registers */
145edfaf05cSVictor Kamensky reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
146fa6d79d2SSantosh Shilimkar NUMERATOR_DENUMERATOR_MASK;
147fa6d79d2SSantosh Shilimkar reg |= num;
148edfaf05cSVictor Kamensky writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
149fa6d79d2SSantosh Shilimkar
150edfaf05cSVictor Kamensky reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
151fa6d79d2SSantosh Shilimkar NUMERATOR_DENUMERATOR_MASK;
152fa6d79d2SSantosh Shilimkar reg |= den;
153edfaf05cSVictor Kamensky writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
154fa6d79d2SSantosh Shilimkar
155afc9d590SLennart Sorensen arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
1565523e409SR Sricharan set_cntfreq();
1575523e409SR Sricharan
158fa6d79d2SSantosh Shilimkar iounmap(base);
1590f622e8cSTony Lindgren }
1600f622e8cSTony Lindgren
omap5_realtime_timer_init(void)1616bb27d73SStephen Warren void __init omap5_realtime_timer_init(void)
162fa6d79d2SSantosh Shilimkar {
163036a3d42STony Lindgren omap_clk_init();
164fa6d79d2SSantosh Shilimkar realtime_counter_init();
1653c7c5dabSSantosh Shilimkar
166ba5d08c0SDaniel Lezcano timer_probe();
167fa6d79d2SSantosh Shilimkar }
168