1 /*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <boot/boot.h>
30 #include <msm7k/gpt.h>
31
rd_cycle_count(void)32 static inline unsigned rd_cycle_count(void)
33 {
34 unsigned cc;
35 asm volatile (
36 "mrc p15, 0, %0, c15, c12, 1\n" :
37 "=r" (cc)
38 );
39 return cc;
40 }
41
rd_dtcm(void)42 static inline unsigned rd_dtcm(void)
43 {
44 unsigned cc;
45 asm volatile (
46 "mrc p15, 0, %0, c9, c1, 0\n" :
47 "=r" (cc)
48 );
49 return cc;
50 }
51
rd_itcm(void)52 static inline unsigned rd_itcm(void)
53 {
54 unsigned cc;
55 asm volatile (
56 "mrc p15, 0, %0, c9, c1, 1\n" :
57 "=r" (cc)
58 );
59 return cc;
60 }
61
perf_enable(void)62 static inline void perf_enable(void)
63 {
64 asm volatile (
65 "mcr p15, 0, %0, c15, c12, 0\n" : : "r" (7)
66 );
67 }
68
perf_disable(void)69 static inline void perf_disable(void)
70 {
71 asm volatile (
72 "mcr p15, 0, %0, c15, c12, 0\n" : : "r" (0)
73 );
74 }
75
cycles_per_second(void)76 unsigned cycles_per_second(void)
77 {
78 unsigned T0, T1;
79
80 perf_enable();
81
82 writel(0, GPT_CLEAR);
83 writel(0, GPT_ENABLE);
84 while(readl(GPT_COUNT_VAL) != 0) ;
85
86 writel(GPT_ENABLE_EN, GPT_ENABLE);
87 T0 = rd_cycle_count();
88 while(readl(GPT_COUNT_VAL) < 32766) ;
89 T1 = rd_cycle_count();
90
91 writel(0, GPT_ENABLE);
92 writel(0, GPT_CLEAR);
93
94 perf_disable();
95
96 return T1-T0;
97 }
98
mdelay(unsigned msecs)99 void mdelay(unsigned msecs)
100 {
101 msecs *= 33;
102
103 writel(0, GPT_CLEAR);
104 writel(0, GPT_ENABLE);
105 while(readl(GPT_COUNT_VAL) != 0) ;
106
107 writel(GPT_ENABLE_EN, GPT_ENABLE);
108 while(readl(GPT_COUNT_VAL) < msecs) ;
109
110 writel(0, GPT_ENABLE);
111 writel(0, GPT_CLEAR);
112 }
113
udelay(unsigned usecs)114 void udelay(unsigned usecs)
115 {
116 usecs = (usecs * 33 + 1000 - 33) / 1000;
117
118 writel(0, GPT_CLEAR);
119 writel(0, GPT_ENABLE);
120 while(readl(GPT_COUNT_VAL) != 0) ;
121
122 writel(GPT_ENABLE_EN, GPT_ENABLE);
123 while(readl(GPT_COUNT_VAL) < usecs) ;
124
125 writel(0, GPT_ENABLE);
126 writel(0, GPT_CLEAR);
127 }
128
print_cpu_speed(void)129 void print_cpu_speed(void)
130 {
131 unsigned cps = cycles_per_second();
132 dprintf("1 second = %d cycles\n%d MHz\n", cps, cps / 1000000);
133 }
134
135 #define A11S_CLK_CNTL 0xC0100100
136 #define A11S_CLK_SEL 0xC0100104
137
138 #define C A11S_CLK_CNTL
139 #define S A11S_CLK_SEL
140
141 #if FROM_APPSBOOT_MBN
142 static unsigned tbl_old[] = {
143 C, 0x640000,
144 S, 2,
145 C, 0x640010,
146 C, 0x64001F,
147 S, 3,
148 C, 0x64101F,
149 C, 0x64171F,
150 S, 2,
151 C, 0x64171F,
152 C, 0x641715,
153 S, 3,
154 S, 5,
155 C, 0x641715,
156 C, 0x641315,
157 S, 4,
158 S, 6,
159 C, 0x641315,
160 C, 0x641312,
161 S, 7,
162 C, 0x641312,
163 C, 0x641112,
164 S, 6,
165 0
166 };
167 #endif
168
169 static unsigned tbl[] = {
170 #if EXPLORE
171 C, 0x640000, S, 2,
172 C, 0x640001, S, 3,
173 C, 0x640201, S, 2,
174 C, 0x640203, S, 3,
175 C, 0x640403, S, 2,
176 C, 0x640405, S, 3,
177 C, 0x640605, S, 2,
178 C, 0x640607, S, 3,
179 C, 0x640807, S, 2,
180 C, 0x640809, S, 3,
181 C, 0x640A09, S, 2,
182 C, 0x640A0B, S, 3,
183 C, 0x640C0B, S, 2,
184 C, 0x640C0D, S, 3,
185 C, 0x640E0D, S, 2,
186 C, 0x640E0F, S, 3,
187 #endif
188 C, 0x640000, S, 2,
189 C, 0x64001F, S, 3,
190 C, 0x64171F, S, 2,
191 C, 0x641715, S, 5,
192 C, 0x641315, S, 6,
193 C, 0x641312, S, 7,
194 C, 0x641112, S, 6,
195 0
196 };
197 #undef C
198 #undef S
199
200 #if TESTCASE
201 unsigned cc_div[16] = {
202 1, 2, 3, 4, 5, 8, 6, 16,
203 1, 1, 1, 1, 1, 1, 1, 32 /* guess */
204 };
205
206 unsigned cc_base[4] = {
207 19200000,
208 245760000,
209 800000000,
210 0
211 };
212
213 unsigned cs_div[4] = {
214 1, 2, 3, 4
215 };
216
info(unsigned c,unsigned s)217 void info(unsigned c, unsigned s)
218 {
219 unsigned src_sel, src_div;
220
221 if(s & 1) {
222 /* src1 selected */
223 src_sel = (c >> 4) & 0x7;
224 src_div = c & 0xF;
225 } else {
226 /* src0 selected */
227 src_sel = (c >> 12) & 0x7;
228 src_div = (c >> 8) & 0xF;
229 }
230
231 unsigned src = s & 1;
232 unsigned pdiv = cs_div[(s >> 1) & 3];
233 unsigned div = cc_div[src_div];
234 unsigned clk = cc_base[src_sel] / div;
235 unsigned pclk = clk / pdiv;
236
237 unsigned cps = cycles_per_second();
238
239 dprintf("CC=0x%x CS=0x%x SRC=%d PDIV=%d SEL=%d DIV=%d CPS=%d ACLK=%d\n",
240 c, s, src, pdiv, src_sel, div, cps, clk);
241 }
242
243
arm11_clock_test(void)244 void arm11_clock_test(void)
245 {
246 unsigned c, s;
247 unsigned *x = tbl;
248
249 while(*x) {
250 unsigned *ptr = (unsigned*) *x++;
251 unsigned val = *x++;
252 *ptr = val;
253
254 if(ptr == ((unsigned*) A11S_CLK_CNTL)) {
255 c = val;
256 } else {
257 s = val;
258 info(c, s);
259 }
260 }
261 }
262 #endif
263
arm11_clock_init(void)264 void arm11_clock_init(void)
265 {
266 unsigned *x = tbl;
267 while(*x) {
268 unsigned *ptr = (unsigned*) *x++;
269 unsigned val = *x++;
270 *ptr = val;
271 }
272 }
273
274
275