1
2
3
4
5#include "roc_api.h"
6#include "roc_priv.h"
7
8struct roc_model *roc_model;
9
10
11#define VENDOR_ARM 0x41
12#define VENDOR_CAVIUM 0x43
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
39static 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
62static uint32_t
63cn10k_part_get(void)
64{
65 uint32_t soc = 0x0;
66 char buf[BUFSIZ];
67 char *ptr;
68 FILE *fd;
69
70
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
98fclose:
99 fclose(fd);
100
101err:
102 return soc;
103}
104
105static bool
106populate_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
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
140static int
141midr_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;
164fclose:
165 fclose(f);
166err:
167 return rc;
168}
169
170static void
171detect_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
180int
181roc_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;
202err:
203 return rc;
204}
205