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