~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/skiboot/hdata/spira.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <device.h>
 
18
#include "spira.h"
 
19
#include <cpu.h>
 
20
#include <vpd.h>
 
21
#include <interrupts.h>
 
22
#include <ccan/str/str.h>
 
23
#include <chip.h>
 
24
#include <fsp-mdst-table.h>
 
25
#include <fsp-attn.h>
 
26
#include <fsp-leds.h>
 
27
 
 
28
#include "hdata.h"
 
29
#include "hostservices.h"
 
30
 
 
31
/* Processor Initialization structure, contains
 
32
 * the initial NIA and MSR values for the entry
 
33
 * point
 
34
 *
 
35
 * Note: It appears to be ignoring the entry point
 
36
 *       and always going to 0x180
 
37
 */
 
38
 
 
39
static int cpu_type;
 
40
 
 
41
__section(".procin.data") struct proc_init_data proc_init_data = {
 
42
        .hdr = HDIF_SIMPLE_HDR("PROCIN", 1, struct proc_init_data),
 
43
        .regs_ptr = HDIF_IDATA_PTR(offsetof(struct proc_init_data, regs), 0x10),
 
44
        .regs = {
 
45
                .nia = CPU_TO_BE64(0x180),
 
46
                .msr = CPU_TO_BE64(0x9000000000000000ULL), /* SF | HV */
 
47
        },
 
48
};
 
49
 
 
50
__section(".cpuctrl.data") struct sp_addr_table cpu_ctl_spat_area;
 
51
__section(".cpuctrl.data") struct sp_attn_area cpu_ctl_sp_attn_area1;
 
52
__section(".cpuctrl.data") struct sp_attn_area cpu_ctl_sp_attn_area2;
 
53
__section(".cpuctrl.data") struct hsr_data_area cpu_ctl_hsr_area;
 
54
 
 
55
__section(".cpuctrl.data") struct cpu_ctl_init_data cpu_ctl_init_data = {
 
56
        .hdr = HDIF_SIMPLE_HDR(CPU_CTL_HDIF_SIG, 2, struct cpu_ctl_init_data),
 
57
        .cpu_ctl = HDIF_IDATA_PTR(offsetof(struct cpu_ctl_init_data, cpu_ctl_lt), sizeof(struct cpu_ctl_legacy_table)),
 
58
#if !defined(TEST)
 
59
        .cpu_ctl_lt = {
 
60
                .spat = {
 
61
                        .addr = CPU_TO_BE64((unsigned long)&(cpu_ctl_spat_area) + SKIBOOT_BASE),
 
62
                        .size = CPU_TO_BE64(sizeof(struct sp_addr_table)),
 
63
                },
 
64
                .sp_attn_area1 = {
 
65
                        .addr = CPU_TO_BE64((unsigned long)&(cpu_ctl_sp_attn_area1) + SKIBOOT_BASE),
 
66
                        .size = CPU_TO_BE64(sizeof(struct sp_attn_area)),
 
67
                },
 
68
                .sp_attn_area2 = {
 
69
                        .addr = CPU_TO_BE64((unsigned long)&(cpu_ctl_sp_attn_area2) + SKIBOOT_BASE),
 
70
                        .size = CPU_TO_BE64(sizeof(struct sp_attn_area)),
 
71
                },
 
72
                .hsr_area = {
 
73
                        .addr = CPU_TO_BE64((unsigned long)&(cpu_ctl_hsr_area) + SKIBOOT_BASE),
 
74
                        .size = CPU_TO_BE64(sizeof(struct hsr_data_area)),
 
75
                },
 
76
        },
 
77
#endif
 
78
};
 
79
 
 
80
/* Populate MDST table
 
81
 *
 
82
 * Note that we only pass sapphire console buffer here so that we can
 
83
 * capture early failure logs. Later dump component (fsp_dump_mdst_init)
 
84
 * creates new table with all the memory sections we are interested and
 
85
 * sends updated table to FSP via MBOX.
 
86
 *
 
87
 * To help the FSP distinguishing between TCE tokens and actual physical
 
88
 * addresses, we set the top bit to 1 on physical addresses
 
89
 */
 
90
#define ADDR_TOP_BIT    (1ul << 63)
 
91
 
 
92
__section(".mdst.data") struct dump_mdst_table init_mdst_table[2] = {
 
93
        {
 
94
                .addr = CPU_TO_BE64(INMEM_CON_START | ADDR_TOP_BIT),
 
95
                .type = CPU_TO_BE32(DUMP_REGION_CONSOLE),
 
96
                .size = CPU_TO_BE32(INMEM_CON_LEN),
 
97
        },
 
98
        {
 
99
                .addr = CPU_TO_BE64(HBRT_CON_START | ADDR_TOP_BIT),
 
100
                .type = CPU_TO_BE32(DUMP_REGION_HBRT_LOG),
 
101
                .size = CPU_TO_BE32(HBRT_CON_LEN),
 
102
        },
 
103
};
 
104
 
 
105
/* SP Interface Root Array, aka SPIRA */
 
106
__section(".spira.data") struct spira spira = {
 
107
        .hdr = HDIF_SIMPLE_HDR("SPIRA ", SPIRA_VERSION, struct spira),
 
108
        .ntuples_ptr = HDIF_IDATA_PTR(offsetof(struct spira, ntuples),
 
109
                                      sizeof(struct spira_ntuples)),
 
110
        .ntuples = {
 
111
                .array_hdr = {
 
112
                        .offset         = CPU_TO_BE32(HDIF_ARRAY_OFFSET),
 
113
                        .ecnt           = CPU_TO_BE32(SPIRA_NTUPLES_COUNT),
 
114
                        .esize
 
115
                                = CPU_TO_BE32(sizeof(struct spira_ntuple)),
 
116
                        .eactsz         = CPU_TO_BE32(0x18),
 
117
                },
 
118
                /* We only populate some n-tuples */
 
119
                .proc_init = {
 
120
                        .addr           = CPU_TO_BE64(PROCIN_OFF),
 
121
                        .alloc_cnt      = CPU_TO_BE16(1),
 
122
                        .act_cnt        = CPU_TO_BE16(1),
 
123
                        .alloc_len
 
124
                        = CPU_TO_BE32(sizeof(struct proc_init_data)),
 
125
                },
 
126
                .heap = {
 
127
                        .addr           = CPU_TO_BE64(SPIRA_HEAP_BASE),
 
128
                        .alloc_cnt      = CPU_TO_BE16(1),
 
129
                        .alloc_len      = CPU_TO_BE32(SPIRA_HEAP_SIZE),
 
130
                },
 
131
                .mdump_src = {
 
132
                        .addr           = CPU_TO_BE64(MDST_TABLE_OFF),
 
133
                        .alloc_cnt      = CPU_TO_BE16(ARRAY_SIZE(init_mdst_table)),
 
134
                        .act_cnt        = CPU_TO_BE16(ARRAY_SIZE(init_mdst_table)),
 
135
                        .alloc_len      =
 
136
                                CPU_TO_BE32(sizeof(init_mdst_table)),
 
137
                },
 
138
#if !defined(TEST)
 
139
                .cpu_ctrl = {
 
140
                        .addr           = CPU_TO_BE64((unsigned long)&cpu_ctl_init_data),
 
141
                        .alloc_cnt      = CPU_TO_BE16(1),
 
142
                        .act_cnt        = CPU_TO_BE16(1),
 
143
                        .alloc_len      =
 
144
                                        CPU_TO_BE32(sizeof(cpu_ctl_init_data)),
 
145
                },
 
146
#endif
 
147
        },
 
148
};
 
