xref: /dpdk/drivers/common/cnxk/roc_model.c (revision b315581c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include <fcntl.h>
6 #include <unistd.h>
7 
8 #include "roc_api.h"
9 #include "roc_priv.h"
10 
11 struct roc_model *roc_model;
12 
13 /* RoC and CPU IDs and revisions */
14 #define VENDOR_ARM    0x41 /* 'A' */
15 #define VENDOR_CAVIUM 0x43 /* 'C' */
16 
17 #define SOC_PART_CN10K 0xD49
18 
19 #define PART_106xx  0xB9
20 #define PART_105xx  0xBA
21 #define PART_105xxN 0xBC
22 #define PART_98xx   0xB1
23 #define PART_96xx   0xB2
24 #define PART_95xx   0xB3
25 #define PART_95xxN  0xB4
26 #define PART_95xxMM 0xB5
27 #define PART_95O    0xB6
28 
29 #define MODEL_IMPL_BITS	  8
30 #define MODEL_IMPL_SHIFT  24
31 #define MODEL_IMPL_MASK	  ((1 << MODEL_IMPL_BITS) - 1)
32 #define MODEL_PART_BITS	  12
33 #define MODEL_PART_SHIFT  4
34 #define MODEL_PART_MASK	  ((1 << MODEL_PART_BITS) - 1)
35 #define MODEL_MAJOR_BITS  4
36 #define MODEL_MAJOR_SHIFT 20
37 #define MODEL_MAJOR_MASK  ((1 << MODEL_MAJOR_BITS) - 1)
38 #define MODEL_MINOR_BITS  4
39 #define MODEL_MINOR_SHIFT 0
40 #define MODEL_MINOR_MASK  ((1 << MODEL_MINOR_BITS) - 1)
41 
42 static const struct model_db {
43 	uint32_t impl;
44 	uint32_t part;
45 	uint32_t major;
46 	uint32_t minor;
47 	uint64_t flag;
48 	char name[ROC_MODEL_STR_LEN_MAX];
49 } model_db[] = {
50 	{VENDOR_ARM, PART_106xx, 0, 0, ROC_MODEL_CN106xx_A0, "cn10ka_a0"},
51 	{VENDOR_ARM, PART_105xx, 0, 0, ROC_MODEL_CNF105xx_A0, "cnf10ka_a0"},
52 	{VENDOR_ARM, PART_105xxN, 0, 0, ROC_MODEL_CNF105xxN_A0, "cnf10kb_a0"},
53 	{VENDOR_CAVIUM, PART_98xx, 0, 0, ROC_MODEL_CN98xx_A0, "cn98xx_a0"},
54 	{VENDOR_CAVIUM, PART_96xx, 0, 0, ROC_MODEL_CN96xx_A0, "cn96xx_a0"},
55 	{VENDOR_CAVIUM, PART_96xx, 0, 1, ROC_MODEL_CN96xx_B0, "cn96xx_b0"},
56 	{VENDOR_CAVIUM, PART_96xx, 2, 0, ROC_MODEL_CN96xx_C0, "cn96xx_c0"},
57 	{VENDOR_CAVIUM, PART_96xx, 2, 1, ROC_MODEL_CN96xx_C0, "cn96xx_c1"},
58 	{VENDOR_CAVIUM, PART_95xx, 0, 0, ROC_MODEL_CNF95xx_A0, "cnf95xx_a0"},
59 	{VENDOR_CAVIUM, PART_95xx, 1, 0, ROC_MODEL_CNF95xx_B0, "cnf95xx_b0"},
60 	{VENDOR_CAVIUM, PART_95xxN, 0, 0, ROC_MODEL_CNF95xxN_A0, "cnf95xxn_a0"},
61 	{VENDOR_CAVIUM, PART_95xxN, 0, 1, ROC_MODEL_CNF95xxN_A0, "cnf95xxn_a1"},
62 	{VENDOR_CAVIUM, PART_95xxN, 1, 0, ROC_MODEL_CNF95xxN_B0, "cnf95xxn_b0"},
63 	{VENDOR_CAVIUM, PART_95O, 0, 0, ROC_MODEL_CNF95xxO_A0, "cnf95O_a0"},
64 	{VENDOR_CAVIUM, PART_95xxMM, 0, 0, ROC_MODEL_CNF95xxMM_A0,
65 	 "cnf95xxmm_a0"}};
66 
67 static uint32_t
cn10k_part_get(void)68 cn10k_part_get(void)
69 {
70 	uint32_t soc = 0x0;
71 	char buf[BUFSIZ];
72 	char *ptr;
73 	FILE *fd;
74 
75 	/* Read the CPU compatible variant */
76 	fd = fopen("/proc/device-tree/compatible", "r");
77 	if (!fd) {
78 		plt_err("Failed to open /proc/device-tree/compatible");
79 		goto err;
80 	}
81 
82 	if (fgets(buf, sizeof(buf), fd) == NULL) {
83 		plt_err("Failed to read from /proc/device-tree/compatible");
84 		goto fclose;
85 	}
86 	ptr = strchr(buf, ',');
87 	if (!ptr) {
88 		plt_err("Malformed 'CPU compatible': <%s>", buf);
89 		goto fclose;
90 	}
91 	ptr++;
92 	if (strcmp("cn10ka", ptr) == 0) {
93 		soc = PART_106xx;
94 	} else if (strcmp("cnf10ka", ptr) == 0) {
95 		soc = PART_105xx;
96 	} else if (strcmp("cnf10kb", ptr) == 0) {
97 		soc = PART_105xxN;
98 	} else {
99 		plt_err("Unidentified 'CPU compatible': <%s>", ptr);
100 		goto fclose;
101 	}
102 
103 fclose:
104 	fclose(fd);
105 
106 err:
107 	return soc;
108 }
109 
110 static bool
populate_model(struct roc_model * model,uint32_t midr)111 populate_model(struct roc_model *model, uint32_t midr)
112 {
113 	uint32_t impl, major, part, minor;
114 	bool found = false;
115 	size_t i;
116 
117 	impl = (midr >> MODEL_IMPL_SHIFT) & MODEL_IMPL_MASK;
118 	part = (midr >> MODEL_PART_SHIFT) & MODEL_PART_MASK;
119 	major = (midr >> MODEL_MAJOR_SHIFT) & MODEL_MAJOR_MASK;
120 	minor = (midr >> MODEL_MINOR_SHIFT) & MODEL_MINOR_MASK;
121 
122 	/* Update part number for cn10k from device-tree */
123 	if (part == SOC_PART_CN10K)
124 		part = cn10k_part_get();
125 
126 	for (i = 0; i < PLT_DIM(model_db); i++)
127 		if (model_db[i].impl == impl && model_db[i].part == part &&
128 		    model_db[i].major == major && model_db[i].minor == minor) {
129 			model->flag = model_db[i].flag;
130 			strncpy(model->name, model_db[i].name,
131 				ROC_MODEL_STR_LEN_MAX - 1);
132 			found = true;
133 			break;
134 		}
135 
136 	if (!found) {
137 		model->flag = 0;
138 		strncpy(model->name, "unknown", ROC_MODEL_STR_LEN_MAX - 1);
139 		plt_err("Invalid RoC model (impl=0x%x, part=0x%x, major=0x%x, minor=0x%x)",
140 			impl, part, major, minor);
141 	}
142 
143 	return found;
144 }
145 
146 static int
midr_get(unsigned long * val)147 midr_get(unsigned long *val)
148 {
149 	const char *file =
150 		"/sys/devices/system/cpu/cpu0/regs/identification/midr_el1";
151 	int rc = UTIL_ERR_FS;
152 	char buf[BUFSIZ];
153 	char *end = NULL;
154 	FILE *f;
155 
156 	if (val == NULL)
157 		goto err;
158 	f = fopen(file, "r");
159 	if (f == NULL)
160 		goto err;
161 
162 	if (fgets(buf, sizeof(buf), f) == NULL)
163 		goto fclose;
164 
165 	*val = strtoul(buf, &end, 0);
166 	if ((buf[0] == '\0') || (end == NULL) || (*end != '\n'))
167 		goto fclose;
168 
169 	rc = 0;
170 fclose:
171 	fclose(f);
172 err:
173 	return rc;
174 }
175 
176 static void
detect_invalid_config(void)177 detect_invalid_config(void)
178 {
179 #ifdef ROC_PLATFORM_CN9K
180 #ifdef ROC_PLATFORM_CN10K
181 	PLT_STATIC_ASSERT(0);
182 #endif
183 #endif
184 }
185 
186 static uint64_t
env_lookup_flag(const char * name)187 env_lookup_flag(const char *name)
188 {
189 	unsigned int i;
190 	struct {
191 		const char *name;
192 		uint64_t flag;
193 	} envs[] = {
194 		{"HW_PLATFORM", ROC_ENV_HW},
195 		{"EMUL_PLATFORM", ROC_ENV_EMUL},
196 		{"ASIM_PLATFORM", ROC_ENV_ASIM},
197 	};
198 
199 	for (i = 0; i < PLT_DIM(envs); i++)
200 		if (!strncmp(envs[i].name, name, strlen(envs[i].name)))
201 			return envs[i].flag;
202 
203 	return 0;
204 }
205 
206 static void
of_env_get(struct roc_model * model)207 of_env_get(struct roc_model *model)
208 {
209 	const char *const path = "/proc/device-tree/soc@0/runplatform";
210 	uint64_t flag;
211 	FILE *fp;
212 
213 	if (access(path, F_OK) != 0) {
214 		strncpy(model->env, "HW_PLATFORM", ROC_MODEL_STR_LEN_MAX - 1);
215 		model->flag |= ROC_ENV_HW;
216 		return;
217 	}
218 
219 	fp = fopen(path, "r");
220 	if (!fp) {
221 		plt_err("Failed to open %s", path);
222 		return;
223 	}
224 
225 	if (!fgets(model->env, sizeof(model->env), fp)) {
226 		plt_err("Failed to read %s", path);
227 		goto err;
228 	}
229 
230 	flag = env_lookup_flag(model->env);
231 	if (flag == 0) {
232 		plt_err("Unknown platform: %s", model->env);
233 		goto err;
234 	}
235 
236 	model->flag |= flag;
237 err:
238 	fclose(fp);
239 }
240 
241 int
roc_model_init(struct roc_model * model)242 roc_model_init(struct roc_model *model)
243 {
244 	int rc = UTIL_ERR_PARAM;
245 	unsigned long midr;
246 
247 	detect_invalid_config();
248 
249 	if (!model)
250 		goto err;
251 
252 	rc = midr_get(&midr);
253 	if (rc)
254 		goto err;
255 
256 	rc = UTIL_ERR_INVALID_MODEL;
257 	if (!populate_model(model, midr))
258 		goto err;
259 
260 	of_env_get(model);
261 
262 	rc = 0;
263 	plt_info("RoC Model: %s (%s)", model->name, model->env);
264 	roc_model = model;
265 err:
266 	return rc;
267 }
268