blob: d08a2bce653cf235cd280c3d499ddce5f64d0b48 [file] [log] [blame]
David Daney58f07772008-12-23 15:22:14 -08001/***********************license start***************
2 * Author: Cavium Networks
3 *
4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK
6 *
David Daney751c9f62011-11-22 14:46:49 +00007 * Copyright (c) 2003-2010 Cavium Networks
David Daney58f07772008-12-23 15:22:14 -08008 *
9 * This file is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, Version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This file is distributed in the hope that it will be useful, but
14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16 * NONINFRINGEMENT. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this file; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * or visit http://www.gnu.org/licenses/.
23 *
24 * This file may also be available under a different license from Cavium.
25 * Contact Cavium Networks for more information
26 ***********************license end**************************************/
27
David Daney58f07772008-12-23 15:22:14 -080028#include <asm/octeon/octeon.h>
29
Aaro Koskinen011f3c62014-12-21 22:54:00 +020030enum octeon_feature_bits __octeon_feature_bits __read_mostly;
31EXPORT_SYMBOL_GPL(__octeon_feature_bits);
32
David Daney58f07772008-12-23 15:22:14 -080033/**
Aaro Koskinen0f240172014-09-08 18:25:40 +030034 * Read a byte of fuse data
35 * @byte_addr: address to read
36 *
37 * Returns fuse value: 0 or 1
38 */
Aaro Koskinenda85e3642014-09-08 18:25:43 +030039static uint8_t __init cvmx_fuse_read_byte(int byte_addr)
Aaro Koskinen0f240172014-09-08 18:25:40 +030040{
41 union cvmx_mio_fus_rcmd read_cmd;
42
43 read_cmd.u64 = 0;
44 read_cmd.s.addr = byte_addr;
45 read_cmd.s.pend = 1;
46 cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64);
47 while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD))
48 && read_cmd.s.pend)
49 ;
50 return read_cmd.s.dat;
51}
52
David Daney58f07772008-12-23 15:22:14 -080053/*
54 * Version of octeon_model_get_string() that takes buffer as argument,
55 * as running early in u-boot static/global variables don't work when
56 * running from flash.
57 */
Aaro Koskinenda85e3642014-09-08 18:25:43 +030058static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
59 char *buffer)
David Daney58f07772008-12-23 15:22:14 -080060{
61 const char *family;
62 const char *core_model;
63 char pass[4];
64 int clock_mhz;
65 const char *suffix;
66 union cvmx_l2d_fus3 fus3;
67 int num_cores;
68 union cvmx_mio_fus_dat2 fus_dat2;
69 union cvmx_mio_fus_dat3 fus_dat3;
70 char fuse_model[10];
71 uint32_t fuse_data = 0;
72
David Daney751c9f62011-11-22 14:46:49 +000073 fus3.u64 = 0;
David Daney182a6d12016-02-09 11:00:09 -080074 if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
David Daney751c9f62011-11-22 14:46:49 +000075 fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
David Daney58f07772008-12-23 15:22:14 -080076 fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
77 fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
David Daney182a6d12016-02-09 11:00:09 -080078 num_cores = cvmx_octeon_num_cores();
David Daney58f07772008-12-23 15:22:14 -080079
Lucas De Marchi25985ed2011-03-30 22:57:33 -030080 /* Make sure the non existent devices look disabled */
David Daney58f07772008-12-23 15:22:14 -080081 switch ((chip_id >> 8) & 0xff) {
82 case 6: /* CN50XX */
83 case 2: /* CN30XX */
84 fus_dat3.s.nodfa_dte = 1;
85 fus_dat3.s.nozip = 1;
86 break;
87 case 4: /* CN57XX or CN56XX */
88 fus_dat3.s.nodfa_dte = 1;
89 break;
90 default:
91 break;
92 }
93
94 /* Make a guess at the suffix */
95 /* NSP = everything */
96 /* EXP = No crypto */
97 /* SCP = No DFA, No zip */
98 /* CP = No DFA, No crypto, No zip */
99 if (fus_dat3.s.nodfa_dte) {
100 if (fus_dat2.s.nocrypto)
101 suffix = "CP";
102 else
103 suffix = "SCP";
104 } else if (fus_dat2.s.nocrypto)
105 suffix = "EXP";
106 else
107 suffix = "NSP";
108
Aaro Koskinen011f3c62014-12-21 22:54:00 +0200109 if (!fus_dat2.s.nocrypto)
110 __octeon_feature_bits |= OCTEON_HAS_CRYPTO;
111
David Daney58f07772008-12-23 15:22:14 -0800112 /*
113 * Assume pass number is encoded using <5:3><2:0>. Exceptions
114 * will be fixed later.
115 */
David Daney751c9f62011-11-22 14:46:49 +0000116 sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);
David Daney58f07772008-12-23 15:22:14 -0800117
118 /*
119 * Use the number of cores to determine the last 2 digits of
120 * the model number. There are some exceptions that are fixed
121 * later.
122 */
123 switch (num_cores) {
David Daney182a6d12016-02-09 11:00:09 -0800124 case 48:
125 core_model = "90";
126 break;
127 case 44:
128 core_model = "88";
129 break;
130 case 40:
131 core_model = "85";
132 break;
David Daney751c9f62011-11-22 14:46:49 +0000133 case 32:
134 core_model = "80";
135 break;
136 case 24:
137 core_model = "70";
138 break;
David Daney58f07772008-12-23 15:22:14 -0800139 case 16:
140 core_model = "60";
141 break;
142 case 15:
143 core_model = "58";
144 break;
145 case 14:
146 core_model = "55";
147 break;
148 case 13:
149 core_model = "52";
150 break;
151 case 12:
152 core_model = "50";
153 break;
154 case 11:
155 core_model = "48";
156 break;
157 case 10:
158 core_model = "45";
159 break;
160 case 9:
161 core_model = "42";
162 break;
163 case 8:
164 core_model = "40";
165 break;
166 case 7:
167 core_model = "38";
168 break;
169 case 6:
170 core_model = "34";
171 break;
172 case 5:
173 core_model = "32";
174 break;
175 case 4:
176 core_model = "30";
177 break;
178 case 3:
179 core_model = "25";
180 break;
181 case 2:
182 core_model = "20";
183 break;
184 case 1:
185 core_model = "10";
186 break;
187 default:
188 core_model = "XX";
189 break;
190 }
191
192 /* Now figure out the family, the first two digits */
193 switch ((chip_id >> 8) & 0xff) {
194 case 0: /* CN38XX, CN37XX or CN36XX */
195 if (fus3.cn38xx.crip_512k) {
196 /*
197 * For some unknown reason, the 16 core one is
198 * called 37 instead of 36.
199 */
200 if (num_cores >= 16)
201 family = "37";
202 else
203 family = "36";
204 } else
205 family = "38";
206 /*
207 * This series of chips didn't follow the standard
208 * pass numbering.
209 */
210 switch (chip_id & 0xf) {
211 case 0:
212 strcpy(pass, "1.X");
213 break;
214 case 1:
215 strcpy(pass, "2.X");
216 break;
217 case 3:
218 strcpy(pass, "3.X");
219 break;
220 default:
221 strcpy(pass, "X.X");
222 break;
223 }
224 break;
225 case 1: /* CN31XX or CN3020 */
226 if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
227 family = "30";
228 else
229 family = "31";
230 /*
231 * This series of chips didn't follow the standard
232 * pass numbering.
233 */
234 switch (chip_id & 0xf) {
235 case 0:
236 strcpy(pass, "1.0");
237 break;
238 case 2:
239 strcpy(pass, "1.1");
240 break;
241 default:
242 strcpy(pass, "X.X");
243 break;
244 }
245 break;
246 case 2: /* CN3010 or CN3005 */
247 family = "30";
248 /* A chip with half cache is an 05 */
249 if (fus3.cn30xx.crip_64k)
250 core_model = "05";
251 /*
252 * This series of chips didn't follow the standard
253 * pass numbering.
254 */
255 switch (chip_id & 0xf) {
256 case 0:
257 strcpy(pass, "1.0");
258 break;
259 case 2:
260 strcpy(pass, "1.1");
261 break;
262 default:
263 strcpy(pass, "X.X");
264 break;
265 }
266 break;
267 case 3: /* CN58XX */
268 family = "58";
David Daney751c9f62011-11-22 14:46:49 +0000269 /* Special case. 4 core, half cache (CP with half cache) */
270 if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
David Daney58f07772008-12-23 15:22:14 -0800271 core_model = "29";
272
273 /* Pass 1 uses different encodings for pass numbers */
274 if ((chip_id & 0xFF) < 0x8) {
275 switch (chip_id & 0x3) {
276 case 0:
277 strcpy(pass, "1.0");
278 break;
279 case 1:
280 strcpy(pass, "1.1");
281 break;
282 case 3:
283 strcpy(pass, "1.2");
284 break;
285 default:
286 strcpy(pass, "1.X");
287 break;
288 }
289 }
290 break;
291 case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */
292 if (fus_dat2.cn56xx.raid_en) {
293 if (fus3.cn56xx.crip_1024k)
294 family = "55";
295 else
296 family = "57";
297 if (fus_dat2.cn56xx.nocrypto)
298 suffix = "SP";
299 else
300 suffix = "SSP";
301 } else {
302 if (fus_dat2.cn56xx.nocrypto)
303 suffix = "CP";
304 else {
305 suffix = "NSP";
306 if (fus_dat3.s.nozip)
307 suffix = "SCP";
David Daney751c9f62011-11-22 14:46:49 +0000308
David Daney182a6d12016-02-09 11:00:09 -0800309 if (fus_dat3.cn56xx.bar2_en)
David Daney751c9f62011-11-22 14:46:49 +0000310 suffix = "NSPB2";
David Daney58f07772008-12-23 15:22:14 -0800311 }
312 if (fus3.cn56xx.crip_1024k)
313 family = "54";
314 else
315 family = "56";
316 }
317 break;
318 case 6: /* CN50XX */
319 family = "50";
320 break;
321 case 7: /* CN52XX */
322 if (fus3.cn52xx.crip_256k)
323 family = "51";
324 else
325 family = "52";
326 break;
David Daney751c9f62011-11-22 14:46:49 +0000327 case 0x93: /* CN61XX */
328 family = "61";
329 if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
330 suffix = "AP";
331 if (fus_dat2.cn61xx.nocrypto)
332 suffix = "CP";
333 else if (fus_dat2.cn61xx.dorm_crypto)
334 suffix = "DAP";
335 else if (fus_dat3.cn61xx.nozip)
336 suffix = "SCP";
337 break;
338 case 0x90: /* CN63XX */
339 family = "63";
340 if (fus_dat3.s.l2c_crip == 2)
341 family = "62";
342 if (num_cores == 6) /* Other core counts match generic */
343 core_model = "35";
344 if (fus_dat2.cn63xx.nocrypto)
345 suffix = "CP";
346 else if (fus_dat2.cn63xx.dorm_crypto)
347 suffix = "DAP";
348 else if (fus_dat3.cn63xx.nozip)
349 suffix = "SCP";
350 else
351 suffix = "AAP";
352 break;
353 case 0x92: /* CN66XX */
354 family = "66";
355 if (num_cores == 6) /* Other core counts match generic */
356 core_model = "35";
357 if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
358 suffix = "AP";
359 if (fus_dat2.cn66xx.nocrypto)
360 suffix = "CP";
361 else if (fus_dat2.cn66xx.dorm_crypto)
362 suffix = "DAP";
363 else if (fus_dat3.cn66xx.nozip)
364 suffix = "SCP";
365 else
366 suffix = "AAP";
367 break;
368 case 0x91: /* CN68XX */
369 family = "68";
370 if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn68xx.nozip)
371 suffix = "CP";
372 else if (fus_dat2.cn68xx.dorm_crypto)
373 suffix = "DAP";
374 else if (fus_dat3.cn68xx.nozip)
375 suffix = "SCP";
376 else if (fus_dat2.cn68xx.nocrypto)
377 suffix = "SP";
378 else
379 suffix = "AAP";
380 break;
David Daney182a6d12016-02-09 11:00:09 -0800381 case 0x94: /* CNF71XX */
382 family = "F71";
383 if (fus_dat3.cnf71xx.nozip)
384 suffix = "SCP";
385 else
386 suffix = "AAP";
387 break;
388 case 0x95: /* CN78XX */
389 if (num_cores == 6) /* Other core counts match generic */
390 core_model = "35";
391 if (OCTEON_IS_MODEL(OCTEON_CN76XX))
392 family = "76";
393 else
394 family = "78";
395 if (fus_dat3.cn78xx.l2c_crip == 2)
396 family = "77";
397 if (fus_dat3.cn78xx.nozip
398 && fus_dat3.cn78xx.nodfa_dte
399 && fus_dat3.cn78xx.nohna_dte) {
400 if (fus_dat3.cn78xx.nozip &&
401 !fus_dat2.cn78xx.raid_en &&
402 fus_dat3.cn78xx.nohna_dte) {
403 suffix = "CP";
404 } else {
405 suffix = "SCP";
406 }
407 } else if (fus_dat2.cn78xx.raid_en == 0)
408 suffix = "HCP";
409 else
410 suffix = "AAP";
411 break;
412 case 0x96: /* CN70XX */
413 family = "70";
414 if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32))
415 family = "71";
416 if (fus_dat2.cn70xx.nocrypto)
417 suffix = "CP";
418 else if (fus_dat3.cn70xx.nodfa_dte)
419 suffix = "SCP";
420 else
421 suffix = "AAP";
422 break;
423 case 0x97: /* CN73XX */
424 if (num_cores == 6) /* Other core counts match generic */
425 core_model = "35";
426 family = "73";
427 if (fus_dat3.cn73xx.l2c_crip == 2)
428 family = "72";
429 if (fus_dat3.cn73xx.nozip
430 && fus_dat3.cn73xx.nodfa_dte
431 && fus_dat3.cn73xx.nohna_dte) {
432 if (!fus_dat2.cn73xx.raid_en)
433 suffix = "CP";
434 else
435 suffix = "SCP";
436 } else
437 suffix = "AAP";
438 break;
439 case 0x98: /* CN75XX */
440 family = "F75";
441 if (fus_dat3.cn78xx.nozip
442 && fus_dat3.cn78xx.nodfa_dte
443 && fus_dat3.cn78xx.nohna_dte)
444 suffix = "SCP";
445 else
446 suffix = "AAP";
447 break;
David Daney58f07772008-12-23 15:22:14 -0800448 default:
449 family = "XX";
450 core_model = "XX";
451 strcpy(pass, "X.X");
452 suffix = "XXX";
453 break;
454 }
455
456 clock_mhz = octeon_get_clock_rate() / 1000000;
David Daney58f07772008-12-23 15:22:14 -0800457 if (family[0] != '3') {
David Daney751c9f62011-11-22 14:46:49 +0000458 int fuse_base = 384 / 8;
459 if (family[0] == '6')
460 fuse_base = 832 / 8;
461
David Daney58f07772008-12-23 15:22:14 -0800462 /* Check for model in fuses, overrides normal decode */
463 /* This is _not_ valid for Octeon CN3XXX models */
David Daney751c9f62011-11-22 14:46:49 +0000464 fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
David Daney58f07772008-12-23 15:22:14 -0800465 fuse_data = fuse_data << 8;
David Daney751c9f62011-11-22 14:46:49 +0000466 fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
David Daney58f07772008-12-23 15:22:14 -0800467 fuse_data = fuse_data << 8;
David Daney751c9f62011-11-22 14:46:49 +0000468 fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
David Daney58f07772008-12-23 15:22:14 -0800469 fuse_data = fuse_data << 8;
David Daney751c9f62011-11-22 14:46:49 +0000470 fuse_data |= cvmx_fuse_read_byte(fuse_base);
David Daney58f07772008-12-23 15:22:14 -0800471 if (fuse_data & 0x7ffff) {
472 int model = fuse_data & 0x3fff;
473 int suffix = (fuse_data >> 14) & 0x1f;
474 if (suffix && model) {
David Daney751c9f62011-11-22 14:46:49 +0000475 /* Have both number and suffix in fuses, so both */
476 sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
David Daney58f07772008-12-23 15:22:14 -0800477 core_model = "";
478 family = fuse_model;
479 } else if (suffix && !model) {
David Daney751c9f62011-11-22 14:46:49 +0000480 /* Only have suffix, so add suffix to 'normal' model number */
481 sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
David Daney58f07772008-12-23 15:22:14 -0800482 core_model = fuse_model;
483 } else {
David Daney751c9f62011-11-22 14:46:49 +0000484 /* Don't have suffix, so just use model from fuses */
David Daney58f07772008-12-23 15:22:14 -0800485 sprintf(fuse_model, "%d", model);
486 core_model = "";
487 family = fuse_model;
488 }
489 }
490 }
David Daney751c9f62011-11-22 14:46:49 +0000491 sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
David Daney58f07772008-12-23 15:22:14 -0800492 return buffer;
493}
Aaro Koskinen653e0522014-09-08 18:25:42 +0300494
495/**
496 * Given the chip processor ID from COP0, this function returns a
497 * string representing the chip model number. The string is of the
498 * form CNXXXXpX.X-FREQ-SUFFIX.
499 * - XXXX = The chip model number
500 * - X.X = Chip pass number
501 * - FREQ = Current frequency in Mhz
502 * - SUFFIX = NSP, EXP, SCP, SSP, or CP
503 *
504 * @chip_id: Chip ID
505 *
506 * Returns Model string
507 */
Aaro Koskinenda85e3642014-09-08 18:25:43 +0300508const char *__init octeon_model_get_string(uint32_t chip_id)
Aaro Koskinen653e0522014-09-08 18:25:42 +0300509{
510 static char buffer[32];
511 return octeon_model_get_string_buffer(chip_id, buffer);
512}