LCOV - code coverage report
Current view: top level - hdata - fsp.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 86 247 34.8 %
Date: 2024-01-02 21:04:04 Functions: 6 11 54.5 %
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-2017 IBM Corp. */
       3                 :            : 
       4                 :            : #include <device.h>
       5                 :            : #include "spira.h"
       6                 :            : #include <cpu.h>
       7                 :            : #include <vpd.h>
       8                 :            : #include <ccan/str/str.h>
       9                 :            : #include <interrupts.h>
      10                 :            : #include <inttypes.h>
      11                 :            : #include <phys-map.h>
      12                 :            : #include <chip.h>
      13                 :            : #include <ipmi.h>
      14                 :            : 
      15                 :            : #include "hdata.h"
      16                 :            : 
      17                 :            : enum sp_type {
      18                 :            :         SP_BAD = 0,
      19                 :            :         SP_UNKNOWN,
      20                 :            :         SP_FSP,
      21                 :            :         SP_BMC,
      22                 :            : };
      23                 :            : 
      24                 :            : static const char * const sp_names[] = {
      25                 :            :         "Broken", "Unknown", "FSP", "BMC",
      26                 :            : };
      27                 :            : 
      28                 :          2 : static enum sp_type find_service_proc_type(const struct HDIF_common_hdr *spss,
      29                 :            :                 int index)
      30                 :            : {
      31                 :            :         const struct spss_sp_impl *sp_impl;
      32                 :            :         int hw_ver, sw_ver, flags;
      33                 :            :         enum sp_type sp_type;
      34                 :            :         bool functional, installed;
      35                 :            : 
      36                 :            :         /* Find an check the SP Implementation structure */
      37                 :          2 :         sp_impl = HDIF_get_idata(spss, SPSS_IDATA_SP_IMPL, NULL);
      38                 :          2 :         if (!CHECK_SPPTR(sp_impl)) {
      39                 :          0 :                 prerror("SP #%d: SPSS/SP_Implementation not found !\n", index);
      40                 :          0 :                 return SP_BAD;
      41                 :            :         }
      42                 :            : 
      43                 :          2 :         hw_ver = be16_to_cpu(sp_impl->hw_version);
      44                 :          2 :         sw_ver = be16_to_cpu(sp_impl->sw_version);
      45                 :          2 :         flags  = be16_to_cpu(sp_impl->func_flags);
      46                 :            : 
      47                 :          2 :         switch (hw_ver) {
      48                 :          2 :         case 0x1:
      49                 :            :         case 0x2: /* We only support FSP2 */
      50                 :          2 :                 sp_type = SP_FSP;
      51                 :          2 :                 break;
      52                 :          0 :         case 0x3:
      53                 :          0 :                 sp_type = SP_BMC;
      54                 :          0 :                 break;
      55                 :          0 :         default:
      56                 :          0 :                 sp_type = SP_UNKNOWN;
      57                 :            :         }
      58                 :            : 
      59                 :          2 :         if (sp_type == SP_UNKNOWN)
      60                 :          0 :                 return SP_UNKNOWN;
      61                 :            : 
      62                 :          2 :         installed  = !!(flags & SPSS_SP_IMPL_FLAGS_INSTALLED);
      63                 :          2 :         functional = !!(flags & SPSS_SP_IMPL_FLAGS_FUNCTIONAL);
      64                 :            : 
      65                 :          2 :         if (!installed || !functional) {
      66                 :          0 :                 prerror("%s #%d not usable: %sinstalled, %sfunctional\n",
      67                 :            :                         sp_names[sp_type], index,
      68                 :            :                         installed  ? "" : "not ",
      69                 :            :                         functional ? "" : "not ");
      70                 :            : 
      71                 :          0 :                 return SP_BAD;
      72                 :            :         }
      73                 :            : 
      74                 :          2 :         prlog(PR_INFO, "%s #%d: HW version %d, SW version %d, chip DD%d.%d\n",
      75                 :            :               sp_names[sp_type], index, hw_ver, sw_ver,
      76                 :            :               sp_impl->chip_version >> 4,
      77                 :            :               sp_impl->chip_version & 0xf);
      78                 :            : 
      79                 :          2 :         return sp_type;
      80                 :            : }
      81                 :            : 
      82                 :            : /*
      83                 :            :  * Note on DT representation of the PSI links and FSPs:
      84                 :            :  *
      85                 :            :  * We create a XSCOM node for each PSI host bridge(one per chip),
      86                 :            :  *
      87                 :            :  * This is done in spira.c
      88                 :            :  *
      89                 :            :  * We do not create the /psi MMIO variant at this stage, it will
      90                 :            :  * be added by the psi driver in skiboot.
      91                 :            :  *
      92                 :            :  * We do not put the FSP(s) as children of these. Instead, we create
      93                 :            :  * a top-level /fsps node with the FSPs as children.
      94                 :            :  *
      95                 :            :  * Each FSP then has a "links" property which is an array of chip IDs
      96                 :            :  */
      97                 :            : 
      98                 :          1 : static struct dt_node *fsp_create_node(const void *spss, int i,
      99                 :            :                                        struct dt_node *parent)
     100                 :            : {
     101                 :            :         const struct spss_sp_impl *sp_impl;
     102                 :            :         struct dt_node *node;
     103                 :            : 
     104                 :          1 :         sp_impl = HDIF_get_idata(spss, SPSS_IDATA_SP_IMPL, NULL);
     105                 :            : 
     106                 :          1 :         node = dt_new_addr(parent, "fsp", i);
     107                 :          1 :         assert(node);
     108                 :            : 
     109                 :          1 :         dt_add_property_cells(node, "reg", i);
     110                 :            : 
     111                 :          1 :         if (be16_to_cpu(sp_impl->hw_version) == 1) {
     112                 :          0 :                 dt_add_property_strings(node, "compatible", "ibm,fsp",
     113                 :            :                                 "ibm,fsp1");
     114                 :            :                 /* Offset into the FSP MMIO space where the mailbox
     115                 :            :                  * registers are */
     116                 :            :                 /* seen in the FSP1 spec */
     117                 :          0 :                 dt_add_property_cells(node, "reg-offset", 0xb0016000);
     118                 :          1 :         } else if (be16_to_cpu(sp_impl->hw_version) == 2) {
     119                 :          1 :                 dt_add_property_strings(node, "compatible", "ibm,fsp",
     120                 :            :                                 "ibm,fsp2");
     121                 :          1 :                 dt_add_property_cells(node, "reg-offset", 0xb0011000);
     122                 :            :         }
     123                 :          1 :         dt_add_property_cells(node, "hw-version", be16_to_cpu(sp_impl->hw_version));
     124                 :          1 :         dt_add_property_cells(node, "sw-version", be16_to_cpu(sp_impl->sw_version));
     125                 :            : 
     126                 :          1 :         if (be16_to_cpu(sp_impl->func_flags) & SPSS_SP_IMPL_FLAGS_PRIMARY)
     127                 :          1 :                 dt_add_property(node, "primary", NULL, 0);
     128                 :            : 
     129                 :          1 :         return node;
     130                 :            : }
     131                 :            : 
     132                 :          1 : static uint32_t fsp_create_link(const struct spss_iopath *iopath, int index,
     133                 :            :                                 int fsp_index)
     134                 :            : {
     135                 :            :         struct dt_node *node;
     136                 :            :         const char *ststr;
     137                 :          1 :         bool current = false;
     138                 :          1 :         bool working = false;
     139                 :            :         uint32_t chip_id;
     140                 :            : 
     141                 :          1 :         switch(be16_to_cpu(iopath->psi.link_status)) {
     142                 :          0 :         case SPSS_IO_PATH_PSI_LINK_BAD_FRU:
     143                 :          0 :                 ststr = "Broken";
     144                 :          0 :                 break;
     145                 :          1 :         case SPSS_IO_PATH_PSI_LINK_CURRENT:
     146                 :          1 :                 ststr = "Active";
     147                 :          1 :                 current = working = true;
     148                 :          1 :                 break;
     149                 :          0 :         case SPSS_IO_PATH_PSI_LINK_BACKUP:
     150                 :          0 :                 ststr = "Backup";
     151                 :          0 :                 working = true;
     152                 :          0 :                 break;
     153                 :          0 :         default:
     154                 :          0 :                 ststr = "Unknown";
     155                 :            :         }
     156                 :          1 :         prlog(PR_DEBUG, "FSP #%d: IO PATH %d is %s PSI Link, GXHB at %" PRIx64 "\n",
     157                 :            :               fsp_index, index, ststr, be64_to_cpu(iopath->psi.gxhb_base));
     158                 :            : 
     159                 :          1 :         chip_id = pcid_to_chip_id(be32_to_cpu(iopath->psi.proc_chip_id));
     160                 :          1 :         node = dt_find_compatible_node_on_chip(dt_root, NULL, "ibm,psihb-x",
     161                 :            :                                                chip_id);
     162                 :          1 :         if (!node) {
     163                 :          0 :                 prerror("FSP #%d: Can't find psihb node for link %d\n",
     164                 :            :                         fsp_index, index);
     165                 :            :         } else {
     166                 :          1 :                 if (current)
     167                 :          1 :                         dt_add_property(node, "boot-link", NULL, 0);
     168                 :          1 :                 dt_add_property_strings(node, "status", working ? "ok" : "bad");
     169                 :            :         }
     170                 :            : 
     171                 :          1 :         return chip_id;
     172                 :            : }
     173                 :            : 
     174                 :          1 : static void fsp_create_links(const void *spss, int index,
     175                 :            :                              struct dt_node *fsp_node)
     176                 :            : {
     177                 :          1 :         __be32 *links = NULL;
     178                 :          1 :         unsigned int i, lp, lcount = 0;
     179                 :            :         int count;
     180                 :            : 
     181                 :          1 :         count = HDIF_get_iarray_size(spss, SPSS_IDATA_SP_IOPATH);
     182                 :          1 :         if (count < 0) {
     183                 :          0 :                 prerror("FSP #%d: Can't find IO PATH array size !\n", index);
     184                 :          0 :                 return;
     185                 :            :         }
     186                 :          1 :         prlog(PR_DEBUG, "FSP #%d: Found %d IO PATH\n", index, count);
     187                 :            : 
     188                 :            :         /* Iterate all links */
     189                 :          2 :         for (i = 0; i < count; i++) {
     190                 :            :                 const struct spss_iopath *iopath;
     191                 :            :                 unsigned int iopath_sz;
     192                 :            :                 uint32_t chip;
     193                 :            : 
     194                 :          1 :                 iopath = HDIF_get_iarray_item(spss, SPSS_IDATA_SP_IOPATH,
     195                 :            :                                               i, &iopath_sz);
     196                 :          1 :                 if (!CHECK_SPPTR(iopath)) {
     197                 :          0 :                         prerror("FSP #%d: Can't find IO PATH %d\n", index, i);
     198                 :          0 :                         break;
     199                 :            :                 }
     200                 :          1 :                 if (be16_to_cpu(iopath->iopath_type) != SPSS_IOPATH_TYPE_PSI) {
     201                 :          0 :                         prerror("FSP #%d: Unsupported IO PATH %d type 0x%04x\n",
     202                 :            :                                 index, i, iopath->iopath_type);
     203                 :          0 :                         continue;
     204                 :            :                 }
     205                 :            : 
     206                 :          1 :                 chip = fsp_create_link(iopath, i, index);
     207                 :          1 :                 lp = lcount++;
     208                 :          1 :                 links = realloc(links, 4 * lcount);
     209                 :          1 :                 links[lp] = cpu_to_be32(chip);
     210                 :            :         }
     211                 :          1 :         if (links)
     212                 :          1 :                 dt_add_property(fsp_node, "ibm,psi-links", links, lcount * 4);
     213                 :            : 
     214                 :          1 :         free(links);
     215                 :            : }
     216                 :            : 
     217                 :          0 : static struct dt_node *add_lpc_io_node(struct dt_node *parent,
     218                 :            :         const char *name, u32 offset, u32 size)
     219                 :            : {
     220                 :            :         struct dt_node *n;
     221                 :            :         char buffer[32];
     222                 :            : 
     223                 :            :         /*
     224                 :            :          * LPC bus addresses have strange DT names, they have the
     225                 :            :          * Bus address space embedded into the unit address e.g.
     226                 :            :          * serial@i3f8 - refers to offset 0x3f8 in the IO space
     227                 :            :          */
     228                 :            : 
     229                 :          0 :         snprintf(buffer, sizeof(buffer), "%s@i%x", name, offset);
     230                 :          0 :         n = dt_new(parent, buffer);
     231                 :          0 :         assert(n);
     232                 :            : 
     233                 :            :         /* first address cell of 1 indicates the LPC IO space */
     234                 :          0 :         dt_add_property_cells(n, "reg", 1, offset, size);
     235                 :            : 
     236                 :          0 :         return n;
     237                 :            : }
     238                 :            : 
     239                 :          0 : static void add_uart(const struct spss_iopath *iopath, struct dt_node *lpc)
     240                 :            : {
     241                 :            :         struct dt_node *serial;
     242                 :            :         u64 base;
     243                 :            : 
     244                 :            :         /* XXX: The spec says this is supposed to be a MMIO address.
     245                 :            :          *      However, in practice we get an LPC IO Space offset.
     246                 :            :          */
     247                 :          0 :         base = be64_to_cpu(iopath->lpc.uart_base);
     248                 :            : 
     249                 :          0 :         serial = add_lpc_io_node(lpc, "serial", base,
     250                 :          0 :                 be32_to_cpu(iopath->lpc.uart_size));
     251                 :            : 
     252                 :          0 :         dt_add_property_string(serial, "compatible", "ns16550");
     253                 :            : 
     254                 :          0 :         dt_add_property_cells(serial, "current-speed",
     255                 :            :                 be32_to_cpu(iopath->lpc.uart_baud));
     256                 :          0 :         dt_add_property_cells(serial, "clock-frequency",
     257                 :            :                 be32_to_cpu(iopath->lpc.uart_clk));
     258                 :          0 :         dt_add_property_cells(serial, "interrupts",
     259                 :            :                               iopath->lpc.uart_int_number);
     260                 :          0 :         dt_add_property_string(serial, "device_type", "serial");
     261                 :            : 
     262                 :            : 
     263                 :          0 :         prlog(PR_DEBUG, "LPC UART: base addr = %#" PRIx64" (%#" PRIx64 ") size = %#x clk = %u, baud = %u\n",
     264                 :            :                 be64_to_cpu(iopath->lpc.uart_base),
     265                 :            :                 base,
     266                 :            :                 be32_to_cpu(iopath->lpc.uart_size),
     267                 :            :                 be32_to_cpu(iopath->lpc.uart_clk),
     268                 :            :                 be32_to_cpu(iopath->lpc.uart_baud));
     269                 :          0 : }
     270                 :            : 
     271                 :          0 : static void add_chip_id_to_sensors(struct dt_node *sensor_node, uint32_t slca_index)
     272                 :            : {
     273                 :            :         unsigned int i;
     274                 :            :         const void *hdif;
     275                 :            :         const struct slca_entry *slca;
     276                 :            :         const struct spira_fru_id *fru_id;
     277                 :            :         const struct sppcrd_chip_info *cinfo;
     278                 :            : 
     279                 :          0 :         slca = slca_get_entry(slca_index);
     280                 :          0 :         if (slca == NULL) {
     281                 :          0 :                 prlog(PR_WARNING, "SENSORS: Invalid slca index\n");
     282                 :          0 :                 return;
     283                 :            :         }
     284                 :            : 
     285                 :          0 :         for_each_ntuple_idx(&spiras->ntuples.proc_chip, hdif, i, SPPCRD_HDIF_SIG) {
     286                 :          0 :                 fru_id = HDIF_get_idata(hdif, SPPCRD_IDATA_FRU_ID, NULL);
     287                 :          0 :                 if (!fru_id)
     288                 :          0 :                         return;
     289                 :            : 
     290                 :          0 :                 if (fru_id->rsrc_id != slca->rsrc_id)
     291                 :          0 :                         continue;
     292                 :            : 
     293                 :          0 :                 cinfo = HDIF_get_idata(hdif, SPPCRD_IDATA_CHIP_INFO, NULL);
     294                 :          0 :                 if (!CHECK_SPPTR(cinfo)) {
     295                 :          0 :                         prlog(PR_ERR, "SENSORS: Bad ChipID data %d\n", i);
     296                 :          0 :                         return;
     297                 :            :                 }
     298                 :            : 
     299                 :          0 :                 dt_add_property_cells(sensor_node,
     300                 :            :                                       "ibm,chip-id", get_xscom_id(cinfo));
     301                 :          0 :                 return;
     302                 :            :         }
     303                 :            : }
     304                 :            : 
     305                 :          0 : static void add_ipmi_sensors(struct dt_node *bmc_node)
     306                 :            : {
     307                 :            :         int i;
     308                 :            :         const struct HDIF_common_hdr *hdif_sensor;
     309                 :            :         const struct ipmi_sensors *ipmi_sensors;
     310                 :            :         struct dt_node *sensors_node, *sensor_node;
     311                 :            : 
     312                 :          0 :         hdif_sensor = get_hdif(&spiras->ntuples.ipmi_sensor, IPMI_SENSORS_HDIF_SIG);
     313                 :          0 :         if (!hdif_sensor) {
     314                 :          0 :                 prlog(PR_DEBUG, "SENSORS: Missing IPMI sensors mappings tuple\n");
     315                 :          0 :                 return;
     316                 :            :         }
     317                 :            : 
     318                 :          0 :         ipmi_sensors = HDIF_get_idata(hdif_sensor, IPMI_SENSORS_IDATA_SENSORS, NULL);
     319                 :          0 :         if (!ipmi_sensors) {
     320                 :          0 :                 prlog(PR_DEBUG, "SENSORS: bad data\n");
     321                 :          0 :                 return;
     322                 :            :         }
     323                 :            : 
     324                 :          0 :         sensors_node = dt_new(bmc_node, "sensors");
     325                 :          0 :         assert(sensors_node);
     326                 :            : 
     327                 :          0 :         dt_add_property_cells(sensors_node, "#address-cells", 1);
     328                 :          0 :         dt_add_property_cells(sensors_node, "#size-cells", 0);
     329                 :            : 
     330                 :          0 :         for (i = 0; i < be32_to_cpu(ipmi_sensors->count); i++) {
     331                 :          0 :                 if(dt_find_by_name_addr(sensors_node, "sensor",
     332                 :          0 :                                         ipmi_sensors->data[i].id)) {
     333                 :          0 :                         prlog(PR_WARNING, "SENSORS: Duplicate sensor ID : %x\n",
     334                 :            :                               ipmi_sensors->data[i].id);
     335                 :          0 :                         continue;
     336                 :            :                 }
     337                 :            : 
     338                 :            :                 /* We support only < MAX_IPMI_SENSORS sensors */
     339                 :          0 :                 if (!(ipmi_sensors->data[i].type < MAX_IPMI_SENSORS))
     340                 :          0 :                         continue;
     341                 :            : 
     342                 :          0 :                 sensor_node = dt_new_addr(sensors_node, "sensor",
     343                 :          0 :                                           ipmi_sensors->data[i].id);
     344                 :          0 :                 assert(sensor_node);
     345                 :          0 :                 dt_add_property_string(sensor_node, "compatible", "ibm,ipmi-sensor");
     346                 :          0 :                 dt_add_property_cells(sensor_node, "reg", ipmi_sensors->data[i].id);
     347                 :          0 :                 dt_add_property_cells(sensor_node, "ipmi-sensor-type",
     348                 :            :                                       ipmi_sensors->data[i].type);
     349                 :            : 
     350                 :          0 :                 add_chip_id_to_sensors(sensor_node,
     351                 :          0 :                                 be32_to_cpu(ipmi_sensors->data[i].slca_index));
     352                 :            :         }
     353                 :            : }
     354                 :            : 
     355                 :          0 : static void bmc_create_node(const struct HDIF_common_hdr *sp)
     356                 :            : {
     357                 :            :         struct dt_node *bmc_node;
     358                 :            :         u32 fw_bar, io_bar, mem_bar, internal_bar, mctp_base;
     359                 :            :         const struct spss_iopath *iopath;
     360                 :            :         const struct spss_sp_impl *sp_impl;
     361                 :            :         struct dt_node *lpcm, *lpc, *n;
     362                 :            :         u64 lpcm_base, lpcm_end;
     363                 :            :         uint32_t chip_id;
     364                 :            :         uint32_t topology_idx;
     365                 :            :         int size;
     366                 :            : 
     367                 :          0 :         bmc_node = dt_new(dt_root, "bmc");
     368                 :          0 :         assert(bmc_node);
     369                 :            : 
     370                 :          0 :         dt_add_property_cells(bmc_node, "#address-cells", 1);
     371                 :          0 :         dt_add_property_cells(bmc_node, "#size-cells", 0);
     372                 :            : 
     373                 :            :         /* Add sensor info under /bmc */
     374                 :          0 :         if (proc_gen < proc_gen_p10)
     375                 :          0 :                 add_ipmi_sensors(bmc_node);
     376                 :            : 
     377                 :          0 :         sp_impl = HDIF_get_idata(sp, SPSS_IDATA_SP_IMPL, &size);
     378                 :          0 :         if (CHECK_SPPTR(sp_impl) && (size > 8)) {
     379                 :          0 :                 dt_add_property_strings(bmc_node, "compatible", sp_impl->sp_family);
     380                 :          0 :                 prlog(PR_INFO, "SP Family is %s\n", sp_impl->sp_family);
     381                 :            :         }
     382                 :            : 
     383                 :          0 :         iopath = HDIF_get_iarray_item(sp, SPSS_IDATA_SP_IOPATH, 0, NULL);
     384                 :            : 
     385                 :          0 :         if (be16_to_cpu(iopath->iopath_type) != SPSS_IOPATH_TYPE_LPC) {
     386                 :          0 :                 prerror("BMC: Non-LPC IOPATH, this is probably broken\n");
     387                 :          0 :                 return;
     388                 :            :         }
     389                 :            : 
     390                 :            :         /*
     391                 :            :          * For now we only instantiate the LPC node for the LPC that is used
     392                 :            :          * for Host <-> BMC comms. The secondary LPCs can be skipped.
     393                 :            :          */
     394                 :          0 :         if (be16_to_cpu(iopath->lpc.link_status) != LPC_STATUS_ACTIVE)
     395                 :          0 :                 return;
     396                 :            : 
     397                 :            : #define GB (1024ul * 1024ul * 1024ul)
     398                 :            :         /*
     399                 :            :          * convert the hdat chip ID the HW chip id so we get the right
     400                 :            :          * phys map offset
     401                 :            :          */
     402                 :          0 :         chip_id = pcid_to_chip_id(be32_to_cpu(iopath->lpc.chip_id));
     403                 :          0 :         topology_idx = pcid_to_topology_idx(be32_to_cpu(iopath->lpc.chip_id));
     404                 :            : 
     405                 :          0 :         __phys_map_get(topology_idx, chip_id, LPC_BUS, 0, &lpcm_base, NULL);
     406                 :          0 :         lpcm = dt_new_addr(dt_root, "lpcm-opb", lpcm_base);
     407                 :          0 :         assert(lpcm);
     408                 :            : 
     409                 :          0 :         dt_add_property_cells(lpcm, "#address-cells", 1);
     410                 :          0 :         dt_add_property_cells(lpcm, "#size-cells", 1);
     411                 :          0 :         dt_add_property_strings(lpcm, "compatible",
     412                 :            :                 "ibm,power9-lpcm-opb", "simple-bus");
     413                 :          0 :         dt_add_property_u64s(lpcm, "reg", lpcm_base, 0x100000000ul);
     414                 :            : 
     415                 :          0 :         dt_add_property_cells(lpcm, "ibm,chip-id", chip_id);
     416                 :            : 
     417                 :            :         /* Setup the ranges for the MMIO LPC */
     418                 :          0 :         lpcm_end = lpcm_base + 2 * GB;
     419                 :          0 :         dt_add_property_cells(lpcm, "ranges",
     420                 :            :                 0x00000000, hi32(lpcm_base), lo32(lpcm_base), 2 * GB,
     421                 :            :                 0x80000000, hi32(lpcm_end),  lo32(lpcm_end),  2 * GB);
     422                 :            : 
     423                 :            :         /*
     424                 :            :          * Despite the name the "BAR" values provided through the HDAT are
     425                 :            :          * the base addresses themselves rather than the BARs
     426                 :            :          */
     427                 :          0 :         fw_bar = be32_to_cpu(iopath->lpc.firmware_bar);
     428                 :          0 :         mem_bar = be32_to_cpu(iopath->lpc.memory_bar);
     429                 :          0 :         io_bar = be32_to_cpu(iopath->lpc.io_bar);
     430                 :          0 :         internal_bar = be32_to_cpu(iopath->lpc.internal_bar);
     431                 :          0 :         mctp_base = be32_to_cpu(iopath->lpc.mctp_base);
     432                 :            : 
     433                 :          0 :         prlog(PR_DEBUG, "LPC: IOPATH chip id = %x\n", chip_id);
     434                 :          0 :         prlog(PR_DEBUG, "LPC: FW BAR       = %#x\n", fw_bar);
     435                 :          0 :         prlog(PR_DEBUG, "LPC: MEM BAR      = %#x\n", mem_bar);
     436                 :          0 :         prlog(PR_DEBUG, "LPC: IO BAR       = %#x\n", io_bar);
     437                 :          0 :         prlog(PR_DEBUG, "LPC: Internal BAR = %#x\n", internal_bar);
     438                 :          0 :         if (proc_gen >= proc_gen_p10) {
     439                 :            :                 /* MCTP is part of FW BAR */
     440                 :          0 :                 prlog(PR_DEBUG, "LPC: MCTP base    = %#x\n", mctp_base);
     441                 :            :         }
     442                 :            : 
     443                 :            :         /*
     444                 :            :          * The internal address space BAR actually points to the LPC master
     445                 :            :          * registers. So we "fix" it by masking off the low bits.
     446                 :            :          *
     447                 :            :          * XXX: we probably need separate base addresses for all these things
     448                 :            :          */
     449                 :          0 :         internal_bar &= 0xf0000000;
     450                 :            : 
     451                 :            :         /* Add the various internal bus devices */
     452                 :          0 :         n = dt_new_addr(lpcm, "opb-master", internal_bar + 0x10000);
     453                 :          0 :         dt_add_property_string(n, "compatible", "ibm,power9-lpcm-opb-master");
     454                 :          0 :         dt_add_property_cells(n, "reg", internal_bar + 0x10000, 0x60);
     455                 :            : 
     456                 :          0 :         n = dt_new_addr(lpcm, "opb-arbiter", internal_bar + 0x11000);
     457                 :          0 :         dt_add_property_string(n, "compatible", "ibm,power9-lpcm-opb-arbiter");
     458                 :          0 :         dt_add_property_cells(n, "reg", internal_bar + 0x11000, 0x8);
     459                 :            : 
     460                 :          0 :         n = dt_new_addr(lpcm, "lpc-controller", internal_bar + 0x12000);
     461                 :          0 :         dt_add_property_string(n, "compatible", "ibm,power9-lpc-controller");
     462                 :          0 :         dt_add_property_cells(n, "reg", internal_bar + 0x12000, 0x100);
     463                 :            : 
     464                 :            :         /*
     465                 :            :          * FIXME: lpc@0 might not be accurate, but i'm pretty sure
     466                 :            :          * lpc@f0000000 isn't right either.
     467                 :            :          */
     468                 :          0 :         lpc = dt_new_addr(lpcm, "lpc", 0x0);
     469                 :          0 :         dt_add_property_cells(lpc, "#address-cells", 2);
     470                 :          0 :         dt_add_property_cells(lpc, "#size-cells", 1);
     471                 :          0 :         dt_add_property_strings(lpc, "compatible",
     472                 :            :                                 "ibm,power9-lpc", "ibm,power8-lpc");
     473                 :            : 
     474                 :          0 :         dt_add_property_cells(lpc, "ranges",
     475                 :            :                 0, 0, mem_bar, 0x10000000, /* MEM space */
     476                 :            :                 1, 0, io_bar,  0x00010000, /* IO space  */
     477                 :            :                 /* we don't expose the internal space */
     478                 :            :                 3, 0, fw_bar,  0x10000000  /* FW space  */
     479                 :            :         );
     480                 :            : 
     481                 :          0 :         add_uart(iopath, lpc);
     482                 :            : 
     483                 :            :         /* BT device info isn't currently populated */
     484                 :          0 :         prlog(PR_DEBUG, "LPC: BT [%#"PRIx64", %#x] sms_int: %u, bmc_int: %u\n",
     485                 :            :                 iopath->lpc.bt_base, iopath->lpc.bt_size,
     486                 :            :                 iopath->lpc.bt_sms_int_num, iopath->lpc.bt_bmc_response_int_num
     487                 :            :         );
     488                 :            : }
     489                 :            : 
     490                 :            : /*
     491                 :            :  * Search for and instanciate BMC nodes. This is mostly the same as fsp_parse()
     492                 :            :  * below, but it can be called earlier since BMCs don't depend on the psihb
     493                 :            :  * nodes being added.
     494                 :            :  */
     495                 :          1 : void bmc_parse(void)
     496                 :            : {
     497                 :          1 :         bool found = false;
     498                 :            :         const void *sp;
     499                 :            :         int i;
     500                 :            : 
     501                 :          1 :         sp = get_hdif(&spiras->ntuples.sp_subsys, SPSS_HDIF_SIG);
     502                 :          1 :         if (!sp)
     503                 :          0 :                 return;
     504                 :            : 
     505                 :          2 :         for_each_ntuple_idx(&spiras->ntuples.sp_subsys, sp, i, SPSS_HDIF_SIG) {
     506                 :          1 :                 if (find_service_proc_type(sp, i) == SP_BMC) {
     507                 :          0 :                         bmc_create_node(sp);
     508                 :          0 :                         found = true;
     509                 :            :                 }
     510                 :            :         }
     511                 :            : 
     512                 :          1 :         if (found)
     513                 :          0 :                 early_uart_init();
     514                 :            : }
     515                 :            : 
     516                 :          1 : void fsp_parse(void)
     517                 :            : {
     518                 :          1 :         struct dt_node *fsp_root = NULL, *fsp_node;
     519                 :            :         const void *sp;
     520                 :            :         int index;
     521                 :            : 
     522                 :            :         /* Find SPSS tuple in SPIRA */
     523                 :          1 :         sp = get_hdif(&spiras->ntuples.sp_subsys, SPSS_HDIF_SIG);
     524                 :          1 :         if (!sp) {
     525                 :          0 :                 prlog(PR_WARNING, "HDAT: No FSP/BMC found!\n");
     526                 :          0 :                 return;
     527                 :            :         }
     528                 :            : 
     529                 :          2 :         for_each_ntuple_idx(&spiras->ntuples.sp_subsys, sp, index, SPSS_HDIF_SIG) {
     530                 :          1 :                 switch (find_service_proc_type(sp, index)) {
     531                 :          1 :                 case SP_FSP:
     532                 :          1 :                         if (!fsp_root) {
     533                 :          1 :                                 fsp_root = dt_new(dt_root, "fsps");
     534                 :          1 :                                 assert(fsp_root);
     535                 :            : 
     536                 :          1 :                                 dt_add_property_cells(fsp_root,
     537                 :            :                                         "#address-cells", 1);
     538                 :          1 :                                 dt_add_property_cells(fsp_root,
     539                 :            :                                         "#size-cells", 0);
     540                 :            :                         }
     541                 :            : 
     542                 :          1 :                         fsp_node = fsp_create_node(sp, index, fsp_root);
     543                 :          1 :                         if (fsp_node)
     544                 :          1 :                                 fsp_create_links(sp, index, fsp_node);
     545                 :            : 
     546                 :          1 :                         break;
     547                 :            : 
     548                 :          0 :                 case SP_BMC:
     549                 :            :                         /* Handled above */
     550                 :          0 :                         break;
     551                 :            : 
     552                 :          0 :                 case SP_BAD:
     553                 :          0 :                         break;
     554                 :            : 
     555                 :          0 :                 default:
     556                 :          0 :                         prerror("SP #%d: This service processor is not supported\n", index);
     557                 :          0 :                         break;
     558                 :            :                 }
     559                 :            :         }
     560                 :            : }

Generated by: LCOV version 1.14