<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/devtree/bld_devtree.C $                               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2013,2014                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <trace/interface.H>
#include <errl/errlentry.H>
#include <targeting/common/target.H>
#include <targeting/common/targetservice.H>
#include <targeting/common/utilFilter.H>
#include <targeting/attrrp.H>
#include <devtree/devtree_reasoncodes.H>
#include <devtree/devtreeif.H>
#include "devtree.H"
#include <sys/mmio.h> //THIRTYTWO_GB
#include <intr/interrupt.H>
#include <vpd/vpd_if.H>
#include <stdio.h>
#include <pnor/pnorif.H>
#include <sys/mm.h>
#include <util/align.H>
#include <vector>
#include <vfs/vfs.H>
#include <fsi/fsiif.H>

trace_desc_t *g_trac_devtree = NULL;
TRAC_INIT(&g_trac_devtree, "DEVTREE", 4096);

namespace DEVTREE
{
using   namespace   TARGETING;

#define CHIPID_EXTRACT_NODE(i_chipid) (i_chipid >> CHIPID_NODE_SHIFT)
#define CHIPID_EXTRACT_PROC(i_chipid) (i_chipid & CHIPID_PROC_MASK)

enum BuildConstants
{
    DEVTREE_DATA_ADDR   =0xFF00000,    /* 256MB - 1MB*/
    DEVTREE_SPACE_SIZE  =0x10000,      /*64KB*/
    XSCOM_NODE_SHIFT    =38,           /*Node pos is 25, so 63-25=38*/
    XSCOM_CHIP_SHIFT    =35,           /*Chip pos is 28, so 63-28=35*/
    CHIPID_NODE_SHIFT   =3,            /*CHIPID is NNNCCC, shift 3*/
    CHIPID_PROC_MASK    =0x7,            /*CHIPID is NNNCCC, shift 3*/
    PHB0_MASK           =0x80,
    MAX_PHBs            =3,             /*Max PHBs per chip is 3*/
    THREADPERCORE       =8,             /*8 threads per core*/
    MHZ                 =1000000,

