1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2021 Marvell. 3 */ 4 5 #include "roc_api.h" 6 #include "roc_priv.h" 7 8 struct roc_model *roc_model; 9 10 /* RoC and CPU IDs and revisions */ 11 #define VENDOR_ARM 0x41 /* 'A' */ 12 #define VENDOR_CAVIUM 0x43 /* 'C' */ 13 14 #define SOC_PART_CN10K 0xD49 15 16 #define PART_106XX 0xB9 17 #define PART_105XX 0xBA 18 #define PART_105XXN 0xBC 19 #define PART_98XX 0xB1 20 #define PART_96XX 0xB2 21 #define PART_95XX 0xB3 22 #define PART_95XXN 0xB4 23 #define PART_95XXMM 0xB5 24 #define PART_95O 0xB6 25 26 #define MODEL_IMPL_BITS 8 27 #define MODEL_IMPL_SHIFT 24 28 #define MODEL_IMPL_MASK ((1 << MODEL_IMPL_BITS) - 1) 29 #define MODEL_PART_BITS 12 30 #define MODEL_PART_SHIFT 4 31 #define MODEL_PART_MASK ((1 << MODEL_PART_BITS) - 1) 32 #define MODEL_MAJOR_BITS 4 33 #define MODEL_MAJOR_SHIFT 20 34 #define MODEL_MAJOR_MASK ((1 << MODEL_MAJOR_BITS) - 1) 35 #define MODEL_MINOR_BITS 4 36 #define MODEL_MINOR_SHIFT 0 37 #define MODEL_MINOR_MASK ((1 << MODEL_MINOR_BITS) - 1) 38 39 static const struct model_db { 40 uint32_t impl; 41 uint32_t part; 42 uint32_t major; 43 uint32_t minor; 44 uint64_t flag; 45 char name[ROC_MODEL_STR_LEN_MAX]; 46 } model_db[] = { 47 {VENDOR_ARM, PART_106XX, 0, 0, ROC_MODEL_CN106XX, "cn10ka"}, 48 {VENDOR_ARM, PART_105XX, 0, 0, ROC_MODEL_CNF105XX, "cnf10ka"}, 49 {VENDOR_ARM, PART_105XXN, 0, 0, ROC_MODEL_CNF105XXN, "cnf10kb"}, 50 {VENDOR_CAVIUM, PART_98XX, 0, 0, ROC_MODEL_CN98xx_A0, "cn98xx_a0"}, 51 {VENDOR_CAVIUM, PART_96XX, 0, 0, ROC_MODEL_CN96xx_A0, "cn96xx_a0"}, 52 {VENDOR_CAVIUM, PART_96XX, 0, 1, ROC_MODEL_CN96xx_B0, "cn96xx_b0"}, 53 {VENDOR_CAVIUM, PART_96XX, 2, 0, ROC_MODEL_CN96xx_C0, "cn96xx_c0"}, 54 {VENDOR_CAVIUM, PART_95XX, 0, 0, ROC_MODEL_CNF95xx_A0, "cnf95xx_a0"}, 55 {VENDOR_CAVIUM, PART_95XX, 1, 0, ROC_MODEL_CNF95xx_B0, "cnf95xx_b0"}, 56 {VENDOR_CAVIUM, PART_95XXN, 0, 0, ROC_MODEL_CNF95XXN_A0, "cnf95xxn_a0"}, 57 {VENDOR_CAVIUM, PART_95O, 0, 0, ROC_MODEL_CNF95XXO_A0, "cnf95O_a0"}, 58 {VENDOR_CAVIUM, PART_95XXMM, 0, 0, ROC_MODEL_CNF95XXMM_A0, 59 "cnf95xxmm_a0"} 60 }; 61 62 static uint32_t 63 cn10k_part_get(void) 64 { 65 uint32_t soc = 0x0; 66 char buf[BUFSIZ]; 67 char *ptr; 68 FILE *fd; 69 70 /* Read the CPU compatible variant */ 71 fd = fopen("/proc/device-tree/compatible", "r"); 72 if (!fd) { 73 plt_err("Failed to open /proc/device-tree/compatible"); 74 goto err; 75 } 76 77 if (fgets(buf, sizeof(buf), fd) == NULL) { 78 plt_err("Failed to read from /proc/device-tree/compatible"); 79 goto fclose; 80 } 81 ptr = strchr(buf, ','); 82 if (!ptr) { 83 plt_err("Malformed 'CPU compatible': <%s>", buf); 84 goto fclose; 85 } 86 ptr++; 87 if (strcmp("cn10ka", ptr) == 0) { 88 soc = PART_106XX; 89 } else if (strcmp("cnf10ka", ptr) == 0) { 90 soc = PART_105XX; 91 } else if (strcmp("cnf10kb", ptr) == 0) { 92 soc = PART_105XXN; 93 } else { 94 plt_err("Unidentified 'CPU compatible': <%s>", ptr); 95 goto fclose; 96 } 97 98 fclose: 99 fclose(fd); 100 101 err: 102 return soc; 103 } 104 105 static bool 106 populate_model(struct roc_model *model, uint32_t midr) 107 { 108 uint32_t impl, major, part, minor; 109 bool found = false; 110 size_t i; 111 112 impl = (midr >> MODEL_IMPL_SHIFT) & MODEL_IMPL_MASK; 113 part = (midr >> MODEL_PART_SHIFT) & MODEL_PART_MASK; 114 major = (midr >> MODEL_MAJOR_SHIFT) & MODEL_MAJOR_MASK; 115 minor = (midr >> MODEL_MINOR_SHIFT) & MODEL_MINOR_MASK; 116 117 /* Update part number for cn10k from device-tree */ 118 if (part == SOC_PART_CN10K) 119 part = cn10k_part_get(); 120 121 for (i = 0; i < PLT_DIM(model_db); i++) 122 if (model_db[i].impl == impl && model_db[i].part == part && 123 model_db[i].major == major && model_db[i].minor == minor) { 124 model->flag = model_db[i].flag; 125 strncpy(model->name, model_db[i].name, 126 ROC_MODEL_STR_LEN_MAX - 1); 127 found = true; 128 break; 129 } 130 131 if (!found) { 132 model->flag = 0; 133 strncpy(model->name, "unknown", ROC_MODEL_STR_LEN_MAX - 1); 134 plt_err("Invalid RoC model (impl=0x%x, part=0x%x)", impl, part); 135 } 136 137 return found; 138 } 139 140 static int 141 midr_get(unsigned long *val) 142 { 143 const char *file = 144 "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1"; 145 int rc = UTIL_ERR_FS; 146 char buf[BUFSIZ]; 147 char *end = NULL; 148 FILE *f; 149 150 if (val == NULL) 151 goto err; 152 f = fopen(file, "r"); 153 if (f == NULL) 154 goto err; 155 156 if (fgets(buf, sizeof(buf), f) == NULL) 157 goto fclose; 158 159 *val = strtoul(buf, &end, 0); 160 if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) 161 goto fclose; 162 163 rc = 0; 164 fclose: 165 fclose(f); 166 err: 167 return rc; 168 } 169 170 static void 171 detect_invalid_config(void) 172 { 173 #ifdef ROC_PLATFORM_CN9K 174 #ifdef ROC_PLATFORM_CN10K 175 PLT_STATIC_ASSERT(0); 176 #endif 177 #endif 178 } 179 180 int 181 roc_model_init(struct roc_model *model) 182 { 183 int rc = UTIL_ERR_PARAM; 184 unsigned long midr; 185 186 detect_invalid_config(); 187 188 if (!model) 189 goto err; 190 191 rc = midr_get(&midr); 192 if (rc) 193 goto err; 194 195 rc = UTIL_ERR_INVALID_MODEL; 196 if (!populate_model(model, midr)) 197 goto err; 198 199 rc = 0; 200 plt_info("RoC Model: %s", model->name); 201 roc_model = model; 202 err: 203 return rc; 204 } 205