149
 
 
150
/* The Hypervisor SPIRA-H Structure */
 
151
__section(".spirah.data") struct spirah spirah = {
 
152
        .hdr = HDIF_SIMPLE_HDR(SPIRAH_HDIF_SIG, SPIRAH_VERSION, struct spirah),
 
153
        .ntuples_ptr = HDIF_IDATA_PTR(offsetof(struct spirah, ntuples),
 
154
                                      sizeof(struct spirah_ntuples)),
 
155
        .ntuples = {
 
156
                .array_hdr = {
 
157
                        .offset         = CPU_TO_BE32(HDIF_ARRAY_OFFSET),
 
158
                        .ecnt           = CPU_TO_BE32(SPIRAH_NTUPLES_COUNT),
 
159
                        .esize
 
160
                                = CPU_TO_BE32(sizeof(struct spira_ntuple)),
 
161
                        .eactsz         = CPU_TO_BE32(0x18),
 
162
                },
 
163
                /* Host Data Areas */
 
164
                .hs_data_area = {
 
165
                        .addr           = CPU_TO_BE64(SPIRA_HEAP_BASE),
 
166
                        .alloc_cnt      = CPU_TO_BE16(1),
 
167
                        .alloc_len      = CPU_TO_BE32(SPIRA_HEAP_SIZE),
 
168
                },
 
169
                /* We only populate some n-tuples */
 
170
                .proc_init = {
 
171
                        .addr           = CPU_TO_BE64(PROCIN_OFF),
 
172
                        .alloc_cnt      = CPU_TO_BE16(1),
 
173
                        .act_cnt        = CPU_TO_BE16(1),
 
174
                        .alloc_len
 
175
                        = CPU_TO_BE32(sizeof(struct proc_init_data)),
 
176
                },
 
177
#if !defined(TEST)
 
178
                .cpu_ctrl = {
 
179
                        .addr           = CPU_TO_BE64((unsigned long)&cpu_ctl_init_data),
 
180
                        .alloc_cnt      = CPU_TO_BE16(1),
 
181
                        .act_cnt        = CPU_TO_BE16(1),
 
182
                        .alloc_len      =
 
183
                                        CPU_TO_BE32(sizeof(cpu_ctl_init_data)),
 
184
                },
 
185
#endif
 
186
                .mdump_src = {
 
187
                        .addr           = CPU_TO_BE64(MDST_TABLE_OFF),
 
188
                        .alloc_cnt      = CPU_TO_BE16(ARRAY_SIZE(init_mdst_table)),
 
189
                        .act_cnt        = CPU_TO_BE16(ARRAY_SIZE(init_mdst_table)),
 
190
                        .alloc_len      =
 
191
                                CPU_TO_BE32(sizeof(init_mdst_table)),
 
192
                },
 
193
        },
 
194
};
 
195
 
 
196
/* The service processor SPIRA-S structure */
 
197
struct spiras *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
struct HDIF_common_hdr *__get_hdif(struct spira_ntuple *n, const char id[],
 
215
                                   const char *file, int line)
 
216
{
 
217
        struct HDIF_common_hdr *h = ntuple_addr(n);
 
218
        if (!spira_check_ptr(h, file, line))
 
219
                return NULL;
 
220
 
 
221
        if (!HDIF_check(h, id)) {
 
222
                prerror("SPIRA: bad tuple %p: expected %s at %s line %d\n",
 
223
                        h, id, file, line);
 
224
                return NULL;
 
225
        }
 
226
        return h;
 
227
}
 
228
 
 
229
static struct dt_node *add_xscom_node(uint64_t base, uint32_t hw_id,
 
230
                                      uint32_t proc_chip_id)
 
231
{
 
232
        struct dt_node *node;
 
233
        uint64_t addr, size;
 
234
        uint64_t freq;
 
235
 
 
236
        addr = base | ((uint64_t)hw_id << PPC_BITLSHIFT(28));
 
237
        size = (u64)1 << PPC_BITLSHIFT(28);
 
238
 
 
239
        prlog(PR_INFO, "XSCOM: Found HW ID 0x%x (PCID 0x%x) @ 0x%llx\n",
 
240
               hw_id, proc_chip_id, (long long)addr);
 
241
 
 
242
        node = dt_new_addr(dt_root, "xscom", addr);
 
243
        if (!node)
 
244
                return NULL;
 
245
 
 
246
        dt_add_property_cells(node, "ibm,chip-id", hw_id);
 
247
        dt_add_property_cells(node, "ibm,proc-chip-id", proc_chip_id);
 
248
        dt_add_property_cells(node, "#address-cells", 1);
 
249
        dt_add_property_cells(node, "#size-cells", 1);
 
250
        dt_add_property(node, "scom-controller", NULL, 0);
 
251
 
 
252
        switch(proc_gen) {
 
253
        case proc_gen_p7:
 
254
                dt_add_property_strings(node, "compatible",
 
255
                                        "ibm,xscom", "ibm,power7-xscom");
 
256
                break;
 
257
        case proc_gen_p8:
 
258
                dt_add_property_strings(node, "compatible",
 
259
                                        "ibm,xscom", "ibm,power8-xscom");
 
260
                break;
 
261
        default:
 
262
                dt_add_property_strings(node, "compatible", "ibm,xscom");
 
263
        }
 
264
        dt_add_property_u64s(node, "reg", addr, size);
 
265
 
 
266
        /* Derive bus frquency */
 
267
        freq = dt_prop_get_u64_def(dt_root, "nest-frequency", 0);
 
268
        freq /= 4;
 
269
        if (freq)
 
270
                dt_add_property_cells(node, "bus-frequency",
 
271
                                      hi32(freq), lo32(freq));
 
272
 
 
273
        return node;
 
274
}
 
275
 
 
276
struct dt_node *find_xscom_for_chip(uint32_t chip_id)
 
277
{
 
278
        struct dt_node *node;
 
279
        uint32_t id;
 
280
 
 
281
        dt_for_each_compatible(dt_root, node, "ibm,xscom") {
 
282
                id = dt_get_chip_id(node);
 
283
                if (id == chip_id)
 
284
                        return node;
 
285
        }
 
286
 
 
287
        return NULL;
 
288
}
 
