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_A0, "cn10ka_a0"}, 48 {VENDOR_ARM, PART_105xx, 0, 0, ROC_MODEL_CNF105xx_A0, "cnf10ka_a0"}, 49 {VENDOR_ARM, PART_105xxN, 0, 0, ROC_MODEL_CNF105xxN_A0, "cnf10kb_a0"}, 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_96xx, 2, 1, ROC_MODEL_CN96xx_C0, "cn96xx_c1"}, 55 {VENDOR_CAVIUM, PART_95xx, 0, 0, ROC_MODEL_CNF95xx_A0, "cnf95xx_a0"}, 56 {VENDOR_CAVIUM, PART_95xx, 1, 0, ROC_MODEL_CNF95xx_B0, "cnf95xx_b0"}, 57 {VENDOR_CAVIUM, PART_95xxN, 0, 0, ROC_MODEL_CNF95xxN_A0, "cnf95xxn_a0"}, 58 {VENDOR_CAVIUM, PART_95xxN, 0, 1, ROC_MODEL_CNF95xxN_A0, "cnf95xxn_a1"}, 59 {VENDOR_CAVIUM, PART_95O, 0, 0, ROC_MODEL_CNF95xxO_A0, "cnf95O_a0"}, 60 {VENDOR_CAVIUM, PART_95xxMM, 0, 0, ROC_MODEL_CNF95xxMM_A0, 61 "cnf95xxmm_a0"}}; 62 63 static uint32_t 64 cn10k_part_get(void) 65 { 66 uint32_t soc = 0x0; 67 char buf[BUFSIZ]; 68 char *ptr; 69 FILE *fd; 70 71 /* Read the CPU compatible variant */ 72 fd = fopen("/proc/device-tree/compatible", "r"); 73 if (!fd) { 74 plt_err("Failed to open /proc/device-tree/compatible"); 75 goto err; 76 } 77 78 if (fgets(buf, sizeof(buf), fd) == NULL) { 79 plt_err("Failed to read from /proc/device-tree/compatible"); 80 goto fclose; 81 } 82 ptr = strchr(buf, ','); 83 if (!ptr) { 84 plt_err("Malformed 'CPU compatible': <%s>", buf); 85 goto fclose; 86 } 87 ptr++; 88 if (strcmp("cn10ka", ptr) == 0) { 89 soc = PART_106xx; 90 } else if (strcmp("cnf10ka", ptr) == 0) { 91 soc = PART_105xx; 92 } else if (strcmp("cnf10kb", ptr) == 0) { 93 soc = PART_105xxN; 94 } else { 95 plt_err("Unidentified 'CPU compatible': <%s>", ptr); 96 goto fclose; 97 } 98 99 fclose: 100 fclose(fd); 101 102 err: 103 return soc; 104 } 105 106 static bool 107 populate_model(struct roc_model *model, uint32_t midr) 108 { 109 uint32_t impl, major, part, minor; 110 bool found = false; 111 size_t i; 112 113 impl = (midr >> MODEL_IMPL_SHIFT) & MODEL_IMPL_MASK; 114 part = (midr >> MODEL_PART_SHIFT) & MODEL_PART_MASK; 115 major = (midr >> MODEL_MAJOR_SHIFT) & MODEL_MAJOR_MASK; 116 minor = (midr >> MODEL_MINOR_SHIFT) & MODEL_MINOR_MASK; 117 118 /* Update part number for cn10k from device-tree */ 119 if (part == SOC_PART_CN10K) 120 part = cn10k_part_get(); 121 122 for (i = 0; i < PLT_DIM(model_db); i++) 123 if (model_db[i].impl == impl && model_db[i].part == part && 124 model_db[i].major == major && model_db[i].minor == minor) { 125 model->flag = model_db[i].flag; 126 strncpy(model->name, model_db[i].name, 127 ROC_MODEL_STR_LEN_MAX - 1); 128 found = true; 129 break; 130 } 131 132 if (!found) { 133 model->flag = 0; 134 strncpy(model->name, "unknown", ROC_MODEL_STR_LEN_MAX - 1); 135 plt_err("Invalid RoC model (impl=0x%x, part=0x%x)", impl, part); 136 } 137 138 return found; 139 } 140 141 static int 142 midr_get(unsigned long *val) 143 { 144 const char *file = 145 "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1"; 146 int rc = UTIL_ERR_FS; 147 char buf[BUFSIZ]; 148 char *end = NULL; 149 FILE *f; 150 151 if (val == NULL) 152 goto err; 153 f = fopen(file, "r"); 154 if (f == NULL) 155 goto err; 156 157 if (fgets(buf, sizeof(buf), f) == NULL) 158 goto fclose; 159 160 *val = strtoul(buf, &end, 0); 161 if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) 162 goto fclose; 163 164 rc = 0; 165 fclose: 166 fclose(f); 167 err: 168 return rc; 169 } 170 171 static void 172 detect_invalid_config(void) 173 { 174 #ifdef ROC_PLATFORM_CN9K 175 #ifdef ROC_PLATFORM_CN10K 176 PLT_STATIC_ASSERT(0); 177 #endif 178 #endif 179 } 180 181 static uint64_t 182 env_lookup_flag(const char *name) 183 { 184 unsigned int i; 185 struct { 186 const char *name; 187 uint64_t flag; 188 } envs[] = { 189 {"HW_PLATFORM", ROC_ENV_HW}, 190 {"EMUL_PLATFORM", ROC_ENV_EMUL}, 191 {"ASIM_PLATFORM", ROC_ENV_ASIM}, 192 }; 193 194 for (i = 0; i < PLT_DIM(envs); i++) 195 if (!strncmp(envs[i].name, name, strlen(envs[i].name))) 196 return envs[i].flag; 197 198 return 0; 199 } 200 201 static void 202 of_env_get(struct roc_model *model) 203 { 204 const char *const path = "/proc/device-tree/soc@0/runplatform"; 205 uint64_t flag; 206 FILE *fp; 207 208 fp = fopen(path, "r"); 209 if (!fp) { 210 plt_err("Failed to open %s", path); 211 return; 212 } 213 214 if (!fgets(model->env, sizeof(model->env), fp)) { 215 plt_err("Failed to read %s", path); 216 goto err; 217 } 218 219 flag = env_lookup_flag(model->env); 220 if (flag == 0) { 221 plt_err("Unknown platform: %s", model->env); 222 goto err; 223 } 224 225 model->flag |= flag; 226 err: 227 fclose(fp); 228 } 229 230 int 231 roc_model_init(struct roc_model *model) 232 { 233 int rc = UTIL_ERR_PARAM; 234 unsigned long midr; 235 236 detect_invalid_config(); 237 238 if (!model) 239 goto err; 240 241 rc = midr_get(&midr); 242 if (rc) 243 goto err; 244 245 rc = UTIL_ERR_INVALID_MODEL; 246 if (!populate_model(model, midr)) 247 goto err; 248 249 of_env_get(model); 250 251 rc = 0; 252 plt_info("RoC Model: %s (%s)", model->name, model->env); 253 roc_model = model; 254 err: 255 return rc; 256 } 257