xref: /openbmc/linux/arch/arm/mach-omap2/timer.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
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