289
 
 
290
static void add_psihb_node(struct dt_node *np)
 
291
{
 
292
        u32 psi_scom, psi_slen;
 
293
        const char *psi_comp;
 
294
 
 
295
        /*
 
296
         * We add a few things under XSCOM that aren't added
 
297
         * by any other HDAT path
 
298
         */
 
299
 
 
300
        /* PSI host bridge */
 
301
        switch(proc_gen) {
 
302
        case proc_gen_p7:
 
303
                psi_scom = 0x2010c00;
 
304
                psi_slen = 0x10;
 
305
                psi_comp = "ibm,power7-psihb-x";
 
306
                break;
 
307
        case proc_gen_p8:
 
308
                psi_scom = 0x2010900;
 
309
                psi_slen = 0x20;
 
310
                psi_comp = "ibm,power8-psihb-x";
 
311
                break;
 
312
        default:
 
313
                psi_comp = NULL;
 
314
        }
 
315
        if (psi_comp) {
 
316
                struct dt_node *psi_np;
 
317
 
 
318
                psi_np = dt_new_addr(np, "psihb", psi_scom);
 
319
                if (!psi_np)
 
320
                        return;
 
321
 
 
322
                dt_add_property_cells(psi_np, "reg", psi_scom, psi_slen);
 
323
                dt_add_property_strings(psi_np, "compatible", psi_comp,
 
324
                                        "ibm,psihb-x");
 
325
        }
 
326
}
 
327
 
 
328
static void add_xscom_add_pcia_assoc(struct dt_node *np, uint32_t pcid)
 
329
{
 
330
        const struct HDIF_common_hdr *hdr;
 
331
        u32 size;
 
332
 
 
333
 
 
334
        /*
 
335
         * The SPPCRD doesn't contain all the affinity data, we have
 
336
         * to dig it out of a core. I assume this is so that node
 
337
         * affinity can be different for groups of cores within the
 
338
         * chip, but for now we are going to ignore that
 
339
         */
 
340
        hdr = get_hdif(&spira.ntuples.pcia, SPPCIA_HDIF_SIG);
 
341
        if (!hdr)
 
342
                return;
 
343
 
 
344
        for_each_pcia(hdr) {
 
345
                const struct sppcia_core_unique *id;
 
346
 
 
347
                id = HDIF_get_idata(hdr, SPPCIA_IDATA_CORE_UNIQUE, &size);
 
348
                if (!id || size < sizeof(*id))
 
349
                        continue;
 
350
 
 
351
                if (be32_to_cpu(id->proc_chip_id) != pcid)
 
352
                        continue;
 
353
 
 
354
                dt_add_property_cells(np, "ibm,ccm-node-id",
 
355
                                      be32_to_cpu(id->ccm_node_id));
 
356
                dt_add_property_cells(np, "ibm,hw-card-id",
 
357
                                      be32_to_cpu(id->hw_card_id));
 
358
                dt_add_property_cells(np, "ibm,hw-module-id",
 
359
                                      be32_to_cpu(id->hw_module_id));
 
360
                if (!dt_find_property(np, "ibm,dbob-id"))
 
361
                        dt_add_property_cells(np, "ibm,dbob-id",
 
362
                                  be32_to_cpu(id->drawer_book_octant_blade_id));
 
363
                dt_add_property_cells(np, "ibm,mem-interleave-scope",
 
364
                                  be32_to_cpu(id->memory_interleaving_scope));
 
365
                return;
 
366
        }
 
367
}
 
368
 
 
369
static bool add_xscom_sppcrd(uint64_t xscom_base)
 
370
{
 
371
        const struct HDIF_common_hdr *hdif;
 
372
        unsigned int i, vpd_sz;
 
373
        const void *vpd;
 
374
        struct dt_node *np, *vpd_node;
 
375
 
 
376
        for_each_ntuple_idx(&spira.ntuples.proc_chip, hdif, i,
 
377
                            SPPCRD_HDIF_SIG) {
 
378
                const struct sppcrd_chip_info *cinfo;
 
379
                u32 ve, version;
 
380
 
 
381
                cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
 
382
                if (!CHECK_SPPTR(cinfo)) {
 
383
                        prerror("XSCOM: Bad ChipID data %d\n", i);
 
384
                        continue;
 
385
                }
 
386
 
 
387
                ve = be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASK;
 
388
                ve >>= CHIP_VERIFY_SHIFT;
 
389
                if (ve == CHIP_VERIFY_NOT_INSTALLED ||
 
390
                    ve == CHIP_VERIFY_UNUSABLE)
 
391
                        continue;
 
392
 
 
393
                /* Create the XSCOM node */
 
394
                np = add_xscom_node(xscom_base,
 
395
                                    be32_to_cpu(cinfo->xscom_id),
 
396
                                    be32_to_cpu(cinfo->proc_chip_id));
 
397
                if (!np)
 
398
                        continue;
 
399
 
 
400
                version = be16_to_cpu(hdif->version);
 
401
 
 
402
                /* Version 0A has additional OCC related stuff */
 
403
                if (version >= 0x000a) {
 
404
                        if (!dt_find_property(np, "ibm,dbob-id"))
 
405
                                dt_add_property_cells(np, "ibm,dbob-id",
 
406
                                        be32_to_cpu(cinfo->dbob_id));
 
407
                        dt_add_property_cells(np, "ibm,occ-functional-state",
 
408
                                              be32_to_cpu(cinfo->occ_state));
 
409
                }
 
410
 
 
411
                /* Add chip VPD */
 
412
                vpd_node = dt_add_vpd_node(hdif, SPPCRD_IDATA_FRU_ID,
 
413
                                           SPPCRD_IDATA_KW_VPD);
 
414
                if (vpd_node)
 
415
                        dt_add_property_cells(vpd_node, "ibm,chip-id",
 
416
                                              be32_to_cpu(cinfo->xscom_id));
 
417
 
 
418
                /* Add module VPD on version A and later */
 
419
                if (version >= 0x000a) {
 
420
                        vpd = HDIF_get_idata(hdif, SPPCRD_IDATA_MODULE_VPD,
 
421
                                             &vpd_sz);
 
422
                        if (CHECK_SPPTR(vpd))
 
423
                                dt_add_property(np, "ibm,module-vpd", vpd,
 
424
                                                vpd_sz);
 
425
                }
 
426
 
 
427
                /*
 
428
                 * Extract additional associativity information from
 
429
                 * the core data. Pick one core on that chip
 
430
                 */
 
431
                add_xscom_add_pcia_assoc(np, be32_to_cpu(cinfo->proc_chip_id));
 
432
 
 
433
                /* Add PSI Host bridge */
 
434
                add_psihb_node(np);
 
435
        }
 
436
 
 
437
        return i > 0;
 
438
}
 
