xref: /dpdk/drivers/common/cnxk/roc_model.c (revision b19f366c)
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