aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cavium-octeon/executive/octeon-model.c
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2011-11-22 09:46:49 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:03:28 -0500
commit751c9f684963d2a066a79d8022c0e79e1159291b (patch)
tree9a196a7c5bab11fe4e089e691e2f00593e51826a /arch/mips/cavium-octeon/executive/octeon-model.c
parent506d24be55d510c7ff79a0cdcabd00649b979bc9 (diff)
MIPS: Oceton: Update model detection code for new chips.
Several newer chips were not covered, update the code to detect them. This necessitates updating cvmx-mio-defs.h as well, because it has new and required definitions. Signed-off-by: David Daney <david.daney@cavium.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2939/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/cavium-octeon/executive/octeon-model.c')
-rw-r--r--arch/mips/cavium-octeon/executive/octeon-model.c119
1 files changed, 85 insertions, 34 deletions
diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c
index c8d35684504e..f4c1b36fdf65 100644
--- a/arch/mips/cavium-octeon/executive/octeon-model.c
+++ b/arch/mips/cavium-octeon/executive/octeon-model.c
@@ -4,7 +4,7 @@
4 * Contact: support@caviumnetworks.com 4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK 5 * This file is part of the OCTEON SDK
6 * 6 *
7 * Copyright (c) 2003-2008 Cavium Networks 7 * Copyright (c) 2003-2010 Cavium Networks
8 * 8 *
9 * This file is free software; you can redistribute it and/or modify 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 10 * it under the terms of the GNU General Public License, Version 2, as
@@ -25,10 +25,6 @@
25 * Contact Cavium Networks for more information 25 * Contact Cavium Networks for more information
26 ***********************license end**************************************/ 26 ***********************license end**************************************/
27 27
28/*
29 * File defining functions for working with different Octeon
30 * models.
31 */
32#include <asm/octeon/octeon.h> 28#include <asm/octeon/octeon.h>
33 29
34/** 30/**
@@ -69,11 +65,12 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
69 char fuse_model[10]; 65 char fuse_model[10];
70 uint32_t fuse_data = 0; 66 uint32_t fuse_data = 0;
71 67
72 fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3); 68 fus3.u64 = 0;
69 if (!OCTEON_IS_MODEL(OCTEON_CN6XXX))
70 fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
73 fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); 71 fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
74 fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); 72 fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
75 73 num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE));
76 num_cores = cvmx_octeon_num_cores();
77 74
78 /* Make sure the non existent devices look disabled */ 75 /* Make sure the non existent devices look disabled */
79 switch ((chip_id >> 8) & 0xff) { 76 switch ((chip_id >> 8) & 0xff) {
@@ -108,7 +105,7 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
108 * Assume pass number is encoded using <5:3><2:0>. Exceptions 105 * Assume pass number is encoded using <5:3><2:0>. Exceptions
109 * will be fixed later. 106 * will be fixed later.
110 */ 107 */
111 sprintf(pass, "%u.%u", ((chip_id >> 3) & 7) + 1, chip_id & 7); 108 sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);
112 109
113 /* 110 /*
114 * Use the number of cores to determine the last 2 digits of 111 * Use the number of cores to determine the last 2 digits of
@@ -116,6 +113,12 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
116 * later. 113 * later.
117 */ 114 */
118 switch (num_cores) { 115 switch (num_cores) {
116 case 32:
117 core_model = "80";
118 break;
119 case 24:
120 core_model = "70";
121 break;
119 case 16: 122 case 16:
120 core_model = "60"; 123 core_model = "60";
121 break; 124 break;
@@ -246,8 +249,8 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
246 break; 249 break;
247 case 3: /* CN58XX */ 250 case 3: /* CN58XX */
248 family = "58"; 251 family = "58";
249 /* Special case. 4 core, no crypto */ 252 /* Special case. 4 core, half cache (CP with half cache) */
250 if ((num_cores == 4) && fus_dat2.cn38xx.nocrypto) 253 if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
251 core_model = "29"; 254 core_model = "29";
252 255
253 /* Pass 1 uses different encodings for pass numbers */ 256 /* Pass 1 uses different encodings for pass numbers */
@@ -285,6 +288,9 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
285 suffix = "NSP"; 288 suffix = "NSP";
286 if (fus_dat3.s.nozip) 289 if (fus_dat3.s.nozip)
287 suffix = "SCP"; 290 suffix = "SCP";
291
292 if (fus_dat3.s.bar2_en)
293 suffix = "NSPB2";
288 } 294 }
289 if (fus3.cn56xx.crip_1024k) 295 if (fus3.cn56xx.crip_1024k)
290 family = "54"; 296 family = "54";
@@ -301,6 +307,60 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
301 else 307 else
302 family = "52"; 308 family = "52";
303 break; 309 break;
310 case 0x93: /* CN61XX */
311 family = "61";
312 if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
313 suffix = "AP";
314 if (fus_dat2.cn61xx.nocrypto)
315 suffix = "CP";
316 else if (fus_dat2.cn61xx.dorm_crypto)
317 suffix = "DAP";
318 else if (fus_dat3.cn61xx.nozip)
319 suffix = "SCP";
320 break;
321 case 0x90: /* CN63XX */
322 family = "63";
323 if (fus_dat3.s.l2c_crip == 2)
324 family = "62";
325 if (num_cores == 6) /* Other core counts match generic */
326 core_model = "35";
327 if (fus_dat2.cn63xx.nocrypto)
328 suffix = "CP";
329 else if (fus_dat2.cn63xx.dorm_crypto)
330 suffix = "DAP";
331 else if (fus_dat3.cn63xx.nozip)
332 suffix = "SCP";
333 else
334 suffix = "AAP";
335 break;
336 case 0x92: /* CN66XX */
337 family = "66";
338 if (num_cores == 6) /* Other core counts match generic */
339 core_model = "35";
340 if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
341 suffix = "AP";
342 if (fus_dat2.cn66xx.nocrypto)
343 suffix = "CP";
344 else if (fus_dat2.cn66xx.dorm_crypto)
345 suffix = "DAP";
346 else if (fus_dat3.cn66xx.nozip)
347 suffix = "SCP";
348 else
349 suffix = "AAP";
350 break;
351 case 0x91: /* CN68XX */
352 family = "68";
353 if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn68xx.nozip)
354 suffix = "CP";
355 else if (fus_dat2.cn68xx.dorm_crypto)
356 suffix = "DAP";
357 else if (fus_dat3.cn68xx.nozip)
358 suffix = "SCP";
359 else if (fus_dat2.cn68xx.nocrypto)
360 suffix = "SP";
361 else
362 suffix = "AAP";
363 break;
304 default: 364 default:
305 family = "XX"; 365 family = "XX";
306 core_model = "XX"; 366 core_model = "XX";
@@ -310,49 +370,40 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
310 } 370 }
311 371
312 clock_mhz = octeon_get_clock_rate() / 1000000; 372 clock_mhz = octeon_get_clock_rate() / 1000000;
313
314 if (family[0] != '3') { 373 if (family[0] != '3') {
374 int fuse_base = 384 / 8;
375 if (family[0] == '6')
376 fuse_base = 832 / 8;
377
315 /* Check for model in fuses, overrides normal decode */ 378 /* Check for model in fuses, overrides normal decode */
316 /* This is _not_ valid for Octeon CN3XXX models */ 379 /* This is _not_ valid for Octeon CN3XXX models */
317 fuse_data |= cvmx_fuse_read_byte(51); 380 fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
318 fuse_data = fuse_data << 8; 381 fuse_data = fuse_data << 8;
319 fuse_data |= cvmx_fuse_read_byte(50); 382 fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
320 fuse_data = fuse_data << 8; 383 fuse_data = fuse_data << 8;
321 fuse_data |= cvmx_fuse_read_byte(49); 384 fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
322 fuse_data = fuse_data << 8; 385 fuse_data = fuse_data << 8;
323 fuse_data |= cvmx_fuse_read_byte(48); 386 fuse_data |= cvmx_fuse_read_byte(fuse_base);
324 if (fuse_data & 0x7ffff) { 387 if (fuse_data & 0x7ffff) {
325 int model = fuse_data & 0x3fff; 388 int model = fuse_data & 0x3fff;
326 int suffix = (fuse_data >> 14) & 0x1f; 389 int suffix = (fuse_data >> 14) & 0x1f;
327 if (suffix && model) { 390 if (suffix && model) {
328 /* 391 /* Have both number and suffix in fuses, so both */
329 * Have both number and suffix in 392 sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
330 * fuses, so both
331 */
332 sprintf(fuse_model, "%d%c",
333 model, 'A' + suffix - 1);
334 core_model = ""; 393 core_model = "";
335 family = fuse_model; 394 family = fuse_model;
336 } else if (suffix && !model) { 395 } else if (suffix && !model) {
337 /* 396 /* Only have suffix, so add suffix to 'normal' model number */
338 * Only have suffix, so add suffix to 397 sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
339 * 'normal' model number.
340 */
341 sprintf(fuse_model, "%s%c", core_model,
342 'A' + suffix - 1);
343 core_model = fuse_model; 398 core_model = fuse_model;
344 } else { 399 } else {
345 /* 400 /* Don't have suffix, so just use model from fuses */
346 * Don't have suffix, so just use
347 * model from fuses.
348 */
349 sprintf(fuse_model, "%d", model); 401 sprintf(fuse_model, "%d", model);
350 core_model = ""; 402 core_model = "";
351 family = fuse_model; 403 family = fuse_model;
352 } 404 }
353 } 405 }
354 } 406 }
355 sprintf(buffer, "CN%s%sp%s-%d-%s", 407 sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
356 family, core_model, pass, clock_mhz, suffix);
357 return buffer; 408 return buffer;
358} 409}