439
 
 
440
static void add_xscom_sppaca(uint64_t xscom_base)
 
441
{
 
442
        const struct HDIF_common_hdr *hdif;
 
443
        unsigned int i;
 
444
        struct dt_node *np, *vpd_node;
 
445
 
 
446
        for_each_ntuple_idx(&spira.ntuples.paca, hdif, i, PACA_HDIF_SIG) {
 
447
                const struct sppaca_cpu_id *id;
 
448
                unsigned int chip_id, size;
 
449
                int ve;
 
450
 
 
451
                /* We only suport old style PACA on P7 ! */
 
452
                assert(proc_gen == proc_gen_p7);
 
453
 
 
454
                id = HDIF_get_idata(hdif, SPPACA_IDATA_CPU_ID, &size);
 
455
 
 
456
                if (!CHECK_SPPTR(id)) {
 
457
                        prerror("XSCOM: Bad processor data %d\n", i);
 
458
                        continue;
 
459
                }
 
460
 
 
461
                ve = be32_to_cpu(id->verify_exists_flags) & CPU_ID_VERIFY_MASK;
 
462
                ve >>= CPU_ID_VERIFY_SHIFT;
 
463
                if (ve == CPU_ID_VERIFY_NOT_INSTALLED ||
 
464
                    ve == CPU_ID_VERIFY_UNUSABLE)
 
465
                        continue;
 
466
 
 
467
                /* Convert to HW chip ID */
 
468
                chip_id = P7_PIR2GCID(be32_to_cpu(id->pir));
 
469
 
 
470
                /* do we already have an XSCOM for this chip? */
 
471
                if (find_xscom_for_chip(chip_id))
 
472
                        continue;
 
473
 
 
474
                /* Create the XSCOM node */
 
475
                np = add_xscom_node(xscom_base, chip_id,
 
476
                                    be32_to_cpu(id->processor_chip_id));
 
477
                if (!np)
 
478
                        continue;
 
479
 
 
480
                /* Add chip VPD */
 
481
                vpd_node = dt_add_vpd_node(hdif, SPPACA_IDATA_FRU_ID,
 
482
                                           SPPACA_IDATA_KW_VPD);
 
483
                if (vpd_node)
 
484
                        dt_add_property_cells(vpd_node, "ibm,chip-id", chip_id);
 
485
 
 
486
                /* Add chip associativity data */
 
487
                dt_add_property_cells(np, "ibm,ccm-node-id",
 
488
                                      be32_to_cpu(id->ccm_node_id));
 
489
                if (size > SPIRA_CPU_ID_MIN_SIZE) {
 
490
                        dt_add_property_cells(np, "ibm,hw-card-id",
 
491
                                              be32_to_cpu(id->hw_card_id));
 
492
                        dt_add_property_cells(np, "ibm,hw-module-id",
 
493
                                          be32_to_cpu(id->hardware_module_id));
 
494
                        if (!dt_find_property(np, "ibm,dbob-id"))
 
495
                                dt_add_property_cells(np, "ibm,dbob-id",
 
496
                                  be32_to_cpu(id->drawer_book_octant_blade_id));
 
497
                        dt_add_property_cells(np, "ibm,mem-interleave-scope",
 
498
                                 be32_to_cpu(id->memory_interleaving_scope));
 
499
                }
 
500
 
 
501
                /* Add PSI Host bridge */
 
502
                add_psihb_node(np);
 
503
        }
 
504
}
 
505
 
 
506
static void add_xscom(void)
 
507
{
 
508
        const void *ms_vpd;
 
509
        const struct msvpd_pmover_bsr_synchro *pmbs;
 
510
        unsigned int size;
 
511
        uint64_t xscom_base;
 
512
 
 
513
        ms_vpd = get_hdif(&spira.ntuples.ms_vpd, MSVPD_HDIF_SIG);
 
514
        if (!ms_vpd) {
 
515
                prerror("XSCOM: Can't find MS VPD\n");
 
516
                return;
 
517
        }
 
518
 
 
519
        pmbs = HDIF_get_idata(ms_vpd, MSVPD_IDATA_PMOVER_SYNCHRO, &size);
 
520
        if (!CHECK_SPPTR(pmbs) || size < sizeof(*pmbs)) {
 
521
                prerror("XSCOM: absent or bad PMBS size %u @ %p\n", size, pmbs);
 
522
                return;
 
523
        }
 
524
 
 
525
        if (!(be32_to_cpu(pmbs->flags) & MSVPD_PMS_FLAG_XSCOMBASE_VALID)) {
 
526
                prerror("XSCOM: No XSCOM base in PMBS, using default\n");
 
527
                return;
 
528
        }
 
529
 
 
530
        xscom_base = be64_to_cpu(pmbs->xscom_addr);
 
531
 
 
532
        /* Some FSP (on P7) give me a crap base address for XSCOM (it has
 
533
         * spurious bits set as far as I can tell). Since only 5 bits 18:22 can
 
534
         * be programmed in hardware, let's isolate these. This seems to give
 
535
         * me the right value on VPL1
 
536
         */
 
537
        if (cpu_type == PVR_TYPE_P7)
 
538
                xscom_base &= 0x80003e0000000000ul;
 
539
 
 
540
        /* Get rid of the top bits */
 
541
        xscom_base = cleanup_addr(xscom_base);
 
542
 
 
543
        /* First, try the new proc_chip ntuples for chip data */
 
544
        if (add_xscom_sppcrd(xscom_base))
 
545
                return;
 
546
 
 
547
        /* Otherwise, check the old-style PACA, looking for unique chips */
 
548
        add_xscom_sppaca(xscom_base);
 
549
}
 
550
 
 
551
static void add_chiptod_node(unsigned int chip_id, int flags)
 
552
{
 
553
        struct dt_node *node, *xscom_node;
 
554
        const char *compat_str;
 
555
        uint32_t addr, len;
 
556
 
 
557
        if ((flags & CHIPTOD_ID_FLAGS_STATUS_MASK) !=
 
558
                        CHIPTOD_ID_FLAGS_STATUS_OK)
 
559
                return;
 
560
 
 
561
        xscom_node = find_xscom_for_chip(chip_id);
 
562
        if (!xscom_node) {
 
563
                prerror("CHIPTOD: No xscom for chiptod %d?\n", chip_id);
 
564
                return;
 
565
        }
 
566
 
 
567
        addr = 0x40000;
 
568
        len = 0x34;
 
569
 
 
570
        switch(proc_gen) {
 
571
        case proc_gen_p7:
 
572
                compat_str = "ibm,power7-chiptod";
 
573
                break;
 
574
        case proc_gen_p8:
 
575
                compat_str = "ibm,power8-chiptod";
 
576
                break;
 
577
        default:
 
578
                return;
 
579
        }
 
580
 
 
581
        prlog(PR_DEBUG, "CHIPTOD: Found on chip 0x%x %s\n", chip_id,
 
582
              (flags & CHIPTOD_ID_FLAGS_PRIMARY) ? "[primary]" :
 
583
              ((flags & CHIPTOD_ID_FLAGS_SECONDARY) ? "[secondary]" : ""));
 
584
 
 
585
        node = dt_new_addr(xscom_node, "chiptod", addr);
 
586
        if (!node)
 
587
                return;
 
588
 
 
589
        dt_add_property_cells(node, "reg", addr, len);
 
590
        dt_add_property_strings(node, "compatible", "ibm,power-chiptod",
 
591
                               compat_str);
 
592
 
 
593
        if (flags & CHIPTOD_ID_FLAGS_PRIMARY)
 
594
                dt_add_property(node, "primary", NULL, 0);
 
595
        if (flags & CHIPTOD_ID_FLAGS_SECONDARY)
 
596
                dt_add_property(node, "secondary", NULL, 0);
 
597
}
 
