cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

octeon-model.c (11824B)


      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
     30enum octeon_feature_bits __octeon_feature_bits __read_mostly;
     31EXPORT_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 */
     39static 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 */
     58static 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 */
    507const 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}