LCOV - code coverage report
Current view: top level - hdata - spira.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 358 761 47.0 %
Date: 2024-01-02 21:04:04 Functions: 28 36 77.8 %
Branches: 0 0 -

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

Generated by: LCOV version 1.14