598
 
 
599
static bool add_chiptod_old(void)
 
600
{
 
601
        const void *hdif;
 
602
        unsigned int i;
 
603
        bool found = false;
 
604
 
 
605
        /*
 
606
         * Locate chiptod ID structures in SPIRA
 
607
         */
 
608
        if (!get_hdif(&spira.ntuples.chip_tod, "TOD   "))
 
609
                return found;
 
610
 
 
611
        for_each_ntuple_idx(&spira.ntuples.chip_tod, hdif, i, "TOD   ") {
 
612
                const struct chiptod_chipid *id;
 
613
 
 
614
                id = HDIF_get_idata(hdif, CHIPTOD_IDATA_CHIPID, NULL);
 
615
                if (!CHECK_SPPTR(id)) {
 
616
                        prerror("CHIPTOD: Bad ChipID data %d\n", i);
 
617
                        continue;
 
618
                }
 
619
 
 
620
                add_chiptod_node(pcid_to_chip_id(be32_to_cpu(id->chip_id)),
 
621
                                 be32_to_cpu(id->flags));
 
622
                found = true;
 
623
        }
 
624
        return found;
 
625
}
 
626
 
 
627
static bool add_chiptod_new(uint32_t master_cpu)
 
628
{
 
629
        const void *hdif;
 
630
        unsigned int i, master_chip;
 
631
        bool found = false;
 
632
 
 
633
        /*
 
634
         * Locate Proc Chip ID structures in SPIRA
 
635
         */
 
636
        if (!get_hdif(&spira.ntuples.proc_chip, SPPCRD_HDIF_SIG))
 
637
                return found;
 
638
 
 
639
        master_chip = pir_to_chip_id(master_cpu);
 
640
 
 
641
        for_each_ntuple_idx(&spira.ntuples.proc_chip, hdif, i,
 
642
                            SPPCRD_HDIF_SIG) {
 
643
                const struct sppcrd_chip_info *cinfo;
 
644
                const struct sppcrd_chip_tod *tinfo;
 
645
                unsigned int size;
 
646
                u32 ve, flags;
 
647
 
 
648
                cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
 
649
                if (!CHECK_SPPTR(cinfo)) {
 
650
                        prerror("CHIPTOD: Bad ChipID data %d\n", i);
 
651
                        continue;
 
652
                }
 
653
 
 
654
                ve = be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASK;
 
655
                ve >>= CHIP_VERIFY_SHIFT;
 
656
                if (ve == CHIP_VERIFY_NOT_INSTALLED ||
 
657
                    ve == CHIP_VERIFY_UNUSABLE)
 
658
                        continue;
 
659
 
 
660
                tinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_TOD, &size);
 
661
                if (!CHECK_SPPTR(tinfo)) {
 
662
                        prerror("CHIPTOD: Bad TOD data %d\n", i);
 
663
                        continue;
 
664
                }
 
665
 
 
666
                flags = be32_to_cpu(tinfo->flags);
 
667
 
 
668
                /* The FSP may strip the chiptod info from HDAT; if we find
 
669
                 * a zero-ed out entry, assume that the chiptod is
 
670
                 * present, but we don't have any primary/secondary info. In
 
671
                 * this case, pick the primary based on the CPU that was
 
672
                 * assigned master.
 
673
                 */
 
674
                if (!size) {
 
675
                        flags = CHIPTOD_ID_FLAGS_STATUS_OK;
 
676
                        if (be32_to_cpu(cinfo->xscom_id) == master_chip)
 
677
                                flags |= CHIPTOD_ID_FLAGS_PRIMARY;
 
678
                }
 
679
 
 
680
                add_chiptod_node(be32_to_cpu(cinfo->xscom_id), flags);
 
681
                found = true;
 
682
        }
 
683
        return found;
 
684
}
 
685
 
 
686
static void add_nx_node(u32 gcid)
 
687
{
 
688
        struct dt_node *nx;
 
689
        const char *cp_str;
 
690
        u32 addr;
 
691
        u32 size;
 
692
        struct dt_node *xscom;
 
693
 
 
694
        xscom = find_xscom_for_chip(gcid);
 
695
        if (xscom == NULL) {
 
696
                prerror("NX%d: did not found xscom node.\n", gcid);
 
697
                return;
 
698
        }
 
699
 
 
700
        /*
 
701
         * The NX register space is relatively self contained on P7+ but
 
702
         * a bit more messy on P8. However it's all contained within the
 
703
         * PB chiplet port 1 so we'll stick to that in the "reg" property
 
704
         * and let the NX "driver" deal with the details.
 
705
         */
 
706
        addr = 0x2010000;
 
707
        size = 0x0004000;
 
708
 
 
709
        switch (proc_gen) {
 
710
        case proc_gen_p7:
 
711
                cp_str = "ibm,power7-nx";
 
712
                break;
 
713
        case proc_gen_p8:
 
714
                cp_str = "ibm,power8-nx";
 
715
                break;
 
716
        default:
 
717
                return;
 
718
        }
 
719
        nx = dt_new_addr(xscom, "nx", addr);
 
720
        if (!nx)
 
721
                return;
 
722
 
 
723
        dt_add_property_cells(nx, "reg", addr, size);
 
724
        dt_add_property_strings(nx, "compatible", "ibm,power-nx", cp_str);
 
725
}
 
726
 
 
727
static void add_nx(void)
 
