1 /* Copyright 2013-2014 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <skiboot.h>
18 #include "spira.h"
19 #include <cpu.h>
20 #include <fsp.h>
21 #include <opal.h>
22 #include <ccan/str/str.h>
23 #include <ccan/array_size/array_size.h>
24 #include <device.h>
25 #include <vpd.h>
26 #include <inttypes.h>
27 #include <string.h>
28
29 #include "hdata.h"
30
io_get_lx_info(const void * kwvpd,unsigned int kwvpd_sz,int lx_idx,struct dt_node * hn)31 static bool io_get_lx_info(const void *kwvpd, unsigned int kwvpd_sz,
32 int lx_idx, struct dt_node *hn)
33 {
34 const void *lxr;
35 char recname[5];
36 uint32_t lxrbuf[2] = { 0, 0 };
37
38 /* Find LXRn, where n is the index passed in*/
39 strcpy(recname, "LXR0");
40 recname[3] += lx_idx;
41 lxr = vpd_find(kwvpd, kwvpd_sz, recname, "LX", NULL);
42 if (!lxr) {
43 /* Not found, try VINI */
44 lxr = vpd_find(kwvpd, kwvpd_sz, "VINI",
45 "LX", NULL);
46 if (lxr)
47 lx_idx = VPD_LOAD_LXRN_VINI;
48 }
49 if (!lxr) {
50 prlog(PR_DEBUG, "CEC: LXR%x not found !\n", lx_idx);
51 return false;
52 }
53
54 memcpy(lxrbuf, lxr, sizeof(uint32_t)*2);
55
56 prlog(PR_DEBUG, "CEC: LXRn=%d LXR=%08x%08x\n", lx_idx, lxrbuf[0], lxrbuf[1]);
57 prlog(PR_DEBUG, "CEC: LX Info added to %llx\n", (long long)hn);
58
59 /* Add the LX info */
60 if (!dt_has_node_property(hn, "ibm,vpd-lx-info", NULL)) {
61 dt_add_property_cells(hn, "ibm,vpd-lx-info",
62 lx_idx,
63 lxrbuf[0],
64 lxrbuf[1]);
65 }
66
67 return true;
68 }
69
70
io_get_loc_code(const void * sp_iohubs,struct dt_node * hn,const char * prop_name)71 static void io_get_loc_code(const void *sp_iohubs, struct dt_node *hn, const char *prop_name)
72 {
73 const struct spira_fru_id *fru_id;
74 unsigned int fru_id_sz;
75 char loc_code[LOC_CODE_SIZE + 1];
76 const char *slca_loc_code;
77
78 /* Find SLCA Index */
79 fru_id = HDIF_get_idata(sp_iohubs, CECHUB_FRU_ID_DATA, &fru_id_sz);
80 if (fru_id) {
81 memset(loc_code, 0, sizeof(loc_code));
82
83 /* Find LOC Code from SLCA Index */
84 slca_loc_code = slca_get_loc_code_index(be16_to_cpu(fru_id->slca_index));
85 if (slca_loc_code) {
86 strncpy(loc_code, slca_loc_code, LOC_CODE_SIZE);
87 if (!dt_has_node_property(hn, prop_name, NULL)) {
88 dt_add_property(hn, prop_name, loc_code,
89 strlen(loc_code) + 1);
90 }
91 prlog(PR_DEBUG, "CEC: %s: %s (SLCA rsrc 0x%x)\n",
92 prop_name, loc_code,
93 be16_to_cpu(fru_id->rsrc_id));
94 } else {
95 prlog(PR_DEBUG, "CEC: SLCA Loc not found: "
96 "index %d\n", fru_id->slca_index);
97 }
98 } else {
99 prlog(PR_DEBUG, "CEC: Hub FRU ID not found...\n");
100 }
101 }
102
io_add_phb3(const struct cechub_io_hub * hub,const struct HDIF_common_hdr * sp_iohubs,unsigned int index,struct dt_node * xcom,unsigned int pe_xscom,unsigned int pci_xscom,unsigned int spci_xscom)103 static struct dt_node *io_add_phb3(const struct cechub_io_hub *hub,
104 const struct HDIF_common_hdr *sp_iohubs,
105 unsigned int index, struct dt_node *xcom,
106 unsigned int pe_xscom,
107 unsigned int pci_xscom,
108 unsigned int spci_xscom)
109 {
110 struct dt_node *pbcq;
111 uint32_t reg[6];
112 unsigned int hdif_vers;
113
114 /* Get HDIF version */
115 hdif_vers = be16_to_cpu(sp_iohubs->version);
116
117 /* Create PBCQ node under xscom */
118 pbcq = dt_new_addr(xcom, "pbcq", pe_xscom);
119 if (!pbcq)
120 return NULL;
121
122 /* "reg" property contains in order the PE, PCI and SPCI XSCOM
123 * addresses
124 */
125 reg[0] = pe_xscom;
126 reg[1] = 0x20;
127 reg[2] = pci_xscom;
128 reg[3] = 0x05;
129 reg[4] = spci_xscom;
130 reg[5] = 0x15;
131 dt_add_property(pbcq, "reg", reg, sizeof(reg));
132
133 /* A couple more things ... */
134 dt_add_property_strings(pbcq, "compatible", "ibm,power8-pbcq");
135 dt_add_property_cells(pbcq, "ibm,phb-index", index);
136 dt_add_property_cells(pbcq, "ibm,hub-id", be16_to_cpu(hub->hub_num));
137
138 /* The loc code of the PHB itself is different from the base
139 * loc code of the slots (It's actually the DCM's loc code).
140 */
141 io_get_loc_code(sp_iohubs, pbcq, "ibm,loc-code");
142
143 /* We indicate that this is an IBM setup, which means that
144 * the presence detect A/B bits are meaningful. So far we
145 * don't know whether they make any sense on customer setups
146 * so we only set that when booting with HDAT
147 */
148 dt_add_property(pbcq, "ibm,use-ab-detect", NULL, 0);
149
150 /* HDAT spec has these in version 0x6A and later */
151 if (hdif_vers >= 0x6a) {
152 u64 eq0 = be64_to_cpu(hub->phb_lane_eq[index][0]);
153 u64 eq1 = be64_to_cpu(hub->phb_lane_eq[index][1]);
154 u64 eq2 = be64_to_cpu(hub->phb_lane_eq[index][2]);
155 u64 eq3 = be64_to_cpu(hub->phb_lane_eq[index][3]);
156
157 dt_add_property_u64s(pbcq, "ibm,lane-eq", eq0, eq1, eq2, eq3);
158 }
159
160 /* Currently we only create a PBCQ node, the actual PHB nodes
161 * will be added by sapphire later on.
162 */
163 return pbcq;
164 }
165
add_pec_stack(const struct cechub_io_hub * hub,struct dt_node * pbcq,int stack_index,int phb_index,u8 active_phbs)166 static struct dt_node *add_pec_stack(const struct cechub_io_hub *hub,
167 struct dt_node *pbcq, int stack_index,
168 int phb_index, u8 active_phbs)
169 {
170 struct dt_node *stack;
171 u64 eq[8];
172 u8 *gen4;
173 int i;
174
175 stack = dt_new_addr(pbcq, "stack", stack_index);
176 assert(stack);
177
178 dt_add_property_cells(stack, "reg", stack_index);
179 dt_add_property_cells(stack, "ibm,phb-index", phb_index);
180 dt_add_property_string(stack, "compatible", "ibm,power9-phb-stack");
181
182 /* XXX: This should probably just return if the PHB is disabled
183 * rather than adding the extra properties.
184 */
185
186 if (active_phbs & (0x80 >> phb_index))
187 dt_add_property_string(stack, "status", "okay");
188 else
189 dt_add_property_string(stack, "status", "disabled");
190
191 for (i = 0; i < 4; i++) /* gen 3 eq settings */
192 eq[i] = be64_to_cpu(hub->phb_lane_eq[phb_index][i]);
193 for (i = 0; i < 4; i++) /* gen 4 eq settings */
194 eq[i+4] = be64_to_cpu(hub->phb4_lane_eq[phb_index][i]);
195
196 /* Lane-eq settings are packed 2 bytes per lane for 16 lanes
197 * On P9 DD2, 1 byte per lane is used in the hardware
198 */
199
200 /* Repack 2 byte lane settings into 1 byte */
201 gen4 = (u8 *)&eq[4];
202 for (i = 0; i < 16; i++)
203 gen4[i] = gen4[2*i];
204
205 dt_add_property_u64s(stack, "ibm,lane-eq", eq[0], eq[1],
206 eq[2], eq[3], eq[4], eq[5]);
207 return stack;
208 }
209
io_add_phb4(const struct cechub_io_hub * hub,const struct HDIF_common_hdr * sp_iohubs,struct dt_node * xcom,unsigned int pec_index,int stacks,int phb_base)210 static struct dt_node *io_add_phb4(const struct cechub_io_hub *hub,
211 const struct HDIF_common_hdr *sp_iohubs,
212 struct dt_node *xcom,
213 unsigned int pec_index,
214 int stacks,
215 int phb_base)
216 {
217 struct dt_node *pbcq;
218 uint32_t reg[4];
219 uint8_t active_phb_mask = hub->fab_br0_pdt;
220 uint32_t pe_xscom = 0x4010c00 + (pec_index * 0x0000400);
221 uint32_t pci_xscom = 0xd010800 + (pec_index * 0x1000000);
222 int i;
223
224 /* Create PBCQ node under xscom */
225 pbcq = dt_new_addr(xcom, "pbcq", pe_xscom);
226 if (!pbcq)
227 return NULL;
228
229 /* "reg" property contains (in order) the PE and PCI XSCOM addresses */
230 reg[0] = pe_xscom;
231 reg[1] = 0x100;
232 reg[2] = pci_xscom;
233 reg[3] = 0x200;
234 dt_add_property(pbcq, "reg", reg, sizeof(reg));
235
236 /* The hubs themselves go under the stacks */
237 dt_add_property_strings(pbcq, "compatible", "ibm,power9-pbcq");
238 dt_add_property_cells(pbcq, "ibm,pec-index", pec_index);
239 dt_add_property_cells(pbcq, "#address-cells", 1);
240 dt_add_property_cells(pbcq, "#size-cells", 0);
241
242 for (i = 0; i < stacks; i++)
243 add_pec_stack(hub, pbcq, i, phb_base + i, active_phb_mask);
244
245 dt_add_property_cells(pbcq, "ibm,hub-id", be16_to_cpu(hub->hub_num));
246
247 /* The loc code of the PHB itself is different from the base
248 * loc code of the slots (It's actually the DCM's loc code).
249 */
250 io_get_loc_code(sp_iohubs, pbcq, "ibm,loc-code");
251
252 prlog(PR_INFO, "CEC: Added PHB4 PBCQ %d with %d stacks\n",
253 pec_index, stacks);
254
255 /* the actual PHB nodes created later on by skiboot */
256 return pbcq;
257 }
258
io_add_p8(const struct cechub_io_hub * hub,const struct HDIF_common_hdr * sp_iohubs)259 static struct dt_node *io_add_p8(const struct cechub_io_hub *hub,
260 const struct HDIF_common_hdr *sp_iohubs)
261 {
262 struct dt_node *xscom;
263 unsigned int i, chip_id;
264
265 chip_id = pcid_to_chip_id(be32_to_cpu(hub->proc_chip_id));
266
267 prlog(PR_INFO, "CEC: HW CHIP=0x%x, HW TOPO=0x%04x\n", chip_id,
268 be16_to_cpu(hub->hw_topology));
269
270 xscom = find_xscom_for_chip(chip_id);
271 if (!xscom) {
272 prerror("P8: Can't find XSCOM for chip %d\n", chip_id);
273 return NULL;
274 }
275
276 /* Create PHBs, max 3 */
277 for (i = 0; i < 3; i++) {
278 if (hub->fab_br0_pdt & (0x80 >> i))
279 /* XSCOM addresses are the same on Murano and Venice */
280 io_add_phb3(hub, sp_iohubs, i, xscom,
281 0x02012000 + (i * 0x400),
282 0x09012000 + (i * 0x400),
283 0x09013c00 + (i * 0x40));
284 }
285
286 /* HACK: We return the XSCOM device for the VPD info */
287 return xscom;
288 }
289
io_add_p9(const struct cechub_io_hub * hub,const struct HDIF_common_hdr * sp_iohubs)290 static struct dt_node *io_add_p9(const struct cechub_io_hub *hub,
291 const struct HDIF_common_hdr *sp_iohubs)
292 {
293 struct dt_node *xscom;
294 unsigned int chip_id;
295
296 chip_id = pcid_to_chip_id(be32_to_cpu(hub->proc_chip_id));
297
298 prlog(PR_INFO, "CEC: HW CHIP=0x%x, HW TOPO=0x%04x\n", chip_id,
299 be16_to_cpu(hub->hw_topology));
300
301 xscom = find_xscom_for_chip(chip_id);
302 if (!xscom) {
303 prerror("P9: Can't find XSCOM for chip %d\n", chip_id);
304 return NULL;
305 }
306
307 prlog(PR_DEBUG, "IOHUB: PHB4 active bridge mask %x\n",
308 (u32) hub->fab_br0_pdt);
309
310 /* Create PBCQs */
311 io_add_phb4(hub, sp_iohubs, xscom, 0, 1, 0);
312 io_add_phb4(hub, sp_iohubs, xscom, 1, 2, 1);
313 io_add_phb4(hub, sp_iohubs, xscom, 2, 3, 3);
314
315 return xscom;
316 }
317
318
io_add_p8_cec_vpd(const struct HDIF_common_hdr * sp_iohubs)319 static void io_add_p8_cec_vpd(const struct HDIF_common_hdr *sp_iohubs)
320 {
321 const struct HDIF_child_ptr *iokids;
322 const void *iokid;
323 const void *kwvpd;
324 unsigned int kwvpd_sz;
325
326 /* P8 LXR0 kept in IO KID Keyword VPD */
327 iokids = HDIF_child_arr(sp_iohubs, CECHUB_CHILD_IO_KIDS);
328 if (!CHECK_SPPTR(iokids)) {
329 prlog(PR_WARNING, "CEC: No IOKID child array !\n");
330 return;
331 }
332 if (!iokids->count) {
333 prlog(PR_WARNING, "CEC: IOKID count is 0 !\n");
334 return;
335 }
336 if (be32_to_cpu(iokids->count) > 1) {
337 prlog(PR_WARNING, "CEC: WARNING ! More than 1 IO KID !!! (%d)\n",
338 iokids->count);
339 /* Ignoring the additional ones */
340 }
341
342 iokid = HDIF_child(sp_iohubs, iokids, 0, "IO KID");
343 if (!iokid) {
344 prlog(PR_WARNING, "CEC: No IO KID structure in child array !\n");
345 return;
346 }
347
348 /* Grab base location code for slots */
349 io_get_loc_code(iokid, dt_root, "ibm,io-base-loc-code");
350
351 kwvpd = HDIF_get_idata(iokid, CECHUB_ASCII_KEYWORD_VPD, &kwvpd_sz);
352 if (!kwvpd) {
353 prlog(PR_WARNING, "CEC: No VPD entry in IO KID !\n");
354 return;
355 }
356
357 /* Grab LX load info */
358 io_get_lx_info(kwvpd, kwvpd_sz, 0, dt_root);
359 }
360
361 /*
362 * Assumptions:
363 *
364 * a) the IOSLOT index is the hub ID -CHECK
365 *
366 */
367
368 static struct dt_node *dt_slots;
369
add_i2c_link(struct dt_node * node,const char * link_name,u32 i2c_link)370 static void add_i2c_link(struct dt_node *node, const char *link_name,
371 u32 i2c_link)
372 {
373 /* FIXME: Do something not shit */
374 dt_add_property_cells(node, link_name, i2c_link);
375 }
376
377 /*
378 * the root of the slots node has #address-cells = 2, <hub-index, phb-index>
379 * can we ditch hub-index?
380 */
381
382
find_slot_details(const struct HDIF_common_hdr * ioslot,int entry)383 static const struct slot_map_details *find_slot_details(
384 const struct HDIF_common_hdr *ioslot, int entry)
385 {
386 const struct slot_map_details *details = NULL;
387 const struct HDIF_array_hdr *arr;
388 unsigned int i;
389
390 arr = HDIF_get_iarray(ioslot, IOSLOT_IDATA_DETAILS, NULL);
391 HDIF_iarray_for_each(arr, i, details)
392 if (be16_to_cpu(details->entry) == entry)
393 break;
394
395 return details;
396 }
397
parse_slot_details(struct dt_node * slot,const struct slot_map_details * details)398 static void parse_slot_details(struct dt_node *slot,
399 const struct slot_map_details *details)
400 {
401 u32 slot_caps;
402
403 /*
404 * generic slot options
405 */
406
407 dt_add_property_cells(slot, "max-power",
408 be16_to_cpu(details->max_power));
409
410 if (details->perst_ctl_type == SLOT_PERST_PHB_OR_SW)
411 dt_add_property(slot, "pci-perst", NULL, 0);
412 else if (details->perst_ctl_type == SLOT_PERST_SW_GPIO)
413 dt_add_property_cells(slot, "gpio-perst", details->perst_gpio);
414
415 if (details->presence_det_type == SLOT_PRESENCE_PCI)
416 dt_add_property(slot, "pci-presence-detect", NULL, 0);
417
418 /*
419 * specific slot capabilities
420 */
421 slot_caps = be32_to_cpu(details->slot_caps);
422
423 if (slot_caps & SLOT_CAP_LSI)
424 dt_add_property(slot, "lsi", NULL, 0);
425
426 if (slot_caps & SLOT_CAP_CAPI) {
427 /* XXX: should we be more specific here?
428 *
429 * Also we should double check that this slot
430 * is a root connected slot.
431 */
432 dt_add_property(slot, "capi", NULL, 0);
433 }
434
435 if (slot_caps & SLOT_CAP_CCARD) {
436 dt_add_property(slot, "cable-card", NULL, 0);
437
438 if (details->presence_det_type == SLOT_PRESENCE_I2C)
439 add_i2c_link(slot, "i2c-presence-detect",
440 be32_to_cpu(details->i2c_cable_card));
441 }
442
443 if (slot_caps & SLOT_CAP_HOTPLUG) {
444 dt_add_property(slot, "hotplug", NULL, 0);
445
446 /*
447 * Power control should only exist when the slot is hotplug
448 * capable
449 */
450 if (details->power_ctrl_type == SLOT_PWR_I2C)
451 add_i2c_link(slot, "i2c-power-ctrl",
452 be32_to_cpu(details->i2c_power_ctl));
453 }
454
455 /*
456 * NB: Additional NVLink specific info is added to this node
457 * when the SMP Link structures are parsed later on.
458 */
459 if (slot_caps & SLOT_CAP_NVLINK)
460 dt_add_property(slot, "nvlink", NULL, 0);
461 }
462
find_slot_entry_node(struct dt_node * root,u32 entry_id)463 struct dt_node *find_slot_entry_node(struct dt_node *root, u32 entry_id)
464 {
465 struct dt_node *node;
466
467 for (node = dt_first(root); node; node = dt_next(root, node)) {
468 if (!dt_has_node_property(node, DT_PRIVATE "entry_id", NULL))
469 continue;
470
471 if (dt_prop_get_u32(node, DT_PRIVATE "entry_id") == entry_id)
472 return node;
473 }
474
475 return NULL;
476 }
477
478 /*
479 * The internal HDAT representation of the various types of slot is kinda
480 * dumb, translate it into something more sensible
481 */
482 enum slot_types {
483 st_root,
484 st_slot,
485 st_rc_slot,
486 st_sw_upstream,
487 st_sw_downstream,
488 st_builtin
489 };
490
st_name(enum slot_types type)491 static const char *st_name(enum slot_types type)
492 {
493 switch(type) {
494 case st_root: return "root-complex";
495 case st_slot: return "pluggable";
496 case st_rc_slot: return "pluggable"; /* differentiate? */
497 case st_sw_upstream: return "switch-up";
498 case st_sw_downstream: return "switch-down";
499 case st_builtin: return "builtin";
500 }
501
502 return "(none)";
503 }
504
xlate_type(uint8_t type,u32 features)505 static enum slot_types xlate_type(uint8_t type, u32 features)
506 {
507 bool is_slot = features & SLOT_FEAT_SLOT;
508
509 switch (type) {
510 case SLOT_TYPE_ROOT_COMPLEX:
511 return is_slot ? st_rc_slot : st_root;
512 case SLOT_TYPE_BUILTIN:
513 return st_builtin;
514 case SLOT_TYPE_SWITCH_UP:
515 return st_sw_upstream;
516 case SLOT_TYPE_SWITCH_DOWN:
517 return is_slot ? st_slot : st_sw_downstream;
518 }
519
520 return -1; /* shouldn't happen */
521 }
522
is_port(struct dt_node * n)523 static bool is_port(struct dt_node *n)
524 {
525 //return dt_node_is_compatible(n, "compatible", "ibm,pcie-port");
526 return dt_node_is_compatible(n, "ibm,pcie-port");
527 }
528
529 /* this only works inside parse_one_ioslot() */
530 #define SM_LOG(level, fmt, ...) \
531 prlog(level, "SLOTMAP: %x:%d:%d " \
532 fmt, /* user input */ \
533 chip_id, entry->phb_index, eid, \
534 ##__VA_ARGS__ /* user args */)
535
536 #define SM_ERR(fmt, ...) SM_LOG(PR_ERR, fmt, ##__VA_ARGS__)
537 #define SM_DBG(fmt, ...) SM_LOG(PR_DEBUG, fmt, ##__VA_ARGS__)
538
parse_one_slot(const struct slot_map_entry * entry,const struct slot_map_details * details,int chip_id)539 static void parse_one_slot(const struct slot_map_entry *entry,
540 const struct slot_map_details *details, int chip_id)
541 {
542 struct dt_node *node, *parent = NULL;
543 u16 eid, pid, vid, did;
544 u32 flags;
545 int type;
546
547 flags = be32_to_cpu(entry->features);
548 type = xlate_type(entry->type, flags);
549
550 eid = be16_to_cpu(entry->entry_id);
551 pid = be16_to_cpu(entry->parent_id);
552
553 SM_DBG("%s - eid = %d, pid = %d, name = %8s\n",
554 st_name(type), eid, pid,
555 strnlen(entry->name, 8) ? entry->name : "");
556
557 /* empty slot, ignore it */
558 if (eid == 0x0 && pid == 0x0)
559 return;
560
561 if (type != st_root && type != st_rc_slot) {
562 parent = find_slot_entry_node(dt_slots, pid);
563 if (!parent) {
564 SM_ERR("Unable to find node for parent slot (id = %d)\n",
565 pid);
566 return;
567 }
568 }
569
570 switch (type) {
571 case st_root:
572 case st_rc_slot:
573 node = dt_new_2addr(dt_slots, "root-complex",
574 chip_id, entry->phb_index);
575 if (!node) {
576 SM_ERR("Couldn't add DT node\n");
577 return;
578 }
579 dt_add_property_cells(node, "reg", chip_id, entry->phb_index);
580 dt_add_property_cells(node, "#address-cells", 2);
581 dt_add_property_cells(node, "#size-cells", 0);
582 dt_add_property_strings(node, "compatible",
583 "ibm,pcie-port", "ibm,pcie-root-port");
584 dt_add_property_cells(node, "ibm,chip-id", chip_id);
585 parent = node;
586
587 /*
588 * The representation of slots attached directly to the
589 * root complex is a bit wierd. If this is just a root
590 * complex then stop here, otherwise fall through to create
591 * the slot node.
592 */
593 if (type == st_root)
594 break;
595
596 /* fallthrough*/
597 case st_sw_upstream:
598 case st_builtin:
599 case st_slot:
600 if (!is_port(parent)) {
601 SM_ERR("%s connected to %s (%d), should be %s or %s!\n",
602 st_name(type), parent->name, pid,
603 st_name(st_root), st_name(st_sw_downstream));
604 return;
605 }
606
607 vid = (be32_to_cpu(entry->vendor_id) & 0xffff);
608 did = (be32_to_cpu(entry->device_id) & 0xffff);
609
610 prlog(PR_DEBUG, "Found %s slot with %x:%x\n",
611 st_name(type), vid, did);
612
613 /* The VID:DID is only meaningful for builtins and switches */
614 if (type == st_sw_upstream && vid && did) {
615 node = dt_new_2addr(parent, st_name(type), vid, did);
616 dt_add_property_cells(node, "reg", vid, did);
617 } else {
618 /*
619 * If we get no vdid then create a "wildcard" slot
620 * that matches any device
621 */
622 node = dt_new(parent, st_name(type));
623 }
624
625 if (type == st_sw_upstream) {
626 dt_add_property_cells(node, "#address-cells", 1);
627 dt_add_property_cells(node, "#size-cells", 0);
628 dt_add_property_cells(node, "upstream-port",
629 entry->up_port);
630 }
631 break;
632
633 case st_sw_downstream: /* slot connected to switch output */
634 node = dt_new_addr(parent, "down-port", entry->down_port);
635 dt_add_property_strings(node, "compatible",
636 "ibm,pcie-port");
637 dt_add_property_cells(node, "reg", entry->down_port);
638
639 break;
640
641 default:
642 SM_ERR("Unknown slot map type %x\n", entry->type);
643 return;
644 }
645
646 /*
647 * Now add any generic slot map properties.
648 */
649
650 /* private since we don't want hdat stuff leaking */
651 dt_add_property_cells(node, DT_PRIVATE "entry_id", eid);
652
653 if (entry->mrw_slot_id)
654 dt_add_property_cells(node, "mrw-slot-id",
655 be16_to_cpu(entry->mrw_slot_id));
656
657 if (entry->lane_mask)
658 dt_add_property_cells(node, "lane-mask",
659 be16_to_cpu(entry->lane_mask));
660
661 /* what is the difference between this and the lane reverse? */
662 if (entry->lane_reverse)
663 dt_add_property_cells(node, "lanes-reversed",
664 be16_to_cpu(entry->lane_reverse));
665
666 if (strnlen(entry->name, sizeof(entry->name))) {
667 /*
668 * HACK: On some platforms (witherspoon) the slot label is
669 * applied to the device rather than the pcie downstream port
670 * that has the slot under it. Hack around this by moving the
671 * slot label up if the parent port doesn't have one.
672 */
673 if (dt_node_is_compatible(node->parent, "ibm,pcie-port") &&
674 !dt_find_property(node->parent, "ibm,slot-label")) {
675 dt_add_property_nstr(node->parent, "ibm,slot-label",
676 entry->name, sizeof(entry->name));
677 }
678
679 dt_add_property_nstr(node, "ibm,slot-label",
680 entry->name, sizeof(entry->name));
681 }
682
683 if (entry->type == st_slot || entry->type == st_rc_slot)
684 dt_add_property(node, "ibm,pluggable", NULL, 0);
685
686 if (details)
687 parse_slot_details(node, details);
688 }
689
690 /*
691 * Under the IOHUB structure we have and idata array describing
692 * the PHBs under each chip. The IOHUB structure also has a child
693 * array called IOSLOT which describes slot map. The i`th element
694 * of the IOSLOT array corresponds to the slot map of the i`th
695 * element of the iohubs idata array.
696 *
697 * Probably.
698 *
699 * Furthermore, arrayarrayarrayarrayarray.
700 */
701
get_slot_node(void)702 static struct dt_node *get_slot_node(void)
703 {
704 struct dt_node *slots = dt_find_by_name(dt_root, "ibm,pcie-slots");
705
706 if (!slots) {
707 slots = dt_new(dt_root, "ibm,pcie-slots");
708 dt_add_property_cells(slots, "#address-cells", 2);
709 dt_add_property_cells(slots, "#size-cells", 0);
710 }
711
712 return slots;
713 }
714
io_parse_slots(const struct HDIF_common_hdr * sp_iohubs,int hub_id)715 static void io_parse_slots(const struct HDIF_common_hdr *sp_iohubs, int hub_id)
716 {
717 const struct HDIF_child_ptr *ioslot_arr;
718 const struct HDIF_array_hdr *entry_arr;
719 const struct HDIF_common_hdr *ioslot;
720 const struct slot_map_entry *entry;
721 unsigned int i, count;
722
723 if (sp_iohubs->child_count <= CECHUB_CHILD_IOSLOTS)
724 return;
725
726 ioslot_arr = HDIF_child_arr(sp_iohubs, CECHUB_CHILD_IOSLOTS);
727 if (!ioslot_arr)
728 return;
729
730 count = be32_to_cpu(ioslot_arr->count); /* should only be 1 */
731 if (!count)
732 return;
733
734 dt_slots = get_slot_node();
735
736 prlog(PR_DEBUG, "CEC: Found slot map for IOHUB %d\n", hub_id);
737 if (count > 1)
738 prerror("CEC: Multiple IOSLOTs found for IO HUB %d\n", hub_id);
739
740 ioslot = HDIF_child(sp_iohubs, ioslot_arr, 0, "IOSLOT");
741 if (!ioslot)
742 return;
743
744 entry_arr = HDIF_get_iarray(ioslot, IOSLOT_IDATA_SLOTMAP, NULL);
745 HDIF_iarray_for_each(entry_arr, i, entry) {
746 const struct slot_map_details *details;
747
748 details = find_slot_details(ioslot,
749 be16_to_cpu(entry->entry_id));
750 parse_one_slot(entry, details, hub_id);
751 }
752 }
753
io_parse_fru(const void * sp_iohubs)754 static void io_parse_fru(const void *sp_iohubs)
755 {
756 unsigned int i;
757 int count;
758
759 count = HDIF_get_iarray_size(sp_iohubs, CECHUB_FRU_IO_HUBS);
760 if (count < 1) {
761 prerror("CEC: IO FRU with no chips !\n");
762 return;
763 }
764
765 prlog(PR_INFO, "CEC: %d chips in FRU\n", count);
766
767 /* Iterate IO hub array */
768 for (i = 0; i < count; i++) {
769 const struct cechub_io_hub *hub;
770 unsigned int size, hub_id;
771 uint32_t chip_id;
772
773 hub = HDIF_get_iarray_item(sp_iohubs, CECHUB_FRU_IO_HUBS,
774 i, &size);
775 if (!hub || size < CECHUB_IOHUB_MIN_SIZE) {
776 prerror("CEC: IO-HUB Chip %d bad idata\n", i);
777 continue;
778 }
779
780 switch (hub->flags & CECHUB_HUB_FLAG_STATE_MASK) {
781 case CECHUB_HUB_FLAG_STATE_OK:
782 prlog(PR_DEBUG, "CEC: IO Hub Chip #%d OK\n", i);
783 break;
784 case CECHUB_HUB_FLAG_STATE_FAILURES:
785 prlog(PR_WARNING, "CEC: IO Hub Chip #%d OK"
786 " with failures\n", i);
787 break;
788 case CECHUB_HUB_FLAG_STATE_NOT_INST:
789 prlog(PR_DEBUG, "CEC: IO Hub Chip #%d"
790 " Not installed\n", i);
791 continue;
792 case CECHUB_HUB_FLAG_STATE_UNUSABLE:
793 prlog(PR_DEBUG, "CEC: IO Hub Chip #%d Unusable\n", i);
794 continue;
795 }
796
797 hub_id = be16_to_cpu(hub->iohub_id);
798
799 /* GX BAR assignment */
800 prlog(PR_DEBUG, "CEC: PChip: %d HUB ID: %04x [EC=0x%x]"
801 " Hub#=%d)\n",
802 be32_to_cpu(hub->proc_chip_id), hub_id,
803 be32_to_cpu(hub->ec_level), be16_to_cpu(hub->hub_num));
804
805 switch(hub_id) {
806 case CECHUB_HUB_MURANO:
807 case CECHUB_HUB_MURANO_SEGU:
808 prlog(PR_INFO, "CEC: Murano !\n");
809 io_add_p8(hub, sp_iohubs);
810 break;
811 case CECHUB_HUB_VENICE_WYATT:
812 prlog(PR_INFO, "CEC: Venice !\n");
813 io_add_p8(hub, sp_iohubs);
814 break;
815 case CECHUB_HUB_NIMBUS_SFORAZ:
816 case CECHUB_HUB_NIMBUS_MONZA:
817 case CECHUB_HUB_NIMBUS_LAGRANGE:
818 prlog(PR_INFO, "CEC: Nimbus !\n");
819 io_add_p9(hub, sp_iohubs);
820 break;
821 case CECHUB_HUB_CUMULUS_DUOMO:
822 prlog(PR_INFO, "CEC: Cumulus !\n");
823 io_add_p9(hub, sp_iohubs);
824 break;
825 default:
826 prlog(PR_ERR, "CEC: Hub ID 0x%04x unsupported !\n",
827 hub_id);
828 }
829
830 chip_id = pcid_to_chip_id(be32_to_cpu(hub->proc_chip_id));
831
832 /* parse the slot map if we have one */
833 io_parse_slots(sp_iohubs, chip_id);
834 }
835
836 if (proc_gen == proc_gen_p8 || proc_gen == proc_gen_p9)
837 io_add_p8_cec_vpd(sp_iohubs);
838 }
839
io_parse(void)840 void io_parse(void)
841 {
842 const struct HDIF_common_hdr *sp_iohubs;
843 unsigned int i, size;
844
845 /* Look for IO Hubs */
846 if (!get_hdif(&spira.ntuples.cec_iohub_fru, "IO HUB")) {
847 prerror("CEC: Cannot locate IO Hub FRU data !\n");
848 return;
849 }
850
851 /*
852 * Note about LXRn numbering ...
853 *
854 * I can't completely make sense of what that is supposed to be, so
855 * for now, what we do is look for the first one we can find and
856 * increment it for each chip. Works for the machines I have here
857 */
858
859 for_each_ntuple_idx(&spira.ntuples.cec_iohub_fru, sp_iohubs, i,
860 CECHUB_FRU_HDIF_SIG) {
861 const struct cechub_hub_fru_id *fru_id_data;
862 unsigned int type;
863 static const char *typestr[] = {
864 "Reservation",
865 "Card",
866 "CPU Card",
867 "Backplane",
868 "Backplane Extension"
869 };
870 fru_id_data = HDIF_get_idata(sp_iohubs, CECHUB_FRU_ID_DATA_AREA,
871 &size);
872 if (!fru_id_data || size < sizeof(struct cechub_hub_fru_id)) {
873 prerror("CEC: IO-HUB FRU %d, bad ID data\n", i);
874 continue;
875 }
876 type = be32_to_cpu(fru_id_data->card_type);
877
878 prlog(PR_INFO, "CEC: HUB FRU %d is %s\n",
879 i, type > 4 ? "Unknown" : typestr[type]);
880
881 /*
882 * We currently only handle the backplane (Juno) and
883 * processor FRU (P8 machines)
884 */
885 if (type != CECHUB_FRU_TYPE_CEC_BKPLANE &&
886 type != CECHUB_FRU_TYPE_CPU_CARD) {
887 prerror("CEC: Unsupported type\n");
888 continue;
889 }
890
891 /* We don't support Hubs connected to pass-through ports */
892 if (fru_id_data->flags & (CECHUB_FRU_FLAG_HEADLESS |
893 CECHUB_FRU_FLAG_PASSTHROUGH)) {
894 prerror("CEC: Headless or Passthrough unsupported\n");
895 continue;
896 }
897
898 /* Ok, we have a reasonable candidate */
899 io_parse_fru(sp_iohubs);
900 }
901 }
902
903