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