Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /* Copyright 2013-2019 IBM Corp. */
3 : :
4 : : #include <inttypes.h>
5 : : #include <device.h>
6 : : #include <cpu.h>
7 : : #include <vpd.h>
8 : : #include <interrupts.h>
9 : : #include <ccan/str/str.h>
10 : : #include <chip.h>
11 : : #include <opal-dump.h>
12 : : #include <fsp-attn.h>
13 : : #include <fsp-leds.h>
14 : : #include <skiboot.h>
15 : : #include <vas.h>
16 : :
17 : : #include "hdata.h"
18 : : #include "hostservices.h"
19 : : #include "naca.h"
20 : : #include "spira.h"
21 : :
22 : : /* Processor Initialization structure, contains
23 : : * the initial NIA and MSR values for the entry
24 : : * point
25 : : *
26 : : * Note: It appears to be ignoring the entry point
27 : : * and always going to 0x180
28 : : */
29 : :
30 : : static int cpu_type;
31 : :
32 : : extern struct proc_init_data proc_init_data;
33 : :
34 : : __section(".procin.data") struct proc_init_data proc_init_data = {
35 : : .hdr = HDIF_SIMPLE_HDR("PROCIN", 1, struct proc_init_data),
36 : : .regs_ptr = HDIF_IDATA_PTR(offsetof(struct proc_init_data, regs), 0x10),
37 : : .regs = {
38 : : .nia = CPU_TO_BE64(0x180),
39 : : .msr = CPU_TO_BE64(MSR_SF | MSR_HV),
40 : : },
41 : : };
42 : :
43 : : extern struct cpu_ctl_init_data cpu_ctl_init_data;
44 : : extern struct sp_addr_table cpu_ctl_spat_area;
45 : : extern struct sp_attn_area cpu_ctl_sp_attn_area1;
46 : : extern struct sp_attn_area cpu_ctl_sp_attn_area2;
47 : : extern struct hsr_data_area cpu_ctl_hsr_area;
48 : :
49 : : /*
50 : : * cpuctrl.data begins at CPU_CTL_OFF - cpu_ctl_init_data is located there.
51 : : * + sizeof(struct cpu_ctl_init_data) - cpu_ctl_spat_area
52 : : * + sizeof(struct sp_addr_table) - cpu_ctl_sp_attn_area1
53 : : * + sizeof(struct sp_attn_area) - cpu_ctl_sp_attn_area2
54 : : * + sizeof(struct sp_attn_area) - cpu_ctl_hsr_area
55 : : *
56 : : * Can't use CPU_TO_BE64 directly on the labels as a constant initialiser.
57 : : *
58 : : * CPU_CTL_INIT_DATA_OFF is offset from 0, the others are addressed from the
59 : : * relocated address (+SKIBOOT_BASE)
60 : : */
61 : : #define CPU_CTL_INIT_DATA_OFF (CPU_CTL_OFF)
62 : : #define CPU_CTL_SPAT_AREA_OFF (CPU_CTL_INIT_DATA_OFF + sizeof(struct cpu_ctl_init_data) + SKIBOOT_BASE)
63 : : #define CPU_CTL_SP_ATTN_AREA1_OFF (ALIGN_UP((CPU_CTL_SPAT_AREA_OFF + sizeof(struct sp_addr_table)), ATTN_AREA_SZ))
64 : : #define CPU_CTL_SP_ATTN_AREA2_OFF (CPU_CTL_SP_ATTN_AREA1_OFF + sizeof(struct sp_attn_area))
65 : : #define CPU_CTL_HSR_AREA_OFF (CPU_CTL_SP_ATTN_AREA2_OFF + sizeof(struct sp_attn_area))
66 : :
67 : : __section(".cpuctrl.data") struct hsr_data_area cpu_ctl_hsr_area;
68 : : __section(".cpuctrl.data") struct sp_attn_area cpu_ctl_sp_attn_area2;
69 : : __section(".cpuctrl.data") struct sp_attn_area cpu_ctl_sp_attn_area1;
70 : : __section(".cpuctrl.data") struct sp_addr_table cpu_ctl_spat_area;
71 : :
72 : : __section(".cpuctrl.data") struct cpu_ctl_init_data cpu_ctl_init_data = {
73 : : .hdr = HDIF_SIMPLE_HDR(CPU_CTL_HDIF_SIG, 2, struct cpu_ctl_init_data),
74 : : .cpu_ctl = HDIF_IDATA_PTR(offsetof(struct cpu_ctl_init_data, cpu_ctl_lt),
75 : : sizeof(struct cpu_ctl_legacy_table)),
76 : : .cpu_ctl_lt = {
77 : : .spat = {
78 : : .addr = CPU_TO_BE64(CPU_CTL_SPAT_AREA_OFF),
79 : : .size = CPU_TO_BE64(sizeof(struct sp_addr_table)),
80 : : },
81 : : .sp_attn_area1 = {
82 : : .addr = CPU_TO_BE64(CPU_CTL_SP_ATTN_AREA1_OFF),
83 : : .size = CPU_TO_BE64(sizeof(struct sp_attn_area)),
84 : : },
85 : : .sp_attn_area2 = {
86 : : .addr = CPU_TO_BE64(CPU_CTL_SP_ATTN_AREA2_OFF),
87 : : .size = CPU_TO_BE64(sizeof(struct sp_attn_area)),
88 : : },
89 : : .hsr_area = {
90 : : .addr = CPU_TO_BE64(CPU_CTL_HSR_AREA_OFF),
91 : : .size = CPU_TO_BE64(sizeof(struct hsr_data_area)),
92 : : },
93 : : },
94 : : };
95 : :
96 : : /* Populate MDST table
97 : : *
98 : : * Note that we only pass sapphire console buffer here so that we can
99 : : * capture early failure logs. Later dump component (fsp_dump_mdst_init)
100 : : * creates new table with all the memory sections we are interested and
101 : : * sends updated table to FSP via MBOX.
102 : : *
103 : : * To help the FSP distinguishing between TCE tokens and actual physical
104 : : * addresses, we set the top bit to 1 on physical addresses
105 : : */
106 : :
107 : : extern struct mdst_table init_mdst_table[];
108 : :
109 : : __section(".mdst.data") struct mdst_table init_mdst_table[2] = {
110 : : {
111 : : .addr = CPU_TO_BE64(INMEM_CON_START | HRMOR_BIT),
112 : : .data_region = DUMP_REGION_CONSOLE,
113 : : .dump_type = DUMP_TYPE_SYSDUMP,
114 : : .size = CPU_TO_BE32(INMEM_CON_LEN),
115 : : },
116 : : {
117 : : .addr = CPU_TO_BE64(HBRT_CON_START | HRMOR_BIT),
118 : : .data_region = DUMP_REGION_HBRT_LOG,
119 : : .dump_type = DUMP_TYPE_SYSDUMP,
120 : : .size = CPU_TO_BE32(HBRT_CON_LEN),
121 : : },
122 : : };
123 : :
124 : : /* The Hypervisor SPIRA-H Structure */
125 : : __section(".spirah.data") struct spirah spirah = {
126 : : .hdr = HDIF_SIMPLE_HDR(SPIRAH_HDIF_SIG, SPIRAH_VERSION, struct spirah),
127 : : .ntuples_ptr = HDIF_IDATA_PTR(offsetof(struct spirah, ntuples),
128 : : sizeof(struct spirah_ntuples)),
129 : : .ntuples = {
130 : : .array_hdr = {
131 : : .offset = CPU_TO_BE32(HDIF_ARRAY_OFFSET),
132 : : .ecnt = CPU_TO_BE32(SPIRAH_NTUPLES_COUNT),
133 : : .esize
134 : : = CPU_TO_BE32(sizeof(struct spira_ntuple)),
135 : : .eactsz = CPU_TO_BE32(0x18),
136 : : },
137 : : /* Host Data Areas */
138 : : .hs_data_area = {
139 : : .addr = CPU_TO_BE64(SPIRA_HEAP_BASE),
140 : : .alloc_cnt = CPU_TO_BE16(1),
141 : : .alloc_len = CPU_TO_BE32(SPIRA_HEAP_SIZE),
142 : : },
143 : : /* We only populate some n-tuples */
144 : : .proc_init = {
145 : : .addr = CPU_TO_BE64(PROCIN_OFF),
146 : : .alloc_cnt = CPU_TO_BE16(1),
147 : : .act_cnt = CPU_TO_BE16(1),
148 : : .alloc_len
149 : : = CPU_TO_BE32(sizeof(struct proc_init_data)),
150 : : },
151 : : .cpu_ctrl = {
152 : : .addr = CPU_TO_BE64(CPU_CTL_INIT_DATA_OFF),
153 : : .alloc_cnt = CPU_TO_BE16(1),
154 : : .act_cnt = CPU_TO_BE16(1),
155 : : .alloc_len =
156 : : CPU_TO_BE32(sizeof(cpu_ctl_init_data)),
157 : : },
158 : : .mdump_src = {
159 : : .addr = CPU_TO_BE64(MDST_TABLE_OFF),
160 : : .alloc_cnt = CPU_TO_BE16(MDST_TABLE_SIZE / sizeof(struct mdst_table)),
161 : : .act_cnt = CPU_TO_BE16(ARRAY_SIZE(init_mdst_table)),
162 : : .alloc_len = CPU_TO_BE32(sizeof(struct mdst_table)),
163 : : .act_len = CPU_TO_BE32(sizeof(struct mdst_table)),
164 : : },
165 : : .mdump_dst = {
166 : : .addr = CPU_TO_BE64(MDDT_TABLE_OFF),
167 : : .alloc_cnt = CPU_TO_BE16(MDDT_TABLE_SIZE / sizeof(struct mddt_table)),
168 : : .act_cnt = CPU_TO_BE16(0),
169 : : .alloc_len = CPU_TO_BE32(sizeof(struct mddt_table)),
170 : : .act_len = CPU_TO_BE32(sizeof(struct mddt_table)),
171 : : },
172 : : .mdump_res = {
173 : : .addr = CPU_TO_BE64(MDRT_TABLE_BASE),
174 : : .alloc_cnt = CPU_TO_BE16(MDRT_TABLE_SIZE / sizeof(struct mdrt_table)),
175 : : /*
176 : : * XXX: Ideally hostboot should use allocated count and
177 : : * length. But looks like hostboot uses actual count
178 : : * and length to get MDRT table size. And post dump
179 : : * hostboot will update act_cnt. Hence update both
180 : : * alloc_cnt and act_cnt.
181 : : */
182 : : .act_cnt = CPU_TO_BE16(MDRT_TABLE_SIZE / sizeof(struct mdrt_table)),
183 : : .alloc_len = CPU_TO_BE32(sizeof(struct mdrt_table)),
184 : : .act_len = CPU_TO_BE32(sizeof(struct mdrt_table)),
185 : : },
186 : : .proc_dump_area = {
187 : : .addr = CPU_TO_BE64(PROC_DUMP_AREA_OFF),
188 : : .alloc_cnt = CPU_TO_BE16(1),
189 : : .act_cnt = CPU_TO_BE16(1),
190 : : .alloc_len = CPU_TO_BE32(sizeof(struct proc_dump_area)),
191 : : .act_len = CPU_TO_BE32(sizeof(struct proc_dump_area)),
192 : : },
193 : : },
194 : : };
195 : :
196 : : /* The service processor SPIRA-S structure */
197 : : struct spiras *skiboot_constant_addr spiras;
198 : :
199 : : /* Overridden for testing. */
200 : : #ifndef spira_check_ptr
201 : : bool spira_check_ptr(const void *ptr, const char *file, unsigned int line)
202 : : {
203 : : if (!ptr)
204 : : return false;
205 : : if (((unsigned long)ptr) >= SPIRA_HEAP_BASE &&
206 : : ((unsigned long)ptr) < (SPIRA_HEAP_BASE + SPIRA_HEAP_SIZE))
207 : : return true;
208 : :
209 : : prerror("SPIRA: Bad pointer %p at %s line %d\n", ptr, file, line);
210 : : return false;
211 : : }
212 : : #endif
213 : :
214 : 216 : struct HDIF_common_hdr *__get_hdif(struct spira_ntuple *n, const char id[],
215 : : const char *file, int line)
216 : : {
217 : 216 : struct HDIF_common_hdr *h = ntuple_addr(n);
218 : : u16 act_cnt, alloc_cnt;
219 : : u32 act_len, alloc_len;
220 : :
221 : 216 : if (!spira_check_ptr(h, file, line))
222 : 1 : return NULL;
223 : :
224 : 215 : act_cnt = be16_to_cpu(n->act_cnt);
225 : 215 : alloc_cnt = be16_to_cpu(n->alloc_cnt);
226 : :
227 : 215 : if (act_cnt > alloc_cnt) {
228 : 0 : prerror("SPIRA: bad ntuple, act_cnt > alloc_cnt (%u > %u)\n",
229 : : act_cnt, alloc_cnt);
230 : 0 : return NULL;
231 : : }
232 : :
233 : 215 : act_len = be32_to_cpu(n->act_len);
234 : 215 : alloc_len = be32_to_cpu(n->alloc_len);
235 : :
236 : 215 : if (act_len > alloc_len) {
237 : 0 : prerror("SPIRA: bad ntuple, act_len > alloc_len (%u > %u)\n",
238 : : act_len, alloc_len);
239 : 0 : return NULL;
240 : : }
241 : :
242 : 215 : if (!HDIF_check(h, id)) {
243 : 0 : prerror("SPIRA: bad tuple %p: expected %s at %s line %d\n",
244 : : h, id, file, line);
245 : 0 : return NULL;
246 : : }
247 : 215 : return h;
248 : : }
249 : :
250 : 25 : uint32_t get_xscom_id(const struct sppcrd_chip_info *cinfo)
251 : : {
252 : 25 : if (proc_gen <= proc_gen_p9)
253 : 25 : return be32_to_cpu(cinfo->xscom_id);
254 : :
255 : : /* On P10 use Processor fabric topology id for chip id */
256 : 0 : return (uint32_t)(cinfo->fab_topology_id);
257 : : }
258 : :
259 : 2 : static struct dt_node *add_xscom_node(uint64_t base,
260 : : const struct sppcrd_chip_info *cinfo)
261 : : {
262 : : struct dt_node *node;
263 : : uint64_t addr, size;
264 : : uint64_t freq;
265 : 2 : uint32_t hw_id = get_xscom_id(cinfo);
266 : 2 : uint32_t proc_chip_id = be32_to_cpu(cinfo->proc_chip_id);
267 : :
268 : 2 : switch (proc_gen) {
269 : 2 : case proc_gen_p8:
270 : : /* On P8 all the chip SCOMs share single region */
271 : 2 : addr = base | ((uint64_t)hw_id << PPC_BITLSHIFT(28));
272 : 2 : break;
273 : 0 : case proc_gen_p9:
274 : : /* On P9 we need to put the chip ID in the natural powerbus
275 : : * position.
276 : : */
277 : 0 : addr = base | (((uint64_t)hw_id) << 42);
278 : 0 : break;
279 : 0 : case proc_gen_p10:
280 : : default:
281 : : /* Use Primary topology table index for xscom address */
282 : 0 : addr = base | (((uint64_t)cinfo->topology_id_table[cinfo->primary_topology_loc]) << 44);
283 : 0 : break;
284 : : };
285 : :
286 : 2 : size = (u64)1 << PPC_BITLSHIFT(28);
287 : :
288 : 2 : prlog(PR_INFO, "XSCOM: Found HW ID 0x%x (PCID 0x%x) @ 0x%llx\n",
289 : : hw_id, proc_chip_id, (long long)addr);
290 : :
291 : 2 : node = dt_new_addr(dt_root, "xscom", addr);
292 : 2 : assert(node);
293 : :
294 : 2 : dt_add_property_cells(node, "ibm,chip-id", hw_id);
295 : 2 : dt_add_property_cells(node, "ibm,proc-chip-id", proc_chip_id);
296 : 2 : dt_add_property_cells(node, "#address-cells", 1);
297 : 2 : dt_add_property_cells(node, "#size-cells", 1);
298 : 2 : dt_add_property(node, "scom-controller", NULL, 0);
299 : :
300 : 2 : switch(proc_gen) {
301 : 2 : case proc_gen_p8:
302 : 2 : dt_add_property_strings(node, "compatible",
303 : : "ibm,xscom", "ibm,power8-xscom");
304 : 2 : break;
305 : 0 : case proc_gen_p9:
306 : 0 : dt_add_property_strings(node, "compatible",
307 : : "ibm,xscom", "ibm,power9-xscom");
308 : 0 : break;
309 : 0 : case proc_gen_p10:
310 : 0 : dt_add_property_strings(node, "compatible",
311 : : "ibm,xscom", "ibm,power10-xscom");
312 : 0 : break;
313 : 0 : default:
314 : 0 : dt_add_property_strings(node, "compatible", "ibm,xscom");
315 : : }
316 : 2 : dt_add_property_u64s(node, "reg", addr, size);
317 : :
318 : : /*
319 : : * The bus-frequency of the xscom node is actually the PIB/PCB
320 : : * frequency. It is derived from the nest-clock via a 4:1 divider
321 : : */
322 : 2 : freq = dt_prop_get_u64_def(dt_root, "nest-frequency", 0);
323 : 2 : freq /= 4;
324 : 2 : if (freq)
325 : 2 : dt_add_property_u64(node, "bus-frequency", freq);
326 : :
327 : 2 : return node;
328 : : }
329 : :
330 : : /*
331 : : * Given a xscom@ node this will return a pointer into the SPPCRD
332 : : * structure corresponding to that node
333 : : */
334 : : #define GET_HDIF_HDR -1
335 : 0 : static const void *xscom_to_pcrd(struct dt_node *xscom, int idata_index)
336 : : {
337 : 0 : struct spira_ntuple *t = &spiras->ntuples.proc_chip;
338 : : const struct HDIF_common_hdr *hdif;
339 : : const void *idata;
340 : : unsigned int size;
341 : : uint32_t i;
342 : : void *base;
343 : :
344 : 0 : i = dt_prop_get_u32_def(xscom, DT_PRIVATE "sppcrd-index", 0xffffffff);
345 : 0 : if (i == 0xffffffff)
346 : 0 : return NULL;
347 : :
348 : 0 : base = get_hdif(t, "SPPCRD");
349 : 0 : assert(base);
350 : 0 : assert(i < be16_to_cpu(t->act_cnt));
351 : :
352 : 0 : hdif = base + i * be32_to_cpu(t->alloc_len);
353 : 0 : assert(hdif);
354 : :
355 : 0 : if (idata_index == GET_HDIF_HDR)
356 : 0 : return hdif;
357 : :
358 : 0 : idata = HDIF_get_idata(hdif, idata_index, &size);
359 : 0 : if (!idata || !size)
360 : 0 : return NULL;
361 : :
362 : 0 : return idata;
363 : : }
364 : :
365 : 6 : struct dt_node *find_xscom_for_chip(uint32_t chip_id)
366 : : {
367 : : struct dt_node *node;
368 : : uint32_t id;
369 : :
370 : 9 : dt_for_each_compatible(dt_root, node, "ibm,xscom") {
371 : 9 : id = dt_get_chip_id(node);
372 : 9 : if (id == chip_id)
373 : 6 : return node;
374 : : }
375 : :
376 : 0 : return NULL;
377 : : }
378 : :
379 : 2 : static void add_psihb_node(struct dt_node *np)
380 : : {
381 : : u32 psi_scom, psi_slen;
382 : : const char *psi_comp;
383 : :
384 : : /*
385 : : * We add a few things under XSCOM that aren't added
386 : : * by any other HDAT path
387 : : */
388 : :
389 : : /* PSI host bridge */
390 : 2 : switch(proc_gen) {
391 : 2 : case proc_gen_p8:
392 : 2 : psi_scom = 0x2010900;
393 : 2 : psi_slen = 0x20;
394 : 2 : psi_comp = "ibm,power8-psihb-x";
395 : 2 : break;
396 : 0 : case proc_gen_p9:
397 : 0 : psi_scom = 0x5012900;
398 : 0 : psi_slen = 0x100;
399 : 0 : psi_comp = "ibm,power9-psihb-x";
400 : 0 : break;
401 : 0 : case proc_gen_p10:
402 : 0 : psi_scom = 0x3011d00;
403 : 0 : psi_slen = 0x100;
404 : 0 : psi_comp = "ibm,power10-psihb-x";
405 : 0 : break;
406 : 0 : default:
407 : 0 : psi_comp = NULL;
408 : : }
409 : 2 : if (psi_comp) {
410 : : struct dt_node *psi_np;
411 : :
412 : 2 : psi_np = dt_new_addr(np, "psihb", psi_scom);
413 : 2 : if (!psi_np)
414 : 0 : return;
415 : :
416 : 2 : dt_add_property_cells(psi_np, "reg", psi_scom, psi_slen);
417 : 2 : dt_add_property_strings(psi_np, "compatible", psi_comp,
418 : : "ibm,psihb-x");
419 : : }
420 : : }
421 : :
422 : 0 : static void add_xive_node(struct dt_node *np)
423 : : {
424 : : struct dt_node *xive;
425 : : const char *comp;
426 : : u32 scom, slen;
427 : :
428 : 0 : switch (proc_gen) {
429 : 0 : case proc_gen_p9:
430 : 0 : scom = 0x5013000;
431 : 0 : slen = 0x300;
432 : 0 : comp = "ibm,power9-xive-x";
433 : 0 : break;
434 : 0 : case proc_gen_p10:
435 : 0 : scom = 0x2010800;
436 : 0 : slen = 0x400;
437 : 0 : comp = "ibm,power10-xive-x";
438 : 0 : break;
439 : 0 : default:
440 : 0 : return;
441 : : }
442 : :
443 : 0 : xive = dt_new_addr(np, "xive", scom);
444 : 0 : dt_add_property_cells(xive, "reg", scom, slen);
445 : 0 : dt_add_property_string(xive, "compatible", comp);
446 : :
447 : : /* HACK: required for simics */
448 : 0 : dt_add_property(xive, "force-assign-bars", NULL, 0);
449 : : }
450 : :
451 : 0 : static void add_vas_node(struct dt_node *np, int idx)
452 : : {
453 : : struct dt_node *vas;
454 : : const char *comp;
455 : : uint64_t base_addr;
456 : :
457 : 0 : if (proc_gen == proc_gen_p9) {
458 : 0 : base_addr = P9_VAS_SCOM_BASE_ADDR;
459 : 0 : comp = "ibm,power9-vas-x";
460 : : } else {
461 : 0 : base_addr = VAS_SCOM_BASE_ADDR;
462 : 0 : comp = "ibm,power10-vas-x";
463 : : }
464 : :
465 : 0 : vas = dt_new_addr(np, "vas", base_addr);
466 : 0 : dt_add_property_cells(vas, "reg", base_addr, 0x300);
467 : 0 : dt_add_property_string(vas, "compatible", comp);
468 : 0 : dt_add_property_cells(vas, "ibm,vas-id", idx);
469 : 0 : }
470 : :
471 : 0 : static void add_ecid_data(const struct HDIF_common_hdr *hdr,
472 : : struct dt_node *xscom)
473 : : {
474 : : char wafer_id[11];
475 : : uint8_t tmp;
476 : : int i;
477 : 0 : uint32_t size = 0;
478 : : struct sppcrd_ecid *ecid;
479 : : const struct HDIF_array_hdr *ec_hdr;
480 : :
481 : 0 : ec_hdr = HDIF_get_idata(hdr, SPPCRD_IDATA_EC_LEVEL, &size);
482 : 0 : if (!ec_hdr || !size)
483 : 0 : return;
484 : :
485 : 0 : ecid = (void *)ec_hdr + be32_to_cpu(ec_hdr->offset);
486 : 0 : dt_add_property_u64s(xscom, "ecid", be64_to_cpu(ecid->low),
487 : : be64_to_cpu(ecid->high));
488 : :
489 : : /*
490 : : * bits 4:63 of ECID data contains wafter ID data (ten 6 bit fields
491 : : * each containing a code).
492 : : */
493 : 0 : for (i = 0; i < 10; i++) {
494 : 0 : tmp = (u8)((be64_to_cpu(ecid->low) >> (i * 6)) & 0x3f);
495 : 0 : if (tmp <= 9)
496 : 0 : wafer_id[9 - i] = tmp + '0';
497 : 0 : else if (tmp >= 0xA && tmp <= 0x23)
498 : 0 : wafer_id[9 - i] = tmp + '0' + 7;
499 : 0 : else if (tmp == 0x3D)
500 : 0 : wafer_id[9 - i] = '-';
501 : 0 : else if (tmp == 0x3E)
502 : 0 : wafer_id[9 - i] = '.';
503 : 0 : else if (tmp == 0x3F)
504 : 0 : wafer_id[9 - i] = ' ';
505 : : else /* Unknown code */
506 : 0 : wafer_id[9 - i] = tmp + '0';
507 : : }
508 : 0 : wafer_id[10] = '\0';
509 : 0 : dt_add_property_nstr(xscom, "wafer-id", wafer_id, 10);
510 : :
511 : 0 : dt_add_property_cells(xscom, "wafer-location",
512 : : (u32)((be64_to_cpu(ecid->high) >> 56) & 0xff),
513 : : (u32)((be64_to_cpu(ecid->high) >> 48) & 0xff));
514 : : }
515 : :
516 : 2 : static void add_xscom_add_pcia_assoc(struct dt_node *np, uint32_t pcid)
517 : : {
518 : : const struct HDIF_common_hdr *hdr;
519 : : u32 size;
520 : :
521 : :
522 : : /*
523 : : * The SPPCRD doesn't contain all the affinity data, we have
524 : : * to dig it out of a core. I assume this is so that node
525 : : * affinity can be different for groups of cores within the
526 : : * chip, but for now we are going to ignore that
527 : : */
528 : 2 : hdr = get_hdif(&spiras->ntuples.pcia, SPPCIA_HDIF_SIG);
529 : 2 : if (!hdr)
530 : 2 : return;
531 : :
532 : 5 : for_each_pcia(spiras, hdr) {
533 : : const struct sppcia_core_unique *id;
534 : :
535 : 5 : id = HDIF_get_idata(hdr, SPPCIA_IDATA_CORE_UNIQUE, &size);
536 : 5 : if (!id || size < sizeof(*id))
537 : 3 : continue;
538 : :
539 : 5 : if (be32_to_cpu(id->proc_chip_id) != pcid)
540 : 3 : continue;
541 : :
542 : 2 : dt_add_property_cells(np, "ibm,ccm-node-id",
543 : : be32_to_cpu(id->ccm_node_id));
544 : 2 : dt_add_property_cells(np, "ibm,hw-card-id",
545 : : be32_to_cpu(id->hw_card_id));
546 : 2 : dt_add_property_cells(np, "ibm,hw-module-id",
547 : : be32_to_cpu(id->hw_module_id));
548 : 2 : if (!dt_find_property(np, "ibm,dbob-id"))
549 : 0 : dt_add_property_cells(np, "ibm,dbob-id",
550 : : be32_to_cpu(id->drawer_book_octant_blade_id));
551 : 2 : if (proc_gen < proc_gen_p9) {
552 : 2 : dt_add_property_cells(np, "ibm,mem-interleave-scope",
553 : : be32_to_cpu(id->memory_interleaving_scope));
554 : : }
555 : 2 : return;
556 : : }
557 : : }
558 : :
559 : 1 : static bool add_xscom_sppcrd(uint64_t xscom_base)
560 : : {
561 : : const struct HDIF_common_hdr *hdif;
562 : : unsigned int i, vpd_sz;
563 : : const void *vpd;
564 : : struct dt_node *np, *vpd_node;
565 : :
566 : 33 : for_each_ntuple_idx(&spiras->ntuples.proc_chip, hdif, i,
567 : : SPPCRD_HDIF_SIG) {
568 : : const struct sppcrd_chip_info *cinfo;
569 : 32 : const struct spira_fru_id *fru_id = NULL;
570 : : unsigned int csize;
571 : : u32 ve, version;
572 : :
573 : 32 : cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, &csize);
574 : 32 : if (!CHECK_SPPTR(cinfo)) {
575 : 0 : prerror("XSCOM: Bad ChipID data %d\n", i);
576 : 30 : continue;
577 : : }
578 : :
579 : 32 : ve = be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASK;
580 : 32 : ve >>= CHIP_VERIFY_SHIFT;
581 : 32 : if (ve == CHIP_VERIFY_NOT_INSTALLED ||
582 : : ve == CHIP_VERIFY_UNUSABLE)
583 : 30 : continue;
584 : :
585 : : /* Create the XSCOM node */
586 : 2 : np = add_xscom_node(xscom_base, cinfo);
587 : 2 : if (!np)
588 : 0 : continue;
589 : :
590 : :
591 : 2 : dt_add_property_cells(np, DT_PRIVATE "sppcrd-index", i);
592 : :
593 : 2 : version = be16_to_cpu(hdif->version);
594 : :
595 : : /* Version 0A has additional OCC related stuff */
596 : 2 : if (version >= 0x000a) {
597 : 2 : if (!dt_find_property(np, "ibm,dbob-id"))
598 : 2 : dt_add_property_cells(np, "ibm,dbob-id",
599 : : be32_to_cpu(cinfo->dbob_id));
600 : 2 : dt_add_property_cells(np, "ibm,occ-functional-state",
601 : : be32_to_cpu(cinfo->occ_state));
602 : : }
603 : :
604 : : /* Add chip VPD */
605 : 2 : vpd_node = dt_add_vpd_node(hdif, SPPCRD_IDATA_FRU_ID,
606 : : SPPCRD_IDATA_KW_VPD);
607 : 2 : if (vpd_node)
608 : 2 : dt_add_property_cells(vpd_node, "ibm,chip-id",
609 : : get_xscom_id(cinfo));
610 : :
611 : 2 : fru_id = HDIF_get_idata(hdif, SPPCRD_IDATA_FRU_ID, NULL);
612 : 2 : if (fru_id)
613 : 2 : slca_vpd_add_loc_code(np, be16_to_cpu(fru_id->slca_index));
614 : :
615 : : /* Add module VPD on version A and later */
616 : 2 : if (version >= 0x000a) {
617 : 2 : vpd = HDIF_get_idata(hdif, SPPCRD_IDATA_MODULE_VPD,
618 : : &vpd_sz);
619 : 2 : if (CHECK_SPPTR(vpd)) {
620 : 2 : dt_add_property(np, "ibm,module-vpd", vpd,
621 : : vpd_sz);
622 : 2 : vpd_data_parse(np, vpd, vpd_sz);
623 : 2 : if (vpd_node)
624 : 2 : dt_add_proc_vendor(vpd_node, vpd, vpd_sz);
625 : : }
626 : : }
627 : :
628 : : /*
629 : : * Extract additional associativity information from
630 : : * the core data. Pick one core on that chip
631 : : */
632 : 2 : add_xscom_add_pcia_assoc(np, be32_to_cpu(cinfo->proc_chip_id));
633 : :
634 : : /* Add PSI Host bridge */
635 : 2 : add_psihb_node(np);
636 : :
637 : 2 : if (proc_gen >= proc_gen_p9) {
638 : 0 : add_xive_node(np);
639 : 0 : parse_i2c_devs(hdif, SPPCRD_IDATA_HOST_I2C, np);
640 : 0 : add_vas_node(np, i);
641 : 0 : add_ecid_data(hdif, np);
642 : :
643 : 0 : if (be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASTER_PROC)
644 : 0 : dt_add_property(np, "primary", NULL, 0);
645 : : }
646 : :
647 : : /*
648 : : * Add sw checkstop scom address (ibm,sw-checkstop-fir)
649 : : *
650 : : * The latest HDAT versions have sw checkstop scom address
651 : : * info. But not sure from which version onwards (at least
652 : : * HDAT spec do not mention that explicitly). Hence use the
653 : : * sppcrd struct size returned by HDIF_get_idata to figure out
654 : : * whether it contains sw checkstop scom address info. Also
655 : : * check if sw_xstop_fir_scom address is non-zero.
656 : : */
657 : 2 : if ((csize >= (offsetof(struct sppcrd_chip_info,
658 : 0 : sw_xstop_fir_bitpos) + 1)) &&
659 : 0 : cinfo->sw_xstop_fir_scom) {
660 : 0 : uint8_t fir_bit = cinfo->sw_xstop_fir_bitpos;
661 : :
662 : 0 : if (!dt_find_property(dt_root, "ibm,sw-checkstop-fir"))
663 : 0 : dt_add_property_cells(dt_root,
664 : : "ibm,sw-checkstop-fir",
665 : : be32_to_cpu(cinfo->sw_xstop_fir_scom),
666 : : fir_bit);
667 : : }
668 : :
669 : 2 : if (proc_gen >= proc_gen_p10) {
670 : 0 : uint8_t primary_loc = cinfo->primary_topology_loc;
671 : :
672 : 0 : if (primary_loc >= CHIP_MAX_TOPOLOGY_ENTRIES) {
673 : 0 : prerror("XSCOM: Invalid primary topology index %d\n",
674 : : primary_loc);
675 : 0 : continue;
676 : : }
677 : 0 : dt_add_property_cells(np, "ibm,primary-topology-index",
678 : : cinfo->topology_id_table[primary_loc]);
679 : : }
680 : : }
681 : :
682 : 1 : return i > 0;
683 : : }
684 : :
685 : 1 : static void add_xscom(void)
686 : : {
687 : : const void *ms_vpd;
688 : : const struct msvpd_pmover_bsr_synchro *pmbs;
689 : : unsigned int size;
690 : : uint64_t xscom_base;
691 : :
692 : 1 : ms_vpd = get_hdif(&spiras->ntuples.ms_vpd, MSVPD_HDIF_SIG);
693 : 1 : if (!ms_vpd) {
694 : 0 : prerror("XSCOM: Can't find MS VPD\n");
695 : 1 : return;
696 : : }
697 : :
698 : 1 : pmbs = HDIF_get_idata(ms_vpd, MSVPD_IDATA_PMOVER_SYNCHRO, &size);
699 : 1 : if (!CHECK_SPPTR(pmbs) || size < sizeof(*pmbs)) {
700 : 0 : prerror("XSCOM: absent or bad PMBS size %u @ %p\n", size, pmbs);
701 : 0 : return;
702 : : }
703 : :
704 : 1 : if (!(be32_to_cpu(pmbs->flags) & MSVPD_PMS_FLAG_XSCOMBASE_VALID)) {
705 : 0 : prerror("XSCOM: No XSCOM base in PMBS, using default\n");
706 : 0 : return;
707 : : }
708 : :
709 : 1 : xscom_base = be64_to_cpu(pmbs->xscom_addr);
710 : :
711 : : /* Get rid of the top bits */
712 : 1 : xscom_base = cleanup_addr(xscom_base);
713 : :
714 : : /* First, try the new proc_chip ntuples for chip data */
715 : 1 : if (add_xscom_sppcrd(xscom_base))
716 : 1 : return;
717 : : }
718 : :
719 : 2 : static void add_chiptod_node(unsigned int chip_id, int flags)
720 : : {
721 : : struct dt_node *node, *xscom_node;
722 : : const char *compat_str;
723 : : uint32_t addr, len;
724 : :
725 : 2 : if ((flags & CHIPTOD_ID_FLAGS_STATUS_MASK) !=
726 : : CHIPTOD_ID_FLAGS_STATUS_OK)
727 : 0 : return;
728 : :
729 : 2 : xscom_node = find_xscom_for_chip(chip_id);
730 : 2 : if (!xscom_node) {
731 : 0 : prerror("CHIPTOD: No xscom for chiptod %d?\n", chip_id);
732 : 0 : return;
733 : : }
734 : :
735 : 2 : addr = 0x40000;
736 : 2 : len = 0x34;
737 : :
738 : 2 : switch(proc_gen) {
739 : 2 : case proc_gen_p8:
740 : 2 : compat_str = "ibm,power8-chiptod";
741 : 2 : break;
742 : 0 : case proc_gen_p9:
743 : 0 : compat_str = "ibm,power9-chiptod";
744 : 0 : break;
745 : 0 : case proc_gen_p10:
746 : 0 : compat_str = "ibm,power10-chiptod";
747 : 0 : break;
748 : 0 : default:
749 : 0 : return;
750 : : }
751 : :
752 : 2 : prlog(PR_DEBUG, "CHIPTOD: Found on chip 0x%x %s\n", chip_id,
753 : : (flags & CHIPTOD_ID_FLAGS_PRIMARY) ? "[primary]" :
754 : : ((flags & CHIPTOD_ID_FLAGS_SECONDARY) ? "[secondary]" : ""));
755 : :
756 : 2 : node = dt_new_addr(xscom_node, "chiptod", addr);
757 : 2 : if (!node)
758 : 0 : return;
759 : :
760 : 2 : dt_add_property_cells(node, "reg", addr, len);
761 : 2 : dt_add_property_strings(node, "compatible", "ibm,power-chiptod",
762 : : compat_str);
763 : :
764 : 2 : if (flags & CHIPTOD_ID_FLAGS_PRIMARY)
765 : 1 : dt_add_property(node, "primary", NULL, 0);
766 : 2 : if (flags & CHIPTOD_ID_FLAGS_SECONDARY)
767 : 1 : dt_add_property(node, "secondary", NULL, 0);
768 : : }
769 : :
770 : 1 : static bool add_chiptod(void)
771 : : {
772 : : const void *hdif;
773 : : unsigned int i;
774 : 1 : bool found = false;
775 : :
776 : : /*
777 : : * Locate Proc Chip ID structures in SPIRA
778 : : */
779 : 1 : if (!get_hdif(&spiras->ntuples.proc_chip, SPPCRD_HDIF_SIG))
780 : 0 : return found;
781 : :
782 : 33 : for_each_ntuple_idx(&spiras->ntuples.proc_chip, hdif, i,
783 : : SPPCRD_HDIF_SIG) {
784 : : const struct sppcrd_chip_info *cinfo;
785 : : const struct sppcrd_chip_tod *tinfo;
786 : : unsigned int size;
787 : : u32 ve, flags;
788 : :
789 : 32 : cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
790 : 32 : if (!CHECK_SPPTR(cinfo)) {
791 : 0 : prerror("CHIPTOD: Bad ChipID data %d\n", i);
792 : 30 : continue;
793 : : }
794 : :
795 : 32 : ve = be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASK;
796 : 32 : ve >>= CHIP_VERIFY_SHIFT;
797 : 32 : if (ve == CHIP_VERIFY_NOT_INSTALLED ||
798 : : ve == CHIP_VERIFY_UNUSABLE)
799 : 30 : continue;
800 : :
801 : 2 : tinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_TOD, &size);
802 : 2 : if (!CHECK_SPPTR(tinfo)) {
803 : 0 : prerror("CHIPTOD: Bad TOD data %d\n", i);
804 : 0 : continue;
805 : : }
806 : :
807 : 2 : flags = be32_to_cpu(tinfo->flags);
808 : :
809 : : /* The FSP may strip the chiptod info from HDAT; if we find
810 : : * a zero-ed out entry, assume that the chiptod is
811 : : * present, but we don't have any primary/secondary info. In
812 : : * this case, pick chip zero as the master.
813 : : */
814 : 2 : if (!size) {
815 : 0 : flags = CHIPTOD_ID_FLAGS_STATUS_OK;
816 : 0 : if (be32_to_cpu(cinfo->xscom_id) == 0x0)
817 : 0 : flags |= CHIPTOD_ID_FLAGS_PRIMARY;
818 : : }
819 : :
820 : 2 : add_chiptod_node(get_xscom_id(cinfo), flags);
821 : 2 : found = true;
822 : : }
823 : 1 : return found;
824 : : }
825 : :
826 : 2 : static void add_nx_node(u32 gcid)
827 : : {
828 : : struct dt_node *nx;
829 : : u32 addr;
830 : : u32 size;
831 : : struct dt_node *xscom;
832 : :
833 : 2 : xscom = find_xscom_for_chip(gcid);
834 : 2 : if (xscom == NULL) {
835 : 0 : prerror("NX%d: did not found xscom node.\n", gcid);
836 : 0 : return;
837 : : }
838 : :
839 : : /*
840 : : * The NX register space is relatively self contained on P7+ but
841 : : * a bit more messy on P8. However it's all contained within the
842 : : * PB chiplet port 1 so we'll stick to that in the "reg" property
843 : : * and let the NX "driver" deal with the details.
844 : : */
845 : 2 : addr = 0x2010000;
846 : 2 : size = 0x0004000;
847 : :
848 : 2 : nx = dt_new_addr(xscom, "nx", addr);
849 : 2 : if (!nx)
850 : 0 : return;
851 : :
852 : 2 : switch (proc_gen) {
853 : 2 : case proc_gen_p8:
854 : 2 : dt_add_property_strings(nx, "compatible", "ibm,power-nx",
855 : : "ibm,power8-nx");
856 : 2 : break;
857 : 0 : case proc_gen_p9:
858 : : case proc_gen_p10:
859 : : /* POWER9 NX is not software compatible with P8 NX */
860 : 0 : dt_add_property_strings(nx, "compatible", "ibm,power9-nx");
861 : 0 : break;
862 : 0 : default:
863 : 0 : return;
864 : : }
865 : :
866 : 2 : dt_add_property_cells(nx, "reg", addr, size);
867 : : }
868 : :
869 : 1 : static void add_nx(void)
870 : : {
871 : : unsigned int i;
872 : : void *hdif;
873 : :
874 : 33 : for_each_ntuple_idx(&spiras->ntuples.proc_chip, hdif, i,
875 : : SPPCRD_HDIF_SIG) {
876 : : const struct sppcrd_chip_info *cinfo;
877 : : u32 ve;
878 : :
879 : 32 : cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
880 : 32 : if (!CHECK_SPPTR(cinfo)) {
881 : 0 : prerror("NX: Bad ChipID data %d\n", i);
882 : 0 : continue;
883 : : }
884 : :
885 : 32 : ve = be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASK;
886 : 32 : ve >>= CHIP_VERIFY_SHIFT;
887 : 32 : if (ve == CHIP_VERIFY_NOT_INSTALLED ||
888 : : ve == CHIP_VERIFY_UNUSABLE)
889 : 30 : continue;
890 : :
891 : 2 : if (cinfo->nx_state)
892 : 2 : add_nx_node(get_xscom_id(cinfo));
893 : : }
894 : 1 : }
895 : :
896 : 1 : static void add_nmmu(void)
897 : : {
898 : : struct dt_node *xscom, *nmmu;
899 : : u32 scom1, scom2;
900 : : u32 chip_id;
901 : :
902 : : /* Nest MMU only exists on POWER9 or later */
903 : 1 : if (proc_gen < proc_gen_p9)
904 : 1 : return;
905 : :
906 : 0 : if (proc_gen == proc_gen_p10) {
907 : 0 : scom1 = 0x2010c40;
908 : 0 : scom2 = 0x3010c40;
909 : : } else
910 : 0 : scom1 = 0x5012c40;
911 : :
912 : 0 : dt_for_each_compatible(dt_root, xscom, "ibm,xscom") {
913 : 0 : nmmu = dt_new_addr(xscom, "nmmu", scom1);
914 : 0 : dt_add_property_strings(nmmu, "compatible", "ibm,power9-nest-mmu");
915 : 0 : dt_add_property_cells(nmmu, "reg", scom1, 0x20);
916 : :
917 : : /*
918 : : * P10 has a second nMMU, a.k.a "south" nMMU.
919 : : * It exists only on P1 and P3
920 : : */
921 : 0 : if (proc_gen == proc_gen_p10) {
922 : :
923 : 0 : chip_id = __dt_get_chip_id(xscom);
924 : 0 : if (chip_id != 2 && chip_id != 6)
925 : 0 : continue;
926 : :
927 : 0 : nmmu = dt_new_addr(xscom, "nmmu", scom2);
928 : 0 : dt_add_property_strings(nmmu, "compatible", "ibm,power9-nest-mmu");
929 : 0 : dt_add_property_cells(nmmu, "reg", scom2, 0x20);
930 : : }
931 : : }
932 : : }
933 : :
934 : 0 : static void dt_init_secureboot_node(const struct iplparams_sysparams *sysparams)
935 : : {
936 : : struct dt_node *node;
937 : : u16 sys_sec_setting;
938 : : u16 hw_key_hash_size;
939 : : u16 host_fw_key_clear;
940 : :
941 : 0 : node = dt_new(dt_root, "ibm,secureboot");
942 : 0 : assert(node);
943 : :
944 : 0 : dt_add_property_strings(node, "compatible",
945 : : "ibm,secureboot", "ibm,secureboot-v2");
946 : :
947 : 0 : sys_sec_setting = be16_to_cpu(sysparams->sys_sec_setting);
948 : 0 : if (sys_sec_setting & SEC_CONTAINER_SIG_CHECKING)
949 : 0 : dt_add_property(node, "secure-enabled", NULL, 0);
950 : 0 : if (sys_sec_setting & SEC_HASHES_EXTENDED_TO_TPM)
951 : 0 : dt_add_property(node, "trusted-enabled", NULL, 0);
952 : 0 : if (sys_sec_setting & PHYSICAL_PRESENCE_ASSERTED)
953 : 0 : dt_add_property(node, "physical-presence-asserted", NULL, 0);
954 : :
955 : 0 : host_fw_key_clear = be16_to_cpu(sysparams->host_fw_key_clear);
956 : 0 : if (host_fw_key_clear & KEY_CLEAR_OS_KEYS)
957 : 0 : dt_add_property(node, "clear-os-keys", NULL, 0);
958 : 0 : if (host_fw_key_clear & KEY_CLEAR_MFG)
959 : 0 : dt_add_property(node, "clear-mfg-keys", NULL, 0);
960 : 0 : if (host_fw_key_clear & KEY_CLEAR_ALL)
961 : 0 : dt_add_property(node, "clear-all-keys", NULL, 0);
962 : :
963 : 0 : hw_key_hash_size = be16_to_cpu(sysparams->hw_key_hash_size);
964 : :
965 : : /* Prevent hw-key-hash buffer overflow by truncating hw-key-hash-size if
966 : : * it is bigger than the hw-key-hash buffer.
967 : : * Secure boot will be enforced later in skiboot, if the hw-key-hash-size
968 : : * was not supposed to be SYSPARAMS_HW_KEY_HASH_MAX.
969 : : */
970 : 0 : if (hw_key_hash_size > SYSPARAMS_HW_KEY_HASH_MAX) {
971 : 0 : prlog(PR_ERR, "IPLPARAMS: hw-key-hash-size=%d too big, "
972 : : "truncating to %d\n", hw_key_hash_size,
973 : : SYSPARAMS_HW_KEY_HASH_MAX);
974 : 0 : hw_key_hash_size = SYSPARAMS_HW_KEY_HASH_MAX;
975 : : }
976 : :
977 : 0 : dt_add_property(node, "hw-key-hash", sysparams->hw_key_hash,
978 : : hw_key_hash_size);
979 : 0 : dt_add_property_cells(node, "hw-key-hash-size", hw_key_hash_size);
980 : 0 : }
981 : :
982 : 1 : static void opal_dump_add_mpipl_boot(const struct iplparams_iplparams *p)
983 : : {
984 : 1 : u32 mdrt_cnt = be16_to_cpu(spirah.ntuples.mdump_res.act_cnt);
985 : 1 : u32 mdrt_max_cnt = MDRT_TABLE_SIZE / sizeof(struct mdrt_table);
986 : : struct dt_node *dump_node;
987 : :
988 : 1 : dump_node = dt_find_by_path(opal_node, "dump");
989 : 1 : if (!dump_node)
990 : 1 : return;
991 : :
992 : : /* Check boot params to detect MPIPL boot or not */
993 : 0 : if (p->cec_ipl_maj_type != IPLPARAMS_MAJ_TYPE_REIPL)
994 : 0 : return;
995 : :
996 : : /*
997 : : * On FSP system we get minor type as post dump IPL and on BMC system
998 : : * we get platform reboot. Hence lets check for both values.
999 : : */
1000 : 0 : if (p->cec_ipl_min_type != IPLPARAMS_MIN_TYPE_POST_DUMP &&
1001 : 0 : p->cec_ipl_min_type != IPLPARAMS_MIN_TYPE_PLAT_REBOOT) {
1002 : 0 : prlog(PR_NOTICE, "DUMP: Non MPIPL reboot "
1003 : : "[minor type = 0x%x]\n", p->cec_ipl_min_type);
1004 : 0 : return;
1005 : : }
1006 : :
1007 : 0 : if (be16_to_cpu(p->cec_ipl_attrib) != IPLPARAMS_ATTRIB_MEM_PRESERVE) {
1008 : 0 : prlog(PR_DEBUG, "DUMP: Memory not preserved\n");
1009 : 0 : return;
1010 : : }
1011 : :
1012 : 0 : if (mdrt_cnt == 0 || mdrt_cnt >= mdrt_max_cnt) {
1013 : 0 : prlog(PR_DEBUG, "DUMP: Invalid MDRT count : %x\n", mdrt_cnt);
1014 : 0 : return;
1015 : : }
1016 : :
1017 : 0 : prlog(PR_NOTICE, "DUMP: Dump found, MDRT count = 0x%x\n", mdrt_cnt);
1018 : :
1019 : 0 : dt_add_property(dump_node, "mpipl-boot", NULL, 0);
1020 : : }
1021 : :
1022 : 0 : static void add_opal_dump_node(void)
1023 : : {
1024 : : __be64 fw_load_area[4];
1025 : : struct dt_node *node;
1026 : :
1027 : 0 : opal_node = dt_new_check(dt_root, "ibm,opal");
1028 : 0 : node = dt_new(opal_node, "dump");
1029 : 0 : assert(node);
1030 : 0 : dt_add_property_string(node, "compatible", "ibm,opal-dump");
1031 : :
1032 : 0 : fw_load_area[0] = cpu_to_be64((u64)KERNEL_LOAD_BASE);
1033 : 0 : fw_load_area[1] = cpu_to_be64(KERNEL_LOAD_SIZE);
1034 : 0 : fw_load_area[2] = cpu_to_be64((u64)INITRAMFS_LOAD_BASE);
1035 : 0 : fw_load_area[3] = cpu_to_be64(INITRAMFS_LOAD_SIZE);
1036 : 0 : dt_add_property(node, "fw-load-area", fw_load_area, sizeof(fw_load_area));
1037 : 0 : }
1038 : :
1039 : 1 : static void add_iplparams_sys_params(const void *iplp, struct dt_node *node)
1040 : : {
1041 : : const struct iplparams_sysparams *p;
1042 : 1 : const struct HDIF_common_hdr *hdif = iplp;
1043 : 1 : u16 version = be16_to_cpu(hdif->version);
1044 : 1 : const char *vendor = NULL;
1045 : : u32 sys_attributes;
1046 : : u64 bus_speed;
1047 : :
1048 : 1 : p = HDIF_get_idata(iplp, IPLPARAMS_SYSPARAMS, NULL);
1049 : 1 : if (!CHECK_SPPTR(p)) {
1050 : 0 : prerror("IPLPARAMS: No SYS Parameters\n");
1051 : : /* Create a generic compatible property */
1052 : 0 : dt_add_property_string(dt_root, "compatible", "ibm,powernv");
1053 : 0 : return;
1054 : : }
1055 : :
1056 : 1 : node = dt_new(node, "sys-params");
1057 : 1 : assert(node);
1058 : 1 : dt_add_property_cells(node, "#address-cells", 0);
1059 : 1 : dt_add_property_cells(node, "#size-cells", 0);
1060 : :
1061 : 1 : dt_add_property_nstr(node, "ibm,sys-model", p->sys_model, 4);
1062 : :
1063 : : /*
1064 : : * Compatible has up to three entries:
1065 : : * "ibm,powernv", the system family and system type.
1066 : : *
1067 : : * On P9 and above the family and type strings come from the HDAT
1068 : : * directly. On P8 we find it from the system ID numbers.
1069 : : */
1070 : 1 : if (proc_gen >= proc_gen_p9) {
1071 : 0 : dt_add_property_strings(dt_root, "compatible", "ibm,powernv",
1072 : : p->sys_family_str, p->sys_type_str);
1073 : :
1074 : 0 : prlog(PR_INFO, "IPLPARAMS: v0x70 Platform family/type: %s/%s\n",
1075 : : p->sys_family_str, p->sys_type_str);
1076 : : } else {
1077 : 1 : u32 sys_type = be32_to_cpu(p->system_type);
1078 : : const char *sys_family;
1079 : :
1080 : 1 : switch (sys_type >> 28) {
1081 : 0 : case 0:
1082 : 0 : sys_family = "ibm,squadrons";
1083 : 0 : break;
1084 : 0 : case 1:
1085 : 0 : sys_family = "ibm,eclipz";
1086 : 0 : break;
1087 : 0 : case 2:
1088 : 0 : sys_family = "ibm,apollo";
1089 : 0 : break;
1090 : 1 : case 3:
1091 : 1 : sys_family = "ibm,firenze";
1092 : 1 : break;
1093 : 0 : default:
1094 : 0 : sys_family = NULL;
1095 : 0 : prerror("IPLPARAMS: Unknown system family\n");
1096 : 0 : break;
1097 : : }
1098 : :
1099 : 1 : dt_add_property_strings(dt_root, "compatible", "ibm,powernv",
1100 : : sys_family);
1101 : 1 : prlog(PR_INFO,
1102 : : "IPLPARAMS: Legacy platform family: %s"
1103 : : " (sys_type=0x%08x)\n", sys_family, sys_type);
1104 : : }
1105 : :
1106 : : /* Grab nest frequency when available */
1107 : 1 : if (version >= 0x005b) {
1108 : 1 : u64 freq = be32_to_cpu(p->nest_freq_mhz);
1109 : :
1110 : 1 : freq *= 1000000;
1111 : 1 : dt_add_property_u64(dt_root, "nest-frequency", freq);
1112 : : }
1113 : :
1114 : : /* Grab ABC bus speed */
1115 : 1 : bus_speed = be32_to_cpu(p->abc_bus_speed);
1116 : 1 : if (bus_speed)
1117 : 1 : dt_add_property_u64(node, "abc-bus-freq-mhz", bus_speed);
1118 : :
1119 : : /* Grab WXYZ bus speed */
1120 : 1 : bus_speed = be32_to_cpu(p->wxyz_bus_speed);
1121 : 1 : if (bus_speed)
1122 : 1 : dt_add_property_u64(node, "wxyz-bus-freq-mhz", bus_speed);
1123 : :
1124 : 1 : if (version >= 0x5f)
1125 : 1 : vendor = p->sys_vendor;
1126 : :
1127 : : /* Workaround a bug where we have NULL vendor */
1128 : 1 : if (!vendor || vendor[0] == '\0')
1129 : 1 : vendor = "IBM";
1130 : :
1131 : 1 : dt_add_property_string(dt_root, "vendor", vendor);
1132 : :
1133 : 1 : sys_attributes = be32_to_cpu(p->sys_attributes);
1134 : 1 : if (sys_attributes & SYS_ATTR_RISK_LEVEL)
1135 : 0 : dt_add_property(node, "elevated-risk-level", NULL, 0);
1136 : :
1137 : : /* Populate OPAL dump node */
1138 : 1 : if (sys_attributes & SYS_ATTR_MPIPL_SUPPORTED)
1139 : 0 : add_opal_dump_node();
1140 : :
1141 : 1 : if (version >= 0x60 && proc_gen >= proc_gen_p9)
1142 : 0 : dt_init_secureboot_node(p);
1143 : : }
1144 : :
1145 : 1 : static void add_iplparams_ipl_params(const void *iplp, struct dt_node *node)
1146 : : {
1147 : : const struct iplparams_iplparams *p;
1148 : : struct dt_node *led_node;
1149 : :
1150 : 1 : p = HDIF_get_idata(iplp, IPLPARAMS_IPLPARAMS, NULL);
1151 : 1 : if (!CHECK_SPPTR(p)) {
1152 : 0 : prerror("IPLPARAMS: No IPL Parameters\n");
1153 : 0 : return;
1154 : : }
1155 : :
1156 : 1 : node = dt_new(node, "ipl-params");
1157 : 1 : assert(node);
1158 : 1 : dt_add_property_cells(node, "#address-cells", 0);
1159 : 1 : dt_add_property_cells(node, "#size-cells", 0);
1160 : :
1161 : : /* On an ASM initiated factory reset, this bit will be set
1162 : : * and the FSP expects the firmware to reset the PCI bus
1163 : : * numbers and respond with a Power Down (CE,4D,02) message
1164 : : */
1165 : 1 : if (be32_to_cpu(p->other_attrib) & IPLPARAMS_OATTR_RST_PCI_BUSNO)
1166 : 0 : dt_add_property_cells(node, "pci-busno-reset-ipl", 1);
1167 : 1 : dt_add_property_strings(node, "cec-ipl-side",
1168 : : (p->ipl_side & IPLPARAMS_CEC_FW_IPL_SIDE_TEMP) ?
1169 : : "temp" : "perm");
1170 : 1 : if (proc_gen >= proc_gen_p9) {
1171 : 0 : dt_add_property_strings(node, "sp-ipl-side",
1172 : : (p->ipl_side & IPLPARAMS_FSP_FW_IPL_SIDE_TEMP) ?
1173 : : "temp" : "perm");
1174 : : } else {
1175 : 1 : dt_add_property_strings(node, "fsp-ipl-side",
1176 : : (p->ipl_side & IPLPARAMS_FSP_FW_IPL_SIDE_TEMP) ?
1177 : : "temp" : "perm");
1178 : : }
1179 : 1 : dt_add_property_cells(node, "os-ipl-mode", p->os_ipl_mode);
1180 : 1 : dt_add_property_strings(node, "cec-major-type",
1181 : : p->cec_ipl_maj_type ? "hot" : "cold");
1182 : :
1183 : : /* Add LED type info under '/ibm,opal/led' node */
1184 : 1 : led_node = dt_find_by_path(opal_node, DT_PROPERTY_LED_NODE);
1185 : 1 : assert(led_node);
1186 : :
1187 : 1 : if (be32_to_cpu(p->other_attrib) & IPLPARAMS_OATRR_LIGHT_PATH)
1188 : 1 : dt_add_property_strings(led_node, DT_PROPERTY_LED_MODE,
1189 : : LED_MODE_LIGHT_PATH);
1190 : : else
1191 : 0 : dt_add_property_strings(led_node, DT_PROPERTY_LED_MODE,
1192 : : LED_MODE_GUIDING_LIGHT);
1193 : :
1194 : : /* Populate opal dump result table */
1195 : 1 : opal_dump_add_mpipl_boot(p);
1196 : : }
1197 : :
1198 : 1 : static void add_iplparams_serials(const void *iplp, struct dt_node *node)
1199 : : {
1200 : : const struct iplparms_serial *ipser;
1201 : : struct dt_node *ser_node;
1202 : : int count, i;
1203 : :
1204 : 1 : count = HDIF_get_iarray_size(iplp, IPLPARMS_IDATA_SERIAL);
1205 : 1 : if (count <= 0)
1206 : 0 : return;
1207 : 1 : prlog(PR_INFO, "IPLPARAMS: %d serial ports in array\n", count);
1208 : :
1209 : 1 : node = dt_new(node, "fsp-serial");
1210 : 1 : assert(node);
1211 : 1 : dt_add_property_cells(node, "#address-cells", 1);
1212 : 1 : dt_add_property_cells(node, "#size-cells", 0);
1213 : :
1214 : 2 : for (i = 0; i < count; i++) {
1215 : : u16 rsrc_id;
1216 : 1 : ipser = HDIF_get_iarray_item(iplp, IPLPARMS_IDATA_SERIAL,
1217 : : i, NULL);
1218 : 1 : if (!CHECK_SPPTR(ipser))
1219 : 0 : continue;
1220 : 1 : rsrc_id = be16_to_cpu(ipser->rsrc_id);
1221 : 1 : prlog(PR_INFO, "IPLPARAMS: Serial %d rsrc: %04x loc: %s\n",
1222 : : i, rsrc_id, ipser->loc_code);
1223 : 1 : ser_node = dt_new_addr(node, "serial", rsrc_id);
1224 : 1 : if (!ser_node)
1225 : 0 : continue;
1226 : :
1227 : 1 : dt_add_property_cells(ser_node, "reg", rsrc_id);
1228 : 1 : dt_add_property_nstr(ser_node, "ibm,loc-code",
1229 : 1 : ipser->loc_code, LOC_CODE_SIZE);
1230 : 1 : dt_add_property_string(ser_node, "compatible",
1231 : : "ibm,fsp-serial");
1232 : : /* XXX handle CALLHOME flag ? */
1233 : : }
1234 : : }
1235 : :
1236 : : /*
1237 : : * Check for platform dump, if present populate DT
1238 : : */
1239 : 1 : static void add_iplparams_platform_dump(const void *iplp, struct dt_node *node)
1240 : : {
1241 : : const struct iplparams_dump *ipl_dump;
1242 : :
1243 : 1 : ipl_dump = HDIF_get_idata(iplp, IPLPARAMS_PLATFORM_DUMP, NULL);
1244 : 1 : if (!CHECK_SPPTR(ipl_dump))
1245 : 0 : return;
1246 : :
1247 : 1 : node = dt_new(node, "platform-dump");
1248 : 1 : assert(node);
1249 : :
1250 : 1 : if (be32_to_cpu(ipl_dump->dump_id)) {
1251 : 0 : dt_add_property_cells(node, "dump-id",
1252 : : be32_to_cpu(ipl_dump->dump_id));
1253 : 0 : dt_add_property_u64(node, "total-size",
1254 : 0 : be64_to_cpu(ipl_dump->act_dump_sz));
1255 : 0 : dt_add_property_u64(node, "hw-dump-size",
1256 : 0 : be32_to_cpu(ipl_dump->act_hw_dump_sz));
1257 : 0 : dt_add_property_cells(node, "plog-id",
1258 : : be32_to_cpu(ipl_dump->plid));
1259 : : }
1260 : : }
1261 : :
1262 : 1 : static void add_iplparams_features(const struct HDIF_common_hdr *iplp)
1263 : : {
1264 : : const struct iplparams_feature *feature;
1265 : : const struct HDIF_array_hdr *array;
1266 : : struct dt_node *fw_features;
1267 : : unsigned int count, i;
1268 : : char name[65];
1269 : :
1270 : 1 : array = HDIF_get_iarray(iplp, IPLPARAMS_FEATURES, &count);
1271 : 1 : if (!array || !count)
1272 : 1 : return;
1273 : :
1274 : 0 : opal_node = dt_new_check(dt_root, "ibm,opal");
1275 : 0 : fw_features = dt_new(opal_node, "fw-features");
1276 : 0 : if (!fw_features)
1277 : 0 : return;
1278 : :
1279 : 0 : HDIF_iarray_for_each(array, i, feature) {
1280 : : struct dt_node *n;
1281 : : uint64_t flags;
1282 : :
1283 : : /* the name field isn't necessarily null terminated */
1284 : : BUILD_ASSERT(sizeof(name) > sizeof(feature->name));
1285 : 0 : strncpy(name, feature->name, sizeof(name)-1);
1286 : 0 : name[sizeof(name)-1] = '\0';
1287 : 0 : flags = be64_to_cpu(feature->flags);
1288 : :
1289 : 0 : if (strlen(name) == 0) {
1290 : 0 : prlog(PR_DEBUG, "IPLPARAMS: FW feature name is NULL\n");
1291 : 0 : continue;
1292 : : }
1293 : :
1294 : 0 : prlog(PR_DEBUG, "IPLPARAMS: FW feature %s = %016"PRIx64"\n",
1295 : : name, flags);
1296 : :
1297 : : /* get rid of tm-suspend-mode-enabled being disabled */
1298 : 0 : if (strcmp(name, "tm-suspend-mode-enabled") == 0)
1299 : 0 : strcpy(name, "tm-suspend-mode");
1300 : :
1301 : 0 : n = dt_new(fw_features, name);
1302 : :
1303 : : /*
1304 : : * This is a bit overkill, but we'll want seperate properties
1305 : : * for each flag bit(s).
1306 : : */
1307 : 0 : if (flags & PPC_BIT(0))
1308 : 0 : dt_add_property(n, "enabled", NULL, 0);
1309 : : else
1310 : 0 : dt_add_property(n, "disabled", NULL, 0);
1311 : : }
1312 : : }
1313 : :
1314 : 1 : static void add_iplparams(void)
1315 : : {
1316 : : struct dt_node *iplp_node;
1317 : : const void *ipl_parms;
1318 : :
1319 : 1 : ipl_parms = get_hdif(&spiras->ntuples.ipl_parms, "IPLPMS");
1320 : 1 : if (!ipl_parms) {
1321 : 0 : prerror("IPLPARAMS: Cannot find IPL Parms in SPIRA\n");
1322 : 0 : return;
1323 : : }
1324 : :
1325 : 1 : iplp_node = dt_new(dt_root, "ipl-params");
1326 : 1 : assert(iplp_node);
1327 : 1 : dt_add_property_cells(iplp_node, "#address-cells", 0);
1328 : 1 : dt_add_property_cells(iplp_node, "#size-cells", 0);
1329 : :
1330 : 1 : add_iplparams_sys_params(ipl_parms, iplp_node);
1331 : 1 : add_iplparams_ipl_params(ipl_parms, iplp_node);
1332 : 1 : add_iplparams_serials(ipl_parms, iplp_node);
1333 : 1 : add_iplparams_platform_dump(ipl_parms, iplp_node);
1334 : 1 : add_iplparams_features(ipl_parms);
1335 : : }
1336 : :
1337 : : /* Various structure contain a "proc_chip_id" which is an arbitrary
1338 : : * numbering used by HDAT to reference chips, which doesn't correspond
1339 : : * to the HW IDs. We want to use the HW IDs everywhere in the DT so
1340 : : * we convert using this.
1341 : : */
1342 : 17 : uint32_t pcid_to_chip_id(uint32_t proc_chip_id)
1343 : : {
1344 : : unsigned int i;
1345 : : const void *hdif;
1346 : :
1347 : : /* First, try the proc_chip ntuples for chip data */
1348 : 22 : for_each_ntuple_idx(&spiras->ntuples.proc_chip, hdif, i,
1349 : : SPPCRD_HDIF_SIG) {
1350 : : const struct sppcrd_chip_info *cinfo;
1351 : :
1352 : 22 : cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO,
1353 : : NULL);
1354 : 22 : if (!CHECK_SPPTR(cinfo)) {
1355 : 0 : prerror("XSCOM: Bad ChipID data %d\n", i);
1356 : 0 : continue;
1357 : : }
1358 : 22 : if (proc_chip_id == be32_to_cpu(cinfo->proc_chip_id))
1359 : 17 : return get_xscom_id(cinfo);
1360 : : }
1361 : :
1362 : : /* Not found, what to do ? Assert ? For now return a number
1363 : : * guaranteed to not exist
1364 : : */
1365 : 0 : return (uint32_t)-1;
1366 : : }
1367 : :
1368 : 0 : uint32_t pcid_to_topology_idx(uint32_t proc_chip_id)
1369 : : {
1370 : : unsigned int i;
1371 : : const void *hdif;
1372 : :
1373 : : /* First, try the proc_chip ntuples for chip data */
1374 : 0 : for_each_ntuple_idx(&spiras->ntuples.proc_chip, hdif, i,
1375 : : SPPCRD_HDIF_SIG) {
1376 : : const struct sppcrd_chip_info *cinfo;
1377 : :
1378 : 0 : cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
1379 : 0 : if (!CHECK_SPPTR(cinfo)) {
1380 : 0 : prerror("XSCOM: Bad ChipID data %d\n", i);
1381 : 0 : continue;
1382 : : }
1383 : 0 : if (proc_chip_id == be32_to_cpu(cinfo->proc_chip_id)) {
1384 : 0 : if (proc_gen <= proc_gen_p9)
1385 : 0 : return get_xscom_id(cinfo);
1386 : : else
1387 : 0 : return ((u32)cinfo->topology_id_table[cinfo->primary_topology_loc]);
1388 : : }
1389 : : }
1390 : :
1391 : : /* Not found, what to do ? Assert ? For now return a number
1392 : : * guaranteed to not exist
1393 : : */
1394 : 0 : return (uint32_t)-1;
1395 : : }
1396 : : /* Create '/ibm,opal/led' node */
1397 : 1 : static void dt_init_led_node(void)
1398 : : {
1399 : : struct dt_node *led_node;
1400 : :
1401 : : /* Create /ibm,opal node, if its not created already */
1402 : 1 : if (!opal_node) {
1403 : 1 : opal_node = dt_new(dt_root, "ibm,opal");
1404 : 1 : assert(opal_node);
1405 : : }
1406 : :
1407 : : /* Crete LED parent node */
1408 : 1 : led_node = dt_new(opal_node, DT_PROPERTY_LED_NODE);
1409 : 1 : assert(led_node);
1410 : 1 : }
1411 : :
1412 : 1 : static void hostservices_parse(void)
1413 : : {
1414 : : struct HDIF_common_hdr *hs_hdr;
1415 : : const void *dt_blob;
1416 : : unsigned int size;
1417 : : unsigned int ntuples_size;
1418 : :
1419 : : /* Deprecated on P9 */
1420 : 1 : if (proc_gen >= proc_gen_p9)
1421 : 0 : return;
1422 : :
1423 : 1 : ntuples_size = sizeof(struct HDIF_array_hdr) +
1424 : 1 : be32_to_cpu(spiras->ntuples.array_hdr.ecnt) *
1425 : : sizeof(struct spira_ntuple);
1426 : :
1427 : 1 : if (offsetof(struct spiras_ntuples, hs_data) >= ntuples_size) {
1428 : 0 : prerror("SPIRA: No host services data found\n");
1429 : 0 : return;
1430 : : }
1431 : :
1432 : 1 : hs_hdr = get_hdif(&spiras->ntuples.hs_data, HSERV_HDIF_SIG);
1433 : 1 : if (!hs_hdr) {
1434 : 0 : prerror("SPIRA: No host services data found\n");
1435 : 0 : return;
1436 : : }
1437 : :
1438 : 1 : dt_blob = HDIF_get_idata(hs_hdr, 0, &size);
1439 : 1 : if (!dt_blob) {
1440 : 0 : prerror("SPIRA: No host services idata found\n");
1441 : 0 : return;
1442 : : }
1443 : 1 : hservices_from_hdat(dt_blob, size);
1444 : : }
1445 : :
1446 : 1 : static void add_stop_levels(void)
1447 : : {
1448 : 1 : struct spira_ntuple *t = &spiras->ntuples.proc_chip;
1449 : : struct HDIF_common_hdr *hdif;
1450 : 1 : u32 stop_levels = ~0;
1451 : 1 : bool valid = false;
1452 : : int i;
1453 : :
1454 : 1 : if (proc_gen < proc_gen_p9)
1455 : 1 : return;
1456 : :
1457 : : /*
1458 : : * OPAL only exports a single set of flags to indicate the supported
1459 : : * STOP modes while the HDAT descibes the support top levels *per chip*
1460 : : * We parse the list of chips to find a common set of STOP levels to
1461 : : * export.
1462 : : */
1463 : 0 : for_each_ntuple_idx(t, hdif, i, SPPCRD_HDIF_SIG) {
1464 : : unsigned int size;
1465 : : const struct sppcrd_chip_info *cinfo =
1466 : 0 : HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, &size);
1467 : : u32 ve, chip_levels;
1468 : :
1469 : 0 : if (!cinfo)
1470 : 0 : continue;
1471 : :
1472 : : /*
1473 : : * If the chip info field is too small then assume we have no
1474 : : * STOP level information.
1475 : : */
1476 : 0 : if (size < 0x44) {
1477 : 0 : stop_levels = 0;
1478 : 0 : break;
1479 : : }
1480 : :
1481 : 0 : ve = be32_to_cpu(cinfo->verif_exist_flags) & CPU_ID_VERIFY_MASK;
1482 : 0 : ve >>= CPU_ID_VERIFY_SHIFT;
1483 : 0 : if (ve == CHIP_VERIFY_NOT_INSTALLED ||
1484 : : ve == CHIP_VERIFY_UNUSABLE)
1485 : 0 : continue;
1486 : :
1487 : 0 : chip_levels = be32_to_cpu(cinfo->stop_levels);
1488 : :
1489 : 0 : prlog(PR_INSANE, "CHIP[%x] supported STOP mask 0x%.8x\n",
1490 : : be32_to_cpu(cinfo->proc_chip_id), chip_levels);
1491 : :
1492 : 0 : stop_levels &= chip_levels;
1493 : 0 : valid = true;
1494 : : }
1495 : :
1496 : 0 : if (!valid)
1497 : 0 : stop_levels = 0;
1498 : :
1499 : 0 : dt_add_property_cells(dt_new_check(opal_node, "power-mgt"),
1500 : : "ibm,enabled-stop-levels", stop_levels);
1501 : : }
1502 : :
1503 : : #define NPU_BASE 0x5011000
1504 : : #define NPU_SIZE 0x2c
1505 : : #define NPU_INDIRECT0 0x8000000009010c3fULL
1506 : : #define NPU_INDIRECT1 0x800000000c010c3fULL
1507 : :
1508 : 0 : static void add_npu(struct dt_node *xscom, const struct HDIF_array_hdr *links,
1509 : : int npu_index)
1510 : : {
1511 : : const struct sppcrd_smp_link *link;
1512 : : struct dt_node *npu;
1513 : : int group_target[6]; /* Tracks the PCI slot targeted each link group */
1514 : 0 : int group_count = 0;
1515 : 0 : int link_count = 0;
1516 : : uint32_t size, chip_id;
1517 : : int i;
1518 : :
1519 : 0 : size = be32_to_cpu(links->esize);
1520 : 0 : chip_id = dt_get_chip_id(xscom);
1521 : :
1522 : 0 : memset(group_target, 0, sizeof(group_target));
1523 : :
1524 : 0 : npu = dt_new_addr(xscom, "npu", NPU_BASE);
1525 : 0 : dt_add_property_cells(npu, "reg", NPU_BASE, NPU_SIZE);
1526 : 0 : dt_add_property_cells(npu, "#size-cells", 0);
1527 : 0 : dt_add_property_cells(npu, "#address-cells", 1);
1528 : :
1529 : 0 : dt_add_property_strings(npu, "compatible", "ibm,power9-npu");
1530 : 0 : dt_add_property_cells(npu, "ibm,npu-index", npu_index);
1531 : :
1532 : 0 : HDIF_iarray_for_each(links, i, link) {
1533 : 0 : uint16_t slot_id = be16_to_cpu(link->pci_slot_idx);
1534 : 0 : uint32_t link_id = be32_to_cpu(link->link_id);
1535 : 0 : uint64_t speed = 0, nvlink_speed = 0;
1536 : : struct dt_node *node;
1537 : :
1538 : : /*
1539 : : * Only add a link node if this link is targeted at a
1540 : : * GPU device.
1541 : : *
1542 : : * If we ever activate it for an opencapi device, we
1543 : : * should revisit the link definitions hard-coded
1544 : : * on ZZ.
1545 : : */
1546 : 0 : if (be32_to_cpu(link->usage) != SMP_LINK_USE_GPU)
1547 : 0 : continue;
1548 : :
1549 : : /*
1550 : : * XXX: The link_id that we get from HDAT is essentially an
1551 : : * arbitrary ID number so we can't use it as the reg for the
1552 : : * link node.
1553 : : *
1554 : : * a) There's a 1-1 mapping between entries in the SMP link
1555 : : * structure and the NPU links.
1556 : : *
1557 : : * b) The SMP link array contains them in ascending order.
1558 : : *
1559 : : * We have some assurances that b) is correct, but if we get
1560 : : * broken link numbering it's something to watch for.
1561 : : *
1562 : : * If we every have actual A-Bus (SMP) link info in here
1563 : : * this is going to break.
1564 : : */
1565 : :
1566 : 0 : prlog(PR_DEBUG, "NPU: %04x:%d: Link (%d) targets slot %u\n",
1567 : : chip_id, link_count, link_count, slot_id);
1568 : :
1569 : 0 : if (link_count >= 6) {
1570 : 0 : prerror("NPU: %04x:%d: Ignoring extra link (max 6)\n",
1571 : : chip_id, link_count);
1572 : 0 : break;
1573 : : }
1574 : :
1575 : 0 : node = dt_new_addr(npu, "link", link_count);
1576 : 0 : if (!node) {
1577 : 0 : prerror("NPU: %04x:%d: Creating link node failed\n",
1578 : : chip_id, link_count);
1579 : 0 : continue;
1580 : : }
1581 : :
1582 : 0 : dt_add_property_string(node, "compatible", "ibm,npu-link");
1583 : 0 : dt_add_property_cells(node, "reg", link_count);
1584 : 0 : dt_add_property_cells(node, "ibm,npu-link-index", link_count);
1585 : 0 : dt_add_property_cells(node, "ibm,workbook-link-id", link_id);
1586 : :
1587 : 0 : dt_add_property_u64s(node, "ibm,npu-phy",
1588 : : link_count < 3 ? NPU_INDIRECT0 : NPU_INDIRECT1);
1589 : 0 : dt_add_property_cells(node, "ibm,npu-lane-mask",
1590 : : be32_to_cpu(link->lane_mask));
1591 : 0 : dt_add_property_cells(node, "ibm,npu-brick-id",
1592 : : be32_to_cpu(link->brick_id));
1593 : :
1594 : 0 : link_count++;
1595 : :
1596 : : /*
1597 : : * Add the group details if this is an NVlink.
1598 : : *
1599 : : * TODO: Cable card stuff.
1600 : : */
1601 : 0 : if (slot_id) {
1602 : : struct dt_node *slot;
1603 : : const char *name;
1604 : : int group;
1605 : :
1606 : : /*
1607 : : * Search the existing groups for one targeting
1608 : : * this PCI slot
1609 : : */
1610 : 0 : for (group = 0; group < group_count; group++)
1611 : 0 : if (group_target[group] == slot_id)
1612 : 0 : break;
1613 : :
1614 : : /* no group, make a new one */
1615 : 0 : if (group == group_count) {
1616 : 0 : group_target[group] = slot_id;
1617 : 0 : group_count++;
1618 : : }
1619 : :
1620 : 0 : dt_add_property_cells(node, "ibm,npu-group-id", group);
1621 : :
1622 : 0 : slot = find_slot_entry_node(dt_root, slot_id);
1623 : 0 : if (!slot) {
1624 : 0 : prerror("NPU: %04x:%d: Unable find node for targeted PCIe slot\n",
1625 : : chip_id, link_count - 1);
1626 : 0 : continue;
1627 : : }
1628 : :
1629 : : /*
1630 : : * The slot_id points to a node that indicates that
1631 : : * this GPU should appear under the slot. Grab the
1632 : : * slot-label from the parent node that represents
1633 : : * the actual slot.
1634 : : */
1635 : 0 : name = dt_prop_get_def(slot->parent, "ibm,slot-label",
1636 : : (char *)"<SLOT NAME MISSING>");
1637 : :
1638 : 0 : prlog(PR_DEBUG, "NPU: %04x:%d: Target slot %s\n",
1639 : : chip_id, link_count - 1, name);
1640 : :
1641 : 0 : dt_add_property_string(node, "ibm,slot-label", name);
1642 : 0 : dt_add_property_cells(node, "ibm,pcie-slot",
1643 : : slot->phandle);
1644 : : }
1645 : :
1646 : : /* Newer fields which might not be populated */
1647 : 0 : if (size <= 0x24)
1648 : 0 : continue;
1649 : :
1650 : 0 : switch (link->link_speed) {
1651 : 0 : case 0: /* 20Gbps */
1652 : 0 : speed = 20000000000ul;
1653 : 0 : nvlink_speed = 0x3;
1654 : 0 : break;
1655 : 0 : case 1: /* 25Gbps */
1656 : 0 : speed = 25000000000ul;
1657 : 0 : nvlink_speed = 0x9;
1658 : 0 : break;
1659 : 0 : case 2: /* 25.78125 Gbps */
1660 : 0 : nvlink_speed = 0x8;
1661 : 0 : speed = 25781250000ul;
1662 : 0 : break;
1663 : : }
1664 : :
1665 : : /* ibm,link-speed is in bps and nvidia,link-speed is ~magic~ */
1666 : 0 : dt_add_property_u64s(node, "ibm,link-speed", speed);
1667 : 0 : dt_add_property_cells(node, "nvidia,link-speed", nvlink_speed);
1668 : :
1669 : 0 : dt_add_property_cells(node, DT_PRIVATE "occ-flag-pos",
1670 : : PPC_BIT(link->occ_flag_bit));
1671 : : }
1672 : :
1673 : 0 : dt_add_property_cells(npu, "ibm,npu-links", link_count);
1674 : 0 : }
1675 : :
1676 : 1 : static void add_npus(void)
1677 : : {
1678 : : struct dt_node *xscom;
1679 : 1 : int npu_index = 0;
1680 : :
1681 : : /* Only consult HDAT for npu2 */
1682 : 1 : if (cpu_type != PVR_TYPE_P9)
1683 : 1 : return;
1684 : :
1685 : 0 : dt_for_each_compatible(dt_root, xscom, "ibm,xscom") {
1686 : : const struct HDIF_array_hdr *links;
1687 : :
1688 : 0 : links = xscom_to_pcrd(xscom, SPPCRD_IDATA_SMP_LINK);
1689 : 0 : if (!links) {
1690 : 0 : prerror("NPU: Unable to find matching SPPCRD for %s\n",
1691 : : xscom->name);
1692 : 0 : continue;
1693 : : }
1694 : :
1695 : : /* should never happen, but stranger things have */
1696 : 0 : if (!dt_find_by_name(dt_root, "ibm,pcie-slots")) {
1697 : 0 : prerror("PCIe slot information missing, can't add npu");
1698 : 0 : continue;
1699 : : }
1700 : :
1701 : : /* some hostboots will give us an empty array */
1702 : 0 : if (be32_to_cpu(links->ecnt))
1703 : 0 : add_npu(xscom, links, npu_index++);
1704 : : }
1705 : : }
1706 : :
1707 : : /*
1708 : : * SPIRA-S is initialized and provided by boot firmware. Check the SPIRA-S
1709 : : * signature to confirm it was provided.
1710 : : */
1711 : 1 : static bool find_spiras(void)
1712 : : {
1713 : : #if !defined(TEST)
1714 : : spiras = (struct spiras *)SPIRA_HEAP_BASE;
1715 : : #endif
1716 : :
1717 : : /* Validate SPIRA-S signature */
1718 : 1 : if (!spiras)
1719 : 0 : return false;
1720 : 1 : if (!HDIF_check(&spiras->hdr, SPIRAS_HDIF_SIG))
1721 : 0 : return false;
1722 : :
1723 : 1 : prlog(PR_DEBUG, "SPIRA-S found.\n");
1724 : 1 : return true;
1725 : : }
1726 : :
1727 : : /*
1728 : : * All the data structure addresses are relative to payload base. Hence adjust
1729 : : * structures that are needed to capture OPAL dump during MPIPL.
1730 : : */
1731 : 1 : static void update_spirah_addr(void)
1732 : : {
1733 : : #if !defined(TEST)
1734 : : if (proc_gen < proc_gen_p9)
1735 : : return;
1736 : :
1737 : : naca.spirah_addr = CPU_TO_BE64(SPIRAH_OFF);
1738 : : naca.spira_addr = 0;
1739 : : spirah.ntuples.hs_data_area.addr = CPU_TO_BE64(SPIRA_HEAP_BASE - SKIBOOT_BASE);
1740 : : spirah.ntuples.mdump_res.addr = CPU_TO_BE64(MDRT_TABLE_BASE - SKIBOOT_BASE);
1741 : : #endif
1742 : 1 : }
1743 : :
1744 : 1 : int parse_hdat(bool is_opal)
1745 : : {
1746 : 1 : cpu_type = PVR_TYPE(mfspr(SPR_PVR));
1747 : :
1748 : 1 : prlog(PR_DEBUG, "Parsing HDAT...\n");
1749 : :
1750 : 1 : if (!find_spiras()) {
1751 : 0 : prlog(PR_ERR, "SPIRA-S not found.\n");
1752 : 0 : return -1;
1753 : : }
1754 : :
1755 : 1 : update_spirah_addr();
1756 : :
1757 : : /*
1758 : : * Basic DT root stuff
1759 : : */
1760 : 1 : dt_add_property_cells(dt_root, "#address-cells", 2);
1761 : 1 : dt_add_property_cells(dt_root, "#size-cells", 2);
1762 : :
1763 : 1 : if (proc_gen < proc_gen_p9)
1764 : 1 : dt_add_property_string(dt_root, "lid-type", is_opal ? "opal" : "phyp");
1765 : :
1766 : : /* Add any BMCs and enable the LPC UART */
1767 : 1 : bmc_parse();
1768 : :
1769 : : /* Create and populate /vpd node */
1770 : 1 : dt_init_vpd_node();
1771 : :
1772 : : /* Create /ibm,opal/led node */
1773 : 1 : dt_init_led_node();
1774 : :
1775 : : /* Parse PCIA */
1776 : 1 : if (!pcia_parse())
1777 : 0 : return -1;
1778 : :
1779 : : /* IPL params */
1780 : 1 : add_iplparams();
1781 : :
1782 : : /* Add XSCOM node (must be before chiptod, IO and FSP) */
1783 : 1 : add_xscom();
1784 : :
1785 : : /* Parse MS VPD */
1786 : 1 : memory_parse();
1787 : :
1788 : : /* Add any FSPs */
1789 : 1 : fsp_parse();
1790 : :
1791 : : /* Add ChipTOD's */
1792 : 1 : if (!add_chiptod())
1793 : 0 : prerror("CHIPTOD: No ChipTOD found !\n");
1794 : :
1795 : : /* Add NX */
1796 : 1 : add_nx();
1797 : :
1798 : : /* Add nest mmu */
1799 : 1 : add_nmmu();
1800 : :
1801 : : /* Add IO HUBs and/or PHBs */
1802 : 1 : io_parse();
1803 : :
1804 : : /* Add NPU nodes */
1805 : 1 : add_npus();
1806 : :
1807 : : /* Parse VPD */
1808 : 1 : vpd_parse();
1809 : :
1810 : : /* Host services information. */
1811 : 1 : hostservices_parse();
1812 : :
1813 : : /* Parse System Attention Indicator inforamtion */
1814 : 1 : slca_dt_add_sai_node();
1815 : :
1816 : 1 : add_stop_levels();
1817 : :
1818 : : /* Parse node secure and trusted boot data */
1819 : 1 : if (proc_gen >= proc_gen_p9)
1820 : 0 : node_stb_parse();
1821 : :
1822 : 1 : prlog(PR_DEBUG, "Parsing HDAT...done\n");
1823 : :
1824 : 1 : return 0;
1825 : : }
|