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 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 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 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 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 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 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 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 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 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 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 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 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