Back to home page

OSCL-LXR

 
 

    


0001 /***********************license start***************
0002  * Author: Cavium Networks
0003  *
0004  * Contact: support@caviumnetworks.com
0005  * This file is part of the OCTEON SDK
0006  *
0007  * Copyright (c) 2003-2017 Cavium, Inc.
0008  *
0009  * This file is free software; you can redistribute it and/or modify
0010  * it under the terms of the GNU General Public License, Version 2, as
0011  * published by the Free Software Foundation.
0012  *
0013  * This file is distributed in the hope that it will be useful, but
0014  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
0015  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
0016  * NONINFRINGEMENT.  See the GNU General Public License for more
0017  * details.
0018  *
0019  * You should have received a copy of the GNU General Public License
0020  * along with this file; if not, write to the Free Software
0021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
0022  * or visit http://www.gnu.org/licenses/.
0023  *
0024  * This file may also be available under a different license from Cavium.
0025  * Contact Cavium Networks for more information
0026  ***********************license end**************************************/
0027 
0028 #include <asm/octeon/octeon.h>
0029 
0030 enum octeon_feature_bits __octeon_feature_bits __read_mostly;
0031 EXPORT_SYMBOL_GPL(__octeon_feature_bits);
0032 
0033 /**
0034  * Read a byte of fuse data
0035  * @byte_addr:   address to read
0036  *
0037  * Returns fuse value: 0 or 1
0038  */
0039 static uint8_t __init cvmx_fuse_read_byte(int byte_addr)
0040 {
0041     union cvmx_mio_fus_rcmd read_cmd;
0042 
0043     read_cmd.u64 = 0;
0044     read_cmd.s.addr = byte_addr;
0045     read_cmd.s.pend = 1;
0046     cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64);
0047     while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD))
0048            && read_cmd.s.pend)
0049         ;
0050     return read_cmd.s.dat;
0051 }
0052 
0053 /*
0054  * Version of octeon_model_get_string() that takes buffer as argument,
0055  * as running early in u-boot static/global variables don't work when
0056  * running from flash.
0057  */
0058 static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
0059                              char *buffer)
0060 {
0061     const char *family;
0062     const char *core_model;
0063     char pass[4];
0064     int clock_mhz;
0065     const char *suffix;
0066     int num_cores;
0067     union cvmx_mio_fus_dat2 fus_dat2;
0068     union cvmx_mio_fus_dat3 fus_dat3;
0069     char fuse_model[10];
0070     uint32_t fuse_data = 0;
0071     uint64_t l2d_fus3 = 0;
0072 
0073     if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
0074         l2d_fus3 = (cvmx_read_csr(CVMX_L2D_FUS3) >> 34) & 0x3;
0075     fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
0076     fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
0077     num_cores = cvmx_octeon_num_cores();
0078 
0079     /* Make sure the non existent devices look disabled */
0080     switch ((chip_id >> 8) & 0xff) {
0081     case 6:     /* CN50XX */
0082     case 2:     /* CN30XX */
0083         fus_dat3.s.nodfa_dte = 1;
0084         fus_dat3.s.nozip = 1;
0085         break;
0086     case 4:     /* CN57XX or CN56XX */
0087         fus_dat3.s.nodfa_dte = 1;
0088         break;
0089     default:
0090         break;
0091     }
0092 
0093     /* Make a guess at the suffix */
0094     /* NSP = everything */
0095     /* EXP = No crypto */
0096     /* SCP = No DFA, No zip */
0097     /* CP = No DFA, No crypto, No zip */
0098     if (fus_dat3.s.nodfa_dte) {
0099         if (fus_dat2.s.nocrypto)
0100             suffix = "CP";
0101         else
0102             suffix = "SCP";
0103     } else if (fus_dat2.s.nocrypto)
0104         suffix = "EXP";
0105     else
0106         suffix = "NSP";
0107 
0108     if (!fus_dat2.s.nocrypto)
0109         __octeon_feature_bits |= OCTEON_HAS_CRYPTO;
0110 
0111     /*
0112      * Assume pass number is encoded using <5:3><2:0>. Exceptions
0113      * will be fixed later.
0114      */
0115     sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);
0116 
0117     /*
0118      * Use the number of cores to determine the last 2 digits of
0119      * the model number. There are some exceptions that are fixed
0120      * later.
0121      */
0122     switch (num_cores) {
0123     case 48:
0124         core_model = "90";
0125         break;
0126     case 44:
0127         core_model = "88";
0128         break;
0129     case 40:
0130         core_model = "85";
0131         break;
0132     case 32:
0133         core_model = "80";
0134         break;
0135     case 24:
0136         core_model = "70";
0137         break;
0138     case 16:
0139         core_model = "60";
0140         break;
0141     case 15:
0142         core_model = "58";
0143         break;
0144     case 14:
0145         core_model = "55";
0146         break;
0147     case 13:
0148         core_model = "52";
0149         break;
0150     case 12:
0151         core_model = "50";
0152         break;
0153     case 11:
0154         core_model = "48";
0155         break;
0156     case 10:
0157         core_model = "45";
0158         break;
0159     case 9:
0160         core_model = "42";
0161         break;
0162     case 8:
0163         core_model = "40";
0164         break;
0165     case 7:
0166         core_model = "38";
0167         break;
0168     case 6:
0169         core_model = "34";
0170         break;
0171     case 5:
0172         core_model = "32";
0173         break;
0174     case 4:
0175         core_model = "30";
0176         break;
0177     case 3:
0178         core_model = "25";
0179         break;
0180     case 2:
0181         core_model = "20";
0182         break;
0183     case 1:
0184         core_model = "10";
0185         break;
0186     default:
0187         core_model = "XX";
0188         break;
0189     }
0190 
0191     /* Now figure out the family, the first two digits */
0192     switch ((chip_id >> 8) & 0xff) {
0193     case 0:     /* CN38XX, CN37XX or CN36XX */
0194         if (l2d_fus3) {
0195             /*
0196              * For some unknown reason, the 16 core one is
0197              * called 37 instead of 36.
0198              */
0199             if (num_cores >= 16)
0200                 family = "37";
0201             else
0202                 family = "36";
0203         } else
0204             family = "38";
0205         /*
0206          * This series of chips didn't follow the standard
0207          * pass numbering.
0208          */
0209         switch (chip_id & 0xf) {
0210         case 0:
0211             strcpy(pass, "1.X");
0212             break;
0213         case 1:
0214             strcpy(pass, "2.X");
0215             break;
0216         case 3:
0217             strcpy(pass, "3.X");
0218             break;
0219         default:
0220             strcpy(pass, "X.X");
0221             break;
0222         }
0223         break;
0224     case 1:     /* CN31XX or CN3020 */
0225         if ((chip_id & 0x10) || l2d_fus3)
0226             family = "30";
0227         else
0228             family = "31";
0229         /*
0230          * This series of chips didn't follow the standard
0231          * pass numbering.
0232          */
0233         switch (chip_id & 0xf) {
0234         case 0:
0235             strcpy(pass, "1.0");
0236             break;
0237         case 2:
0238             strcpy(pass, "1.1");
0239             break;
0240         default:
0241             strcpy(pass, "X.X");
0242             break;
0243         }
0244         break;
0245     case 2:     /* CN3010 or CN3005 */
0246         family = "30";
0247         /* A chip with half cache is an 05 */
0248         if (l2d_fus3)
0249             core_model = "05";
0250         /*
0251          * This series of chips didn't follow the standard
0252          * pass numbering.
0253          */
0254         switch (chip_id & 0xf) {
0255         case 0:
0256             strcpy(pass, "1.0");
0257             break;
0258         case 2:
0259             strcpy(pass, "1.1");
0260             break;
0261         default:
0262             strcpy(pass, "X.X");
0263             break;
0264         }
0265         break;
0266     case 3:     /* CN58XX */
0267         family = "58";
0268         /* Special case. 4 core, half cache (CP with half cache) */
0269         if ((num_cores == 4) && l2d_fus3 && !strncmp(suffix, "CP", 2))
0270             core_model = "29";
0271 
0272         /* Pass 1 uses different encodings for pass numbers */
0273         if ((chip_id & 0xFF) < 0x8) {
0274             switch (chip_id & 0x3) {
0275             case 0:
0276                 strcpy(pass, "1.0");
0277                 break;
0278             case 1:
0279                 strcpy(pass, "1.1");
0280                 break;
0281             case 3:
0282                 strcpy(pass, "1.2");
0283                 break;
0284             default:
0285                 strcpy(pass, "1.X");
0286                 break;
0287             }
0288         }
0289         break;
0290     case 4:     /* CN57XX, CN56XX, CN55XX, CN54XX */
0291         if (fus_dat2.cn56xx.raid_en) {
0292             if (l2d_fus3)
0293                 family = "55";
0294             else
0295                 family = "57";
0296             if (fus_dat2.cn56xx.nocrypto)
0297                 suffix = "SP";
0298             else
0299                 suffix = "SSP";
0300         } else {
0301             if (fus_dat2.cn56xx.nocrypto)
0302                 suffix = "CP";
0303             else {
0304                 suffix = "NSP";
0305                 if (fus_dat3.s.nozip)
0306                     suffix = "SCP";
0307 
0308                 if (fus_dat3.cn38xx.bar2_en)
0309                     suffix = "NSPB2";
0310             }
0311             if (l2d_fus3)
0312                 family = "54";
0313             else
0314                 family = "56";
0315         }
0316         break;
0317     case 6:     /* CN50XX */
0318         family = "50";
0319         break;
0320     case 7:     /* CN52XX */
0321         if (l2d_fus3)
0322             family = "51";
0323         else
0324             family = "52";
0325         break;
0326     case 0x93:      /* CN61XX */
0327         family = "61";
0328         if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
0329             suffix = "AP";
0330         if (fus_dat2.cn61xx.nocrypto)
0331             suffix = "CP";
0332         else if (fus_dat2.cn61xx.dorm_crypto)
0333             suffix = "DAP";
0334         else if (fus_dat3.cn61xx.nozip)
0335             suffix = "SCP";
0336         break;
0337     case 0x90:      /* CN63XX */
0338         family = "63";
0339         if (fus_dat3.s.l2c_crip == 2)
0340             family = "62";
0341         if (num_cores == 6) /* Other core counts match generic */
0342             core_model = "35";
0343         if (fus_dat2.cn63xx.nocrypto)
0344             suffix = "CP";
0345         else if (fus_dat2.cn63xx.dorm_crypto)
0346             suffix = "DAP";
0347         else if (fus_dat3.cn61xx.nozip)
0348             suffix = "SCP";
0349         else
0350             suffix = "AAP";
0351         break;
0352     case 0x92:      /* CN66XX */
0353         family = "66";
0354         if (num_cores == 6) /* Other core counts match generic */
0355             core_model = "35";
0356         if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
0357             suffix = "AP";
0358         if (fus_dat2.cn66xx.nocrypto)
0359             suffix = "CP";
0360         else if (fus_dat2.cn66xx.dorm_crypto)
0361             suffix = "DAP";
0362         else if (fus_dat3.cn61xx.nozip)
0363             suffix = "SCP";
0364         else
0365             suffix = "AAP";
0366         break;
0367     case 0x91:      /* CN68XX */
0368         family = "68";
0369         if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn61xx.nozip)
0370             suffix = "CP";
0371         else if (fus_dat2.cn68xx.dorm_crypto)
0372             suffix = "DAP";
0373         else if (fus_dat3.cn61xx.nozip)
0374             suffix = "SCP";
0375         else if (fus_dat2.cn68xx.nocrypto)
0376             suffix = "SP";
0377         else
0378             suffix = "AAP";
0379         break;
0380     case 0x94:      /* CNF71XX */
0381         family = "F71";
0382         if (fus_dat3.cn61xx.nozip)
0383             suffix = "SCP";
0384         else
0385             suffix = "AAP";
0386         break;
0387     case 0x95:      /* CN78XX */
0388         if (num_cores == 6) /* Other core counts match generic */
0389             core_model = "35";
0390         if (OCTEON_IS_MODEL(OCTEON_CN76XX))
0391             family = "76";
0392         else
0393             family = "78";
0394         if (fus_dat3.cn78xx.l2c_crip == 2)
0395             family = "77";
0396         if (fus_dat3.cn78xx.nozip
0397             && fus_dat3.cn78xx.nodfa_dte
0398             && fus_dat3.cn78xx.nohna_dte) {
0399             if (fus_dat3.cn78xx.nozip &&
0400                 !fus_dat2.cn78xx.raid_en &&
0401                 fus_dat3.cn78xx.nohna_dte) {
0402                 suffix = "CP";
0403             } else {
0404                 suffix = "SCP";
0405             }
0406         } else if (fus_dat2.cn78xx.raid_en == 0)
0407             suffix = "HCP";
0408         else
0409             suffix = "AAP";
0410         break;
0411     case 0x96:      /* CN70XX */
0412         family = "70";
0413         if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32))
0414             family = "71";
0415         if (fus_dat2.cn70xx.nocrypto)
0416             suffix = "CP";
0417         else if (fus_dat3.cn70xx.nodfa_dte)
0418             suffix = "SCP";
0419         else
0420             suffix = "AAP";
0421         break;
0422     case 0x97:      /* CN73XX */
0423         if (num_cores == 6) /* Other core counts match generic */
0424             core_model = "35";
0425         family = "73";
0426         if (fus_dat3.cn73xx.l2c_crip == 2)
0427             family = "72";
0428         if (fus_dat3.cn73xx.nozip
0429                 && fus_dat3.cn73xx.nodfa_dte
0430                 && fus_dat3.cn73xx.nohna_dte) {
0431             if (!fus_dat2.cn73xx.raid_en)
0432                 suffix = "CP";
0433             else
0434                 suffix = "SCP";
0435         } else
0436             suffix = "AAP";
0437         break;
0438     case 0x98:      /* CN75XX */
0439         family = "F75";
0440         if (fus_dat3.cn78xx.nozip
0441             && fus_dat3.cn78xx.nodfa_dte
0442             && fus_dat3.cn78xx.nohna_dte)
0443             suffix = "SCP";
0444         else
0445             suffix = "AAP";
0446         break;
0447     default:
0448         family = "XX";
0449         core_model = "XX";
0450         strcpy(pass, "X.X");
0451         suffix = "XXX";
0452         break;
0453     }
0454 
0455     clock_mhz = octeon_get_clock_rate() / 1000000;
0456     if (family[0] != '3') {
0457         int fuse_base = 384 / 8;
0458         if (family[0] == '6')
0459             fuse_base = 832 / 8;
0460 
0461         /* Check for model in fuses, overrides normal decode */
0462         /* This is _not_ valid for Octeon CN3XXX models */
0463         fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
0464         fuse_data = fuse_data << 8;
0465         fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
0466         fuse_data = fuse_data << 8;
0467         fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
0468         fuse_data = fuse_data << 8;
0469         fuse_data |= cvmx_fuse_read_byte(fuse_base);
0470         if (fuse_data & 0x7ffff) {
0471             int model = fuse_data & 0x3fff;
0472             int suffix = (fuse_data >> 14) & 0x1f;
0473             if (suffix && model) {
0474                 /* Have both number and suffix in fuses, so both */
0475                 sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
0476                 core_model = "";
0477                 family = fuse_model;
0478             } else if (suffix && !model) {
0479                 /* Only have suffix, so add suffix to 'normal' model number */
0480                 sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
0481                 core_model = fuse_model;
0482             } else {
0483                 /* Don't have suffix, so just use model from fuses */
0484                 sprintf(fuse_model, "%d", model);
0485                 core_model = "";
0486                 family = fuse_model;
0487             }
0488         }
0489     }
0490     sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
0491     return buffer;
0492 }
0493 
0494 /**
0495  * Given the chip processor ID from COP0, this function returns a
0496  * string representing the chip model number. The string is of the
0497  * form CNXXXXpX.X-FREQ-SUFFIX.
0498  * - XXXX = The chip model number
0499  * - X.X = Chip pass number
0500  * - FREQ = Current frequency in Mhz
0501  * - SUFFIX = NSP, EXP, SCP, SSP, or CP
0502  *
0503  * @chip_id: Chip ID
0504  *
0505  * Returns Model string
0506  */
0507 const char *__init octeon_model_get_string(uint32_t chip_id)
0508 {
0509     static char buffer[32];
0510     return octeon_model_get_string_buffer(chip_id, buffer);
0511 }