~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/cavium-octeon/executive/octeon-model.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /***********************license start***************
  2  * Author: Cavium Networks
  3  *
  4  * Contact: support@caviumnetworks.com
  5  * This file is part of the OCTEON SDK
  6  *
  7  * Copyright (c) 2003-2017 Cavium, Inc.
  8  *
  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 
 28 #include <asm/octeon/octeon.h>
 29 
 30 enum octeon_feature_bits __octeon_feature_bits __read_mostly;
 31 EXPORT_SYMBOL_GPL(__octeon_feature_bits);
 32 
 33 /**
 34  * Read a byte of fuse data
 35  * @byte_addr:   address to read
 36  *
 37  * Returns fuse value: 0 or 1
 38  */
 39 static uint8_t __init cvmx_fuse_read_byte(int byte_addr)
 40 {
 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 
 53 /*
 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  */
 58 static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
 59                                                          char *buffer)
 60 {
 61         const char *family;
 62         const char *core_model;
 63         char pass[4];
 64         int clock_mhz;
 65         const char *suffix;
 66         int num_cores;
 67         union cvmx_mio_fus_dat2 fus_dat2;
 68         union cvmx_mio_fus_dat3 fus_dat3;
 69         char fuse_model[10];
 70         uint32_t fuse_data = 0;
 71         uint64_t l2d_fus3 = 0;
 72 
 73         if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
 74                 l2d_fus3 = (cvmx_read_csr(CVMX_L2D_FUS3) >> 34) & 0x3;
 75         fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
 76         fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
 77         num_cores = cvmx_octeon_num_cores();
 78 
 79         /* Make sure the non existent devices look disabled */
 80         switch ((chip_id >> 8) & 0xff) {
 81         case 6:         /* CN50XX */
 82         case 2:         /* CN30XX */
 83                 fus_dat3.s.nodfa_dte = 1;
 84                 fus_dat3.s.nozip = 1;
 85                 break;
 86         case 4:         /* CN57XX or CN56XX */
 87                 fus_dat3.s.nodfa_dte = 1;
 88                 break;
 89         default:
 90                 break;
 91         }
 92 
 93         /* Make a guess at the suffix */
 94         /* NSP = everything */
 95         /* EXP = No crypto */
 96         /* SCP = No DFA, No zip */
 97         /* CP = No DFA, No crypto, No zip */
 98         if (fus_dat3.s.nodfa_dte) {
 99                 if (fus_dat2.s.nocrypto)
100                         suffix = "CP";
101                 else
102                         suffix = "SCP";
103         } else if (fus_dat2.s.nocrypto)
104                 suffix = "EXP";
105         else
106                 suffix = "NSP";
107 
108         if (!fus_dat2.s.nocrypto)
109                 __octeon_feature_bits |= OCTEON_HAS_CRYPTO;
110 
111         /*
112          * Assume pass number is encoded using <5:3><2:0>. Exceptions
113          * will be fixed later.
114          */
115         sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);
116 
117         /*
118          * Use the number of cores to determine the last 2 digits of
119          * the model number. There are some exceptions that are fixed
120          * later.
121          */
122         switch (num_cores) {
123         case 48:
124                 core_model = "90";
125                 break;
126         case 44:
127                 core_model = "88";
128                 break;
129         case 40:
130                 core_model = "85";
131                 break;
132         case 32:
133                 core_model = "80";
134                 break;
135         case 24:
136                 core_model = "70";
137                 break;
138         case 16:
139                 core_model = "60";
140                 break;
141         case 15:
142                 core_model = "58";
143                 break;
144         case 14:
145                 core_model = "55";
146                 break;
147         case 13:
148                 core_model = "52";
149                 break;
150         case 12:
151                 core_model = "50";
152                 break;
153         case 11:
154                 core_model = "48";
155                 break;
156         case 10:
157                 core_model = "45";
158                 break;
159         case 9:
160                 core_model = "42";
161                 break;
162         case 8:
163                 core_model = "40";
164                 break;
165         case 7:
166                 core_model = "38";
167                 break;
168         case 6:
169                 core_model = "34";
170                 break;
171         case 5:
172                 core_model = "32";
173                 break;
174         case 4:
175                 core_model = "30";
176                 break;
177         case 3:
178                 core_model = "25";
179                 break;
180         case 2:
181                 core_model = "20";
182                 break;
183         case 1:
184                 core_model = "10";
185                 break;
186         default:
187                 core_model = "XX";
188                 break;
189         }
190 
191         /* Now figure out the family, the first two digits */
192         switch ((chip_id >> 8) & 0xff) {
193         case 0:         /* CN38XX, CN37XX or CN36XX */
194                 if (l2d_fus3) {
195                         /*
196                          * For some unknown reason, the 16 core one is
197                          * called 37 instead of 36.
198                          */
199                         if (num_cores >= 16)
200                                 family = "37";
201                         else
202                                 family = "36";
203                 } else
204                         family = "38";
205                 /*
206                  * This series of chips didn't follow the standard
207                  * pass numbering.
208                  */
209                 switch (chip_id & 0xf) {
210                 case 0:
211                         strcpy(pass, "1.X");
212                         break;
213                 case 1:
214                         strcpy(pass, "2.X");
215                         break;
216                 case 3:
217                         strcpy(pass, "3.X");
218                         break;
219                 default:
220                         strcpy(pass, "X.X");
221                         break;
222                 }
223                 break;
224         case 1:         /* CN31XX or CN3020 */
225                 if ((chip_id & 0x10) || l2d_fus3)
226                         family = "30";
227                 else
228                         family = "31";
229                 /*
230                  * This series of chips didn't follow the standard
231                  * pass numbering.
232                  */
233                 switch (chip_id & 0xf) {
234                 case 0:
235                         strcpy(pass, "1.0");
236                         break;
237                 case 2:
238                         strcpy(pass, "1.1");
239                         break;
240                 default:
241                         strcpy(pass, "X.X");
242                         break;
243                 }
244                 break;
245         case 2:         /* CN3010 or CN3005 */
246                 family = "30";
247                 /* A chip with half cache is an 05 */
248                 if (l2d_fus3)
249                         core_model = "05";
250                 /*
251                  * This series of chips didn't follow the standard
252                  * pass numbering.
253                  */
254                 switch (chip_id & 0xf) {
255                 case 0:
256                         strcpy(pass, "1.0");
257                         break;
258                 case 2:
259                         strcpy(pass, "1.1");
260                         break;
261                 default:
262                         strcpy(pass, "X.X");
263                         break;
264                 }
265                 break;
266         case 3:         /* CN58XX */
267                 family = "58";
268                 /* Special case. 4 core, half cache (CP with half cache) */
269                 if ((num_cores == 4) && l2d_fus3 && !strncmp(suffix, "CP", 2))
270                         core_model = "29";
271 
272                 /* Pass 1 uses different encodings for pass numbers */
273                 if ((chip_id & 0xFF) < 0x8) {
274                         switch (chip_id & 0x3) {
275                         case 0:
276                                 strcpy(pass, "1.0");
277                                 break;
278                         case 1:
279                                 strcpy(pass, "1.1");
280                                 break;
281                         case 3:
282                                 strcpy(pass, "1.2");
283                                 break;
284                         default:
285                                 strcpy(pass, "1.X");
286                                 break;
287                         }
288                 }
289                 break;
290         case 4:         /* CN57XX, CN56XX, CN55XX, CN54XX */
291                 if (fus_dat2.cn56xx.raid_en) {
292                         if (l2d_fus3)
293                                 family = "55";
294                         else
295                                 family = "57";
296                         if (fus_dat2.cn56xx.nocrypto)
297                                 suffix = "SP";
298                         else
299                                 suffix = "SSP";
300                 } else {
301                         if (fus_dat2.cn56xx.nocrypto)
302                                 suffix = "CP";
303                         else {
304                                 suffix = "NSP";
305                                 if (fus_dat3.s.nozip)
306                                         suffix = "SCP";
307 
308                                 if (fus_dat3.cn38xx.bar2_en)
309                                         suffix = "NSPB2";
310                         }
311                         if (l2d_fus3)
312                                 family = "54";
313                         else
314                                 family = "56";
315                 }
316                 break;
317         case 6:         /* CN50XX */
318                 family = "50";
319                 break;
320         case 7:         /* CN52XX */
321                 if (l2d_fus3)
322                         family = "51";
323                 else
324                         family = "52";
325                 break;
326         case 0x93:              /* CN61XX */
327                 family = "61";
328                 if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
329                         suffix = "AP";
330                 if (fus_dat2.cn61xx.nocrypto)
331                         suffix = "CP";
332                 else if (fus_dat2.cn61xx.dorm_crypto)
333                         suffix = "DAP";
334                 else if (fus_dat3.cn61xx.nozip)
335                         suffix = "SCP";
336                 break;
337         case 0x90:              /* CN63XX */
338                 family = "63";
339                 if (fus_dat3.s.l2c_crip == 2)
340                         family = "62";
341                 if (num_cores == 6)     /* Other core counts match generic */
342                         core_model = "35";
343                 if (fus_dat2.cn63xx.nocrypto)
344                         suffix = "CP";
345                 else if (fus_dat2.cn63xx.dorm_crypto)
346                         suffix = "DAP";
347                 else if (fus_dat3.cn61xx.nozip)
348                         suffix = "SCP";
349                 else
350                         suffix = "AAP";
351                 break;
352         case 0x92:              /* CN66XX */
353                 family = "66";
354                 if (num_cores == 6)     /* Other core counts match generic */
355                         core_model = "35";
356                 if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
357                         suffix = "AP";
358                 if (fus_dat2.cn66xx.nocrypto)
359                         suffix = "CP";
360                 else if (fus_dat2.cn66xx.dorm_crypto)
361                         suffix = "DAP";
362                 else if (fus_dat3.cn61xx.nozip)
363                         suffix = "SCP";
364                 else
365                         suffix = "AAP";
366                 break;
367         case 0x91:              /* CN68XX */
368                 family = "68";
369                 if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn61xx.nozip)
370                         suffix = "CP";
371                 else if (fus_dat2.cn68xx.dorm_crypto)
372                         suffix = "DAP";
373                 else if (fus_dat3.cn61xx.nozip)
374                         suffix = "SCP";
375                 else if (fus_dat2.cn68xx.nocrypto)
376                         suffix = "SP";
377                 else
378                         suffix = "AAP";
379                 break;
380         case 0x94:              /* CNF71XX */
381                 family = "F71";
382                 if (fus_dat3.cn61xx.nozip)
383                         suffix = "SCP";
384                 else
385                         suffix = "AAP";
386                 break;
387         case 0x95:              /* CN78XX */
388                 if (num_cores == 6)     /* Other core counts match generic */
389                         core_model = "35";
390                 if (OCTEON_IS_MODEL(OCTEON_CN76XX))
391                         family = "76";
392                 else
393                         family = "78";
394                 if (fus_dat3.cn78xx.l2c_crip == 2)
395                         family = "77";
396                 if (fus_dat3.cn78xx.nozip
397                     && fus_dat3.cn78xx.nodfa_dte
398                     && fus_dat3.cn78xx.nohna_dte) {
399                         if (fus_dat3.cn78xx.nozip &&
400                                 !fus_dat2.cn78xx.raid_en &&
401                                 fus_dat3.cn78xx.nohna_dte) {
402                                 suffix = "CP";
403                         } else {
404                                 suffix = "SCP";
405                         }
406                 } else if (fus_dat2.cn78xx.raid_en == 0)
407                         suffix = "HCP";
408                 else
409                         suffix = "AAP";
410                 break;
411         case 0x96:              /* CN70XX */
412                 family = "70";
413                 if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32))
414                         family = "71";
415                 if (fus_dat2.cn70xx.nocrypto)
416                         suffix = "CP";
417                 else if (fus_dat3.cn70xx.nodfa_dte)
418                         suffix = "SCP";
419                 else
420                         suffix = "AAP";
421                 break;
422         case 0x97:              /* CN73XX */
423                 if (num_cores == 6)     /* Other core counts match generic */
424                         core_model = "35";
425                 family = "73";
426                 if (fus_dat3.cn73xx.l2c_crip == 2)
427                         family = "72";
428                 if (fus_dat3.cn73xx.nozip
429                                 && fus_dat3.cn73xx.nodfa_dte
430                                 && fus_dat3.cn73xx.nohna_dte) {
431                         if (!fus_dat2.cn73xx.raid_en)
432                                 suffix = "CP";
433                         else
434                                 suffix = "SCP";
435                 } else
436                         suffix = "AAP";
437                 break;
438         case 0x98:              /* CN75XX */
439                 family = "F75";
440                 if (fus_dat3.cn78xx.nozip
441                     && fus_dat3.cn78xx.nodfa_dte
442                     && fus_dat3.cn78xx.nohna_dte)
443                         suffix = "SCP";
444                 else
445                         suffix = "AAP";
446                 break;
447         default:
448                 family = "XX";
449                 core_model = "XX";
450                 strcpy(pass, "X.X");
451                 suffix = "XXX";
452                 break;
453         }
454 
455         clock_mhz = octeon_get_clock_rate() / 1000000;
456         if (family[0] != '3') {
457                 int fuse_base = 384 / 8;
458                 if (family[0] == '6')
459                         fuse_base = 832 / 8;
460 
461                 /* Check for model in fuses, overrides normal decode */
462                 /* This is _not_ valid for Octeon CN3XXX models */
463                 fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
464                 fuse_data = fuse_data << 8;
465                 fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
466                 fuse_data = fuse_data << 8;
467                 fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
468                 fuse_data = fuse_data << 8;
469                 fuse_data |= cvmx_fuse_read_byte(fuse_base);
470                 if (fuse_data & 0x7ffff) {
471                         int model = fuse_data & 0x3fff;
472                         int suffix = (fuse_data >> 14) & 0x1f;
473                         if (suffix && model) {
474                                 /* Have both number and suffix in fuses, so both */
475                                 sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
476                                 core_model = "";
477                                 family = fuse_model;
478                         } else if (suffix && !model) {
479                                 /* Only have suffix, so add suffix to 'normal' model number */
480                                 sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
481                                 core_model = fuse_model;
482                         } else {
483                                 /* Don't have suffix, so just use model from fuses */
484                                 sprintf(fuse_model, "%d", model);
485                                 core_model = "";
486                                 family = fuse_model;
487                         }
488                 }
489         }
490         sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
491         return buffer;
492 }
493 
494 /**
495  * Given the chip processor ID from COP0, this function returns a
496  * string representing the chip model number. The string is of the
497  * form CNXXXXpX.X-FREQ-SUFFIX.
498  * - XXXX = The chip model number
499  * - X.X = Chip pass number
500  * - FREQ = Current frequency in Mhz
501  * - SUFFIX = NSP, EXP, SCP, SSP, or CP
502  *
503  * @chip_id: Chip ID
504  *
505  * Returns Model string
506  */
507 const char *__init octeon_model_get_string(uint32_t chip_id)
508 {
509         static char buffer[32];
510         return octeon_model_get_string_buffer(chip_id, buffer);
511 }
512 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php