728
{
 
729
        unsigned int i;
 
730
        void *hdif;
 
731
 
 
732
        for_each_ntuple_idx(&spira.ntuples.proc_chip, hdif, i,
 
733
                        SPPCRD_HDIF_SIG) {
 
734
                const struct sppcrd_chip_info *cinfo;
 
735
                u32 ve;
 
736
 
 
737
                cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
 
738
                if (!CHECK_SPPTR(cinfo)) {
 
739
                        prerror("NX: Bad ChipID data %d\n", i);
 
740
                        continue;
 
741
                }
 
742
 
 
743
                ve = be32_to_cpu(cinfo->verif_exist_flags) & CHIP_VERIFY_MASK;
 
744
                ve >>= CHIP_VERIFY_SHIFT;
 
745
                if (ve == CHIP_VERIFY_NOT_INSTALLED ||
 
746
                                ve == CHIP_VERIFY_UNUSABLE)
 
747
                        continue;
 
748
 
 
749
                if (cinfo->nx_state)
 
750
                        add_nx_node(be32_to_cpu(cinfo->xscom_id));
 
751
        }
 
752
}
 
753
 
 
754
 
 
755
static void add_iplparams_sys_params(const void *iplp, struct dt_node *node)
 
756
{
 
757
        const struct iplparams_sysparams *p;
 
758
        u32 sys_type;
 
759
        const char *sys_family;
 
760
        const struct HDIF_common_hdr *hdif = iplp;
 
761
        u16 version = be16_to_cpu(hdif->version);
 
762
 
 
763
        p = HDIF_get_idata(iplp, IPLPARAMS_SYSPARAMS, NULL);
 
764
        if (!CHECK_SPPTR(p)) {
 
765
                prerror("IPLPARAMS: No SYS Parameters\n");
 
766
                /* Create a generic compatible property */
 
767
                dt_add_property_string(dt_root, "compatible", "ibm,powernv");
 
768
                return;
 
769
        }
 
770
 
 
771
        node = dt_new(node, "sys-params");
 
772
        assert(node);
 
773
        dt_add_property_cells(node, "#address-cells", 0);
 
774
        dt_add_property_cells(node, "#size-cells", 0);
 
775
 
 
776
        dt_add_property_nstr(node, "ibm,sys-model", p->sys_model, 4);
 
777
 
 
778
        /* Compatible is 2 entries: ibm,powernv and ibm,<platform>
 
779
         */
 
780
        sys_type = be32_to_cpu(p->system_type);
 
781
        switch(sys_type >> 28) {
 
782
        case 0:
 
783
                sys_family = "ibm,squadrons";
 
784
                break;
 
785
        case 1:
 
786
                sys_family = "ibm,eclipz";
 
787
                break;
 
788
        case 2:
 
789
                sys_family = "ibm,apollo";
 
790
                break;
 
791
        case 3:
 
792
                sys_family = "ibm,firenze";
 
793
                break;
 
794
        default:
 
795
                sys_family = NULL;
 
796
                prerror("IPLPARAMS: Unknown system family\n");
 
797
                break;
 
798
        }
 
799
        dt_add_property_strings(dt_root, "compatible", "ibm,powernv",
 
800
                                sys_family);
 
801
 
 
802
        /* Grab nest frequency when available */
 
803
        if (version >= 0x005b) {
 
804
                u64 freq = be32_to_cpu(p->nest_freq_mhz);
 
805
 
 
806
                freq *= 1000000;
 
807
                dt_add_property_cells(dt_root, "nest-frequency",
 
808
                                      hi32(freq), lo32(freq));
 
809
        }
 
810
}
 
811
 
 
812
static void add_iplparams_ipl_params(const void *iplp, struct dt_node *node)
 
813
{
 
814
        const struct iplparams_iplparams *p;
 
815
        struct dt_node *led_node;
 
816
 
 
817
        p = HDIF_get_idata(iplp, IPLPARAMS_IPLPARAMS, NULL);
 
818
        if (!CHECK_SPPTR(p)) {
 
819
                prerror("IPLPARAMS: No IPL Parameters\n");
 
820
                return;
 
821
        }
 
822
 
 
823
        node = dt_new(node, "ipl-params");
 
824
        assert(node);
 
825
        dt_add_property_cells(node, "#address-cells", 0);
 
826
        dt_add_property_cells(node, "#size-cells", 0);
 
827
 
 
828
        /* On an ASM initiated factory reset, this bit will be set
 
829
         * and the FSP expects the firmware to reset the PCI bus
 
830
         * numbers and respond with a Power Down (CE,4D,02) message
 
831
         */
 
832
        if (be32_to_cpu(p->other_attrib) & IPLPARAMS_OATTR_RST_PCI_BUSNO)
 
833
                dt_add_property_cells(node, "pci-busno-reset-ipl", 1);
 
834
        dt_add_property_strings(node, "cec-ipl-side",
 
835
                                (p->ipl_side & IPLPARAMS_CEC_FW_IPL_SIDE_TEMP) ?
 
836
                                "temp" : "perm");
 
837
        dt_add_property_strings(node, "fsp-ipl-side",
 
838
                                (p->ipl_side & IPLPARAMS_FSP_FW_IPL_SIDE_TEMP) ?
 
839
                                "temp" : "perm");
 
840
        dt_add_property_cells(node, "os-ipl-mode", p->os_ipl_mode);
 
841
        dt_add_property_strings(node, "cec-major-type",
 
842
                                p->cec_ipl_maj_type ? "hot" : "cold");
 
843
 
 
844
        /* Add LED type info under '/ibm,opal/led' node */
 
845
        led_node = dt_find_by_path(opal_node, DT_PROPERTY_LED_NODE);
 
846
        assert(led_node);
 
847
 
 
848
        if (be32_to_cpu(p->other_attrib) & IPLPARAMS_OATRR_LIGHT_PATH)
 
849
                dt_add_property_strings(led_node, DT_PROPERTY_LED_MODE,
 
850
                                        LED_MODE_LIGHT_PATH);
 
851
        else
 
852
                dt_add_property_strings(led_node, DT_PROPERTY_LED_MODE,
 
853
                                        LED_MODE_GUIDING_LIGHT);
 
854
}
 
855
 
 
856
static void add_iplparams_serials(const void *iplp, struct dt_node *node)
 
857
{
 
858
        const struct iplparms_serial *ipser;
 
859
        struct dt_node *ser_node;
 
860
        int count, i;
 
861
        
 
862
        count = HDIF_get_iarray_size(iplp, IPLPARMS_IDATA_SERIAL);
 
863
        if (!count) {
 
864
                prerror("IPLPARAMS: No serial ports\n");
 
865
                return;
 
866
        }
 
867
        prlog(PR_INFO, "IPLPARAMS: %d serial ports in array\n", count);
 
868
 
 
869
        node = dt_new(node, "fsp-serial");
 
870
        assert(node);
 
871
        dt_add_property_cells(node, "#address-cells", 1);
 
872
        dt_add_property_cells(node, "#size-cells", 0);
 
873
 
 
874
        for (i = 0; i < count; i++) {
 
875
                u16 rsrc_id;
 
876
                ipser = HDIF_get_iarray_item(iplp, IPLPARMS_IDATA_SERIAL,
 
877
                                             i, NULL);
 
878
                if (!CHECK_SPPTR(ipser))
 
879
                        continue;
 
880
                rsrc_id = be16_to_cpu(ipser->rsrc_id);
 
881
                prlog(PR_INFO, "IPLPARAMS: Serial %d rsrc: %04x loc: %s\n",
 
882
                      i, rsrc_id, ipser->loc_code);
 
883
                ser_node = dt_new_addr(node, "serial", rsrc_id);
 
884
                if (!ser_node)
 
885
                        continue;
 
886
 
 
887
                dt_add_property_cells(ser_node, "reg", rsrc_id);
 
888
                dt_add_property_nstr(ser_node, "ibm,loc-code",
 
889
                                     ipser->loc_code, LOC_CODE_SIZE);
 
890
                dt_add_property_string(ser_node, "compatible",
 
891
                                       "ibm,fsp-serial");
 
892
                /* XXX handle CALLHOME flag ? */
 
893
        }
 
894
}
 
