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