    /* The Cache unit address (and reg property) is mostly free-for-all
     * as long as there is no collisions. On HDAT machines we use the
     * following encoding which I encourage you to also follow to limit
     * surprises:
     *
     * L2   :  (0x20 << 24) | PIR (PIR is PIR value of thread 0 of core)
     * L3   :  (0x30 << 24) | PIR
     * L3.5 :  (0x35 << 24) | PIR */
    L2_HDR              = (0x20 << 24),
    L3_HDR              = (0x30 << 24),
    CEN_ID_SHIFT        = 4,
    CEN_ID_TAG          = 0x80000000,
};



uint32_t getProcChipId(const TARGETING::Target * i_pProc)
{
    uint32_t l_fabId = i_pProc->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
    uint32_t l_procPos = i_pProc->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
    return ( (l_fabId << CHIPID_NODE_SHIFT) + l_procPos);
}

uint64_t getHomerPhysAddr(const TARGETING::Target * i_pProc)
{
    //If running Sapphire need to place this at the top of memory
    uint64_t homerPhysAddrBase = VMM_HOMER_REGION_START_ADDR;
    if(TARGETING::is_sapphire_load())
    {
        homerPhysAddrBase = TARGETING::get_top_mem_addr();
        assert (homerPhysAddrBase != 0,
                "bld_devtree: Top of memory was 0!");
        homerPhysAddrBase -= VMM_ALL_HOMER_OCC_MEMORY_SIZE;
    }

    uint8_t tmpPos = i_pProc->getAttr<ATTR_POSITION>();
    uint64_t tmpOffset = tmpPos*VMM_HOMER_INSTANCE_SIZE;
    uint64_t targHomer = homerPhysAddrBase + tmpOffset;

    TRACFCOMP( g_trac_devtree, "proc ChipID [%X] HOMER is at %.16X",
               getProcChipId(i_pProc), targHomer );

    return targHomer;
}


void bld_xscom_node(devTree * i_dt, dtOffset_t & i_parentNode,
                    const TARGETING::Target * i_pProc, uint32_t i_chipid)
{
    const char* xscomNodeName = "xscom";
    const char* todNodeName = "chiptod";
    const char* pciNodeName = "pbcq";

    // Grab a system object to work with
    TARGETING::Target* sys = NULL;
    TARGETING::targetService().getTopLevelTarget(sys);

    uint64_t l_xscomBaseAddr =
      sys->getAttr<TARGETING::ATTR_XSCOM_BASE_ADDRESS>();

    /**********************************************************/
    /*                   Xscom node                           */
    /**********************************************************/
    uint64_t l_xscomAddr = l_xscomBaseAddr +
      (static_cast<uint64_t>(i_chipid) << XSCOM_CHIP_SHIFT);

    dtOffset_t xscomNode = i_dt->addNode(i_parentNode, xscomNodeName,
                                         l_xscomAddr);

    i_dt->addPropertyCell32(xscomNode, "#address-cells", 1);
    i_dt->addPropertyCell32(xscomNode, "#size-cells", 1);
    i_dt->addProperty(xscomNode, "scom-controller");
    const char* xscom_compatStrs[] = {"ibm,xscom","ibm,power8-xscom",NULL};
    i_dt->addPropertyStrings(xscomNode, "compatible", xscom_compatStrs);

    i_dt->addPropertyCell32(xscomNode, "ibm,chip-id", i_chipid);

    uint64_t xscom_prop[2] = { l_xscomAddr,  THIRTYTWO_GB};
    i_dt->addPropertyCells64(xscomNode, "reg", xscom_prop, 2);

    /*PSI Host Bridge*/
    uint32_t l_psiInfo = 0x2010900; /*PSI Host Bridge Scom addr*/
    dtOffset_t psiNode = i_dt->addNode(xscomNode, "psihb", l_psiInfo);
    const char* psi_compatStrs[] = {"ibm,power8-psihb-x",
    "ibm,psihb-x", NULL};
    i_dt->addPropertyStrings(psiNode, "compatible", psi_compatStrs);
    uint32_t psi_prop[2] = { l_psiInfo, 0x20 }; //# of scoms in range
    i_dt->addPropertyCells32(psiNode, "reg", psi_prop, 2);
    i_dt->addPropertyString(psiNode, "status", "ok");

    /*ChipTod*/
    uint32_t l_todInfo = 0x40000; /*Chip tod Scom addr*/
    dtOffset_t todNode = i_dt->addNode(xscomNode, todNodeName, l_todInfo);
    const char* tod_compatStrs[] = {"ibm,power-chiptod",
    "ibm,power8-chiptod", NULL};
    i_dt->addPropertyStrings(todNode, "compatible", tod_compatStrs);
    uint32_t tod_prop[2] = { l_todInfo, 0x34 }; //# of scoms in range
    i_dt->addPropertyCells32(todNode, "reg", tod_prop, 2);

    //Mark TOD pri/sec
    uint8_t l_role = i_pProc->getAttr<ATTR_TOD_ROLE>();
    if(l_role & TARGETING::TOD_ROLE_PRIMARY)
    {
        i_dt->addProperty(todNode, "primary");
    }
    if(l_role & TARGETING::TOD_ROLE_SECONDARY)
    {
        i_dt->addProperty(todNode, "secondary");
    }

    if(i_chipid == 0x0) //Master chip
    {
        uint32_t l_lpcInfo = 0xB0020; /*ECCB FW addr*/
        dtOffset_t lpcNode = i_dt->addNode(xscomNode,"lpc",l_lpcInfo);
        i_dt->addPropertyString(lpcNode, "compatible", "ibm,power8-lpc");
        uint32_t lpc_prop[2] = { l_lpcInfo, 0x4 }; //# of scoms in range
        i_dt->addPropertyCells32(lpcNode, "reg", lpc_prop, 2);
        i_dt->addPropertyCell32(lpcNode, "#address-cells", 2);
        i_dt->addPropertyCell32(lpcNode, "#size-cells", 1);

    }

    /*NX*/
    uint32_t l_nxInfo = 0x2010000; /*NX Scom addr*/
    dtOffset_t nxNode = i_dt->addNode(xscomNode, "nx", l_nxInfo);
    const char* nx_compatStrs[] = {"ibm,power-nx",
    "ibm,power8-nx", NULL};
    i_dt->addPropertyStrings(nxNode, "compatible", nx_compatStrs);
    uint32_t nx_prop[2] = { l_nxInfo, 0x4000 }; //# of scoms in range
    i_dt->addPropertyCells32(nxNode, "reg", nx_prop, 2);


    /*PCIE*/
    uint8_t l_phbActive =
      i_pProc->getAttr<TARGETING::ATTR_PROC_PCIE_PHB_ACTIVE>();<commit_msg>Change 'lpc' to 'isa' in devtree.<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/devtree/bld_devtree.C $                               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2013,2014                        */
/* [+] Google Inc.                                                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <trace/interface.H>
#include <errl/errlentry.H>
#include <targeting/common/target.H>
#include <targeting/common/targetservice.H>
#include <targeting/common/utilFilter.H>
#include <targeting/attrrp.H>
#include <devtree/devtree_reasoncodes.H>
#include <devtree/devtreeif.H>
#include "devtree.H"
#include <sys/mmio.h> //THIRTYTWO_GB
#include <intr/interrupt.H>
#include <vpd/vpd_if.H>
#include <stdio.h>
#include <pnor/pnorif.H>
#include <sys/mm.h>
#include <util/align.H>
#include <vector>
#include <vfs/vfs.H>
#include <fsi/fsiif.H>

trace_desc_t *g_trac_devtree = NULL;
TRAC_INIT(&g_trac_devtree, "DEVTREE", 4096);

namespace DEVTREE
{
using   namespace   TARGETING;

#define CHIPID_EXTRACT_NODE(i_chipid) (i_chipid >> CHIPID_NODE_SHIFT)
#define CHIPID_EXTRACT_PROC(i_chipid) (i_chipid & CHIPID_PROC_MASK)

enum BuildConstants
{
    DEVTREE_DATA_ADDR   =0xFF00000,    /* 256MB - 1MB*/
    DEVTREE_SPACE_SIZE  =0x10000,      /*64KB*/
    XSCOM_NODE_SHIFT    =38,           /*Node pos is 25, so 63-25=38*/
    XSCOM_CHIP_SHIFT    =35,           /*Chip pos is 28, so 63-28=35*/
    CHIPID_NODE_SHIFT   =3,            /*CHIPID is NNNCCC, shift 3*/
    CHIPID_PROC_MASK    =0x7,            /*CHIPID is NNNCCC, shift 3*/
    PHB0_MASK           =0x80,
    MAX_PHBs            =3,             /*Max PHBs per chip is 3*/
    THREADPERCORE       =8,             /*8 threads per core*/
    MHZ                 =1000000,

    /* The Cache unit address (and reg property) is mostly free-for-all
     * as long as there is no collisions. On HDAT machines we use the
     * following encoding which I encourage you to also follow to limit
     * surprises:
     *
     * L2   :  (0x20 << 24) | PIR (PIR is PIR value of thread 0 of core)
     * L3   :  (0x30 << 24) | PIR
     * L3.5 :  (0x35 << 24) | PIR */
    L2_HDR              = (0x20 << 24),
    L3_HDR              = (0x30 << 24),
    CEN_ID_SHIFT        = 4,
    CEN_ID_TAG          = 0x80000000,
};



uint32_t getProcChipId(const TARGETING::Target * i_pProc)
{
    uint32_t l_fabId = i_pProc->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>();
    uint32_t l_procPos = i_pProc->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>();
    return ( (l_fabId << CHIPID_NODE_SHIFT) + l_procPos);
}

uint64_t getHomerPhysAddr(const TARGETING::Target * i_pProc)
{
    //If running Sapphire need to place this at the top of memory
    uint64_t homerPhysAddrBase = VMM_HOMER_REGION_START_ADDR;
    if(TARGETING::is_sapphire_load())
    {
        homerPhysAddrBase = TARGETING::get_top_mem_addr();
        assert (homerPhysAddrBase != 0,
                "bld_devtree: Top of memory was 0!");
        homerPhysAddrBase -= VMM_ALL_HOMER_OCC_MEMORY_SIZE;
    }

    uint8_t tmpPos = i_pProc->getAttr<ATTR_POSITION>();
    uint64_t tmpOffset = tmpPos*VMM_HOMER_INSTANCE_SIZE;
    uint64_t targHomer = homerPhysAddrBase + tmpOffset;

    TRACFCOMP( g_trac_devtree, "proc ChipID [%X] HOMER is at %.16X",
               getProcChipId(i_pProc), targHomer );

    return targHomer;
}


void bld_xscom_node(devTree * i_dt, dtOffset_t & i_parentNode,
                    const TARGETING::Target * i_pProc, uint32_t i_chipid)
{
    const char* xscomNodeName = "xscom";
    const char* todNodeName = "chiptod";
    const char* pciNodeName = "pbcq";

    // Grab a system object to work with
    TARGETING::Target* sys = NULL;
    TARGETING::targetService().getTopLevelTarget(sys);

    uint64_t l_xscomBaseAddr =
      sys->getAttr<TARGETING::ATTR_XSCOM_BASE_ADDRESS>();

    /**********************************************************/
    /*                   Xscom node                           */
    /**********************************************************/
    uint64_t l_xscomAddr = l_xscomBaseAddr +
      (static_cast<uint64_t>(i_chipid) << XSCOM_CHIP_SHIFT);

    dtOffset_t xscomNode = i_dt->addNode(i_parentNode, xscomNodeName,
                                         l_xscomAddr);

    i_dt->addPropertyCell32(xscomNode, "#address-cells", 1);
    i_dt->addPropertyCell32(xscomNode, "#size-cells", 1);
    i_dt->addProperty(xscomNode, "scom-controller");
    const char* xscom_compatStrs[] = {"ibm,xscom","ibm,power8-xscom",NULL};
    i_dt->addPropertyStrings(xscomNode, "compatible", xscom_compatStrs);

    i_dt->addPropertyCell32(xscomNode, "ibm,chip-id", i_chipid);

    uint64_t xscom_prop[2] = { l_xscomAddr,  THIRTYTWO_GB};
    i_dt->addPropertyCells64(xscomNode, "reg", xscom_prop, 2);

    /*PSI Host Bridge*/
    uint32_t l_psiInfo = 0x2010900; /*PSI Host Bridge Scom addr*/
    dtOffset_t psiNode = i_dt->addNode(xscomNode, "psihb", l_psiInfo);
    const char* psi_compatStrs[] = {"ibm,power8-psihb-x",
    "ibm,psihb-x", NULL};
    i_dt->addPropertyStrings(psiNode, "compatible", psi_compatStrs);
    uint32_t psi_prop[2] = { l_psiInfo, 0x20 }; //# of scoms in range
    i_dt->addPropertyCells32(psiNode, "reg", psi_prop, 2);
    i_dt->addPropertyString(psiNode, "status", "ok");

    /*ChipTod*/
    uint32_t l_todInfo = 0x40000; /*Chip tod Scom addr*/
    dtOffset_t todNode = i_dt->addNode(xscomNode, todNodeName, l_todInfo);
    const char* tod_compatStrs[] = {"ibm,power-chiptod",
    "ibm,power8-chiptod", NULL};
    i_dt->addPropertyStrings(todNode, "compatible", tod_compatStrs);
    uint32_t tod_prop[2] = { l_todInfo, 0x34 }; //# of scoms in range
    i_dt->addPropertyCells32(todNode, "reg", tod_prop, 2);

    //Mark TOD pri/sec
    uint8_t l_role = i_pProc->getAttr<ATTR_TOD_ROLE>();
    if(l_role & TARGETING::TOD_ROLE_PRIMARY)
    {
        i_dt->addProperty(todNode, "primary");
    }
    if(l_role & TARGETING::TOD_ROLE_SECONDARY)
    {
        i_dt->addProperty(todNode, "secondary");
    }

    if(i_chipid == 0x0) //Master chip
    {
        uint32_t l_lpcInfo = 0xB0020; /*ECCB FW addr*/
        dtOffset_t lpcNode = i_dt->addNode(xscomNode,"isa",l_lpcInfo);
        i_dt->addPropertyString(lpcNode, "compatible", "ibm,power8-lpc");
        uint32_t lpc_prop[2] = { l_lpcInfo, 0x4 }; //# of scoms in range
        i_dt->addPropertyCells32(lpcNode, "reg", lpc_prop, 2);
        i_dt->addPropertyCell32(lpcNode, "#address-cells", 2);
        i_dt->addPropertyCell32(lpcNode, "#size-cells", 1);

    }

    /*NX*/
    uint32_t l_nxInfo = 0x2010000; /*NX Scom addr*/
    dtOffset_t nxNode = i_dt->addNode(xscomNode, "nx", l_nxInfo);
    const char* nx_compatStrs[] = {"ibm,power-nx",
    "ibm,power8-nx", NULL};
    i_dt->addPropertyStrings(nxNode, "compatible", nx_compatStrs);
    uint32_t nx_prop[2] = { l_nxInfo, 0x4000 }; //# of scoms in range
    i_dt->addPropertyCells32(nxNode, "reg", nx_prop, 2);


    /*PCIE*/
    uint8_t l_phbActive =
      i_pProc->getAttr<TARGETING::ATTR_PROC_PCIE_PHB_ACTIVE>();
{'fraction_non_alphanumeric': 0.1287750945592086, 'fraction_numerical': 0.028396857724759965, 'mean_word_length': 2.081032628182144, 'pattern_counts': {'":': 0, '<': 81, '<?xml version=': 0, '>': 117, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 68, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5874702', 'n_tokens_mistral': 6074, 'n_tokens_neox': 5649, 'n_words': 1176}