895
 
 
896
/*
 
897
 * Check for platform dump, if present populate DT
 
898
 */
 
899
static void add_iplparams_platform_dump(const void *iplp, struct dt_node *node)
 
900
{
 
901
        const struct iplparams_dump *ipl_dump;
 
902
 
 
903
        ipl_dump = HDIF_get_idata(iplp, IPLPARAMS_PLATFORM_DUMP, NULL);
 
904
        if (!CHECK_SPPTR(ipl_dump))
 
905
                return;
 
906
 
 
907
        node = dt_new(node, "platform-dump");
 
908
        assert(node);
 
909
 
 
910
        if (be32_to_cpu(ipl_dump->dump_id)) {
 
911
                dt_add_property_cells(node, "dump-id",
 
912
                                      be32_to_cpu(ipl_dump->dump_id));
 
913
                dt_add_property_u64(node, "total-size",
 
914
                                    be64_to_cpu(ipl_dump->act_dump_sz));
 
915
                dt_add_property_u64(node, "hw-dump-size",
 
916
                                    be32_to_cpu(ipl_dump->act_hw_dump_sz));
 
917
                dt_add_property_cells(node, "plog-id",
 
918
                                      be32_to_cpu(ipl_dump->plid));
 
919
        }
 
920
}
 
921
 
 
922
static void add_iplparams(void)
 
923
{
 
924
        struct dt_node *iplp_node;
 
925
        const void *ipl_parms;
 
926
 
 
927
        ipl_parms = get_hdif(&spira.ntuples.ipl_parms, "IPLPMS");
 
928
        if (!ipl_parms) {
 
929
                prerror("IPLPARAMS: Cannot find IPL Parms in SPIRA\n");
 
930
                return;
 
931
        }
 
932
 
 
933
        iplp_node = dt_new(dt_root, "ipl-params");
 
934
        assert(iplp_node);
 
935
        dt_add_property_cells(iplp_node, "#address-cells", 0);
 
936
        dt_add_property_cells(iplp_node, "#size-cells", 0);
 
937
 
 
938
        add_iplparams_sys_params(ipl_parms, iplp_node);
 
939
        add_iplparams_ipl_params(ipl_parms, iplp_node);
 
940
        add_iplparams_serials(ipl_parms, iplp_node);
 
941
        add_iplparams_platform_dump(ipl_parms, iplp_node);
 
942
}
 
943
 
 
944
/* Various structure contain a "proc_chip_id" which is an arbitrary
 
945
 * numbering used by HDAT to reference chips, which doesn't correspond
 
946
 * to the HW IDs. We want to use the HW IDs everywhere in the DT so
 
947
 * we convert using this.
 
948
 *
 
949
 * Note: On P7, the HW ID is the XSCOM "GCID" including the T bit which
 
950
 * is *different* from the chip ID portion of the interrupt server#
 
951
 * (or PIR). See the explanations in chip.h
 
952
 */
 
953
uint32_t pcid_to_chip_id(uint32_t proc_chip_id)
 
954
{
 
955
        unsigned int i;
 
956
        const void *hdif;
 
957
 
 
958
        /* First, try the proc_chip ntuples for chip data */
 
959
        for_each_ntuple_idx(&spira.ntuples.proc_chip, hdif, i,
 
960
                            SPPCRD_HDIF_SIG) {
 
961
                const struct sppcrd_chip_info *cinfo;
 
962
 
 
963
                cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO,
 
964
                                                NULL);
 
965
                if (!CHECK_SPPTR(cinfo)) {
 
966
                        prerror("XSCOM: Bad ChipID data %d\n", i);
 
967
                        continue;
 
968
                }
 
969
                if (proc_chip_id == be32_to_cpu(cinfo->proc_chip_id))
 
970
                        return be32_to_cpu(cinfo->xscom_id);
 
971
        }
 
972
 
 
973
        /* Otherwise, check the old-style PACA, looking for unique chips */
 
974
        for_each_ntuple_idx(&spira.ntuples.paca, hdif, i, PACA_HDIF_SIG) {
 
975
                const struct sppaca_cpu_id *id;
 
976
 
 
977
                /* We only suport old style PACA on P7 ! */
 
978
                assert(proc_gen == proc_gen_p7);
 
979
 
 
980
                id = HDIF_get_idata(hdif, SPPACA_IDATA_CPU_ID, NULL);
 
981
 
 
982
                if (!CHECK_SPPTR(id)) {
 
983
                        prerror("XSCOM: Bad processor data %d\n", i);
 
984
                        continue;
 
985
                }
 
986
 
 
987
                if (proc_chip_id == be32_to_cpu(id->processor_chip_id))
 
988
                        return P7_PIR2GCID(be32_to_cpu(id->pir));
 
989
        }
 
990
 
 
991
        /* Not found, what to do ? Assert ? For now return a number
 
992
         * guaranteed to not exist
 
993
         */
 
994
        return (uint32_t)-1;
 
995
}
 
996
 
 
997
/* Create '/ibm,opal/led' node */
 
998
static void dt_init_led_node(void)
 
999
{
 
1000
        struct dt_node *led_node;
 
1001
 
 
1002
        /* Create /ibm,opal node, if its not created already */
 
1003
        if (!opal_node) {
 
1004
                opal_node = dt_new(dt_root, "ibm,opal");
 
1005
                assert(opal_node);
 
1006
        }
 
1007
 
 
1008
        /* Crete LED parent node */
 
1009
        led_node = dt_new(opal_node, DT_PROPERTY_LED_NODE);
 
1010
        assert(led_node);
 
1011
}
 
1012
 
 
1013
static void dt_init_vpd_node(void)
 
1014
{
 
1015
        struct dt_node *dt_vpd;
 
1016
 
 
1017
        dt_vpd = dt_new(dt_root, "vpd");
 
1018
        assert(dt_vpd);
 
1019
        dt_add_property_string(dt_vpd, "compatible", "ibm,opal-v3-vpd");
 
1020
}
 
