diff options
author | David Daney <david.daney@cavium.com> | 2011-11-22 09:46:49 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-12-07 17:03:28 -0500 |
commit | 751c9f684963d2a066a79d8022c0e79e1159291b (patch) | |
tree | 9a196a7c5bab11fe4e089e691e2f00593e51826a /arch/mips/cavium-octeon/executive/octeon-model.c | |
parent | 506d24be55d510c7ff79a0cdcabd00649b979bc9 (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.c | 119 |
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 | } |