Merge tag 'nfs-for-5.20-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[linux-block.git] / arch / arm / mach-omap2 / timer.c
CommitLineData
1dbae815 1/*
0f622e8c 2 * linux/arch/arm/mach-omap2/timer.c
1dbae815
TL
3 *
4 * OMAP2 GP timer support.
5 *
f248076c
PW
6 * Copyright (C) 2009 Nokia Corporation
7 *
5a3a388f
KH
8 * Update to use new clocksource/clockevent layers
9 * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
10 * Copyright (C) 2007 MontaVista Software, Inc.
11 *
12 * Original driver:
1dbae815
TL
13 * Copyright (C) 2005 Nokia Corporation
14 * Author: Paul Mundt <paul.mundt@nokia.com>
96de0e25 15 * Juha Yrjölä <juha.yrjola@nokia.com>
77900a2f 16 * OMAP Dual-mode timer framework support by Timo Teras
1dbae815
TL
17 *
18 * Some parts based off of TI's 24xx code:
19 *
44169075 20 * Copyright (C) 2004-2009 Texas Instruments, Inc.
1dbae815
TL
21 *
22 * Roughly modelled after the OMAP1 MPU timer code.
44169075 23 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
1dbae815
TL
24 *
25 * This file is subject to the terms and conditions of the GNU General Public
26 * License. See the file "COPYING" in the main directory of this archive
27 * for more details.
28 */
f8ce2547 29#include <linux/clk.h>
5a3a388f 30#include <linux/clocksource.h>
b481113a 31
dbc04161 32#include "soc.h"
7d7e1eba 33#include "common.h"
afc9d590 34#include "control.h"
5523e409 35#include "omap-secure.h"
1dbae815 36
fa6d79d2
SS
37#define REALTIME_COUNTER_BASE 0x48243200
38#define INCREMENTER_NUMERATOR_OFFSET 0x10
39#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14
40#define NUMERATOR_DENUMERATOR_MASK 0xfffff000
41
5523e409
S
42static unsigned long arch_timer_freq;
43
44void set_cntfreq(void)
45{
46 omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
47}
f248076c 48
fa6d79d2
SS
49/*
50 * The realtime counter also called master counter, is a free-running
51 * counter, which is related to real time. It produces the count used
52 * by the CPU local timer peripherals in the MPU cluster. The timer counts
53 * at a rate of 6.144 MHz. Because the device operates on different clocks
54 * in different power modes, the master counter shifts operation between
55 * clocks, adjusting the increment per clock in hardware accordingly to
56 * maintain a constant count rate.
57 */
58static void __init realtime_counter_init(void)
59{
60 void __iomem *base;
61 static struct clk *sys_clk;
62 unsigned long rate;
afc9d590
LS
63 unsigned int reg;
64 unsigned long long num, den;
fa6d79d2
SS
65
66 base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
67 if (!base) {
68 pr_err("%s: ioremap failed\n", __func__);
69 return;
70 }
7f585bbf 71 sys_clk = clk_get(NULL, "sys_clkin");
533b2981 72 if (IS_ERR(sys_clk)) {
fa6d79d2
SS
73 pr_err("%s: failed to get system clock handle\n", __func__);
74 iounmap(base);
75 return;
76 }
77
78 rate = clk_get_rate(sys_clk);
afc9d590
LS
79
80 if (soc_is_dra7xx()) {
81 /*
82 * Errata i856 says the 32.768KHz crystal does not start at
83 * power on, so the CPU falls back to an emulated 32KHz clock
84 * based on sysclk / 610 instead. This causes the master counter
85 * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
86 * (OR sysclk * 75 / 244)
87 *
88 * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
89 * Of course any board built without a populated 32.768KHz
90 * crystal would also need this fix even if the CPU is fixed
91 * later.
92 *
93 * Either case can be detected by using the two speedselect bits
94 * If they are not 0, then the 32.768KHz clock driving the
95 * coarse counter that corrects the fine counter every time it
96 * ticks is actually rate/610 rather than 32.768KHz and we
97 * should compensate to avoid the 570ppm (at 20MHz, much worse
98 * at other rates) too fast system time.
99 */
100 reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
101 if (reg & DRA7_SPEEDSELECT_MASK) {
102 num = 75;
103 den = 244;
104 goto sysclk1_based;
105 }
106 }
107
fa6d79d2
SS
108 /* Numerator/denumerator values refer TRM Realtime Counter section */
109 switch (rate) {
572b24e6 110 case 12000000:
fa6d79d2
SS
111 num = 64;
112 den = 125;
113 break;
572b24e6 114 case 13000000:
fa6d79d2
SS
115 num = 768;
116 den = 1625;
117 break;
118 case 19200000:
119 num = 8;
120 den = 25;
121 break;
38a1981c
S
122 case 20000000:
123 num = 192;
124 den = 625;
125 break;
572b24e6 126 case 26000000:
fa6d79d2
SS
127 num = 384;
128 den = 1625;
129 break;
572b24e6 130 case 27000000:
fa6d79d2
SS
131 num = 256;
132 den = 1125;
133 break;
134 case 38400000:
135 default:
136 /* Program it for 38.4 MHz */
137 num = 4;
138 den = 25;
139 break;
140 }
141
afc9d590 142sysclk1_based:
fa6d79d2 143 /* Program numerator and denumerator registers */
edfaf05c 144 reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
fa6d79d2
SS
145 NUMERATOR_DENUMERATOR_MASK;
146 reg |= num;
edfaf05c 147 writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
fa6d79d2 148
edfaf05c 149 reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
fa6d79d2
SS
150 NUMERATOR_DENUMERATOR_MASK;
151 reg |= den;
edfaf05c 152 writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
fa6d79d2 153
afc9d590 154 arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
5523e409
S
155 set_cntfreq();
156
fa6d79d2 157 iounmap(base);
6f80b3bb
IG
158}
159
6bb27d73 160void __init omap5_realtime_timer_init(void)
fa6d79d2 161{
036a3d42 162 omap_clk_init();
fa6d79d2 163 realtime_counter_init();
3c7c5dab 164
ba5d08c0 165 timer_probe();
fa6d79d2 166}