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