1021
 
 
1022
static void hostservices_parse(void)
 
1023
{
 
1024
        struct HDIF_common_hdr *hs_hdr;
 
1025
        const void *dt_blob;
 
1026
        unsigned int size;
 
1027
        unsigned int ntuples_size;
 
1028
 
 
1029
        ntuples_size = sizeof(struct HDIF_array_hdr) + 
 
1030
                be32_to_cpu(spira.ntuples.array_hdr.ecnt) *
 
1031
                sizeof(struct spira_ntuple);
 
1032
 
 
1033
        if (offsetof(struct spira_ntuples, hs_data) >= ntuples_size) {
 
1034
                prerror("SPIRA: No host services data found\n");
 
1035
                return;
 
1036
        }
 
1037
 
 
1038
        hs_hdr = get_hdif(&spira.ntuples.hs_data, HSERV_HDIF_SIG);
 
1039
        if (!hs_hdr) {
 
1040
                prerror("SPIRA: No host services data found\n");
 
1041
                return;
 
1042
        }
 
1043
 
 
1044
        dt_blob = HDIF_get_idata(hs_hdr, 0, &size);
 
1045
        if (!dt_blob) {
 
1046
                prerror("SPIRA: No host services idata found\n");
 
1047
                return;
 
1048
        }
 
1049
        hservices_from_hdat(dt_blob, size);
 
1050
}
 
1051
 
 
1052
/*
 
1053
 * Legacy SPIRA is being deprecated and we have new SPIRA-H/S structures.
 
1054
 * But on older system (p7?) we will continue to get legacy SPIRA.
 
1055
 *
 
1056
 * SPIRA-S is initialized and provided by FSP. We use SPIRA-S signature
 
1057
 * to identify supported format. Also if required adjust spira pointer.
 
1058
 */
 
1059
static void fixup_spira(void)
 
1060
{
 
1061
#if !defined(TEST)
 
1062
        spiras = (struct spiras *)CPU_TO_BE64(SPIRA_HEAP_BASE);
 
1063
#endif
 
1064
 
 
1065
        /* Validate SPIRA-S signature */
 
1066
        if (!spiras)
 
1067
                return;
 
1068
        if (!HDIF_check(&spiras->hdr, SPIRAS_HDIF_SIG))
 
1069
                return;
 
1070
 
 
1071
        prlog(PR_NOTICE, "SPIRA-S found.\n");
 
1072
 
 
1073
        spira.ntuples.sp_subsys = spiras->ntuples.sp_subsys;
 
1074
        spira.ntuples.ipl_parms = spiras->ntuples.ipl_parms;
 
1075
        spira.ntuples.nt_enclosure_vpd = spiras->ntuples.nt_enclosure_vpd;
 
1076
        spira.ntuples.slca = spiras->ntuples.slca;
 
1077
        spira.ntuples.backplane_vpd = spiras->ntuples.backplane_vpd;
 
1078
        spira.ntuples.system_vpd = spiras->ntuples.system_vpd;
 
1079
        spira.ntuples.proc_init = spirah.ntuples.proc_init;
 
1080
        spira.ntuples.clock_vpd = spiras->ntuples.clock_vpd;
 
1081
        spira.ntuples.anchor_vpd = spiras->ntuples.anchor_vpd;
 
1082
        spira.ntuples.op_panel_vpd = spiras->ntuples.op_panel_vpd;
 
1083
        spira.ntuples.misc_cec_fru_vpd = spiras->ntuples.misc_cec_fru_vpd;
 
1084
        spira.ntuples.ms_vpd = spiras->ntuples.ms_vpd;
 
1085
        spira.ntuples.cec_iohub_fru = spiras->ntuples.cec_iohub_fru;
 
1086
        spira.ntuples.cpu_ctrl = spirah.ntuples.cpu_ctrl;
 
1087
        spira.ntuples.mdump_src = spirah.ntuples.mdump_src;
 
1088
        spira.ntuples.mdump_dst = spirah.ntuples.mdump_dst;
 
1089
        spira.ntuples.mdump_res  = spirah.ntuples.mdump_res;
 
1090
        spira.ntuples.pcia = spiras->ntuples.pcia;
 
1091
        spira.ntuples.proc_chip = spiras->ntuples.proc_chip;
 
1092
        spira.ntuples.hs_data = spiras->ntuples.hs_data;
 
1093
}
 
1094
 
 
1095
int parse_hdat(bool is_opal, uint32_t master_cpu)
 
1096
{
 
1097
        cpu_type = PVR_TYPE(mfspr(SPR_PVR));
 
1098
 
 
1099
        prlog(PR_DEBUG, "Parsing HDAT...\n");
 
1100
 
 
1101
        fixup_spira();
 
1102
 
 
1103
        dt_root = dt_new_root("");
 
1104
 
 
1105
        /*
 
1106
         * Basic DT root stuff
 
1107
         */
 
1108
        dt_add_property_cells(dt_root, "#address-cells", 2);
 
1109
        dt_add_property_cells(dt_root, "#size-cells", 2);
 
1110
        dt_add_property_string(dt_root, "lid-type", is_opal ? "opal" : "phyp");
 
1111
 
 
1112
        /* Create /vpd node */
 
1113
        dt_init_vpd_node();
 
1114
 
 
1115
        /* Create /ibm,opal/led node */
 
1116
        dt_init_led_node();
 
1117
 
 
1118
        /* Parse SPPACA and/or PCIA */
 
1119
        if (!pcia_parse())
 
1120
                if (paca_parse() < 0)
 
1121
                        return -1;
 
1122
 
 
1123
        /* IPL params */
 
1124
        add_iplparams();
 
1125
 
 
1126
        /* Parse MS VPD */
 
1127
        memory_parse();
 
1128
 
 
1129
        /* Add XSCOM node (must be before chiptod & IO ) */
 
1130
        add_xscom();
 
1131
 
 
1132
        /* Add FSP */
 
1133
        fsp_parse();
 
1134
 
 
1135
        /* Add ChipTOD's */
 
1136
        if (!add_chiptod_old() && !add_chiptod_new(master_cpu))
 
1137
                prerror("CHIPTOD: No ChipTOD found !\n");
 
1138
 
 
1139
        /* Add NX */
 
1140
        add_nx();
 
1141
 
 
1142
        /* Add IO HUBs and/or PHBs */
 
1143
        io_parse();
 
1144
 
 
1145
        /* Parse VPD */
 
1146
        vpd_parse();
 
1147
 
 
1148
        /* Host services information. */
 
1149
        hostservices_parse();
 
1150
 
 
1151
        /* Parse System Attention Indicator inforamtion */
 
1152
        slca_dt_add_sai_node();
 
1153
 
 
1154
        prlog(PR_INFO, "Parsing HDAT...done\n");
 
1155
 
 
1156
        return 0;
 
1157
}