root/arch/mips/cavium-octeon/executive/octeon-model.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cvmx_fuse_read_byte
  2. octeon_model_get_string_buffer
  3. octeon_model_get_string

   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 }

/* [<][>][^][v][top][bottom][index][help] */