1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
11 struct roc_model *roc_model;
13 /* RoC and CPU IDs and revisions */
14 #define VENDOR_ARM 0x41 /* 'A' */
15 #define VENDOR_CAVIUM 0x43 /* 'C' */
17 #define SOC_PART_CN10K 0xD49
19 #define PART_106xx 0xB9
20 #define PART_105xx 0xBA
21 #define PART_105xxN 0xBC
22 #define PART_103xx 0xBE
23 #define PART_98xx 0xB1
24 #define PART_96xx 0xB2
25 #define PART_95xx 0xB3
26 #define PART_95xxN 0xB4
27 #define PART_95xxMM 0xB5
30 #define MODEL_IMPL_BITS 8
31 #define MODEL_IMPL_SHIFT 24
32 #define MODEL_IMPL_MASK ((1 << MODEL_IMPL_BITS) - 1)
33 #define MODEL_PART_BITS 12
34 #define MODEL_PART_SHIFT 4
35 #define MODEL_PART_MASK ((1 << MODEL_PART_BITS) - 1)
36 #define MODEL_MAJOR_BITS 4
37 #define MODEL_MAJOR_SHIFT 20
38 #define MODEL_MAJOR_MASK ((1 << MODEL_MAJOR_BITS) - 1)
39 #define MODEL_MINOR_BITS 4
40 #define MODEL_MINOR_SHIFT 0
41 #define MODEL_MINOR_MASK ((1 << MODEL_MINOR_BITS) - 1)
43 static const struct model_db {
49 char name[ROC_MODEL_STR_LEN_MAX];
51 {VENDOR_ARM, PART_106xx, 0, 0, ROC_MODEL_CN106xx_A0, "cn10ka_a0"},
52 {VENDOR_ARM, PART_105xx, 0, 0, ROC_MODEL_CNF105xx_A0, "cnf10ka_a0"},
53 {VENDOR_ARM, PART_103xx, 0, 0, ROC_MODEL_CN103xx_A0, "cn10kb_a0"},
54 {VENDOR_ARM, PART_105xxN, 0, 0, ROC_MODEL_CNF105xxN_A0, "cnf10kb_a0"},
55 {VENDOR_CAVIUM, PART_98xx, 0, 0, ROC_MODEL_CN98xx_A0, "cn98xx_a0"},
56 {VENDOR_CAVIUM, PART_96xx, 0, 0, ROC_MODEL_CN96xx_A0, "cn96xx_a0"},
57 {VENDOR_CAVIUM, PART_96xx, 0, 1, ROC_MODEL_CN96xx_B0, "cn96xx_b0"},
58 {VENDOR_CAVIUM, PART_96xx, 2, 0, ROC_MODEL_CN96xx_C0, "cn96xx_c0"},
59 {VENDOR_CAVIUM, PART_96xx, 2, 1, ROC_MODEL_CN96xx_C0, "cn96xx_c1"},
60 {VENDOR_CAVIUM, PART_95xx, 0, 0, ROC_MODEL_CNF95xx_A0, "cnf95xx_a0"},
61 {VENDOR_CAVIUM, PART_95xx, 1, 0, ROC_MODEL_CNF95xx_B0, "cnf95xx_b0"},
62 {VENDOR_CAVIUM, PART_95xxN, 0, 0, ROC_MODEL_CNF95xxN_A0, "cnf95xxn_a0"},
63 {VENDOR_CAVIUM, PART_95xxN, 0, 1, ROC_MODEL_CNF95xxN_A0, "cnf95xxn_a1"},
64 {VENDOR_CAVIUM, PART_95xxN, 1, 0, ROC_MODEL_CNF95xxN_B0, "cnf95xxn_b0"},
65 {VENDOR_CAVIUM, PART_95O, 0, 0, ROC_MODEL_CNF95xxO_A0, "cnf95O_a0"},
66 {VENDOR_CAVIUM, PART_95xxMM, 0, 0, ROC_MODEL_CNF95xxMM_A0,
77 /* Read the CPU compatible variant */
78 fd = fopen("/proc/device-tree/compatible", "r");
80 plt_err("Failed to open /proc/device-tree/compatible");
84 if (fgets(buf, sizeof(buf), fd) == NULL) {
85 plt_err("Failed to read from /proc/device-tree/compatible");
88 ptr = strchr(buf, ',');
90 plt_err("Malformed 'CPU compatible': <%s>", buf);
94 if (strcmp("cn10ka", ptr) == 0) {
96 } else if (strcmp("cnf10ka", ptr) == 0) {
98 } else if (strcmp("cnf10kb", ptr) == 0) {
100 } else if (strcmp("cn10kb", ptr) == 0) {
103 plt_err("Unidentified 'CPU compatible': <%s>", ptr);
115 populate_model(struct roc_model *model, uint32_t midr)
117 uint32_t impl, major, part, minor;
121 impl = (midr >> MODEL_IMPL_SHIFT) & MODEL_IMPL_MASK;
122 part = (midr >> MODEL_PART_SHIFT) & MODEL_PART_MASK;
123 major = (midr >> MODEL_MAJOR_SHIFT) & MODEL_MAJOR_MASK;
124 minor = (midr >> MODEL_MINOR_SHIFT) & MODEL_MINOR_MASK;
126 /* Update part number for cn10k from device-tree */
127 if (part == SOC_PART_CN10K)
128 part = cn10k_part_get();
130 for (i = 0; i < PLT_DIM(model_db); i++)
131 if (model_db[i].impl == impl && model_db[i].part == part &&
132 model_db[i].major == major && model_db[i].minor == minor) {
133 model->flag = model_db[i].flag;
134 strncpy(model->name, model_db[i].name,
135 ROC_MODEL_STR_LEN_MAX - 1);
142 strncpy(model->name, "unknown", ROC_MODEL_STR_LEN_MAX - 1);
143 plt_err("Invalid RoC model (impl=0x%x, part=0x%x, major=0x%x, minor=0x%x)",
144 impl, part, major, minor);
151 midr_get(unsigned long *val)
154 "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1";
155 int rc = UTIL_ERR_FS;
162 f = fopen(file, "r");
166 if (fgets(buf, sizeof(buf), f) == NULL)
169 *val = strtoul(buf, &end, 0);
170 if ((buf[0] == '\0') || (end == NULL) || (*end != '\n'))
181 detect_invalid_config(void)
183 #ifdef ROC_PLATFORM_CN9K
184 #ifdef ROC_PLATFORM_CN10K
185 PLT_STATIC_ASSERT(0);
191 env_lookup_flag(const char *name)
198 {"HW_PLATFORM", ROC_ENV_HW},
199 {"EMUL_PLATFORM", ROC_ENV_EMUL},
200 {"ASIM_PLATFORM", ROC_ENV_ASIM},
203 for (i = 0; i < PLT_DIM(envs); i++)
204 if (!strncmp(envs[i].name, name, strlen(envs[i].name)))
211 of_env_get(struct roc_model *model)
213 const char *const path = "/proc/device-tree/soc@0/runplatform";
217 if (access(path, F_OK) != 0) {
218 strncpy(model->env, "HW_PLATFORM", ROC_MODEL_STR_LEN_MAX - 1);
219 model->flag |= ROC_ENV_HW;
223 fp = fopen(path, "r");
225 plt_err("Failed to open %s", path);
229 if (!fgets(model->env, sizeof(model->env), fp)) {
230 plt_err("Failed to read %s", path);
234 flag = env_lookup_flag(model->env);
236 plt_err("Unknown platform: %s", model->env);
246 roc_model_init(struct roc_model *model)
248 int rc = UTIL_ERR_PARAM;
251 detect_invalid_config();
256 rc = midr_get(&midr);
260 rc = UTIL_ERR_INVALID_MODEL;
261 if (!populate_model(model, midr))
267 plt_info("RoC Model: %s (%s)", model->name, model->env);