Beispiel #1
0
fapi2::ReturnCode eff_memory_size( const fapi2::Target<fapi2::TARGET_TYPE_DMI>& i_target, uint64_t& o_size )
{
    o_size = 0;

    for (const auto& mba : mss::find_targets<fapi2::TARGET_TYPE_MBA>(i_target))
    {
        uint8_t l_sizes[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {};
        uint8_t l_func_dimms_bitmap = 0;

        FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR, mba,  l_func_dimms_bitmap),
                  "Failed to access attribute ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR for %s", mss::c_str(mba) );

        FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_SIZE, mba, l_sizes),
                  "Failed to access attribute ATTR_CEN_EFF_DIMM_SIZE for %s", mss::c_str(mba) );

        for( size_t p = 0; p < MAX_PORTS_PER_MBA; ++p)
        {
            for( size_t d = 0; d < MAX_DIMM_PER_PORT; ++d)
            {
                if( is_dimm_functional(l_func_dimms_bitmap, p, d) )
                {
                    o_size += l_sizes[p][d];
                }
            }// dimm
        }// port
    }// mba

fapi_try_exit:
    return fapi2::current_err;
}
Beispiel #2
0
static fapi2::ReturnCode setup_pcie_work_around_attributes(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const fapi2::buffer<uint64_t>& i_ecid_part)
{
    uint8_t l_version = 0;
    i_ecid_part.extractToRight<DD_LEVEL, DD_LEVEL_LEN>(l_version);

    {
        // Workarounds for DD1.00 modulues
        fapi2::ATTR_CHIP_EC_FEATURE_PCIE_LOCK_PHASE_ROTATOR_Type l_ec_feature_pcie_lock_phase_rotator = 0;
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_PCIE_LOCK_PHASE_ROTATOR, i_target,
                               l_ec_feature_pcie_lock_phase_rotator),
                 "Error from FAPI_ATTR_GET (ATTR_CHIP_EC_FEATURE_PCIE_LOCK_PHASE_ROTATOR)");

        uint8_t l_value = 0;

        if (l_ec_feature_pcie_lock_phase_rotator && (l_version < ddLevelPciePart))
        {
            FAPI_DBG("seeing version 1.00 (0x%x) setting ATTR_PROC_PCIE_PCS_RX_ROT_EXTEL", l_version);
            l_value = 1;
        }

        for (auto& l_pec_trgt : i_target.getChildren<fapi2::TARGET_TYPE_PEC>(fapi2::TARGET_STATE_FUNCTIONAL))
        {
            FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PROC_PCIE_PCS_RX_ROT_EXTEL, l_pec_trgt, l_value),
                     "Error from FAPI_ATTR_SET (ATTR_PROC_PCIE_PCS_RX_ROT_EXTEL)");
        }

    }
    {
        // Workarounds for DD1.01/DD1.02 modules
        fapi2::ATTR_CHIP_EC_FEATURE_PCIE_DISABLE_FDDC_Type l_ec_feature_pcie_disable_fddc = 0;
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_PCIE_DISABLE_FDDC, i_target, l_ec_feature_pcie_disable_fddc),
                 "Error from FAPI_ATTR_GET (ATTR_CHIP_EC_FEATURE_PCIE_DISABLE_FDDC)");

        uint8_t l_value = 1;

        if (l_ec_feature_pcie_disable_fddc && (l_version >= ddLevelPciePart))
        {
            FAPI_DBG("seeing version >= 1.01 (0x%x) clearing ATTR_PROC_PCIE_PCS_RX_DFE_FDDC", l_version);
            l_value = 0;
        }

        for (auto& l_pec_trgt : i_target.getChildren<fapi2::TARGET_TYPE_PEC>(fapi2::TARGET_STATE_FUNCTIONAL))
        {
            FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PROC_PCIE_PCS_RX_DFE_FDDC, l_pec_trgt, l_value),
                     "Error from FAPI_ATTR_SET (ATTR_PROC_PCIE_PCS_RX_DFE_FDDC)");
        }
    }

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}
    ///
    /// @brief Utility function to check parameters and find a DIMM target
    /// @param[in] i_mba mba target
    /// @param[in] i_port Port number
    /// @param[in] i_dimm Dimm number
    /// @param[in] i_rank Rank number
    /// @param[out] o_dimm Dimm target
    /// @return FAPI2_RC_SUCCESS iff okay
    ///
    fapi2::ReturnCode dimmBadDqCheckParamFindDimm(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba,
            const uint8_t i_port,
            const uint8_t i_dimm,
            const uint8_t i_rank,
            fapi2::Target<fapi2::TARGET_TYPE_DIMM>& o_dimm)
    {
        uint8_t l_port = 0;
        uint8_t l_dimm = 0;
        std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>> l_dimms;
        std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>>::const_iterator dimmIter;

        FAPI_ASSERT((i_port < MAX_PORTS_PER_MBA) &&
                    (i_dimm < MAX_DIMM_PER_PORT) &&
                    (i_rank < MAX_RANKS_PER_DIMM),
                    fapi2::CEN_BAD_DQ_DIMM_BAD_PARAM().
                    set_MBA(i_mba).
                    set_FFDC_PORT(i_port).
                    set_FFDC_DIMM(i_dimm).
                    set_FFDC_RANK(i_rank),
                    "dimmBadDqCheckParamFindDimm: %s Bad parameter. %d:%d:%d",
                    mss::c_str(i_mba), i_port, i_dimm, i_rank);

        // Get the functional DIMMs associated with the MBA chiplet
        l_dimms = i_mba.getChildren<fapi2::TARGET_TYPE_DIMM>();
        // Find the DIMM with the correct MBA port/dimm

        for (dimmIter = l_dimms.begin(); dimmIter != l_dimms.end(); ++dimmIter)
        {
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_PORT, *dimmIter, l_port));

            if (l_port == i_port)
            {
                FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MBA_DIMM, *dimmIter, l_dimm));

                if (l_dimm == i_dimm)
                {
                    o_dimm = *dimmIter;
                    break;
                }
            }
        }

        FAPI_ASSERT(dimmIter != l_dimms.end(),
                    fapi2::CEN_BAD_DQ_DIMM_NOT_FOUND().
                    set_MBA(i_mba).
                    set_FFDC_PORT(i_port).
                    set_FFDC_DIMM(i_dimm),
                    "dimmBadDqCheckParamFindDimm: "
                    "Did not find DIMM for %s:%d:%d",
                    mss::c_str(i_mba), i_port, i_dimm);

    fapi_try_exit:
        return fapi2::current_err;
    }
Beispiel #4
0
///
/// @brief p9_htm_reset procedure entry point
/// See doxygen in p9_htm_reset.H
///
    fapi2::ReturnCode p9_htm_reset(
        const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
    {
        FAPI_DBG("Entering");
        fapi2::ReturnCode l_rc;
        uint8_t l_corePos = 0;
        auto l_modeRegList = std::vector<uint64_t>();
        auto l_coreChiplets = i_target.getChildren<fapi2::TARGET_TYPE_CORE>();

        uint8_t l_nhtmType;
        uint8_t l_chtmType[NUM_CHTM_ENGINES];

        // Get ATTR_NHTM_TRACE_TYPE
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_NHTM_TRACE_TYPE, i_target, l_nhtmType),
                 "p9_htm_reset: Error getting ATTR_NHTM_TRACE_TYPE, l_rc 0x%.8X",
                 (uint64_t)fapi2::current_err);

        // Get ATTR_CHTM_TRACE_TYPE
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHTM_TRACE_TYPE, i_target,
                               l_chtmType),
                 "p9_htm_reset: Error getting ATTR_CHTM_TRACE_TYPE, l_rc 0x%.8X",
                 (uint64_t)fapi2::current_err);

        // Reset NHTM trace
        // Note: reset NHTM0 will also reset NHTM1 in global mode
        if (l_nhtmType != fapi2::ENUM_ATTR_NHTM_TRACE_TYPE_DISABLE)
        {
            FAPI_TRY( resetHTM(i_target, 0),
                      "p9_htm_reset: resetHTM() returns error NHTM"
                      "l_rc 0x%.8X", (uint64_t)fapi2::current_err );
        }

        // Reset CHTM
        for (auto l_core : l_coreChiplets)
        {
            // Get the core position
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_core, l_corePos),
                     "Error getting ATTR_CHIP_UNIT_POS");
            FAPI_DBG("Reset HTM on core %u....", l_corePos);

            if (l_chtmType[l_corePos] != fapi2::ENUM_ATTR_CHTM_TRACE_TYPE_DISABLE)
            {
                FAPI_TRY(resetHTM(l_core, l_corePos),
                         "p9_htm_reset: resetHTM() returns error: CHTM %u, "
                         "l_rc 0x%.8X", l_corePos, (uint64_t)fapi2::current_err );
            }
        }

    fapi_try_exit:
        FAPI_DBG("Exiting");
        return fapi2::current_err;
    }
    /// @brief FW Team Utility function that sets the Bad DQ Bitmap.
    /// @param[in] i_mba  Reference to MBA Chiplet
    /// @param[in] i_port MBA port number (0-(MAX_PORTS_PER_MBA - 1))
    /// @param[in] i_dimm MBA port DIMM number (0-(MAX_DIMM_PER_PORT - 1))
    /// @param[in] i_rank DIMM rank number (0-(MAX_RANKS_PER_DIMM -1))
    /// @param[in] i_data Reference to data where Bad DQ bitmap is copied from
    /// @return FAPI2_RC_SUCCESS
    fapi2::ReturnCode dimmSetBadDqBitmap(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba,
                                         const uint8_t i_port,
                                         const uint8_t i_dimm,
                                         const uint8_t i_rank,
                                         const uint8_t (&i_data)[DIMM_DQ_RANK_BITMAP_SIZE])
    {
        FAPI_INF(">>dimmSetBadDqBitmap. %s:%d:%d:%d", mss::c_str(i_mba), i_port, i_dimm, i_rank);

        // Check parameters and find the DIMM fapi2::Target<fapi2::TARGET_TYPE_MBA>
        fapi2::Target<fapi2::TARGET_TYPE_DIMM> l_dimm;

        // Get the Bad DQ bitmap by querying ATTR_BAD_DQ_BITMAP.
        // Use a heap based array to avoid large stack alloc
        uint8_t (&l_dqBitmap)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE] =
            *(reinterpret_cast<uint8_t(*)[MAX_RANKS_PER_DIMM][DIMM_DQ_RANK_BITMAP_SIZE]>
              (new uint8_t[MAX_RANKS_PER_DIMM * DIMM_DQ_RANK_BITMAP_SIZE]));

        FAPI_TRY(dimmBadDqCheckParamFindDimm(i_mba, i_port, i_dimm, i_rank, l_dimm));
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_BAD_DQ_BITMAP, l_dimm, l_dqBitmap));

        // Add the rank bitmap to the DIMM bitmap and write the bitmap
        memcpy(l_dqBitmap[i_rank], i_data, DIMM_DQ_RANK_BITMAP_SIZE);

        FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_BAD_DQ_BITMAP, l_dimm, l_dqBitmap));

        delete [] &l_dqBitmap;

        FAPI_INF("<<dimmSetBadDqBitmap");
    fapi_try_exit:
        return fapi2::current_err;
    }
Beispiel #6
0
fapi2::ReturnCode pm_occ_fir_reset(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_IMP("pm_occ_fir_reset Enter");

    uint8_t firinit_done_flag = 0;
    p9pmFIR::PMFir <p9pmFIR::FIRTYPE_OCC_LFIR> l_occFir(i_target);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PM_FIRINIT_DONE_ONCE_FLAG,
                           i_target, firinit_done_flag),
             "ERROR: Failed to fetch the entry status of FIRINIT");

    if (firinit_done_flag == 1)
    {
        FAPI_TRY(l_occFir.get(p9pmFIR::REG_FIRMASK),
                 "ERROR: Failed to get the OCC FIR MASK value");

        /* Fetch the OCC FIR MASK; Save it to HWP attribute; clear its contents */
        FAPI_TRY(l_occFir.saveMask(),
                 "ERROR: Failed to save the OCC FIR Mask to the attribute");
    }

    FAPI_TRY(l_occFir.setAllRegBits(p9pmFIR::REG_FIRMASK),
             "ERROR: Faled to set the OCC FIR MASK");

    FAPI_TRY(l_occFir.put(),
             "ERROR:Failed to write to the OCC FIR MASK");

fapi_try_exit:
    return fapi2::current_err;
}
/**
 * @brief Returns SPD_MODULE_REVISION_CODE data
 *
 * The fields are different sizes for DDR3 and DDR4, this HWP copies the value
 * to the attribute size in the common FAPI Attribute
 *
 * @param[in]  i_dimm Reference to DIMM fapi target
 * @param[in]  i_attr The Attribute to get
 * @param[out] o_pVal Pointer to data buffer filled in with attribute data
 * @param[in]  i_len  Size of o_pVal
 * @param[in]  i_type DDR Type
 *
 * @return fapi::ReturnCode Indicating success or error
 */
fapi::ReturnCode get_SPD_MODULE_REVISION_CODE(const fapi::Target & i_dimm,
    const fapi::getSpdAttr::Attr i_attr,
    void * o_pVal,
    const size_t i_len,
    const fapi::ATTR_SPD_DRAM_DEVICE_TYPE_Type i_type)
{
    fapi::ATTR_SPD_MODULE_REVISION_CODE_Type & o_val =
        *(reinterpret_cast<fapi::ATTR_SPD_MODULE_REVISION_CODE_Type *>(o_pVal));
    o_val = 0;

    fapi::ReturnCode l_rc = checkSize(i_attr, i_len, sizeof(o_val));

    if (!l_rc)
    {
        if (i_type == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
        {
            // Size of DDR3 data matches DDR neutral attribute (uint32_t)
            l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_REVISION_CODE_DDR3, &i_dimm,
                                 o_val);

            if (l_rc)
            {
                FAPI_ERR("get_SPD_MODULE_REVISION_CODE: Error getting DDR3 attr");
            }
        }
        else
        {
            // Size of DDR4 data (uint8_t) is smaller than the DDR neutral
            // attribute (uint32_t)
            fapi::ATTR_SPD_MODULE_REVISION_CODE_DDR4_Type l_code = 0;
            l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_REVISION_CODE_DDR4, &i_dimm,
                                 l_code);

            if (l_rc)
            {
                FAPI_ERR("get_SPD_MODULE_NOMINAL_VOLTAGE: Error getting DDR4 attr");
            }
            else
            {
                o_val = static_cast<fapi::ATTR_SPD_MODULE_REVISION_CODE_Type>(
                    l_code);
            }
        }
    }

    return l_rc;
}
Beispiel #8
0
// ----------------------------------------------------------------------
// Function definitions
// ----------------------------------------------------------------------
fapi2::ReturnCode p9_pm_firinit(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const p9pm::PM_FLOW_MODE i_mode)
{
    FAPI_IMP("p9_pm_firinit start");

    fapi2::ReturnCode l_rc;
    uint8_t l_pm_firinit_flag;
    fapi2::buffer<uint64_t> l_data64;

    // CHECKING FOR FIRS BEFORE RESET and INIT
    FAPI_DBG("Checking PBA FIRs");
    FAPI_TRY(fapi2::getScom(i_target, PU_PBAFIR , l_data64),
             "ERROR: Failed to fetch PBA FIR");

    if(l_data64)
    {
        FAPI_INF("WARNING: PBA has active error(s)");
    }

    // Handle PBA FIRs, Masks and actions
    FAPI_DBG("Calling PBA firinit ...");
    FAPI_EXEC_HWP(l_rc, p9_pm_pba_firinit, i_target, i_mode);
    FAPI_TRY(l_rc);

    // Handle Core and Quad errors
    FAPI_DBG("Calling PPM firinit ...");
    FAPI_EXEC_HWP(l_rc, p9_pm_ppm_firinit, i_target, i_mode);
    FAPI_TRY(l_rc);

    // Handle CME FIRs, Masks and actions
    FAPI_DBG("Calling CME firinit ...");
    FAPI_EXEC_HWP(l_rc, p9_pm_cme_firinit, i_target, i_mode);
    FAPI_TRY(l_rc);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PM_FIRINIT_DONE_ONCE_FLAG, i_target,
                           l_pm_firinit_flag),
             "ERROR: Failed to fetch the firinit call status flag");

    // Set the ATTR_PM_FIRINIT_DONE_ONCE_FLAG attribute
    if (i_mode == p9pm::PM_INIT)
    {
        if (l_pm_firinit_flag != 1)
        {
            l_pm_firinit_flag = 1;
            FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PM_FIRINIT_DONE_ONCE_FLAG,
                                   i_target, l_pm_firinit_flag),
                     "ERROR: Failed to set firinit call status after init");
        }
    }

fapi_try_exit:
    FAPI_INF("p9_pm_firinit end");
    return fapi2::current_err;
} // END p9_pm_firinit
Beispiel #9
0
/// @brief configure chiplet pervasive FIRs / XFIRs
///
/// @param[in]     i_target_chiplet   Reference to TARGET_TYPE_PERV target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
fapi2::ReturnCode p9_sbe_common_configure_chiplet_FIR(
    const fapi2::Target<fapi2::TARGET_TYPE_PERV>& i_target_chiplet)
{
    uint8_t l_unit_idx;
    fapi2::buffer<uint64_t> l_scom_data;
    FAPI_INF("p9_sbe_common_configure_chiplet_FIR: Entering ...");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target_chiplet, l_unit_idx),
             "Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS)");
    l_unit_idx--;

    // PERV LFIR
    FAPI_DBG("Configuring PERV LFIR (chiplet ID: %02X)", l_unit_idx + 1);

    // reset pervasive FIR
    l_scom_data = 0;
    FAPI_TRY(fapi2::putScom(i_target_chiplet, PERV_LOCAL_FIR, l_scom_data),
             "Error from putScom (PERV_LOCAL_FIR)");

    // configure pervasive FIR action/mask
    l_scom_data = PERV_LFIR_ACTION0[l_unit_idx];
    FAPI_TRY(fapi2::putScom(i_target_chiplet, PERV_LOCAL_FIR_ACTION0, l_scom_data),
             "Error from putScom (PERV_LOCAL_FIR_ACTION0)");

    l_scom_data = PERV_LFIR_ACTION1[l_unit_idx];
    FAPI_TRY(fapi2::putScom(i_target_chiplet, PERV_LOCAL_FIR_ACTION1, l_scom_data),
             "Error from putScom (PERV_LOCAL_FIR_ACTION1)");

    l_scom_data = PERV_LFIR_MASK[l_unit_idx];
    FAPI_TRY(fapi2::putScom(i_target_chiplet, PERV_LOCAL_FIR_MASK, l_scom_data),
             "Error from putScom (PERV_LOCAL_FIR_MASK)");

    // XFIR
    FAPI_DBG("Configuring chiplet XFIR (chiplet ID: %02X)", l_unit_idx + 1);
    // reset XFIR
    l_scom_data = 0;
    FAPI_TRY(fapi2::putScom(i_target_chiplet, PERV_XFIR, l_scom_data),
             "Error from putScom (PERV_XFIR)");

    // configure XFIR mask
    l_scom_data = PERV_XFIR_MASK[l_unit_idx];
    FAPI_TRY(fapi2::putScom(i_target_chiplet, PERV_FIR_MASK, l_scom_data),
             "Error from putScom (PERV_FIR_MASK");

    FAPI_INF("p9_sbe_common_configure_chiplet_FIR: Exiting ...");

fapi_try_exit:
    return fapi2::current_err;

}
/**
 * @brief Returns the DIMM DDR Type
 *
 * This function only supports DDR3 and DDR4
 *
 * @param[in]  i_dimm Reference to DIMM fapi target.
 * @param[out] o_type Filled in with the DIMM DDR Type.
 *
 * @return fapi::ReturnCode Indicating success or error
 */
fapi::ReturnCode getDdrType(const fapi::Target & i_dimm,
                            fapi::ATTR_SPD_DRAM_DEVICE_TYPE_Type & o_type)
{
    fapi::ReturnCode l_rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_DEVICE_TYPE, &i_dimm,
                                          o_type);
    if (l_rc)
    {
        FAPI_ERR("getSpdAttrAccessor: Error querying DDR type");
    }
    else if ((o_type != fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3) &&
             (o_type != fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4))
    {
        FAPI_ERR("getSpdAttrAccessor: Invalid DIMM DDR Type 0x%02x", o_type);
        const fapi::Target & DIMM = i_dimm;
        const fapi::ATTR_SPD_DRAM_DEVICE_TYPE_Type & TYPE = o_type;
        FAPI_SET_HWP_ERROR(l_rc, RC_GET_SPD_ACCESSOR_INVALID_DDR_TYPE);
    }

    return l_rc;
}
Beispiel #11
0
/// @brief get children for all chiplets
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @param[out]    o_pg_vector     vector of targets
/// @return  FAPI2_RC_SUCCESS if success, else error code.
fapi2::ReturnCode p9_sbe_common_get_pg_vector(const
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip,
        fapi2::buffer<uint64_t>& o_pg_vector)
{
    fapi2::buffer<uint8_t> l_read_attrunitpos;
    FAPI_INF("p9_sbe_common_get_pg_vector: Entering ...");

    for (auto& l_target_cplt : i_target_chip.getChildren<fapi2::TARGET_TYPE_PERV> (fapi2::TARGET_STATE_FUNCTIONAL))
    {
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_target_cplt, l_read_attrunitpos));
        uint8_t bitPos = l_read_attrunitpos;
        o_pg_vector.setBit(bitPos);
    }

    FAPI_INF("p9_sbe_common_get_pg_vector: Exiting ...");

fapi_try_exit:
    return fapi2::current_err;

}
Beispiel #12
0
fapi2::ReturnCode addOMIBase(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
                             uint64_t& io_mmioAddr)
{
    std::vector<uint64_t> l_base_addr_nm0;
    std::vector<uint64_t> l_base_addr_nm1;
    std::vector<uint64_t> l_base_addr_m;
    uint64_t l_addr_offset;
    uint64_t l_base_addr_mmio;

    fapi2::Target<fapi2::TARGET_TYPE_OMI> l_omi_target;
    fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chip_target;

    l_omi_target = i_target.getParent<fapi2::TARGET_TYPE_OMI>();
    l_chip_target = l_omi_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    // determine base address of chip MMIO range
    FAPI_TRY(p9_fbc_utils_get_chip_base_address(l_chip_target,
             EFF_FBC_GRP_CHIP_IDS,
             l_base_addr_nm0,
             l_base_addr_nm1,
             l_base_addr_m,
             l_base_addr_mmio),
             "Error from p9_fbc_utils_get_chip_base_address");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET,
                           l_omi_target,
                           l_addr_offset),
             "Error from FAPI_ATTR_GET (ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET)");

    io_mmioAddr |= (l_base_addr_mmio | l_addr_offset);

fapi_try_exit:

    FAPI_DBG("Exiting with return code : 0x%08X...", (uint64_t) fapi2::current_err);
    return fapi2::current_err;
}
/**
 * @brief Returns SPD_SDRAM_BANKS data
 *
 * The raw data has different meanings for DDR3 and DDR4, this HWP translates
 * each to the enumeration in the common FAPI Attribute
 *
 * @param[in]  i_dimm Reference to DIMM fapi target
 * @param[in]  i_attr The Attribute to get
 * @param[out] o_pVal Pointer to data buffer filled in with attribute data
 * @param[in]  i_len  Size of o_pVal
 * @param[in]  i_type DDR Type
 *
 * @return fapi::ReturnCode Indicating success or error
 */
fapi::ReturnCode get_SPD_SDRAM_BANKS(const fapi::Target & i_dimm,
    const fapi::getSpdAttr::Attr i_attr,
    void * o_pVal,
    const size_t i_len,
    const fapi::ATTR_SPD_DRAM_DEVICE_TYPE_Type i_type)
{
    fapi::ATTR_SPD_SDRAM_BANKS_Type & o_val =
        *(reinterpret_cast<fapi::ATTR_SPD_SDRAM_BANKS_Type *>(o_pVal));
    o_val = 0;

    fapi::ReturnCode l_rc = checkSize(i_attr, i_len, sizeof(o_val));

    if (!l_rc)
    {
        if (i_type == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
        {
            fapi::ATTR_SPD_SDRAM_BANKS_DDR3_Type l_banks = 0;
            l_rc = FAPI_ATTR_GET(ATTR_SPD_SDRAM_BANKS_DDR3, &i_dimm, l_banks);

            if (l_rc)
            {
                FAPI_ERR("get_SPD_SDRAM_BANKS: Error getting DDR3 attr");
            }
            else
            {
                switch (l_banks)
                {
                case fapi::ENUM_ATTR_SPD_SDRAM_BANKS_DDR3_B8:
                    o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_B8;
                    break;
                case fapi::ENUM_ATTR_SPD_SDRAM_BANKS_DDR3_B16:
                    o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_B16;
                    break;
                case fapi::ENUM_ATTR_SPD_SDRAM_BANKS_DDR3_B32:
                    o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_B32;
                    break;
                case fapi::ENUM_ATTR_SPD_SDRAM_BANKS_DDR3_B64:
                    o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_B64;
                    break;
                default:
                   FAPI_ERR("get_SPD_SDRAM_BANKS: Unrecognized DDR3 attr 0x%x",
                            l_banks);
                   o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_UNKNOWN;
                }
            }
        }
        else
        {
            fapi::ATTR_SPD_SDRAM_BANKS_DDR4_Type l_banks = 0;
            l_rc = FAPI_ATTR_GET(ATTR_SPD_SDRAM_BANKS_DDR4, &i_dimm, l_banks);

            if (l_rc)
            {
                FAPI_ERR("get_SPD_SDRAM_BANKS: Error getting DDR4 attr");
            }
            else
            {
                switch (l_banks)
                {
                case fapi::ENUM_ATTR_SPD_SDRAM_BANKS_DDR4_B4:
                    o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_B4;
                    break;
                case fapi::ENUM_ATTR_SPD_SDRAM_BANKS_DDR4_B8:
                    o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_B8;
                    break;
                   FAPI_ERR("get_SPD_SDRAM_BANKS: Unrecognized DDR4 attr 0x%x",
                            l_banks);
                   o_val = fapi::ENUM_ATTR_SPD_SDRAM_BANKS_UNKNOWN;
                }
            }
        }
    }

    return l_rc;
}
  // parameters:
  // 'i_target' is chip target
  //
  // returns:
  // FAPI_RC_SUCCESS (success, EX chiplets entered fast winkle)
  //
  // getscom/putscom/getattribute fapi errors
  // fapi error assigned from eCMD function failure
  //
  //------------------------------------------------------------------------------
  fapi::ReturnCode proc_mpipl_ex_cleanup(const fapi::Target & i_target) {
    const char          *procedureName = "proc_mpipl_ex_cleanup";
    fapi::ReturnCode    rc; //fapi return code
    uint32_t            rc_ecmd = 0;    //ecmd return code value
    ecmdDataBufferBase  fsi_data(64); //64-bit data buffer
    uint8_t             attr_chip_unit_pos; //EX chiplet's unit offset within chip with respect to similar EX units
    const uint64_t      EX_OFFSET_MULT = 0x01000000; //Multiplier used to calculate offset for respective EX chiplet

    uint64_t            address;   // Varible for computed addresses
    uint64_t            offset;
    char                reg_name[32];  // Character array for register names


    // Relevant PMGP0 bits
//    const uint32_t      PM_DISABLE = 0;
    const uint32_t      BLOCK_REG_WKUP_SOURCE = 53;


    // Relevant PMGP1 bits  
    const uint32_t      WINKLE_POWER_OFF_SEL = 5;

    std::vector<fapi::Target> v_ex_chiplets; //Vector of EX chiplets


    do
    {
        //Entering fapi function
        FAPI_INF("Entering %s", procedureName);

        //Get vector of EX chiplets
        rc = fapiGetChildChiplets(  i_target, 
                                    fapi::TARGET_TYPE_EX_CHIPLET, 
                                    v_ex_chiplets, 
                                    fapi::TARGET_STATE_FUNCTIONAL); 
        if (rc) 
        {
             FAPI_ERR("%s: fapiGetChildChiplets error", procedureName);
             break;
        }

        FAPI_INF("Processing target %s", i_target.toEcmdString());
        
        //Parse thru EX chiplets and prepare fast-winkled cores for deep operations
        //Loop thru EX chiplets in vector
        for (uint32_t counter = 0; counter < v_ex_chiplets.size(); counter++)
        {

            // Get EX chiplet number
            rc = FAPI_ATTR_GET( ATTR_CHIP_UNIT_POS,
                                &(v_ex_chiplets[counter]),
                                attr_chip_unit_pos);
            if (rc)
            {
                FAPI_ERR("%s: fapiGetAttribute error (ATTR_CHIP_UNIT_POS)", procedureName);
                break;
            }
            FAPI_INF("EX chiplet pos = 0x%02X", attr_chip_unit_pos);


            // Calculate the address offset based on chiplet number
            offset = EX_OFFSET_MULT * attr_chip_unit_pos;
                        
            // -----------------------------------------------------------------
            FAPI_DBG("\tOriginal register contents");
            address = EX_GP3_0x100F0012 + offset;
            strcpy(reg_name, "GP3");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            
            address = EX_PMGP0_0x100F0100 + offset;
            strcpy(reg_name, "PMGP0");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));

            address = EX_PMGP1_0x100F0103 + offset;
            strcpy(reg_name, "PMGP1");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            // -----------------------------------------------------------------

            // Clean up configuration remnants of the fast-winkle configuration
            // that  was used to flush the chiplets after checkstop.  EX chiplets
            // will have been through SBE EX Init with certain step skippled due 
            // to MPIPL.
            
            FAPI_INF("Re-establish Deep Winkle mode default");
            address = EX_PMGP1_OR_0x100F0105 + offset;
            strcpy(reg_name, "PMGP1 OR");

            rc_ecmd |= fsi_data.flushTo0();
            rc_ecmd |= fsi_data.setBit(WINKLE_POWER_OFF_SEL);
            if(rc_ecmd)
            {
                FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX) with rc %x", reg_name, address, rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(i_target, address, fsi_data);
            if (rc)
            {
                FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address);
                break;
            }

            FAPI_INF("Clear block wakeup sources to PM logic.  PM is NOT re-enabled");
            // (eg clear Block Interrrupt Sources)
            address = EX_PMGP0_AND_0x100F0101 + offset;
            strcpy(reg_name, "PMGP0 AND");

            rc_ecmd |= fsi_data.flushTo1();
//            rc_ecmd |= fsi_data.clearBit(PM_DISABLE);
            rc_ecmd |= fsi_data.clearBit(BLOCK_REG_WKUP_SOURCE);
            if(rc_ecmd)
            {
                FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX)", reg_name, address);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(i_target, address, fsi_data);
            if (rc)
            {
                 FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address);
                break;
            }
            
            // -----------------------------------------------------------------
            FAPI_DBG("\tUpdated register contents");
            address = EX_GP3_0x100F0012 + offset;
            strcpy(reg_name, "GP3");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            
            address = EX_PMGP0_0x100F0100 + offset;
            strcpy(reg_name, "PMGP0");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));

            address = EX_PMGP1_0x100F0103 + offset;
            strcpy(reg_name, "PMGP1");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            // -----------------------------------------------------------------
        } // chiplet loop

        // Error exit from above loop
        // Not really needed as outer while(0) is next but here for consistent structure
        if (!rc.ok())
        {
            break;
        }
    } while (0);

    //Exiting fapi function
    FAPI_INF("Exiting %s", procedureName);

    return rc;
  }
Beispiel #15
0
///
/// @brief Check validity of SMP topology
///
/// @param[in] i_op    Enumerated type representing SMP build phase (HB or FSP)
/// @param[in] i_smp   Fully specified structure encapsulating SMP
///
/// @return FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode
p9_build_smp_check_topology(const p9_build_smp_operation i_op,
                            p9_build_smp_system& i_smp)
{
    // check that fabric topology is logically valid
    // 1) in a given group, all chips are connected to every other
    //    chip in the group, by an X bus (if pump mode = chip_is_node)
    // 2) each chip is connected to its partner chip (with same chip id)
    //    in every other group, by an A bus or X bus (if pump mode = chip_is_group)

    fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
    fapi2::ATTR_PROC_FABRIC_PUMP_MODE_Type l_pump_mode;
    fapi2::buffer<uint8_t> l_group_ids_in_system;
    fapi2::buffer<uint8_t> l_chip_ids_in_groups;

    // determine pump mode
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_PUMP_MODE, FAPI_SYSTEM, l_pump_mode),
             "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_PUMP_MODE");

    // build set of all valid group IDs in system
    for (auto g_iter = i_smp.groups.begin();
         g_iter != i_smp.groups.end();
         g_iter++)
    {
        FAPI_INF("Adding g%d", g_iter->first);
        FAPI_TRY(l_group_ids_in_system.setBit(g_iter->first),
                 "Error from setBit (l_group_ids_in_system)");

        // build set of all valid chip IDs in group
        for (auto p_iter = g_iter->second.chips.begin();
             p_iter != g_iter->second.chips.end();
             p_iter++)
        {
            FAPI_INF("Adding g%d:p%d", g_iter->first, p_iter->first);
            FAPI_TRY(l_chip_ids_in_groups.setBit(p_iter->first),
                     "Error from setBit (l_chip_ids_in_groups)");
        }
    }

    // iterate over all groups
    for (auto g_iter = i_smp.groups.begin();
         g_iter != i_smp.groups.end();
         g_iter++)
    {
        // iterate over all chips in current group
        for (auto p_iter = g_iter->second.chips.begin();
             p_iter != g_iter->second.chips.end();
             p_iter++)
        {
            FAPI_DBG("Checking connectivity for g%d:p%d", g_iter->first, p_iter->first);
            bool intergroup_set_match = false;
            fapi2::buffer<uint8_t> l_connected_group_ids;
            bool intragroup_set_match = false;
            fapi2::buffer<uint8_t> l_connected_chip_ids;

            uint8_t l_x_en[P9_FBC_UTILS_MAX_X_LINKS] = { 0 };
            uint8_t l_a_en[P9_FBC_UTILS_MAX_A_LINKS] = { 0 };
            uint8_t l_x_rem_chip_id[P9_FBC_UTILS_MAX_X_LINKS] = { 0 };
            uint8_t l_a_rem_group_id[P9_FBC_UTILS_MAX_A_LINKS] = { 0 };

            // add IDs associated with current chip, to make direct set comparison easy
            FAPI_TRY(l_connected_group_ids.setBit(p_iter->second.group_id),
                     "Error from setBit (l_connected_group_ids)");

            FAPI_TRY(l_connected_chip_ids.setBit(p_iter->second.chip_id),
                     "Error from setBit (l_connected_chip_ids)");

            // process X links, mark reachable group/chip IDs
            FAPI_INF("Processing X links for g%d:p%d", g_iter->first, p_iter->first);
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_X_ATTACHED_CHIP_CNFG, *(p_iter->second.target), l_x_en),
                     "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_X_ATTACHED_CHIP_CNFG)");

            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_X_ATTACHED_CHIP_ID, *(p_iter->second.target), l_x_rem_chip_id),
                     "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_X_ATTACHED_CHIP_ID)");

            for (uint8_t l_link_id = 0; l_link_id < P9_FBC_UTILS_MAX_X_LINKS; l_link_id++)
            {
                if (l_x_en[l_link_id])
                {
                    FAPI_TRY(p9_build_smp_validate_link(*(p_iter->second.target),
                                                        P9_FBC_XBUS_LINK_CTL_ARR[l_link_id],
                                                        l_x_en[l_link_id]),
                             "Error from p9_build_smp_validate_link (g%d:p%d X%d)",
                             g_iter->first, p_iter->first, l_link_id);

                    if (l_pump_mode == fapi2::ENUM_ATTR_PROC_FABRIC_PUMP_MODE_CHIP_IS_NODE)
                    {
                        FAPI_TRY(l_connected_chip_ids.setBit(l_x_rem_chip_id[l_link_id]),
                                 "Error from setBit (l_connected_chip_ids, X)");
                    }
                    else
                    {
                        FAPI_TRY(l_connected_group_ids.setBit(l_x_rem_chip_id[l_link_id]),
                                 "Error from setBit (l_connected_group_ids, X)");
                    }
                }
            }

            // process A links, mark reachable group/chip IDs
            FAPI_INF("Processing A links for g%d:p%d", g_iter->first, p_iter->first);
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG, *(p_iter->second.target), l_a_en),
                     "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG)");

            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_A_ATTACHED_CHIP_ID, *(p_iter->second.target), l_a_rem_group_id),
                     "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_A_ATTACHED_CHIP_ID)");

            for (uint8_t l_link_id = 0; l_link_id < P9_FBC_UTILS_MAX_A_LINKS; l_link_id++)
            {
                if (l_a_en[l_link_id])
                {
                    FAPI_TRY(p9_build_smp_validate_link(*(p_iter->second.target),
                                                        P9_FBC_ABUS_LINK_CTL_ARR[l_link_id],
                                                        l_a_en[l_link_id]),
                             "Error from p9_build_smp_validate_link (g%d:p%d A%d)",
                             g_iter->first, p_iter->first, l_link_id);

                    FAPI_TRY(l_connected_group_ids.setBit(l_a_rem_group_id[l_link_id]),
                             "Error from setBit (l_connected_group_ids, A)");
                }

            }

            // compare ID sets, emit error if they don't match
            intergroup_set_match = (l_group_ids_in_system == l_connected_group_ids);
            intragroup_set_match = (l_chip_ids_in_groups == l_connected_chip_ids);

            if (!intergroup_set_match || !intragroup_set_match)
            {
                // display target information
                char l_target_str[fapi2::MAX_ECMD_STRING_LEN];
                fapi2::toString(*(p_iter->second.target), l_target_str, sizeof(l_target_str));

                if (!intragroup_set_match)
                {
                    FAPI_ERR("Target %s is not fully connected (X) to all other chips in its group",
                             l_target_str);
                }

                if (!intergroup_set_match)
                {
                    FAPI_ERR("Target %s is not fully connected (X/A) to all other groups in the system",
                             l_target_str);
                }

                FAPI_ASSERT(false,
                            fapi2::P9_BUILD_SMP_INVALID_TOPOLOGY()
                            .set_TARGET(*(p_iter->second.target))
                            .set_OP(i_op)
                            .set_GROUP_ID(p_iter->second.group_id)
                            .set_CHIP_ID(p_iter->second.chip_id)
                            .set_INTERGROUP_CONNECTIONS_OK(intergroup_set_match)
                            .set_CONNECTED_GROUP_IDS(l_connected_group_ids)
                            .set_GROUP_IDS_IN_SYSTEM(l_group_ids_in_system)
                            .set_INTRAGROUP_CONNECTIONS_OK(intragroup_set_match)
                            .set_CONNECTED_CHIP_IDS(l_connected_chip_ids)
                            .set_CHIP_IDS_IN_GROUPS(l_chip_ids_in_groups)
                            .set_FBC_PUMP_MODE(l_pump_mode),
                            "Invalid fabric topology detected");
            }
        }
    }

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}
Beispiel #16
0
    ///
    ///@brief mss_thermal_init procedure. Configure and start the OCC cache and Centaur thermal cache
    ///@param[in]  i_target  Reference to centaur target
    ///@return ReturnCode
    ///
    fapi2::ReturnCode p9c_mss_thermal_init(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target)
    {
        FAPI_INF("*** Running mss_thermal_init ***");

        constexpr uint32_t I2C_SETUP_UPPER_HALF = 0xD2314049;
        constexpr uint32_t I2C_SETUP_LOWER_HALF = 0x05000000;
        constexpr uint32_t ACT_MASK_UPPER_HALF = 0x00018000;
        constexpr uint32_t ACT_MASK_LOWER_HALF = 0x00000000;
        // OCC polls cacheline every 2 ms (could vary from this, as seen on scope)
        // For I2C bus at 50kHz (9.6 ms max to read 8 sensors), use interval of 15 for margin and to prevent stall errors when 8 sensors are enabled to be read
        constexpr uint32_t CONFIG_INTERVAL_TIMER = 15;
        constexpr uint32_t CONFIG_STALL_TIMER = 128;
        constexpr uint8_t I2C_BUS_ENCODE_PRIMARY = 0;
        constexpr uint8_t I2C_BUS_ENCODE_SECONDARY = 8;
        constexpr uint8_t MAX_NUM_DIMM_SENSORS = 8;
        constexpr uint8_t MAX_I2C_BUSSES = 2;

        // Variable declaration
        uint8_t l_dimm_ranks_array[MAX_MBA_PER_CEN][MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};    // Number of ranks for each configured DIMM in each MBA
        uint8_t l_custom_dimm[MAX_MBA_PER_CEN] = {0};               // Custom DIMM
        uint8_t l_mba_pos = 0;                        // Current MBA for populating rank array
        fapi2::buffer<uint64_t> l_data;
        fapi2::buffer<uint64_t> l_data_scac_enable;
        fapi2::buffer<uint64_t> l_data_scac_addrmap;
        uint8_t l_cdimm_sensor_map = 0;
        uint8_t l_cdimm_sensor_map_primary = 0;
        uint8_t l_cdimm_sensor_map_secondary = 0;
        uint8_t l_cdimm_number_dimm_temp_sensors = 0;
        uint8_t l_i2c_address_map = 0;
        uint8_t l_data_scac_addrmap_offset = 0;
        uint8_t l_i2c_bus_encode = 0;
        uint8_t l_sensor_map_mask = 0;
        uint8_t l_master_i2c_temp_sensor_enable = 0;
        uint8_t l_spare_i2c_temp_sensor_enable = 0;
        uint32_t l_dimm_sensor_cache_addr_map = 0;
        fapi2::buffer<uint64_t> l_reset;
        uint8_t l_enable_safemode_throttle = 0;
        // Get input attributes from MBAs
        const auto l_target_mba_array = i_target.getChildren<fapi2::TARGET_TYPE_MBA>();

        //********************************************
        // Centaur internal temperature polling setup
        //********************************************
        // setup hang pulse
        FAPI_TRY(fapi2::getScom(i_target, CEN_PCBSLNEST_HANG_PULSE_0_REG_PCB, l_data));
        l_data.setBit<1>().setBit<2>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_PCBSLNEST_HANG_PULSE_0_REG_PCB, l_data));
        FAPI_TRY(fapi2::getScom(i_target, CEN_TCN_THERM_MODE_REG_PCB, l_data));
        // setup DTS enables  NOTE: Does this need to be scom'd before enable dts sampling? LM
        l_data.setBit<20>().setBit<21>();
        // setup pulse count and enable DTS sampling
        l_data.setBit<5>().setBit<6>().setBit<7>().setBit<8>().setBit<9>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_TCN_THERM_MODE_REG_PCB, l_data));
        // issue a reset
        l_data.flush<0>().setBit<0>().setBit<1>().setBit<2>().setBit<3>().setBit<4>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_TCN_CONTROL_REG_PCB, l_data));
        // Centaur internal temperature polling setup complete

        for (const auto& mba : l_target_mba_array)
        {
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, mba, l_mba_pos), "Failed to get attr ATTR_CHIP_UNIT_POS on %s",
                     mss::c_str(mba));
            FAPI_INF("MBA_POS: %d", l_mba_pos);

            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, mba, l_dimm_ranks_array[l_mba_pos]),
                     "Failed to get attr ATTR_CEN_EFF_NUM_RANKS_PER_DIMM on %s", mss::c_str(mba));
            FAPI_INF("EFF_NUM_RANKS: %d:%d:%d:%d", l_dimm_ranks_array[l_mba_pos][0][0], l_dimm_ranks_array[l_mba_pos][0][1],
                     l_dimm_ranks_array[l_mba_pos][1][0], l_dimm_ranks_array[l_mba_pos][1][1]);

            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, mba,  l_custom_dimm[l_mba_pos]),
                     "Failed to get attr ATTR_CEN_EFF_CUSTOM_DIMM on %s", mss::c_str(mba));
            FAPI_INF("ATTR_EFF_CUSTOM_DIMM: %d", l_custom_dimm[l_mba_pos]);
        }

        // Get attributes for dimm temperature sensor mapping for only a custom dimm so we don't get an error
        // Get attritute for custom dimms for enablement on the master i2c bus
        if ((l_custom_dimm[0] == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
            || (l_custom_dimm[1] == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES))
        {
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_CDIMM_SENSOR_MAP_PRIMARY, i_target,  l_cdimm_sensor_map_primary),
                     "Failed to get attr ATTR_CEN_VPD_CDIMM_SENSOR_MAP_PRIMARY on %s", mss::c_str(i_target));
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_CDIMM_SENSOR_MAP_SECONDARY, i_target,  l_cdimm_sensor_map_secondary),
                     "Failed to get attr ATTR_CEN_VPD_CDIMM_SENSOR_MAP_SECONDARY on %s", mss::c_str(i_target));
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_CDIMM_MASTER_I2C_TEMP_SENSOR_ENABLE,
                                   fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_master_i2c_temp_sensor_enable),
                     "Failed to get attr ATTR_CEN_MRW_CDIMM_MASTER_I2C_TEMP_SENSOR_ENABLE on %s", mss::c_str(i_target));
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_CDIMM_SPARE_I2C_TEMP_SENSOR_ENABLE,
                                   fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_spare_i2c_temp_sensor_enable),
                     "Failed to get attr ATTR_CEN_MRW_CDIMM_SPARE_I2C_TEMP_SENSOR_ENABLE on %s", mss::c_str(i_target));
        }
        else
        {
            // sensor cache address map for non custom dimm temperature sensors (which i2c bus and i2c address they are)
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MEM_SENSOR_CACHE_ADDR_MAP, i_target,  l_dimm_sensor_cache_addr_map),
                     "Failed to get attr ATTR_CEN_MRW_MEM_SENSOR_CACHE_ADDR_MAP on %s", mss::c_str(i_target));
        }

        // Configure Centaur Thermal Cache

        // ---------------------------------
        // Clear the master enable bit
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_CONFIG, l_data));
        l_data.clearBit<0>(); //Master enable is bit 0
        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_CONFIG, l_data));

        // ---------------------------------
        // Mask FIR bit 33
        // Sets if any sensor cache addresses are written while the master enable is set
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_FIRMASK, l_data));
        l_data.setBit<33>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_FIRMASK, l_data));

        // ---------------------------------
        // Program PibTarget<fapi2::TARGET_TYPE_MBA> Register
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_PIBTARGET, l_data));
        l_data.insert<0, 32, 0>(CEN_I2CM_CONTROL_REGISTER_0_WOX);
        l_data.insert<32, 32, 0>(CEN_I2CM_CONTROL_REGISTER_0_WOX);
        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_PIBTARGET, l_data));

        // ---------------------------------
        // Program I2CMCtrl Register
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_I2CMCTRL_SCAC_I2CMCTRL, l_data));
        l_data.insert<0, 32, 0>(I2C_SETUP_UPPER_HALF);
        l_data.insert<32, 32, 0>(I2C_SETUP_LOWER_HALF);
        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_I2CMCTRL_SCAC_I2CMCTRL, l_data));


        // ---------------------------------
        // Program Action Mask Register
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_ACTIONMASK, l_data));
        l_data.insert<0, 32, 0>(ACT_MASK_UPPER_HALF);
        l_data.insert<32, 32, 0>(ACT_MASK_LOWER_HALF);
        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_ACTIONMASK, l_data));


        // ---------------------------------
        // Program SensorCacheConfiguration Register
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_CONFIG, l_data));
        l_data.setBit<1>();   //Sync to OCC_Read signal
        l_data.insert < 11, 5, 32 - 5 > (CONFIG_INTERVAL_TIMER);
        l_data.insert < 16, 8, 32 - 8 > (CONFIG_STALL_TIMER);
        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_CONFIG, l_data));

        // --------------------------------------------------------
        // Program SensorCacheEnable and SensorAddressMap Registers
        // --------------------------------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_ENABLE, l_data_scac_enable));

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_ADDRMAP, l_data_scac_addrmap));

        if ((l_custom_dimm[0] == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
            || (l_custom_dimm[1] == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES))
        {

            l_cdimm_number_dimm_temp_sensors = 0;

            // cycle through both primary and secondary i2c busses, determine i2c address and enable bits
            for (uint8_t l_i2c_bus = 0; l_i2c_bus < MAX_I2C_BUSSES; l_i2c_bus++)
            {
                for (uint8_t l_dimm_sensor = 0; l_dimm_sensor < MAX_NUM_DIMM_SENSORS; l_dimm_sensor++)
                {
                    if (l_i2c_bus == 0)
                    {
                        l_i2c_bus_encode = I2C_BUS_ENCODE_PRIMARY;
                        l_cdimm_sensor_map = l_cdimm_sensor_map_primary;
                    }
                    else
                    {
                        l_i2c_bus_encode = I2C_BUS_ENCODE_SECONDARY;
                        l_cdimm_sensor_map = l_cdimm_sensor_map_secondary;
                    }

                    switch (l_dimm_sensor)
                    {
                        case 0:
                            l_sensor_map_mask = 0x01;
                            break;

                        case 1:
                            l_sensor_map_mask = 0x02;
                            break;

                        case 2:
                            l_sensor_map_mask = 0x04;
                            break;

                        case 3:
                            l_sensor_map_mask = 0x08;
                            break;

                        case 4:
                            l_sensor_map_mask = 0x10;
                            break;

                        case 5:
                            l_sensor_map_mask = 0x20;
                            break;

                        case 6:
                            l_sensor_map_mask = 0x40;
                            break;

                        case 7:
                            l_sensor_map_mask = 0x80;
                            break;

                        default:
                            l_sensor_map_mask = 0x00;
                    }

                    if ((l_cdimm_sensor_map & l_sensor_map_mask) != 0)
                    {
                        if(
                            (
                                (l_i2c_bus == 0)
                                &&
                                (l_master_i2c_temp_sensor_enable ==
                                 fapi2::ENUM_ATTR_CEN_MRW_CDIMM_MASTER_I2C_TEMP_SENSOR_ENABLE_ON)
                            )
                            ||
                            (
                                (l_i2c_bus == 1)
                                &&
                                (l_spare_i2c_temp_sensor_enable ==
                                 fapi2::ENUM_ATTR_CEN_MRW_CDIMM_SPARE_I2C_TEMP_SENSOR_ENABLE_ON)
                            )
                        )

                        {
                            FAPI_TRY(l_data_scac_enable.setBit(l_cdimm_number_dimm_temp_sensors));
                        }

                        l_i2c_address_map = l_dimm_sensor + l_i2c_bus_encode;
                        l_data_scac_addrmap_offset = l_cdimm_number_dimm_temp_sensors * 4;
                        FAPI_TRY(l_data_scac_addrmap.insert(l_i2c_address_map, l_data_scac_addrmap_offset , 4, 4));
                        l_cdimm_number_dimm_temp_sensors++;
                        FAPI_ASSERT(l_cdimm_number_dimm_temp_sensors <= MAX_NUM_DIMM_SENSORS,
                                    fapi2::CEN_MSS_CDIMM_INVALID_NUMBER_SENSORS().
                                    set_MEM_CHIP(i_target).
                                    set_FFDC_DATA_1(l_cdimm_sensor_map_primary).
                                    set_FFDC_DATA_2(l_cdimm_sensor_map_secondary),
                                    "Invalid number of dimm temperature sensors specified in the CDIMM VPD MW keyword");

                    } // end if sensor map and mask != 0
                } // end for sensor
            } //end for i2c bus
        } //end if custom dimm
        else
        {
            // Iterate through the num_ranks array to determine what DIMMs are plugged
            // Enable sensor monitoring for each plugged DIMM
            uint32_t l_iterator = 0;

            for (uint32_t l_mba_index = 0; l_mba_index < MAX_MBA_PER_CEN; l_mba_index++)
            {
                if (l_dimm_ranks_array[l_mba_index][0][0] != 0)
                {
                    FAPI_TRY(l_data_scac_enable.setBit(l_iterator));
                }

                l_iterator++;

                if (l_dimm_ranks_array[l_mba_index][0][1] != 0)
                {
                    FAPI_TRY(l_data_scac_enable.setBit(l_iterator));
                }

                l_iterator++;

                if (l_dimm_ranks_array[l_mba_index][1][0] != 0)
                {
                    FAPI_TRY(l_data_scac_enable.setBit(l_iterator));
                }

                l_iterator++;

                if (l_dimm_ranks_array[l_mba_index][1][1] != 0)
                {
                    FAPI_TRY(l_data_scac_enable.setBit(l_iterator));
                }

                l_iterator++;
            }

            l_data_scac_addrmap.insert<0, 32, 0>(l_dimm_sensor_cache_addr_map);

        } //end not custom dimm

        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_ENABLE, l_data_scac_enable));

        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_ADDRMAP, l_data_scac_addrmap));

        //---------------------------------
        // Reset the I2CM
        //---------------------------------

        l_reset.setBit<0>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_I2CM_RESET_REGISTER_0_WOX, l_reset));

        // ---------------------------------
        // Set the master enable bit
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_SCAC_CONFIG, l_data));
        l_data.setBit<0>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_SCAC_CONFIG, l_data));

        // Configure Centaur Thermal Cache COMPLETED

        // Disable Emergency Throttles

        // ---------------------------------
        // Clear the emergency throttle FIR bit (MBS FIR 21)
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_MBS_FIR_REG, l_data));
        l_data.clearBit<21>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_MBS_FIR_REG, l_data));


        // ---------------------------------
        // Reset emergency throttle in progress bit (EMER THROT 0)
        // ---------------------------------

        FAPI_TRY(fapi2::getScom(i_target, CEN_MBSEMERTHROQ, l_data));
        l_data.clearBit<0>();
        FAPI_TRY(fapi2::putScom(i_target, CEN_MBSEMERTHROQ, l_data));

        // Disable Emergency Throttles COMPLETED


        // Write the IPL Safe Mode Throttles
        // For centaur DD2 and above since OCC only writes runtime throttles for this

        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_ENABLE_SAFEMODE_THROTTLE,
                               i_target,
                               l_enable_safemode_throttle));

        if (l_enable_safemode_throttle)
        {
            uint32_t l_safemode_throttle_n_per_mba;
            uint32_t l_safemode_throttle_n_per_chip;
            uint32_t l_throttle_d;

            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_SAFEMODE_MEM_THROTTLE_NUMERATOR_PER_MBA,
                                   fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
                                   l_safemode_throttle_n_per_mba));

            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_SAFEMODE_MEM_THROTTLE_NUMERATOR_PER_CHIP,
                                   fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
                                   l_safemode_throttle_n_per_chip));

            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_MEM_THROTTLE_DENOMINATOR,
                                   fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
                                   l_throttle_d));

            // write the N/M throttle control register
            for (const auto& mba : l_target_mba_array)
            {
                FAPI_TRY(fapi2::getScom(mba, CEN_MBA_MBA_FARB3Q, l_data));
                l_data.insertFromRight<0, 15>(l_safemode_throttle_n_per_mba);
                l_data.insertFromRight<15, 16>(l_safemode_throttle_n_per_chip);
                l_data.insertFromRight<31, 14>(l_throttle_d);
                FAPI_TRY(fapi2::putScom(mba, CEN_MBA_MBA_FARB3Q, l_data));
            }
        }

        // If mss_unmask_fetch_errors gets it's own bad rc,
        // it will commit the passed in rc (if non-zero), and return it's own bad rc.
        // Else if mss_unmask_fetch_errors runs clean,
        // it will just return the passed in rc.
        FAPI_TRY(mss_unmask_fetch_errors(i_target));

        FAPI_INF("*** mss_thermal_init COMPLETE ***");
    fapi_try_exit:
        return fapi2::current_err;

    } //end mss_thermal_init
fapi2::ReturnCode
p9_rng_init_phase2(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_INF("Start");
    fapi2::buffer<uint64_t> l_rng_cfg_data;
    fapi2::buffer<uint64_t> l_rng_bar_data;
    fapi2::buffer<uint64_t> l_rng_failed_int_data;
    fapi2::buffer<uint64_t> l_security_switch_data;

    uint16_t l_rng_cfg_self_test_hard_fail_status = 0;
    uint8_t  l_nx_rng_bar_enable = 0;
    uint64_t l_nx_rng_bar_addr = 0;
    uint64_t l_nx_rng_bar_base_addr_offset = 0;
    uint8_t  l_nx_rng_failed_int_enable = 0;
    uint64_t l_nx_rng_failed_int_addr = 0;
    std::vector<uint64_t> l_base_addr_nm0, l_base_addr_nm1, l_base_addr_m;
    uint64_t l_base_addr_mmio;
    uint8_t  l_HW403701;

    // 5. RNG is allowed to run for M cycles (M = enough time to complete init;
    // recommend 1 second of time).
    // NOTE: accomplished by delay in execution time between phase1/phase2 HWPs

    // get the self test hard fail status in RNG CFG register
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_HW403701,
                           i_target,
                           l_HW403701),
             "Error from FAPI_ATTR_GET (ATTR_CHIP_EC_FEATURE_HW403701)");

    FAPI_TRY(fapi2::getScom(i_target, PU_NX_RNG_CFG, l_rng_cfg_data),
             "Error from getScom (NX RNG Status and Control Register)");

    if (!l_HW403701)
    {
        // 6. Host boot checks RNG fail bits again and if a fail is detected
        // then RNG is declared broken

        FAPI_DBG("Checking RNG fail status...");
        // exit if failure is reported in self test hard fail status field
        l_rng_cfg_data.extractToRight<PU_NX_RNG_CFG_FAIL_REG,
                                      PU_NX_RNG_CFG_FAIL_REG_LEN>(l_rng_cfg_self_test_hard_fail_status);
        FAPI_ASSERT(!l_rng_cfg_self_test_hard_fail_status,
                    fapi2::P9_RNG_INIT_SELF_TEST_FAILED_ERR().
                    set_TARGET(i_target).
                    set_SELF_TEST_HARD_FAIL_STATUS(l_rng_cfg_self_test_hard_fail_status),
                    "Self test hard fail status indicates failure");
    }
    else
    {
        FAPI_DBG("Skipping check of RNG fail status...");
    }

    // 7. Host boot maps RNG BARs (see Section 5.31 RNG BAR on page 185).
    // • NX RNG BAR (not mapped/enabled if RNG is broken)
    // • NCU RNG BAR (always mapped to good RNG)
    // • NX RNG Fail Interrupt Addres

    // self test indicates no hard fail
    // if instructed to map the BAR:
    // - enable NX RNG MMIO BAR and get the bar address attributes
    // - optionally map NX RNG failed interrupt address
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_NX_RNG_BAR_ENABLE,
                           i_target,
                           l_nx_rng_bar_enable),
             "Error from FAPI_ATTR_GET (ATTR_PROC_NX_BAR_ENABLE)");

    FAPI_TRY(p9_fbc_utils_get_chip_base_address(i_target,
             EFF_FBC_GRP_CHIP_IDS,
             l_base_addr_nm0,
             l_base_addr_nm1,
             l_base_addr_m,
             l_base_addr_mmio),
             "Error from p9_fbc_utils_get_chip_base_address");

    // get RNG BAR addr
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_NX_RNG_BAR_BASE_ADDR_OFFSET,
                           i_target.getParent<fapi2::TARGET_TYPE_SYSTEM>(),
                           l_nx_rng_bar_base_addr_offset),
             "Error from FAPI_ATTR_GET (ATTR_PROC_NX_BAR_BASE_ADDR_OFFSET)");

    // caculate the NX RNG BAR ADDR based on the bar adddr offset
    l_nx_rng_bar_addr = l_base_addr_mmio;
    l_nx_rng_bar_addr += l_nx_rng_bar_base_addr_offset;

    if (l_nx_rng_bar_enable == fapi2::ENUM_ATTR_PROC_NX_RNG_BAR_ENABLE_ENABLE)
    {
        // map NX RNG MMIO BAR
        l_rng_bar_data.setBit<PU_NX_MMIO_BAR_ENABLE>();
        l_rng_bar_data.insert<PU_NX_MMIO_BAR_BAR,
                              PU_NX_MMIO_BAR_BAR_LEN, PU_NX_MMIO_BAR_BAR>(l_nx_rng_bar_addr);
        FAPI_TRY(fapi2::putScom(i_target, PU_NX_MMIO_BAR, l_rng_bar_data),
                 "Error from putScom (PU_NX_MMIO_BAR)");

        // map NX RNG failed interrupt address
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_NX_RNG_FAILED_INT_ENABLE,
                               i_target,
                               l_nx_rng_failed_int_enable),
                 "Error from FAPI_ATTR_GET (ATTR_PROC_NX_RNG_FAILED_INT_ENABLE)");
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_NX_RNG_FAILED_INT_ADDR,
                               i_target,
                               l_nx_rng_failed_int_addr),
                 "Error from FAPI_ATTR_GET (ATTR_PROC_NX_RNG_FAILED_INT_ADDR)");

        if (l_nx_rng_failed_int_enable ==
            fapi2::ENUM_ATTR_PROC_NX_RNG_FAILED_INT_ENABLE_ENABLE)
        {
            l_rng_failed_int_data.setBit<PU_RNG_FAILED_INT_ENABLE>();
            l_rng_failed_int_data.insert<PU_RNG_FAILED_INT_ADDRESS,
                                         PU_RNG_FAILED_INT_ADDRESS_LEN, PU_RNG_FAILED_INT_ADDRESS>
                                         (l_nx_rng_failed_int_addr);

            FAPI_TRY(fapi2::putScom(i_target,
                                    PU_RNG_FAILED_INT,
                                    l_rng_failed_int_data),
                     "Error from putScom (NX RNG Failed Interrupt Address Register");
        }
        else
        {
            FAPI_DBG("Skipping setup of NX RNG Failed Interrupt Address Register");
        }
    }
    else
    {
        FAPI_DBG("Skipping NX RNG BAR programming!");
    }

    // set NX RNG enable
    l_rng_cfg_data.setBit<PU_NX_RNG_CFG_ENABLE>();
    FAPI_TRY(fapi2::putScom(i_target, PU_NX_RNG_CFG, l_rng_cfg_data),
             "Error from putScom (NX RNG Status and Control Register)");

    // 8. Host boot sets the NX “sticky bit” that asserts
    // tc_nx_block_rng_scom_wr. If tc_nx_block_rng_scom_wr = 1 writes to RNG
    // SCOM register addresses 32 - 38 and 40 are blocked. An attempted
    // write sets Power-Bus Interface FIR Data Register[Write to RNG SCOM
    // reg detected when writes disabled].

    // set NX sticky bit to block future RNG SCOM writes
    // (tc_nx_block_rng_scom_wr)
    FAPI_TRY(fapi2::getScom(i_target,
                            PU_SECURITY_SWITCH_REGISTER_SCOM,
                            l_security_switch_data),
             "Error from getScom (Security Switch Register");

    l_security_switch_data.setBit<PU_SECURITY_SWITCH_REGISTER_NX_RAND_NUM_GEN_LOCK>();

    FAPI_TRY(fapi2::putScom(i_target,
                            PU_SECURITY_SWITCH_REGISTER_SCOM,
                            l_security_switch_data),
             "Error from putScom (Security Switch Register");

fapi_try_exit:
    FAPI_INF("End");
    return fapi2::current_err;
}
///
/// @brief mss_volt_vddr_offset procedure. Determines operating vddr voltage for dimms behind a vddr voltage domain
/// @param[in] i_targets  Reference to vector of Centaur Targets in a particular vddr power domain
/// @return ReturnCode
///
    fapi2::ReturnCode p9c_mss_volt_vddr_offset(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>>& i_targets)
    {
        // If we're passed an empty vector, exit out
        if(i_targets.empty())
        {
            FAPI_INF("Empty vector of targets passed to VDDR offset. Exiting..");
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // Constexpr's to pretty up some of the code
        constexpr double PERCENT = 100;
        constexpr uint64_t ATTR_VOLT_CONVERSION = 10000;
        // Note: per the power/thermal team, 5625 is the utilization for the max DMI speed at 1600 memory frequency
        // Please note, if dynamic VID is needed on all P9 centaur systems, then this value will become an MRW attribute
        // Currently, dynamic voltage is only needed on custom DIMM systems, if it is needed on ISDIMM systems, then the data bus utilization code will need to change:
        // ISDIMM systems could hypothetically have DIMM's on only one given MBA. In that case the data bus utilization will increase. We should then just look into using the attribute.
        constexpr uint64_t DATA_BUS_UTIL = 5625;

        // Declares variables
        fapi2::ReturnCode l_bad_vpd_rc = fapi2::FAPI2_RC_SUCCESS;
        uint32_t l_vpd_master_power_slope = 0;
        uint32_t l_vpd_master_power_intercept = 0;
        uint32_t l_volt_util_active = 0;
        uint32_t l_volt_util_inactive = 0;
        uint32_t l_volt_slope = 0;
        uint32_t l_volt_intercept = 0;
        uint32_t l_good_master_power_slope = 0;
        uint32_t l_good_master_power_intercept = 0;
        uint32_t l_num_dimms_to_add = 0;
        uint32_t l_var_power_on_vddr = 0;
        uint32_t l_num_logical_dimms = 0;
        uint8_t l_dram_gen = 0;
        uint8_t l_enable = 0;
        uint8_t l_is_functional = 0;
        uint8_t l_ec_disable_attr = 0;
        uint8_t l_percent_uplift = 0;
        uint8_t l_percent_uplift_idle = 0;
        uint32_t l_vddr_max_limit_mv = 0;
        uint32_t l_param_vddr_voltage_mv = 0;
        uint32_t l_data_bus_util = 0;

        // Gets and checks the DRAM generation and centaur configuration
        // Note: Plug rules checks haven't been done up to this point
        // The below checks that all DRAM have the same generation on this VDDR rail and returns the valid DRAM generation
        FAPI_TRY(check_dram_gen_plug(i_targets, l_dram_gen));

        // Voltage should not be updated if the disable is set
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_VDDR_OFFSET_ENABLE, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_enable));

        // Attribute is disabled, just exit
        if(l_enable == fapi2::ENUM_ATTR_MSS_MRW_VDDR_OFFSET_ENABLE_DISABLE)
        {
            FAPI_INF("ATTR_MSS_MRW_VDDR_OFFSET_ENABLE is set to be disabled. Exiting....., %d", l_enable);
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // Checks if any MC's have the disable attribute set, if so, set to MSS_VOLT value
        // If not, continue with the code
        for(const auto& l_chip : i_targets)
        {
            //reads in the attribute
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_CENTAUR_EC_FEATURE_DISABLE_VDDR_DYNAMIC_VID, l_chip, l_ec_disable_attr));

            // Disable is set, read mss_volt and exit out of the code
            if(l_ec_disable_attr)
            {
                break;
            }
        }

        // Disable is set, sets the l_enable attribute based upon MSS_VOLT attribute
        if(l_ec_disable_attr)
        {
            FAPI_INF("Found Centaur with EC disable attribute set. Setting ATTR_CEN_MSS_VDDR_OFFSET based upon ATTR_CEN_MSS_VOLT");

            //sets the output attributes
            for(const auto& l_chip : i_targets)
            {
                FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT, l_chip, l_param_vddr_voltage_mv));
                FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_VDDR_OFFSET, l_chip, l_param_vddr_voltage_mv));
            }//end for

            return  fapi2::FAPI2_RC_SUCCESS;
        }

        // Gets the attributes and computes var_power_on based upon whether the DRAM type is DDR3 or DDR4
        if(l_dram_gen == fapi2::ENUM_ATTR_CEN_SPD_DRAM_DEVICE_TYPE_DDR3)
        {
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_DDR3_VDDR_SLOPE, i_targets[0], l_volt_slope));
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_DDR3_VDDR_INTERCEPT, i_targets[0], l_volt_intercept));
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_DDR3_VDDR_MAX_LIMIT, i_targets[0], l_vddr_max_limit_mv));
        }
        // DDR4
        else
        {
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_DDR4_VDDR_SLOPE, i_targets[0], l_volt_slope));
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_DDR4_VDDR_INTERCEPT, i_targets[0], l_volt_intercept));
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MRW_DDR4_VDDR_MAX_LIMIT, i_targets[0], l_vddr_max_limit_mv));
        }

        // Gets the data bus utilization and picks the lower of the two values
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_MAX_DRAM_DATABUS_UTIL,
                               fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
                               l_data_bus_util));
        l_data_bus_util = l_data_bus_util < DATA_BUS_UTIL ? l_data_bus_util : DATA_BUS_UTIL;

        // Computes the active and inactive attribute values
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT,
                               fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
                               l_percent_uplift));
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT_IDLE,
                               fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
                               l_percent_uplift_idle));


        l_volt_util_active = l_data_bus_util;
        l_volt_util_inactive = 0;

        // Checks to make sure that none of the values that were read were set to zeros
        FAPI_ASSERT((l_volt_util_active != 0) &&
                    (l_volt_slope != 0) &&
                    (l_volt_intercept != 0) &&
                    (l_vddr_max_limit_mv != 0),
                    fapi2::CEN_MSS_VOLT_VDDR_OFFSET_VALUE_ERROR()
                    .set_CEN_TARGET(i_targets[0])
                    .set_VDDR_UTIL_ACTIVE(l_volt_util_active)
                    .set_VDDR_SLOPE(l_volt_slope)
                    .set_VDDR_INTERCEPT(l_volt_intercept)
                    .set_VDDR_MAX_LIMIT(l_vddr_max_limit_mv),
                    "%s One or more dynamic VDD attributes is 0 slope_util_active %lu slope %lu slope_intercept %lu!  Exiting....",
                    mss::c_str(i_targets[0]), l_volt_util_active, l_volt_slope, l_volt_intercept);

        // Print to check the calculation
        FAPI_INF("l_data_bus_util %d per 10k l_volt_util_active: %d per 10k l_volt_util_inactive: %d per 10k",
                 l_data_bus_util, l_volt_util_active, l_volt_util_inactive);


        l_num_dimms_to_add = 1;

        // Computes the preliminary VDDR value
        for(const auto& l_chip : i_targets)
        {
            // Gets the functional attribute to check for an active centaur
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FUNCTIONAL, l_chip, l_is_functional));

            // Gets the power slope values and does error checks if this card is functional, as it should have good VPD.  if the card is non-functional, continue using good VPD power slope values
            auto l_rc = FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_MASTER_POWER_SLOPE, l_chip, l_vpd_master_power_slope);

            if(l_is_functional == fapi2::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL)
            {
                FAPI_TRY(l_rc);
            }

            l_rc = FAPI_ATTR_GET(fapi2::ATTR_CEN_CDIMM_VPD_MASTER_POWER_INTERCEPT, l_chip, l_vpd_master_power_intercept);

            if(l_is_functional == fapi2::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL)
            {
                FAPI_TRY(l_rc);
            }

            // Removes leading bits from the VPD MASTER POWER attributes, leaving only the values needed for the power calculations
            l_vpd_master_power_slope &= 0x1FFF;
            l_vpd_master_power_intercept &= 0x1FFF;

            // Checks to make sure that the attribute values are non-zero - calls out all bad DIMMs
            if(((l_vpd_master_power_slope * l_vpd_master_power_intercept) == 0)
               && (l_is_functional == fapi2::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL))
            {
                FAPI_ASSERT((l_volt_util_active != 0) &&
                            (l_volt_slope != 0) &&
                            (l_volt_intercept != 0),
                            fapi2::CEN_MSS_VOLT_VDDR_OFFSET_VPD_VALUE_ERROR()
                            .set_CEN_TARGET(i_targets[0])
                            .set_VPD_MASTER_POWER_SLOPE(l_vpd_master_power_slope)
                            .set_VPD_MASTER_POWER_INTERCEPT(l_vpd_master_power_intercept),
                            "%s One or more VPD Power slope attributes is 0.  Logging error and looking for additional bad DIMMs. power_slope  %lu power_intercept %lu!  Exiting....",
                            mss::c_str(i_targets[0]), l_vpd_master_power_slope, l_vpd_master_power_intercept);

                // Using a generic error here as we already logged the other error above
                l_bad_vpd_rc = fapi2::FAPI2_RC_INVALID_PARAMETER;
                continue;
            }
            // One or more DIMM has already been called out, skip doing the calculation and continue to try to find bad DIMMs
            else if(l_bad_vpd_rc)
            {
                FAPI_INF("Already found a bad DIMM.  Skipping calculations on this DIMM.");
                continue;
            }
            // Has not found good master_power_slopes and has bad master power slopes
            else if(((l_good_master_power_slope == 0) || (l_good_master_power_intercept == 0)) &&
                    ((l_vpd_master_power_slope == 0) || (l_vpd_master_power_intercept == 0)))
            {
                l_num_dimms_to_add++;
                FAPI_INF("Found bad l_vpd_master_power_slope or l_vpd_master_power_intercept values on non-functional DIMM. Program has not found good values yet, adding one more DIMM to run when good values are found. Currently going to run %d DIMMs in the next dimm.",
                         l_num_dimms_to_add);
                continue;
            }
            // Found bad master power slope or power intercept but has good master power slope or intercepts
            else if(((l_vpd_master_power_slope == 0) || (l_vpd_master_power_intercept == 0)) &&
                    ((l_good_master_power_slope > 0) && (l_good_master_power_intercept > 0)))
            {
                // Uses assumed (last good master power slope and intercept) values for these calculations
                FAPI_INF("Found bad l_vpd_master_power_slope or l_vpd_master_power_intercept values on non-functional DIMM. Program is using the last good values for the calculations for this DIMM.");
                l_vpd_master_power_slope = l_good_master_power_slope;
                l_vpd_master_power_intercept = l_good_master_power_intercept;
            }
            // Found good master power slopes -> set the good master power slope values
            else if((l_vpd_master_power_slope > 0) && (l_vpd_master_power_intercept > 0 ))
            {
                l_good_master_power_slope = l_vpd_master_power_slope;
                l_good_master_power_intercept = l_vpd_master_power_intercept;
            }

            // Loops through all MBA chiplets to compare the compute the total number of logical dimms associated with a centaur
            l_num_logical_dimms = 0;

            for(const auto& l_mba : mss::find_targets<fapi2::TARGET_TYPE_MBA>(l_chip))
            {
                l_num_logical_dimms += mss::count_dimm(l_mba);
            }//end for

            // Multiply by total number of active logical dimms
            {
                // Temporary variables to compress the functions below
                const bool l_functional = l_is_functional == fapi2::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL;
                const auto l_volt_util = l_functional ? l_volt_util_active : l_volt_util_inactive;

                // Calculates the uplift percentage
                const auto UPLIFT = (PERCENT + l_percent_uplift) / PERCENT;
                // Note: static cast makes the entire calcuation a floating point calculation, which is what we want
                // Calculates the power usage per active DIMM
                const auto POWER_CURVE = (static_cast<double>(l_vpd_master_power_slope) * l_volt_util / ATTR_VOLT_CONVERSION) +
                                         l_vpd_master_power_intercept;

                // Calculates the power on VDDR
                l_var_power_on_vddr += static_cast<uint32_t>(l_num_dimms_to_add * POWER_CURVE * l_num_logical_dimms * UPLIFT);
                FAPI_INF("%s l_var_power_on_vddr: %d cW l_vpd_master_power_slope: %d cW l_volt_util_%sactive: %d per 10k l_vpd_master_power_intercept %d cW l_num_logical_dimms %d l_percent_uplift %d %%",
                         mss::c_str(l_chip), l_var_power_on_vddr, l_vpd_master_power_slope, l_functional ? "" : "in",
                         l_volt_util_active, l_vpd_master_power_intercept, l_num_logical_dimms, l_percent_uplift);
            }

            // Resets the number of DIMMs to add.
            l_num_dimms_to_add = 1;
        }//end for

        // Found a bad DIMM, exit
        FAPI_TRY(l_bad_vpd_rc, "Found one or more functional DIMM with bad VPD. Exiting....");

        // Debug print
        FAPI_INF("l_var_power_on_vddr: %d cW l_volt_slope: %d uV/W l_volt_intercept: %d mV",
                 l_var_power_on_vddr, l_volt_slope, l_volt_intercept);

        // Computes and converts the voltage offset into mV
        // Naked numbers are for this calculation and are a one to one port from the p8 code base
        l_param_vddr_voltage_mv = (500 + l_var_power_on_vddr * l_volt_slope / 100) / 1000 + l_volt_intercept;
        FAPI_INF("l_param_vddr_voltage_mv: %d mV", l_param_vddr_voltage_mv);

        // Found that the VDDR voltage is over the maximum limit
        if(l_param_vddr_voltage_mv > l_vddr_max_limit_mv)
        {
            FAPI_INF("l_param_vddr_voltage_mv, %d mV, is over l_vddr_max_limit_mv of %d mV.", l_param_vddr_voltage_mv,
                     l_vddr_max_limit_mv);
            FAPI_INF("Setting l_param_vddr_voltage_mv to l_vddr_max_limit_mv");
            l_param_vddr_voltage_mv = l_vddr_max_limit_mv;
        }

        // Prints out the final attribute value
        FAPI_INF("ATTR_CEN_MSS_VDDR_OFFSET: %d mV", l_param_vddr_voltage_mv);

        // Sets the output attributes
        for(const auto& l_chip : i_targets)
        {
            FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_VDDR_OFFSET, l_chip, l_param_vddr_voltage_mv));
        }//end for

    fapi_try_exit:
        return fapi2::current_err;
    }
fapi2::ReturnCode
p9_hcd_core_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target,
    const bool i_sync_stop_quad_clk)
{
    FAPI_INF(">>p9_hcd_core_stopclocks");
    fapi2::ReturnCode                              l_rc;
    fapi2::buffer<uint64_t>                        l_ccsr;
    fapi2::buffer<uint64_t>                        l_data64;
    fapi2::buffer<uint64_t>                        l_temp64;
    uint32_t                                       l_loops1ms;
    uint8_t                                        l_attr_chip_unit_pos;
    uint8_t                                        l_attr_vdm_enabled;
    uint8_t                                        l_attr_sdisn_setup;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto  l_quad = i_target.getParent<fapi2::TARGET_TYPE_EQ>();
    auto  l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto  l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    auto l_ex_vector = l_quad.getChildren<fapi2::TARGET_TYPE_EX>
                       (fapi2::TARGET_STATE_FUNCTIONAL);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_SDISN_SETUP, l_chip,
                           l_attr_sdisn_setup));

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLED,      l_chip,
                           l_attr_vdm_enabled));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,    l_perv,
                           l_attr_chip_unit_pos));
    l_attr_chip_unit_pos = (l_attr_chip_unit_pos -
                            p9hcd::PERV_TO_CORE_POS_OFFSET) % 4;

    //Check if EQ is powered off; if so, return
    FAPI_TRY(fapi2::getScom(l_quad, EQ_PPM_PFSNS, l_data64),
             "Error reading data from EQ_PPM_PFSNS");

    if (l_data64.getBit<EQ_PPM_PFSNS_VDD_PFETS_DISABLED_SENSE>())
    {
        FAPI_DBG("Set core as stopped in STOP history register");
        FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0)));
        return fapi2::current_err;
    }

    //Check if core is powered off; if so, return
    FAPI_TRY(fapi2::getScom(i_target, C_PPM_PFSNS, l_data64),
             "Error reading data from C_PPM_PFSNS");

    if (l_data64.getBit<C_PPM_PFSNS_VDD_PFETS_DISABLED_SENSE>())
    {
        FAPI_DBG("Set core as stopped in STOP history register");
        FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0)));
        return fapi2::current_err;
    }


    // ----------------------------
    // Prepare to stop core clocks
    // ----------------------------

    FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]");
    FAPI_TRY(getScom(i_target, C_PPM_GPMMR_SCOM, l_data64));

    if (!l_data64.getBit<15>())
    {
        FAPI_DBG("Gracefully turn off power management, continue anyways if fail");
        /// @todo RTC158181 suspend_pm()
    }

    FAPI_DBG("Check core clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_CORE>(i_target);

    if (l_rc)
    {
        FAPI_INF("Clock controller of this core chiplet is inaccessible, return");
        goto fapi_try_exit;
    }

    FAPI_DBG("Check cache clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(l_quad);

    if (l_rc)
    {
        FAPI_INF("WARNING: core is enabled while cache is not, continue anyways");
    }
    else
    {

        FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]");
        FAPI_TRY(getScom(l_quad, EQ_CLOCK_STAT_SL, l_data64));

        FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]");
        FAPI_TRY(getScom(l_quad, EQ_CPLT_CTRL1, l_temp64));

        if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0)
        {

#ifdef DD2
            FAPI_DBG("Halting the PGPE ...");
            l_rc = ppe_halt(l_chip, PGPE_BASE_ADDRESS);
            FAPI_ASSERT_NOEXIT(!l_rc,
                               fapi2::CORE_STOPCLKS_PGPE_HALT_TIMEOUT()
                               .set_CHIP(l_chip),
                               "PSTATE GPE Halt timeout");

            FAPI_DBG("Halting the SGPE ...");
            l_rc = ppe_halt(l_chip, SGPE_BASE_ADDRESS);
            FAPI_ASSERT_NOEXIT(!l_rc,
                               fapi2::CORE_STOPCLKS_SGPE_HALT_TIMEOUT()
                               .set_CHIP(l_chip),
                               "STOP GPE Halt timeout");

            FAPI_DBG("Clear the atomic lock on EQ %d", l_attr_chip_unit_pos);
            l_rc = p9_clear_atomic_lock(l_quad);
            FAPI_ASSERT_NOEXIT(!l_rc,
                               fapi2::CORE_STOPCLKS_ATOMIC_LOCK_FAIL()
                               .set_EQ(l_quad),
                               "EQ Atomic Halt timeout");

            for ( auto& ex : l_ex_vector )
            {
                fapi2::ATTR_CHIP_UNIT_POS_Type  l_cme_id = 0;
                FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, ex, l_cme_id));

                FAPI_DBG("Halting CME %d", l_cme_id );
                uint64_t l_cme_base_address = getCmeBaseAddress (l_cme_id);
                l_rc = ppe_halt(l_chip, l_cme_base_address);
                FAPI_ASSERT_NOEXIT(!l_rc,
                                   fapi2::CACHE_STOPCLKS_CME_HALT_TIMEOUT()
                                   .set_EX(ex),
                                   "CME Halt timeout");
            }

#endif

            //if a core is only in special wakeup and asserting pm_exit,
            //then setting 6,7 of SICR will cause pm_exit to drop and
            //the core will re-enter a power saving state
            FAPI_DBG("Prevent Core-L2 Quiesce from removing PM_EXIT CME_SCOM_LMCR[22]");
            FAPI_TRY(putScom(l_quad,
                             (l_attr_chip_unit_pos < 2) ?
                             EX_0_CME_SCOM_LMCR_OR : EX_1_CME_SCOM_LMCR_OR,
                             (BIT64(22))));

            FAPI_DBG("Assert Core-L2/CC Quiesces via CME_SCOM_SICR[6,8]/[7,9]");
            FAPI_TRY(putScom(l_quad,
                             (l_attr_chip_unit_pos < 2) ?
                             EX_0_CME_SCOM_SICR_OR : EX_1_CME_SCOM_SICR_OR,
                             (BIT64(6 + (l_attr_chip_unit_pos % 2)) |
                              BIT64(8 + (l_attr_chip_unit_pos % 2)))));
        }
    }

    FAPI_DBG("Assert pm_mux_disable to get PCB Mux from CME via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_SET(7)));

    FAPI_DBG("Override possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_OR, MASK_SET(1)));

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop core clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, C_SCAN_REGION_TYPE, MASK_ZERO));

    if(i_sync_stop_quad_clk)
    {
        FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION in SLAVE mode");
        l_data64 = (p9hcd::CLK_STOP_CMD_SLAVE     |
                    p9hcd::CLK_REGION_ALL_BUT_PLL |
                    p9hcd::CLK_THOLD_ALL);
        FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64));

    }
    else
    {
        FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION");
        l_data64 = (p9hcd::CLK_STOP_CMD           |
                    p9hcd::CLK_REGION_ALL_BUT_PLL |
                    p9hcd::CLK_THOLD_ALL);
        FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64));

        FAPI_DBG("Poll for core clocks stopped via CPLT_STAT0[8]");
        l_loops1ms = 1E6 / CORE_CLK_STOP_POLLING_HW_NS_DELAY;

        do
        {
            fapi2::delay(CORE_CLK_STOP_POLLING_HW_NS_DELAY,
                         CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY);

            FAPI_TRY(getScom(i_target, C_CPLT_STAT0, l_data64));
        }
        while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0));

        FAPI_ASSERT((l_loops1ms != 0),
                    fapi2::PMPROC_CORECLKSTOP_TIMEOUT().set_CORECPLTSTAT(l_data64),
                    "Core Clock Stop Timeout");

        FAPI_DBG("Check core clocks stopped via CLOCK_STAT_SL[4-13]");
        FAPI_TRY(getScom(i_target, C_CLOCK_STAT_SL, l_data64));

        FAPI_ASSERT((((~l_data64) & p9hcd::CLK_REGION_ALL_BUT_PLL) == 0),
                    fapi2::PMPROC_CORECLKSTOP_FAILED().set_CORECLKSTAT(l_data64),
                    "Core Clock Stop Failed");
        FAPI_DBG("Core clocks stopped now");
    }

    // -------------------------------
    // Disable core clock sync
    // -------------------------------

    FAPI_DBG("Drop core clock sync enable via CPPM_CACCR[15]");
    FAPI_TRY(putScom(i_target, C_CPPM_CACCR_CLEAR, MASK_SET(15)));

    FAPI_DBG("Poll for core clock sync done to drop via CPPM_CACSR[13]");
    l_loops1ms = 1E6 / CORE_CLK_SYNC_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_SYNC_POLLING_HW_NS_DELAY,
                     CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPPM_CACSR, l_data64));
    }
    while((l_data64.getBit<13>() == 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSYNCDROP_TIMEOUT().set_COREPPMCACSR(l_data64),
                "Core Clock Sync Drop Timeout");
    FAPI_DBG("Core clock sync done dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert skew sense to skew adjust fence via NET_CTRL0[22]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(22)));

    FAPI_DBG("Drop ABIST_SRAM_MODE_DC to support ABIST Recovery via BIST[1]");
    FAPI_TRY(getScom(i_target, C_BIST, l_data64));
    FAPI_TRY(putScom(i_target, C_BIST, DATA_UNSET(1)));

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, p9hcd::CLK_REGION_ALL));

    if (l_attr_sdisn_setup)
    {
        FAPI_DBG("DD1 Only: Drop sdis_n(flushing LCBES condition) vai CPLT_CONF0[34]");
        FAPI_TRY(putScom(i_target, C_CPLT_CONF0_CLEAR, MASK_SET(34)));
    }

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enabled == fapi2::ENUM_ATTR_VDM_ENABLED_TRUE)
    {
        FAPI_DBG("Set VDM Disable via CPPM_VDMCR[1]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_OR, MASK_SET(1)));
        FAPI_DBG("Drop VDM Poweron via CPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Update stop history
    // -------------------------------

    FAPI_DBG("Set core as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0)));

    // -------------------------------
    // Clean up
    // -------------------------------

    FAPI_DBG("Return possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_CLEAR, MASK_SET(1)));

    FAPI_DBG("Drop pm_mux_disable to release PCB Mux via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_UNSET(7)));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_core_stopclocks");
    return fapi2::current_err;
}
// HWP entry point, comments in header
fapi::ReturnCode proc_chiplet_scominit(const fapi::Target & i_target)
{
    fapi::ReturnCode rc;
    uint32_t rc_ecmd = 0;

    fapi::TargetType target_type;
    std::vector<fapi::Target> initfile_targets;
    std::vector<fapi::Target> ex_targets;
    std::vector<fapi::Target> mcs_targets;
    uint8_t nx_enabled;
    uint8_t mcs_pos;
    uint8_t ex_pos;
    uint8_t num_ex_targets;
    uint8_t master_mcs_pos = 0xFF;
    fapi::Target master_mcs;
    uint8_t enable_xbus_resonant_clocking = 0x0;
    uint8_t i2c_slave_address = 0x0;
    uint8_t dual_capp_present = 0x0;

    ecmdDataBufferBase data(64);
    ecmdDataBufferBase cfam_data(32);
    ecmdDataBufferBase mask(64);

    bool               is_master = false;

    // mark HWP entry
    FAPI_INF("proc_chiplet_scominit: Start");

    do
    {
        rc = proc_check_master_sbe_seeprom(i_target, is_master);
        if (!rc.ok())
        {
            FAPI_ERR("proc_cen_ref_clk_enable: Error from proc_check_master_sbe_seeprom");
            break;
        }

        // obtain target type to determine which initfile(s) to execute
        target_type = i_target.getType();

        // chip level target
        if (target_type == fapi::TARGET_TYPE_PROC_CHIP)
        {
            // execute FBC SCOM initfile
            initfile_targets.push_back(i_target);
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_FBC_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_FBC_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_FBC_IF,
                         i_target.toEcmdString());
                break;
            }

            // execute PSI SCOM initfile
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_PSI_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_PSI_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_PSI_IF,
                         i_target.toEcmdString());
                break;
            }

            // execute TP bridge SCOM initfile
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF,
                         i_target.toEcmdString());
                break;
            }

            // query NX partial good attribute
            rc = FAPI_ATTR_GET(ATTR_PROC_NX_ENABLE,
                               &i_target,
                               nx_enabled);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_PROC_NX_ENABLE");
                break;
            }

            // apply NX/AS SCOM initfiles only if partial good attribute is set
            if (nx_enabled == fapi::ENUM_ATTR_PROC_NX_ENABLE_ENABLE)
            {
                // execute NX SCOM initfile
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_NX_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_NX_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_NX_IF,
                             i_target.toEcmdString());
                    break;
                }

                // execute CXA SCOM initfile
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_CXA_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_CXA_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_CXA_IF,
                             i_target.toEcmdString());
                    break;
                }

                // configure CXA APC master LCO settings
                rc = fapiGetChildChiplets(i_target,
                                          fapi::TARGET_TYPE_EX_CHIPLET,
                                          ex_targets,
                                          fapi::TARGET_STATE_FUNCTIONAL);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiGetChildChiplets (EX) on %s",
                             i_target.toEcmdString());
                    break;
                }

                // form valid LCO target list
                for (std::vector<fapi::Target>::iterator i = ex_targets.begin();
                     i != ex_targets.end();
                     i++)
                {
                    // determine EX chiplet number
                    rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*i), ex_pos);

                    if (!rc.ok())
                    {
                        FAPI_ERR("proc_chiplet_scominit: Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS) on %s",
                                 i->toEcmdString());
                        break;
                    }

                    rc_ecmd |= data.setBit(ex_pos-((ex_pos < 8)?(1):(3)));
                }
                if (!rc.ok())
                {
                    break;
                }

                num_ex_targets = ex_targets.size();
                rc_ecmd |= data.insertFromRight(
                    num_ex_targets,
                    CAPP_APC_MASTER_LCO_TARGET_MIN_START_BIT,
                    (CAPP_APC_MASTER_LCO_TARGET_MIN_END_BIT-
                     CAPP_APC_MASTER_LCO_TARGET_MIN_START_BIT+1));

                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting APC Master LCO Target register data buffer",
                             rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }

                rc = fapiPutScom(i_target,
                                 CAPP_APC_MASTER_LCO_TARGET_0x02013021,
                                 data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (CAPP_APC_MASTER_LCO_TARGET_0x02013021) on %s",
                             i_target.toEcmdString());
                    break;
                }

                // get dual CAPP presence attribute
                FAPI_DBG("proc_chiplet_scominit: Querying dual CAPP feature attribute");
                rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_DUAL_CAPP_PRESENT,
                                   &i_target,
                                   dual_capp_present);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_CHIP_EC_FEATURE_DUAL_CAPP_PRESENT");
                    break;
                }
                
                if (dual_capp_present != 0)
                {
                    rc = fapiPutScom(i_target,
                                     CAPP1_APC_MASTER_LCO_TARGET_0x020131A1,
                                     data);
                    if (!rc.ok())
                    {
                        FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (CAPP1_APC_MASTER_LCO_TARGET_0x020131A1) on %s",
                                 i_target.toEcmdString());
                        break;
                    }
                }

                // execute AS SCOM initfile
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_AS_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_AS_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_AS_IF,
                             i_target.toEcmdString());
                    break;
                }
            }
            else
            {
                FAPI_DBG("proc_chiplet_scominit: Skipping execution of %s/%s/%s (partial good)",
                         PROC_CHIPLET_SCOMINIT_NX_IF, PROC_CHIPLET_SCOMINIT_CXA_IF, PROC_CHIPLET_SCOMINIT_AS_IF);
            }

            // conditionally enable I2C Slave
            rc = FAPI_ATTR_GET(ATTR_I2C_SLAVE_ADDRESS,
                               &i_target,
                               i2c_slave_address);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_I2C_SLAVE_ADDRESS on %s",
                         i_target.toEcmdString());
                break;
            }
            rc = fapiGetScom(i_target,
                             I2C_SLAVE_CONFIG_REG_0x000D0000,
                             data);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: fapiGetScom error (I2C_SLAVE_CONFIG_REG_0x000D0000) on %s",
                         i_target.toEcmdString());
                break;
            }
            if (i2c_slave_address)
            {
                FAPI_DBG("proc_chiplet_scominit: I2C Slave enabled (%s) address = %d",
                     i_target.toEcmdString(),i2c_slave_address);

                //set I2C address
                rc_ecmd |= data.insert(i2c_slave_address,0,7);

                // disable error state.  when this is enabled and there
                // is an error from I2CS it locks up the I2CS and no
                // more operations are allowed unless cleared
                // through FSI.  Not good for a FSPless system.
                rc_ecmd |= data.clearBit(23);

                // enable I2C interface
                rc_ecmd |= data.setBit(21);

            }
            else
            {
                FAPI_DBG("proc_chiplet_scominit: I2C Slave disabled (%s)",
                     i_target.toEcmdString());

                // disable I2C interface when attribute = 0x0
                rc_ecmd |= data.clearBit(21);
            }

            if (rc_ecmd)
            {
                FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting I2C Slave register data buffer",
                         rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }

            rc = fapiPutScom(i_target,
                             I2C_SLAVE_CONFIG_REG_0x000D0000,
                             data);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (I2C_SLAVE_CONFIG_REG_0x000D0000) on %s",
                         i_target.toEcmdString());
                break;
            }

            // conditionally enable resonant clocking for XBUS
            rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_XBUS_RESONANT_CLK_VALID,
                               &i_target,
                               enable_xbus_resonant_clocking);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_CHIP_EC_FEATURE_XBUS_RESONANT_CLK_VALID on %s",
                         i_target.toEcmdString());
                break;
            }

            if (enable_xbus_resonant_clocking)
            {
                FAPI_DBG("proc_chiplet_scominit: Enabling XBUS resonant clocking");
                rc = fapiGetScom(i_target,
                                 MBOX_FSIGP6_0x00050015,
                                 data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiGetScom error (MBOX_FSIGP6_0x00050015) on %s",
                             i_target.toEcmdString());
                    break;
                }

                rc_ecmd |= data.insertFromRight(
                    XBUS_RESONANT_CLOCK_CONFIG,
                    MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_START_BIT,
                    (MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_END_BIT-
                     MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_START_BIT+1));

                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting FSI GP6 register data buffer",
                             rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }

                if (is_master) 
                {
                    rc = fapiPutScom(i_target,
                                 MBOX_FSIGP6_0x00050015,
                                 data);
                    if (!rc.ok())
                    {
                        FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (MBOX_FSIGP6_0x00050015) on %s",
                             i_target.toEcmdString());
                        break;
                    }
                }
                else 
                {
                    cfam_data.insert(data, 0, 32, 0);
                    rc = fapiPutCfamRegister(i_target, CFAM_FSI_GP6_0x00002815, cfam_data);
                    if (rc)
                    {
                        FAPI_ERR("proc_cen_ref_clk_enable: fapiPutCfamRegister error (CFAM_FSI_GP8_0x00001017)");
                        break;
                    }
                }
            }

            // execute A/X/PCI/DMI FIR init SCOM initfile
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF,
                         i_target.toEcmdString());
                break;
            }

            // execute NV scominit file
            uint8_t exist_NV = 0x00;
            rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_NV_PRESENT, &i_target, exist_NV);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error getting attribute value ATTR_CHIP_EC_FEATURE_NV_PRESENT");
                break;
            }
            if (exist_NV)
            {
                FAPI_INF("proc_chiplet_scominit: Executing  %s on %s",
                         PROC_CHIPLET_SCOMINIT_NPU_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                        rc,
                        fapiHwpExecInitFile,
                        initfile_targets,
                        PROC_CHIPLET_SCOMINIT_NPU_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_NPU_IF,
                             i_target.toEcmdString());
                    break;
                }

                // cleanup FIR bit (NPU FIR bit 27) caused by NDL/NTL parity error
                rc_ecmd = data.flushTo1();
                rc_ecmd = data.clearBit(NPU_FIR_NTL_DL2TL_PARITY_ERR_BIT);
                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%Xforming NPU FIR cleanup data buffer",
                  	   rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }
                rc = fapiPutScom(i_target, NPU_FIR_AND_0x08013D81, data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (NPU_FIR_AND_0x08013D81) on %s",
                             i_target.toEcmdString());
                    break;
                }
                rc = fapiPutScom(i_target, NPU_FIR_MASK_AND_0x08013D84, data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (NPU_FIR_MASK_AND_0x08013D84) on %s",
                             i_target.toEcmdString());
                    break;
                }
            }
            else
            {
                FAPI_INF("proc_chiplet_scominit: NV link logic not present, scom initfile processing skipped");
            }

            // determine set of functional MCS chiplets
            rc = fapiGetChildChiplets(i_target,
                                      fapi::TARGET_TYPE_MCS_CHIPLET,
                                      mcs_targets,
                                      fapi::TARGET_STATE_FUNCTIONAL);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiGetChildChiplets (MCS) on %s",
                         i_target.toEcmdString());
                break;
            }

            // apply MCS SCOM initfile only for functional chiplets
            for (std::vector<fapi::Target>::iterator i = mcs_targets.begin();
                 (i != mcs_targets.end()) && rc.ok();
                 i++)
            {
                // execute MCS SCOM initfile
                initfile_targets.clear();
                initfile_targets.push_back(*i);
                initfile_targets.push_back(i_target);
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_MCS_IF, i->toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_MCS_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_MCS_IF,
                             i->toEcmdString());
                    break;
                }

                // determine MCS position
                rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*i), mcs_pos);

                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS) on %s",
                             i->toEcmdString());
                    break;
                }

                if (mcs_pos < master_mcs_pos)
                {
                    fapi::Target cen_target_unused;
                    rc = fapiGetOtherSideOfMemChannel(*i,
                                                      cen_target_unused,
                                                      fapi::TARGET_STATE_FUNCTIONAL);
                    // use return code only to indicate presence of connected Centaur,
                    // do not propogate/emit error if not connected
                    if (rc.ok())
                    {
                        FAPI_DBG("Updating master_mcs_pos to %d", mcs_pos);
                        FAPI_DBG("  Target: %s", cen_target_unused.toEcmdString());
                        master_mcs = *i;
                        master_mcs_pos = mcs_pos;
                    }
                    else
                    {
                        rc = fapi::FAPI_RC_SUCCESS;
                    }
                }

            }
            if (!rc.ok())
            {
                break;
            }

            if (master_mcs.getType() == fapi::TARGET_TYPE_MCS_CHIPLET)
            {
                // set MCMODE0Q_ENABLE_CENTAUR_SYNC on first target only
                // (this bit is required to be set on at most one MCS/chip)
                rc_ecmd |= data.flushTo0();
                rc_ecmd |= data.setBit(MCSMODE0_EN_CENTAUR_SYNC_BIT);
                rc_ecmd |= mask.setBit(MCSMODE0_EN_CENTAUR_SYNC_BIT);

                // check buffer manipulation return codes
                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%X setting up MCSMODE0 data buffer",
                             rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }

                // write register with updated content
                rc = fapiPutScomUnderMask(master_mcs,
                                          MCS_MCSMODE0_0x02011807,
                                          data,
                                          mask);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScomUnderMask error (MCS_MCSMODE0_0x02011807) on %s",
                             master_mcs.toEcmdString());
                    break;
                }

            }
        }
        // unsupported target type
        else
        {
            FAPI_ERR("proc_chiplet_scominit: Unsupported target type");
            const fapi::Target & TARGET = i_target;
            FAPI_SET_HWP_ERROR(rc, RC_PROC_CHIPLET_SCOMINIT_INVALID_TARGET);
            break;
        }
    } while(0);

    // mark HWP exit
    FAPI_INF("proc_chiplet_scominit: End");
    return rc;
}
Beispiel #21
0
fapi::ReturnCode mss_volt(std::vector<fapi::Target> & i_targets_memb)
{

    fapi::ReturnCode l_rc;
    uint8_t l_dimm_functionality=0;
    uint8_t l_spd_dramtype=0;
    uint8_t l_spd_volts=0;
    uint8_t l_spd_volts_all_dimms=0x06;  //start assuming all voltages supported
    uint8_t l_dram_ddr3_found_flag=0;
    uint8_t l_dram_ddr4_found_flag=0;
    uint8_t l_volt_override = 0x00;
    uint8_t l_volt_override_domain = 0x00;

    uint32_t l_selected_dram_voltage=0;  //this gets written into all centaurs when done.
    uint32_t l_selected_dram_voltage_vpp=0;
    uint32_t l_tolerated_dram_voltage = MAX_TOLERATED_VOLT; //initially set to the max tolerated voltage

    do
    {
        // Iterate through the list of centaurs
        for (uint32_t i=0; i < i_targets_memb.size(); i++)
        {
            std::vector<fapi::Target> l_mbaChiplets;
            // Get associated MBA's on this centaur
            l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
            if (l_rc) break;


	    l_rc = FAPI_ATTR_GET(ATTR_MSS_VOLT_OVERRIDE, &i_targets_memb[i], l_volt_override);
	    if (l_rc) break;

	    // Note if there is an overrride being applied on the domain
	    if ( (l_volt_override != fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_NONE) && (l_volt_override_domain == fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_NONE) )
	    {
	    	l_volt_override_domain = l_volt_override;
	    }

	    // Error if our overides are not the same across the domain
	    if (l_volt_override_domain != l_volt_override)
	    {
                        // this just needs to callout the mismatching memb.
                        const uint8_t &OVERRIDE_TYPE = l_volt_override;
                        const uint8_t &OVERRIDE_DOMAIN_TYPE = l_volt_override_domain;
                        const fapi::Target &MEMB_TARGET = i_targets_memb[i];
                        FAPI_ERR("Mismatch volt override request.  Domain: 0x%x  Current Target Requests: 0x%x", l_volt_override_domain, l_volt_override);
                        FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_OVERIDE_MIXING);
                        fapiLogError(l_rc);
	    }

            // Loop through the 2 MBA's
            for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
            {
                std::vector<fapi::Target> l_dimm_targets;
                // Get a vector of DIMM targets
                l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                if (l_rc) break;

                for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                {
                    l_rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_DEVICE_TYPE, &l_dimm_targets[k], l_spd_dramtype);
                    if (l_rc) break;
                    l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_NOMINAL_VOLTAGE, &l_dimm_targets[k], l_spd_volts);
                    if (l_rc) break;
                    l_rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_dimm_targets[k], l_dimm_functionality);
                    if (l_rc) break;

                    // spd_volts:  bit0= NOT 1.5V bit1=1.35V bit2=1.25V, assume a 1.20V in future for DDR4
                    // check for supported voltage/dram type combo  DDR3=12, DDR4=13
                    if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
                    {
                        l_dram_ddr3_found_flag=1;
                    }
                    else if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4)
                    {
                        l_dram_ddr4_found_flag=1;
                    }
                    else 
                    {
                        // this just needs to be deconfiged at the dimm level
                        const uint8_t &DEVICE_TYPE = l_spd_dramtype;
                        const fapi::Target &DIMM_TARGET = l_dimm_targets[k];
                        FAPI_ERR("Unknown DRAM Device Type 0x%x", l_spd_dramtype);
                        FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_UNRECOGNIZED_DRAM_DEVICE_TYPE);
                        fapiLogError(l_rc);
                    }

                    if(l_dimm_functionality == fapi::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL)
                    {
                        //AND dimm voltage capabilities together to find aggregate voltage support on all dimms
                        l_spd_volts_all_dimms = l_spd_volts_all_dimms & l_spd_volts;
                    }

                }//end of dimms loop
                if (l_rc)
                {
                    break;
                }
            }//end of mba loop
            if (l_rc)
            {
                break;
            }
        }//end of centaur (memb) loop      
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }

        // now we figure out if we have a supported ddr type and voltage
        // note: only support DDR3=1.35V and DDR4=1.2xV


        // Mixed Dimms, Deconfig the DDR4.
        if (l_dram_ddr3_found_flag && l_dram_ddr4_found_flag)
        {
            std::vector<fapi::Target> l_dimm_targets_deconfig;
            // Iterate through the list of centaurs
            for (uint32_t i=0; i < i_targets_memb.size(); i++)
            {
                std::vector<fapi::Target> l_mbaChiplets;
                // Get associated MBA's on this centaur
                l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
                if (l_rc) break;
                // Loop through the 2 MBA's
                for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
                {
                    std::vector<fapi::Target> l_dimm_targets;
                    // Get a vector of DIMM targets
                    l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                    if (l_rc) break;
                    for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                    {

                        l_rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_DEVICE_TYPE, &l_dimm_targets[k], l_spd_dramtype);
                        if (l_rc) break;

                        if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4)
                        {
                            const fapi::Target &DIMM_DDR4_TARGET = l_dimm_targets[k];
                            const uint8_t &DEVICE_TYPE = l_spd_dramtype;
                            FAPI_ERR("mss_volt: DDR3 and DDR4 mixing not allowed");
                            FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_DDR_TYPE_MIXING_UNSUPPORTED);
                            fapiLogError(l_rc);
                        }

                    }//end of dimms loop
                    if (l_rc)
                    {
                        break;
                    }
                }//end of mba loop
                if (l_rc)
                {
                    break;
                }
            }//end of centaur (memb) loop 

        }
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }


	if (l_volt_override != fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_NONE)
	{
	    if (l_volt_override == fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_VOLT_135)
	    {
		l_tolerated_dram_voltage = 1350;
		FAPI_INF( "mss_volt_overide being applied.  MSS_VOLT_OVERRIDE: 1.35V");
		FAPI_INF( "NOTE: Still checking for violations of tolerated voltage.  If DIMMs cannot tolerate, the override will not be applied.");
	    }
	    if (l_volt_override == fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_VOLT_120)
	    {
	        l_tolerated_dram_voltage = 1200;
		FAPI_INF( "mss_volt_overide being applied.  MSS_VOLT_OVERRIDE: 1.20V");
		FAPI_INF( "NOTE: Still checking for violations of tolerated voltage.  If DIMMs cannot tolerate, the override will not be applied.");
	    }
	    else
	    {
                const uint8_t &OVERRIDE_TYPE = l_volt_override;
                FAPI_ERR("Unknown volt override request.  Override Request: 0x%x", l_volt_override);
                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_OVERIDE_UKNOWN);
                fapiLogError(l_rc);
	    }

	}
        else if (l_dram_ddr3_found_flag && ((l_spd_volts_all_dimms & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35) == fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35))
        {
            l_selected_dram_voltage=1350;
	    l_selected_dram_voltage_vpp = DDR3_VPP_VOLT;
        }
        else if (l_dram_ddr4_found_flag && ((l_spd_volts_all_dimms & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2X) == fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2X))
        {
            l_selected_dram_voltage=1200;
            l_selected_dram_voltage_vpp = DDR4_VPP_VOLT;
        }
        else if ((l_spd_volts_all_dimms & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) != fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5)
        {
            l_selected_dram_voltage=1500;
	    l_selected_dram_voltage_vpp = DDR3_VPP_VOLT;
        }
        else
        {

            std::vector<fapi::Target> l_dimm_targets_deconfig;
            // Iterate through the list of centaurs
            for (uint32_t i=0; i < i_targets_memb.size(); i++)
            {
                std::vector<fapi::Target> l_mbaChiplets;
                // Get associated MBA's on this centaur
                l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
                if (l_rc) break;
                // Loop through the 2 MBA's
                for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
                {
                    std::vector<fapi::Target> l_dimm_targets; 
                    // Get a vector of DIMM targets
                    l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                    if (l_rc) break;
                    for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                    {
                        l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_NOMINAL_VOLTAGE, &l_dimm_targets[k], l_spd_volts);
                        if (l_rc) break;

                        if((l_spd_volts & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) == fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5)
                        {
                            const fapi::Target &DIMM_UV_TARGET = l_dimm_targets[k];
                            const uint8_t &DIMM_VOLTAGE = l_spd_volts;
                            FAPI_ERR("One or more DIMMs do not support required voltage for DIMM type");
                            FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_DDR_TYPE_REQUIRED_VOLTAGE);
                            fapiLogError(l_rc);
                        }

                    }//end of dimms loop
                    if (l_rc)
                    {
                        break;
                    }
                }//end of mba loop
                if (l_rc)
                {
                    break;
                }
            }//end of centaur (memb) loop  
        }
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }



        // Must check to see if we violate Tolerent voltages of Non-functional Dimms
        // If so we must error/deconfigure on the dimm level primarily then centaur level.
        // Iterate through the list of centaurs
        for (uint32_t i=0; i < i_targets_memb.size(); i++)
        {
            std::vector<fapi::Target> l_dimm_targets_deconfig;

            l_tolerated_dram_voltage = MAX_TOLERATED_VOLT; // using 1.5 as this is the largest supported voltage
            std::vector<fapi::Target> l_mbaChiplets;
            // Get associated MBA's on this centaur
            l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
            if (l_rc) break;
            for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
            {
                std::vector<fapi::Target> l_dimm_targets;
                // Get a vector of DIMM targets
                l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                if (l_rc) break;
                for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                {
                    l_rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_dimm_targets[k], l_dimm_functionality);
                    if (l_rc) break;

                    if(l_dimm_functionality == fapi::ENUM_ATTR_FUNCTIONAL_NON_FUNCTIONAL)
                    {
                        if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
                        {
                            if (l_tolerated_dram_voltage > MAX_TOLERATED_DDR3_VOLT)
                            {
                                l_tolerated_dram_voltage =  MAX_TOLERATED_DDR3_VOLT;
                            }

                            if (MAX_TOLERATED_DDR3_VOLT < l_selected_dram_voltage)
                            {
                                FAPI_ERR("One or more DIMMs classified non-functional has a"
                                         " tolerated voltage below selected voltage.");
                                const fapi::Target & CHIP_TARGET = l_dimm_targets[k];
                                const uint8_t &DIMM_VOLTAGE = l_selected_dram_voltage;
                                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION);
                                fapiLogError(l_rc);
                            }
                        }
                        if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4)
                        {
                            if (l_tolerated_dram_voltage > MAX_TOLERATED_DDR4_VOLT)
                            {
                                l_tolerated_dram_voltage =  MAX_TOLERATED_DDR4_VOLT;
                            }

                            if (MAX_TOLERATED_DDR4_VOLT < l_selected_dram_voltage)
                            {
                                FAPI_ERR("One or more DIMMs classified non-functional has a"
                                         " tolerated voltage below selected voltage.");
                                const fapi::Target & CHIP_TARGET = l_dimm_targets[k];
                                const uint8_t &DIMM_VOLTAGE = l_selected_dram_voltage;
                                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION);
                                fapiLogError(l_rc);
                            }
                        }

                    }//End of functional check
                }//End of Dimm loop
                if (l_rc)
                {
                    break;
                }
            }// End of MBA loop
            if (l_rc)
            {
                break;
            }
            if ( l_tolerated_dram_voltage < l_selected_dram_voltage )
            {

                FAPI_ERR("Deconfiguring the associated Centaur.");
                const fapi::Target & CHIP_TARGET = i_targets_memb[i];
                const uint8_t &DIMM_VOLTAGE = l_selected_dram_voltage;
                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION);
                break;
            }
        }//End of Centaur (MEMB) loop
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }

        // Iterate through the list of centaurs again, to update ATTR
        for (uint32_t i=0; i < i_targets_memb.size(); i++)
        {
            l_rc = FAPI_ATTR_SET(ATTR_MSS_VOLT, &i_targets_memb[i], l_selected_dram_voltage);
            FAPI_INF( "mss_volt calculation complete.  MSS_VOLT: %d", l_selected_dram_voltage);
            if (l_rc) break;

	    l_rc = FAPI_ATTR_SET(ATTR_MSS_VOLT_VPP, &i_targets_memb[i], l_selected_dram_voltage_vpp);
            FAPI_INF( "mss_volt calculation complete.  MSS_VOLT_VPP: %d", l_selected_dram_voltage_vpp);
            if (l_rc) break;

        }
    }while(0);
    return l_rc;
}
Beispiel #22
0
// NOTE: see doxygen comments in header
fapi2::ReturnCode
p9_smp_link_layer(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const bool i_train_electrical,
    const bool i_train_optical)
{
    FAPI_INF("Start");

    FAPI_DBG("Input args: i_train_electrical: %d, i_train_optical: %d\n",
             i_train_electrical, i_train_optical);

    // logical link (X/A) configuration parameters
    // enable on local end
    uint8_t l_x_en[P9_FBC_UTILS_MAX_X_LINKS];
    uint8_t l_a_en[P9_FBC_UTILS_MAX_A_LINKS];

    // process set of enabled links
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_X_ATTACHED_CHIP_CNFG,
                           i_target,
                           l_x_en),
             "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_X_ATTACHED_CHIP_CNFG");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG,
                           i_target,
                           l_a_en),
             "Error from FAPI_ATTR_GET (ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG");

    for (uint8_t l_link = 0; l_link < P9_FBC_UTILS_MAX_X_LINKS; l_link++)
    {
        if (l_x_en[l_link])
        {
            if (i_train_electrical &&
                (P9_FBC_XBUS_LINK_CTL_ARR[l_link].endp_type == ELECTRICAL))
            {
                FAPI_DBG("Training link X%d (electrical)", l_link);
                FAPI_TRY(p9_smp_link_layer_train_link_electrical(
                             i_target,
                             P9_FBC_XBUS_LINK_CTL_ARR[l_link],
                             l_x_en[l_link]),
                         "Error from p9_smp_link_layer_train_link (X, electrical)");
            }

            if (i_train_optical &&
                (P9_FBC_XBUS_LINK_CTL_ARR[l_link].endp_type == OPTICAL))
            {
                FAPI_DBG("Training link X%d (optical)", l_link);
                FAPI_TRY(p9_smp_link_layer_train_link_optical(
                             i_target,
                             P9_FBC_XBUS_LINK_CTL_ARR[l_link],
                             l_x_en[l_link]),
                         "Error from p9_smp_link_layer_train_link (X, optical)");
            }
        }
        else
        {
            FAPI_DBG("Skipping link X%d", l_link);
        }
    }

    for (uint8_t l_link = 0; l_link < P9_FBC_UTILS_MAX_A_LINKS; l_link++)
    {
        if (l_a_en[l_link])
        {
            if (i_train_optical &&
                (P9_FBC_ABUS_LINK_CTL_ARR[l_link].endp_type == OPTICAL))
            {
                FAPI_DBG("Training link A%d", l_link);
                FAPI_TRY(p9_smp_link_layer_train_link_optical(
                             i_target,
                             P9_FBC_ABUS_LINK_CTL_ARR[l_link],
                             l_a_en[l_link]),
                         "Error from p9_smp_link_layer_train_link (A)");
            }
        }
        else
        {
            FAPI_DBG("Skipping link A%d", l_link);
        }
    }

fapi_try_exit:
    FAPI_INF("End");
    return fapi2::current_err;
}
Beispiel #23
0
///
/// @brief Engage DLL/TL training for a single fabric link (X/A)
///        running on O PHY
///
/// @param[in] i_target Reference to processor chip target
/// @param[in] i_ctl Reference to link control structure
/// @param[in] i_en Defines sublinks to enable
///
/// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode
p9_smp_link_layer_train_link_optical(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const p9_fbc_link_ctl_t& i_ctl,
    const uint8_t i_en)
{
    FAPI_DBG("Start");
    fapi2::buffer<uint64_t> l_dll_control_data;
    fapi2::buffer<uint64_t> l_dll_control_mask;
    fapi2::Target<fapi2::TARGET_TYPE_OBUS> l_loc_target;
    fapi2::Target<fapi2::TARGET_TYPE_OBUS> l_rem_target;
    fapi2::ATTR_CHIP_EC_FEATURE_HW419022_Type l_hw419022 = 0;

    bool l_even = (i_en == fapi2::ENUM_ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG_TRUE) ||
                  (i_en == fapi2::ENUM_ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG_EVEN_ONLY);

    bool l_odd = (i_en == fapi2::ENUM_ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG_TRUE) ||
                 (i_en == fapi2::ENUM_ATTR_PROC_FABRIC_A_ATTACHED_CHIP_CNFG_ODD_ONLY);

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_HW419022,
                           i_target,
                           l_hw419022),
             "Error from FAPI_ATTR_GET (fapi2::ATTR_CHIP_EC_FEATURE_HW419022)");

    // find local endpoint target associated with this link
    for (auto& l_target : i_target.getChildren<fapi2::TARGET_TYPE_OBUS>())
    {
        uint8_t l_unit_pos;
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,
                               l_target,
                               l_unit_pos),
                 "Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS)");

        if (l_unit_pos == i_ctl.endp_unit_id)
        {
            l_loc_target = l_target;
            break;
        }
    }

    FAPI_TRY(l_loc_target.getOtherEnd(l_rem_target),
             "Error from getOtherEnd");

    if (!l_hw419022)
    {
        if (l_even)
        {
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_PHY_TRAINING>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_PHY_TRAINING>();
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_STARTUP>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_STARTUP>();
        }

        if (l_odd)
        {
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_PHY_TRAINING>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_PHY_TRAINING>();
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_STARTUP>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_STARTUP>();
        }

        FAPI_TRY(fapi2::putScomUnderMask(i_target,
                                         i_ctl.dl_control_addr,
                                         l_dll_control_data,
                                         l_dll_control_mask),
                 "Error writing DLL control register (0x%08X)!",
                 i_ctl.dl_control_addr);
    }
    else
    {
        // force assertion of run_lane
        if (l_even)
        {
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_RUN_LANE_OVERRIDE>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_RUN_LANE_OVERRIDE>();
        }

        if (l_odd)
        {
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_RUN_LANE_OVERRIDE>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_RUN_LANE_OVERRIDE>();
        }

        FAPI_TRY(fapi2::putScomUnderMask(i_target,
                                         i_ctl.dl_control_addr,
                                         l_dll_control_data,
                                         l_dll_control_mask),
                 "Error writing DLL control register (0x%08X, force RUN_LANE)",
                 i_ctl.dl_control_addr);

        // ensure that DL RX sees lane lock
        if (l_even)
        {
            FAPI_TRY(p9_smp_link_layer_lock_lanes(i_target,
                                                  l_loc_target,
                                                  l_rem_target,
                                                  i_ctl,
                                                  true),
                     "Error from p9_smp_link_layer_lock_lanes (even)");
        }

        if (l_odd)
        {
            FAPI_TRY(p9_smp_link_layer_lock_lanes(i_target,
                                                  l_loc_target,
                                                  l_rem_target,
                                                  i_ctl,
                                                  false),
                     "Error from p9_smp_link_layer_lock_lanes (odd)");
        }

        // enable link startup
        if (l_even)
        {
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_STARTUP>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_STARTUP>();
        }

        if (l_odd)
        {
            l_dll_control_data.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_STARTUP>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_STARTUP>();
        }

        FAPI_TRY(fapi2::putScomUnderMask(i_target,
                                         i_ctl.dl_control_addr,
                                         l_dll_control_data,
                                         l_dll_control_mask),
                 "Error writing DLL control register (0x%08X, set LINK_STARTUP)!",
                 i_ctl.dl_control_addr);

        // disable run lane override
        if (l_even)
        {
            l_dll_control_data.clearBit<OBUS_LL0_IOOL_CONTROL_LINK0_RUN_LANE_OVERRIDE>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK0_RUN_LANE_OVERRIDE>();
        }

        if (l_odd)
        {
            l_dll_control_data.clearBit<OBUS_LL0_IOOL_CONTROL_LINK1_RUN_LANE_OVERRIDE>();
            l_dll_control_mask.setBit<OBUS_LL0_IOOL_CONTROL_LINK1_RUN_LANE_OVERRIDE>();
        }

        FAPI_TRY(fapi2::putScomUnderMask(i_target,
                                         i_ctl.dl_control_addr,
                                         l_dll_control_data,
                                         l_dll_control_mask),
                 "Error writing DLL control register (0x%08X, clar RUN_LANE_OVERRIDE)!",
                 i_ctl.dl_control_addr);

        // clear TX lane control override, set to ENABLED
        if (l_even)
        {
            uint64_t l_addr = i_ctl.dl_control_addr +
                              OFFSET_FROM_DL_CONTROL_TO_TX_EVEN_LANE_CONTROL;

            FAPI_TRY(fapi2::putScom(i_target,
                                    l_addr,
                                    0x0000000000000000ULL),
                     "Error from putScom (0x%08X, ENABLE)", l_addr);
        }

        if (l_odd)
        {
            uint64_t l_addr = i_ctl.dl_control_addr +
                              OFFSET_FROM_DL_CONTROL_TO_TX_ODD_LANE_CONTROL;

            FAPI_TRY(fapi2::putScom(i_target,
                                    l_addr,
                                    0x0000000000000000ULL),
                     "Error from putScom (0x%08X, ENABLE)", l_addr);
        }
    }

    // CQ: HW453889 :: MFG Abus Stress >>>
    //
    // Use rx_pr_data_a_offset to shift the offset by +1/2 or +2/4
    {
        uint8_t l_pr_offset_even = 0;
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_O_MFG_STRESS_PR_OFFSET_EVEN,
                               i_target,
                               l_pr_offset_even),
                 "Error from FAPI_ATTR_GET (ATTR_IO_O_MFG_STRESS_OFFSET_EVEN)");

        if (l_even && (l_pr_offset_even != 0))
        {
            FAPI_TRY(p9_smp_phy_mfg_stress(i_target, l_loc_target, l_pr_offset_even, true));
        }

        uint8_t l_pr_offset_odd = 0;
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_O_MFG_STRESS_PR_OFFSET_ODD,
                               i_target,
                               l_pr_offset_odd),
                 "Error from FAPI_ATTR_GET (ATTR_IO_O_MFG_STRESS_OFFSET_ODD)");

        if (l_odd && (l_pr_offset_odd != 0))
        {
            FAPI_TRY(p9_smp_phy_mfg_stress(i_target, l_loc_target, l_pr_offset_odd, false));
        }
    }
    // CQ: HW453889 :: MFG Abus Stress <<<


fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}
fapi2::ReturnCode p9a_omi_setup_bars(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_DBG("Start");
    std::vector<uint64_t> l_base_addr_nm0;
    std::vector<uint64_t> l_base_addr_nm1;
    std::vector<uint64_t> l_base_addr_m;
    fapi2::buffer<uint64_t> l_mmio_bar;
    fapi2::buffer<uint64_t> l_cfg_bar;
    uint64_t l_base_addr_mmio;
    uint8_t l_pos;
    uint8_t l_mcc_pos;
    uint64_t l_ext_mask;

    // determine base address of chip MMIO range
    FAPI_TRY(p9_fbc_utils_get_chip_base_address(i_target,
             EFF_FBC_GRP_CHIP_IDS,
             l_base_addr_nm0,
             l_base_addr_nm1,
             l_base_addr_m,
             l_base_addr_mmio),
             "Error from p9_fbc_utils_get_chip_base_address");

    FAPI_TRY(p9a_get_ext_mask(l_ext_mask));

    FAPI_DBG("l_ext_mask: %x", l_ext_mask);
    FAPI_DBG("l_base_addr_mmio: 0x%llx", l_base_addr_mmio);

    for (auto l_mcc : i_target.getChildren<fapi2::TARGET_TYPE_MCC>())
    {
        fapi2::ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET_Type l_bar_offset;
        uint64_t l_omi_inband_addr = 0;
        fapi2::buffer<uint64_t> l_scom_data;

        auto l_omi_targets = l_mcc.getChildren<fapi2::TARGET_TYPE_OMI>();

        if (l_omi_targets.size() > 0)
        {

            // Set the sizes for the MMIO/Config bars
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_mcc, l_pos),
                     "Error getting ATTR_CHIP_UNIT_POS, l_rc 0x%.8X",
                     (uint64_t)fapi2::current_err);

            l_scom_data.flush<0>();
            // 2GB cfg and MMIO
            l_scom_data.insertFromRight<P9A_MI_MCFGP0_MCFGPR0_CONFIGURATION_GROUP_SIZE,
                                        P9A_MI_MCFGP0_MCFGPR0_CONFIGURATION_GROUP_SIZE_LEN>(mss::exp::ib::EXPLR_IB_BAR_SIZE);
            l_scom_data.insertFromRight<P9A_MI_MCFGP0_MCFGPR0_MMIO_GROUP_SIZE,
                                        P9A_MI_MCFGP0_MCFGPR0_MMIO_GROUP_SIZE_LEN>(mss::exp::ib::EXPLR_IB_BAR_SIZE);

            // Write to reg
            if (l_pos % 2 == 0)
            {
                FAPI_INF("Write MCFGP0 reg 0x%.16llX, Value 0x%.16llX",
                         P9A_MI_MCFGP0, l_scom_data);
                FAPI_TRY(fapi2::putScom(l_mcc.getParent<fapi2::TARGET_TYPE_MI>(), P9A_MI_MCFGP0, l_scom_data),
                         "Error writing to MCS_MCFGP reg");
            }
            else
            {
                FAPI_INF("Write MCFGP1 reg 0x%.16llX, Value 0x%.16llX",
                         P9A_MI_MCFGP1, l_scom_data);
                FAPI_TRY(fapi2::putScom(l_mcc.getParent<fapi2::TARGET_TYPE_MI>(), P9A_MI_MCFGP1, l_scom_data),
                         "Error writing to MCS_MCFGP reg");
            }

            for (auto l_omi : l_omi_targets)
            {
                // retrieve OMI pos
                FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,
                                       l_omi,
                                       l_pos),
                         "Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS)");

                // retrieve inband BAR offset
                FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET,
                                       l_omi,
                                       l_bar_offset),
                         "Error from FAPI_ATTR_GET (ATTR_OMI_INBAND_BAR_BASE_ADDR_OFFSET)");

                FAPI_DBG("l_bar_offset: 0x%llx", l_bar_offset);

                // If this is channel B, then the B bit must be set.  If it is not, then the B bit must not be set.
                FAPI_ASSERT( ((l_pos % 2) == 1) ==  // Is this B channel?
                             ((l_bar_offset & mss::exp::ib::EXPLR_IB_BAR_B_BIT) == mss::exp::ib::EXPLR_IB_BAR_B_BIT),

                             fapi2::PROC_OMI_SETUP_BARS_INVALID_BAR()
                             .set_TARGET(l_omi)
                             .set_BAR_VALUE(l_bar_offset),
                             "B Channel requires BAR size bit set");

                FAPI_ASSERT(((l_bar_offset & mss::exp::ib::EXPLR_IB_BAR_MASK_ZERO) == 0),
                            fapi2::PROC_OMI_SETUP_BARS_INVALID_BAR()
                            .set_TARGET(l_omi)
                            .set_BAR_VALUE(l_bar_offset),
                            "Bar size not honored");

                FAPI_ASSERT(((l_bar_offset & mss::exp::ib::EXPLR_IB_MMIO_OFFSET) == 0),
                            fapi2::PROC_OMI_SETUP_BARS_INVALID_BAR()
                            .set_TARGET(l_omi)
                            .set_BAR_VALUE(l_bar_offset),
                            "MMIO bit must not be set");

                l_omi_inband_addr = l_bar_offset;
            }

            FAPI_DBG("l_omi_inband_addr: 0x%llx", l_omi_inband_addr);

            // Force A Bar value
            l_omi_inband_addr = l_omi_inband_addr & (~mss::exp::ib::EXPLR_IB_BAR_B_BIT);

            FAPI_DBG("l_omi_inband_addr: 0x%llx", l_omi_inband_addr);

            // Add MMIO address for the chip
            l_omi_inband_addr = l_omi_inband_addr | l_base_addr_mmio;

            FAPI_DBG("l_omi_inband_addr: 0x%llx", l_omi_inband_addr);

            // Get cfg bar value
            fapi2::buffer<uint64_t> l_omi_inband_buf = l_omi_inband_addr;
            FAPI_DBG("l_omi_inband_buf: 0x%llx", l_omi_inband_buf);
            FAPI_TRY(extendBarAddress(l_ext_mask, l_omi_inband_buf, l_cfg_bar));

            FAPI_DBG("l_cfg_bar: 0x%llx", l_cfg_bar);

            // Get MMIO bar value
            l_omi_inband_addr = l_omi_inband_addr | mss::exp::ib::EXPLR_IB_MMIO_OFFSET;
            l_omi_inband_buf = l_omi_inband_addr;
            FAPI_DBG("l_omi_inband_buf: 0x%llx", l_omi_inband_buf);
            FAPI_TRY(extendBarAddress(l_ext_mask, l_omi_inband_buf, l_mmio_bar));

            FAPI_DBG("l_mmio_bar: 0x%llx", l_mmio_bar);

            // Write the channel cfg reg
            l_scom_data.flush<0>();
            l_scom_data.setBit<P9A_MI_MCFGPR0_CONFIGURATION_VALID>(); //Enable CFG
            l_scom_data.setBit<P9A_MI_MCFGPR0_MMIO_VALID>(); //Enable MMIO
            l_scom_data.insert<P9A_MI_MCFGPR0_CONFIGURATION_GROUP_BASE_ADDRESS,
                               P9A_MI_MCFGPR0_CONFIGURATION_GROUP_BASE_ADDRESS_LEN>(l_cfg_bar);
            l_scom_data.insert<P9A_MI_MCFGPR0_MMIO_GROUP_BASE_ADDRESS,
                               P9A_MI_MCFGPR0_MMIO_GROUP_BASE_ADDRESS_LEN>(l_mmio_bar);

            // get MI target to configure MCFGPR
            fapi2::Target<fapi2::TARGET_TYPE_MI> l_mi =
                l_mcc.getParent<fapi2::TARGET_TYPE_MI>();
            // retrieve DMI pos
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,
                                   l_mcc,
                                   l_mcc_pos),
                     "Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS)");

            // configure inband channel 0 MCFGPR0
            if(l_mcc_pos % 2 == 0)
            {
                FAPI_TRY(putScom(l_mi, P9A_MI_MCFGPR0, l_scom_data));
            }
            // configure inband channel 1 MCFGPR1
            else
            {
                FAPI_TRY(putScom(l_mi, P9A_MI_MCFGPR1, l_scom_data));
            }
        }
    }

fapi_try_exit:
    FAPI_DBG("End");
    return fapi2::current_err;
}
/**
 * @brief Returns SPD_MODULE_NOMINAL_VOLTAGE data
 *
 * The raw data has different meanings for DDR3 and DDR4, this HWP translates
 * each to the enumeration in the common FAPI Attribute
 *
 * @param[in]  i_dimm Reference to DIMM fapi target
 * @param[in]  i_attr The Attribute to get
 * @param[out] o_pVal Pointer to data buffer filled in with attribute data
 * @param[in]  i_len  Size of o_pVal
 * @param[in]  i_type DDR Type
 *
 * @return fapi::ReturnCode Indicating success or error
 */
fapi::ReturnCode get_SPD_MODULE_NOMINAL_VOLTAGE(const fapi::Target & i_dimm,
    const fapi::getSpdAttr::Attr i_attr,
    void * o_pVal,
    const size_t i_len,
    const fapi::ATTR_SPD_DRAM_DEVICE_TYPE_Type i_type)
{
    fapi::ATTR_SPD_MODULE_NOMINAL_VOLTAGE_Type & o_val =
        *(reinterpret_cast<fapi::ATTR_SPD_MODULE_NOMINAL_VOLTAGE_Type *>(
            o_pVal));
    o_val = 0;

    fapi::ReturnCode l_rc = checkSize(i_attr, i_len, sizeof(o_val));

    if (!l_rc)
    {
        if (i_type == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
        {
            fapi::ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR3_Type l_voltage = 0;
            l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR3, &i_dimm,
                                 l_voltage);

            if (l_rc)
            {
                FAPI_ERR("get_SPD_MODULE_NOMINAL_VOLTAGE: Error getting DDR3 attr");
            }
            else
            {
                if (l_voltage &
                    fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR3_NOTOP1_5)
                {
                    o_val |=
                        fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5;
                }
                if (l_voltage &
                    fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR3_OP1_35)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35;
                }
                if (l_voltage &
                    fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR3_OP1_2X)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2X;
                }
            }
        }
        else
        {
            fapi::ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR4_Type l_voltage = 0;
            l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR4, &i_dimm,
                                 l_voltage);

            if (l_rc)
            {
                FAPI_ERR("get_SPD_MODULE_NOMINAL_VOLTAGE: Error getting DDR4 attr");
            }
            else
            {
                if (l_voltage &
                    fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR4_OP1_2V)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2V;
                }
                if (l_voltage &
                    fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_DDR4_END1_2V)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_END1_2V;
                }
            }
        }
    }

    return l_rc;
}
Beispiel #26
0
//------------------------------------------------------------------------------
// function: utility subroutine to set/clear A bus iovalid bits on one chip
// parameters: i_proc_chip     => structure providing:
//                                o target for this chip
//                                o A busses to act on
//             i_set_not_clear => define desired operation (true=set,
//                                false=clear)
// returns: FAPI_RC_SUCCESS if operation was successful, else error
//------------------------------------------------------------------------------
fapi::ReturnCode proc_fab_iovalid_manage_a_links(
    const proc_fab_iovalid_proc_chip& i_proc_chip,
    bool i_set_not_clear)
{
    ecmdDataBufferBase gp0_iovalid_active(64);
    ecmdDataBufferBase secure_iovalid_data(64);
    ecmdDataBufferBase secure_iovalid_mask(64);

    // return codes
    uint32_t rc_ecmd = 0;
    fapi::ReturnCode rc;

    // secure iovalid attribute
    uint8_t secure_iovalid_present_attr = 1;

    // mark function entry
    FAPI_DBG("proc_fab_iovalid_manage_a_links: Start");

    do
    {
        // query secure iovalid attribute, used to qualify iovalid set only
        rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_SECURE_IOVALID_PRESENT,
                           &(i_proc_chip.this_chip),
                           secure_iovalid_present_attr);
        if (!rc.ok())
        {
            FAPI_ERR("proc_fab_iovalid_manage_a_links: Error querying ATTR_CHIP_EC_FEATURE_SECURE_IOVALID_PRESENT");
            break;
        }
            
        if (i_proc_chip.a0)
        {
            FAPI_DBG("proc_fab_iovalid_manage_a_links: Adding link A0 to active link mask");
            rc_ecmd |= gp0_iovalid_active.setBit(A_GP0_A0_IOVALID_BIT);
            if (secure_iovalid_present_attr && i_set_not_clear)
            {
                FAPI_DBG("proc_fab_iovalid_manage_a_links: Adding link A0 to active link mask (secure)");
                if (i_set_not_clear)
                {
                    rc_ecmd |= secure_iovalid_data.setBit(ADU_IOS_LINK_EN_A0_IOVALID_BIT);
                }
                rc_ecmd |= secure_iovalid_mask.setBit(ADU_IOS_LINK_EN_A0_IOVALID_BIT);
            }
        }
        if (i_proc_chip.a1)
        {
            FAPI_DBG("proc_fab_iovalid_manage_a_links: Adding link A1 to active link mask");
            rc_ecmd |= gp0_iovalid_active.setBit(A_GP0_A1_IOVALID_BIT);
            if (secure_iovalid_present_attr && i_set_not_clear)
            {
                FAPI_DBG("proc_fab_iovalid_manage_a_links: Adding link A1 to active link mask (secure)");
                if (i_set_not_clear)
                {
                    rc_ecmd |= secure_iovalid_data.setBit(ADU_IOS_LINK_EN_A1_IOVALID_BIT);
                }
                rc_ecmd |= secure_iovalid_mask.setBit(ADU_IOS_LINK_EN_A1_IOVALID_BIT);
            }
        }
        if (i_proc_chip.a2)
        {
            FAPI_DBG("proc_fab_iovalid_manage_a_links: Adding link A2 to active link mask");
            rc_ecmd |= gp0_iovalid_active.setBit(A_GP0_A2_IOVALID_BIT);
            if (secure_iovalid_present_attr && i_set_not_clear)
            {
                FAPI_DBG("proc_fab_iovalid_manage_a_links: Adding link A2 to active link mask (secure)");
                if (i_set_not_clear)
                {
                    rc_ecmd |= secure_iovalid_data.setBit(ADU_IOS_LINK_EN_A2_IOVALID_BIT);
                }
                rc_ecmd |= secure_iovalid_mask.setBit(ADU_IOS_LINK_EN_A2_IOVALID_BIT);
            }
        }
        
        // check aggregate return code from buffer manipulation operations
        if (rc_ecmd)
        {
            FAPI_ERR("proc_fab_iovalid_manage_a_links: Error 0x%x setting up active link mask data buffersa",
                     rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }

        // write appropriate GP0 mask register to perform desired operation
        rc = proc_fab_iovalid_write_active_mask(i_proc_chip.this_chip,
                                                gp0_iovalid_active,
                                                i_set_not_clear,
                                                A_GP0_AND_0x08000004,
                                                A_GP0_OR_0x08000005);
        if (!rc.ok())
        {
            FAPI_ERR("proc_fab_iovalid_manage_a_links: Error from proc_fab_iovalid_write_active_mask");
            break;
        }

        // manage secure iovalids if present
        // do not attempt to drop secure iovalid
        // running on FSP (stopclocks), this code will be unable to adjust this register
        // clearing the GP0 settings should be sufficient to drop the downstream iovalids
        if (secure_iovalid_present_attr && i_set_not_clear)
        {
            rc = fapiPutScomUnderMask(i_proc_chip.this_chip,
                                      ADU_IOS_LINK_EN_0x02020019,
                                      secure_iovalid_data,
                                      secure_iovalid_mask);
            if (!rc.ok())
            {
                FAPI_ERR("proc_fab_iovalid_manage_a_links: fapiPutScomUnderMask error (ADU_IOS_LINK_EN_0x02020019)");
                break;
            }
        }
    } while(0);

    // mark function exit
    FAPI_DBG("proc_fab_iovalid_manage_a_links: End");
    return rc;
}
/**
 * @brief Returns SPD_CAS_LATENCIES_SUPPORTED data
 *
 * The raw data has different meanings for DDR3 and DDR4, this HWP translates
 * each to the enumeration in the common FAPI Attribute
 *
 * @param[in]  i_dimm Reference to DIMM fapi target
 * @param[in]  i_attr The Attribute to get
 * @param[out] o_pVal Pointer to data buffer filled in with attribute data
 * @param[in]  i_len  Size of o_pVal
 * @param[in]  i_type DDR Type
 *
 * @return fapi::ReturnCode Indicating success or error
 */
fapi::ReturnCode get_SPD_CAS_LATENCIES_SUPPORTED(const fapi::Target & i_dimm,
    const fapi::getSpdAttr::Attr i_attr,
    void * o_pVal,
    const size_t i_len,
    const fapi::ATTR_SPD_DRAM_DEVICE_TYPE_Type i_type)
{
    fapi::ATTR_SPD_CAS_LATENCIES_SUPPORTED_Type & o_val =
        *(reinterpret_cast<fapi::ATTR_SPD_CAS_LATENCIES_SUPPORTED_Type *>(
            o_pVal));
    o_val = 0;

    fapi::ReturnCode l_rc = checkSize(i_attr, i_len, sizeof(o_val));

    if (!l_rc)
    {
        if (i_type == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
        {
            fapi::ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_Type cl = 0;
            l_rc = FAPI_ATTR_GET(ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3, &i_dimm,
                                 cl);
            if (l_rc)
            {
                FAPI_ERR("get_SPD_CAS_LATENCIES_SUPPORTED: Error getting DDR3 attr");
            }
            else
            {
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_4)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_4;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_5)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_5;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_6)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_6;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_7)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_7;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_8)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_8;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_9)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_9;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_10)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_10;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_11)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_11;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_12)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_12;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_13)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_13;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_14)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_14;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_15)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_15;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_16)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_16;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_17)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_17;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR3_CL_18)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_18;
                }
            }
        }
        else
        {
            fapi::ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_Type cl = 0;
            l_rc = FAPI_ATTR_GET(ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4, &i_dimm,
                                 cl);
            if (l_rc)
            {
                FAPI_ERR("get_SPD_CAS_LATENCIES_SUPPORTED: Error getting DDR4 attr");
            }
            else
            {
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_7)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_7;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_8)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_8;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_9)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_9;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_10)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_10;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_11)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_11;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_12)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_12;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_13)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_13;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_14)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_14;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_15)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_15;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_16)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_16;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_17)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_17;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_18)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_18;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_19)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_19;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_20)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_20;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_21)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_21;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_22)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_22;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_23)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_23;
                }
                if (cl & fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_DDR4_CL_24)
                {
                    o_val |= fapi::ENUM_ATTR_SPD_CAS_LATENCIES_SUPPORTED_CL_24;
                }
            }
        }
    }

    return l_rc;
}
Beispiel #28
0
//------------------------------------------------------------------------------
// HWP entry point
//------------------------------------------------------------------------------
fapi::ReturnCode proc_fab_iovalid(
    std::vector<proc_fab_iovalid_proc_chip>& i_proc_chips,
    bool i_set_not_clear)
{
    // return code
    fapi::ReturnCode rc;
    // iterator for HWP input vector
    std::vector<proc_fab_iovalid_proc_chip>::const_iterator iter;

    // partial good attributes
    uint8_t abus_enable_attr;
    uint8_t xbus_enable_attr;
    bool x_changed = false;
    bool a_changed = false;

    // mark HWP entry
    FAPI_IMP("proc_fab_iovalid: Entering ...");

    do
    {
        // loop over all chips in input vector
        for (iter = i_proc_chips.begin();
             iter != i_proc_chips.end();
             iter++)
        {
            // process X links
            if (iter->x0 ||
                iter->x1 ||
                iter->x2 ||
                iter->x3)
            {
                // query XBUS partial good attribute
                rc = FAPI_ATTR_GET(ATTR_PROC_X_ENABLE,
                                   &(iter->this_chip),
                                   xbus_enable_attr);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_fab_iovalid: Error querying ATTR_PROC_X_ENABLE");
                    break;
                }

                if (xbus_enable_attr != fapi::ENUM_ATTR_PROC_X_ENABLE_ENABLE)
                {
                    FAPI_ERR("proc_fab_iovalid: Partial good attribute error");
                    const fapi::Target & TARGET = iter->this_chip;
                    FAPI_SET_HWP_ERROR(rc, RC_PROC_FAB_IOVALID_X_PARTIAL_GOOD_ERR);
                    break;
                }

                rc = proc_fab_iovalid_manage_x_links(*iter, i_set_not_clear);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_fab_iovalid: Error from proc_fab_iovalid_manage_x_links");
                    break;
                }

                rc = proc_fab_iovalid_manage_x_fir(*iter, i_set_not_clear);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_fab_iovalid: Error from proc_fab_iovalid_manage_x_fir");
                    break;
                }

                x_changed = true;
            }

            // process A links
            if (iter->a0 ||
                iter->a1 ||
                iter->a2)
            {
                // query ABUS partial good attribute
                rc = FAPI_ATTR_GET(ATTR_PROC_A_ENABLE,
                                   &(iter->this_chip),
                                   abus_enable_attr);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_fab_iovalid: Error querying ATTR_PROC_A_ENABLE");
                    break;
                }

                if (abus_enable_attr != fapi::ENUM_ATTR_PROC_A_ENABLE_ENABLE)
                {
                    FAPI_ERR("proc_fab_iovalid: Partial good attribute error");
                    const fapi::Target & TARGET = iter->this_chip;
                    FAPI_SET_HWP_ERROR(rc, RC_PROC_FAB_IOVALID_A_PARTIAL_GOOD_ERR);
                    break;
                }

                rc = proc_fab_iovalid_manage_a_links(*iter, i_set_not_clear);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_fab_iovalid: Error from proc_fab_iovalid_manage_a_links");
                    break;
                }

                rc = proc_fab_iovalid_manage_a_fir(*iter, i_set_not_clear);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_fab_iovalid: Error from proc_fab_iovalid_manage_a_fir");
                    break;
                }

                a_changed = true;
            }

            if (x_changed || a_changed)
            {
                rc = proc_fab_iovalid_manage_ras_fir(*iter, i_set_not_clear);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_fab_iovalid: Error from proc_fab_iovalid_manage_ras_fir");
                    break;
                }
            }
        }
    } while(0);

    // log function exit
    FAPI_IMP("proc_fab_iovalid: Exiting ...");
    return rc;
}
//******************************************************************************
//* name=mss_eff_config_rank_group, param=i_target_mba, return=ReturnCode
//******************************************************************************
fapi::ReturnCode mss_eff_config_rank_group(const fapi::Target i_target_mba) {
   fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS;
   const char * const PROCEDURE_NAME = "mss_eff_config_rank_group";
   const fapi::Target& TARGET_MBA = i_target_mba;
   FAPI_INF("*** Running %s on %s ... ***", PROCEDURE_NAME, i_target_mba.toEcmdString());

   const uint8_t PORT_SIZE = 2;
   const uint8_t DIMM_SIZE = 2;
   // ATTR_EFF_DRAM_GEN: EMPTY = 0, DDR3 = 1, DDR4 = 2,
   // ATTR_EFF_DIMM_TYPE: CDIMM = 0, RDIMM = 1, UDIMM = 2, LRDIMM = 3,
   uint8_t num_ranks_per_dimm_u8array[PORT_SIZE][DIMM_SIZE];
   uint8_t dram_gen_u8;
   uint8_t dimm_type_u8;

   rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target_mba, num_ranks_per_dimm_u8array); if(rc) return rc;
   rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target_mba, dram_gen_u8); if(rc) return rc;
   rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_TYPE, &i_target_mba, dimm_type_u8); if(rc) return rc;

   uint8_t primary_rank_group0_u8array[PORT_SIZE];
   uint8_t primary_rank_group1_u8array[PORT_SIZE];
   uint8_t primary_rank_group2_u8array[PORT_SIZE];
   uint8_t primary_rank_group3_u8array[PORT_SIZE];
   uint8_t secondary_rank_group0_u8array[PORT_SIZE];
   uint8_t secondary_rank_group1_u8array[PORT_SIZE];
   uint8_t secondary_rank_group2_u8array[PORT_SIZE];
   uint8_t secondary_rank_group3_u8array[PORT_SIZE];
   uint8_t tertiary_rank_group0_u8array[PORT_SIZE];
   uint8_t tertiary_rank_group1_u8array[PORT_SIZE];
   uint8_t tertiary_rank_group2_u8array[PORT_SIZE];
   uint8_t tertiary_rank_group3_u8array[PORT_SIZE];
   uint8_t quanternary_rank_group0_u8array[PORT_SIZE];
   uint8_t quanternary_rank_group1_u8array[PORT_SIZE];
   uint8_t quanternary_rank_group2_u8array[PORT_SIZE];
   uint8_t quanternary_rank_group3_u8array[PORT_SIZE];

   for (uint8_t cur_port = 0; cur_port < PORT_SIZE; cur_port += 1) {
      //Removed 32G CDIMM 1R dualdrop workaround.
      //NOTE: Needs mss_draminit_training.C v1.57 or newer.
      //if ((dimm_type_u8 == CDIMM) && (num_ranks_per_dimm_u8array[cur_port][0] == 1) && (num_ranks_per_dimm_u8array[cur_port][1] == 1)) {
         // NOTE: 32G CDIMM 1R dualdrop workaround, normally primary_rank_group0=0, primary_rank_group1=4.
         //primary_rank_group0_u8array[cur_port] = 0;
         //primary_rank_group1_u8array[cur_port] = INVALID;
         //primary_rank_group2_u8array[cur_port] = INVALID;
         //primary_rank_group3_u8array[cur_port] = INVALID;
         //secondary_rank_group0_u8array[cur_port] = 4;
         //secondary_rank_group1_u8array[cur_port] = INVALID;
         //secondary_rank_group2_u8array[cur_port] = INVALID;
         //secondary_rank_group3_u8array[cur_port] = INVALID;
         //tertiary_rank_group0_u8array[cur_port] = INVALID;
         //tertiary_rank_group1_u8array[cur_port] = INVALID;
         //tertiary_rank_group2_u8array[cur_port] = INVALID;
         //tertiary_rank_group3_u8array[cur_port] = INVALID;
         //quanternary_rank_group0_u8array[cur_port] = INVALID;
         //quanternary_rank_group1_u8array[cur_port] = INVALID;
         //quanternary_rank_group2_u8array[cur_port] = INVALID;
         //quanternary_rank_group3_u8array[cur_port] = INVALID;
      //} else if (dimm_type_u8 == LRDIMM) {
      if (dimm_type_u8 == LRDIMM) {
         primary_rank_group2_u8array[cur_port] = INVALID;
         secondary_rank_group2_u8array[cur_port] = INVALID;
         tertiary_rank_group2_u8array[cur_port] = INVALID;
         quanternary_rank_group2_u8array[cur_port] = INVALID;

         primary_rank_group3_u8array[cur_port] = INVALID;
         secondary_rank_group3_u8array[cur_port] = INVALID;
         tertiary_rank_group3_u8array[cur_port] = INVALID;
         quanternary_rank_group3_u8array[cur_port] = INVALID;

         // dimm 0 (far socket)
         switch (num_ranks_per_dimm_u8array[cur_port][0]) {
           case 4:               // 4 rank lrdimm
                 primary_rank_group0_u8array[cur_port] = 0;
                 secondary_rank_group0_u8array[cur_port] = 1;
                 tertiary_rank_group0_u8array[cur_port] = 2;
                 quanternary_rank_group0_u8array[cur_port] = 3;
                 break;
           case 8:               // 8 rank lrdimm falls through to 2 rank case
         // Rank Multiplication mode needed, CS2 & CS3 used as address lines into LRBuffer
         // RM=4 -> only 2 CS valid, each CS controls 4 ranks with CS2 & CS3 as address
         // CS0 = rank 0, 2, 4, 6;  CS1 = rank 1, 3, 5, 7
           case 2:               // 2 rank lrdimm
                 primary_rank_group0_u8array[cur_port] = 0;
                 secondary_rank_group0_u8array[cur_port] = 1;
                 tertiary_rank_group0_u8array[cur_port] = INVALID;
                 quanternary_rank_group0_u8array[cur_port] = INVALID;
                 break;
           case 1:               // 1 rank lrdimm
                 primary_rank_group0_u8array[cur_port] = 0;
                 secondary_rank_group0_u8array[cur_port] = INVALID;
                 tertiary_rank_group0_u8array[cur_port] = INVALID;
                 quanternary_rank_group0_u8array[cur_port] = INVALID;
                 break;
           default:              // not 1, 2, 4, or 8 ranks
                 primary_rank_group0_u8array[cur_port] = INVALID;
                 secondary_rank_group0_u8array[cur_port] = INVALID;
                 tertiary_rank_group0_u8array[cur_port] = INVALID;
                 quanternary_rank_group0_u8array[cur_port] = INVALID;
         }
         // dimm 1 (near socket)
         switch (num_ranks_per_dimm_u8array[cur_port][1]) {
           case 4:               // 4 rank lrdimm
                 primary_rank_group1_u8array[cur_port] = 4;
                 secondary_rank_group1_u8array[cur_port] = 5;
                 tertiary_rank_group1_u8array[cur_port] = 6;
                 quanternary_rank_group1_u8array[cur_port] = 7;
                 break;
           case 8:               // 8 rank lrdimm falls through to case 2
         // Rank Multiplication mode needed, CS6 & CS7 used as address lines into LRBuffer
         // RM=4 -> only 2 CS valid, each CS controls 4 ranks with CS6 & CS7 as address
         // CS4 = rank 0, 2, 4, 6;  CS5 = rank 1, 3, 5, 7
           case 2:               // 2 rank lrdimm, RM=0
                 primary_rank_group1_u8array[cur_port] = 4;
                 secondary_rank_group1_u8array[cur_port] = 5;
                 tertiary_rank_group1_u8array[cur_port] = INVALID;
                 quanternary_rank_group1_u8array[cur_port] = INVALID;
                 break;
           case 1:               // 1 rank lrdimm
                 primary_rank_group1_u8array[cur_port] = 4;
                 secondary_rank_group1_u8array[cur_port] = INVALID;
                 tertiary_rank_group1_u8array[cur_port] = INVALID;
                 quanternary_rank_group1_u8array[cur_port] = INVALID;
                 break;
           default:              // not 1, 2, 4, or 8 ranks
                 primary_rank_group1_u8array[cur_port] = INVALID;
                 secondary_rank_group1_u8array[cur_port] = INVALID;
                 tertiary_rank_group1_u8array[cur_port] = INVALID;
                 quanternary_rank_group1_u8array[cur_port] = INVALID;
         }

      } else { // RDIMM or CDIMM
         if ((num_ranks_per_dimm_u8array[cur_port][0] > 0) && (num_ranks_per_dimm_u8array[cur_port][1] == 0)) {
            primary_rank_group0_u8array[cur_port] = 0;
            if (num_ranks_per_dimm_u8array[cur_port][0] > 1) {
               primary_rank_group1_u8array[cur_port] = 1;
            } else {
               primary_rank_group1_u8array[cur_port] = INVALID;
            }
            if (num_ranks_per_dimm_u8array[cur_port][0] > 2) {
               primary_rank_group2_u8array[cur_port] = 2;
               primary_rank_group3_u8array[cur_port] = 3;
            } else {
               primary_rank_group2_u8array[cur_port] = INVALID;
               primary_rank_group3_u8array[cur_port] = INVALID;
            }
            secondary_rank_group0_u8array[cur_port] = INVALID;
            secondary_rank_group1_u8array[cur_port] = INVALID;
            secondary_rank_group2_u8array[cur_port] = INVALID;
            secondary_rank_group3_u8array[cur_port] = INVALID;
         } else if ((num_ranks_per_dimm_u8array[cur_port][0] > 0) && (num_ranks_per_dimm_u8array[cur_port][1] > 0)) {
            if (num_ranks_per_dimm_u8array[cur_port][0] != num_ranks_per_dimm_u8array[cur_port][1]) {
               FAPI_ERR("%s: FAILED!", PROCEDURE_NAME);
               FAPI_ERR("Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0], num_ranks_per_dimm_u8array[cur_port][1], i_target_mba.toEcmdString(), cur_port);
               FAPI_SET_HWP_ERROR(rc, RC_MSS_EFF_CONFIG_RANK_GROUP_NON_MATCH_RANKS);
               return rc;
            }
            primary_rank_group0_u8array[cur_port] = 0;
            primary_rank_group1_u8array[cur_port] = 4;
            primary_rank_group2_u8array[cur_port] = INVALID;
            primary_rank_group3_u8array[cur_port] = INVALID;
            secondary_rank_group0_u8array[cur_port] = INVALID;
            secondary_rank_group1_u8array[cur_port] = INVALID;
            secondary_rank_group2_u8array[cur_port] = INVALID;
            secondary_rank_group3_u8array[cur_port] = INVALID;
            if (num_ranks_per_dimm_u8array[cur_port][0] == 2) {
               primary_rank_group2_u8array[cur_port] = 1;
               primary_rank_group3_u8array[cur_port] = 5;
            } else if (num_ranks_per_dimm_u8array[cur_port][0] == 4) {
               primary_rank_group2_u8array[cur_port] = 2;
               primary_rank_group3_u8array[cur_port] = 6;
               secondary_rank_group0_u8array[cur_port] = 1;
               secondary_rank_group1_u8array[cur_port] = 5;
               secondary_rank_group2_u8array[cur_port] = 3;
               secondary_rank_group3_u8array[cur_port] = 7;
            } else if (num_ranks_per_dimm_u8array[cur_port][0] != 1) {
               FAPI_ERR("%s: FAILED!", PROCEDURE_NAME);
               FAPI_ERR("Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0], num_ranks_per_dimm_u8array[cur_port][1], i_target_mba.toEcmdString(), cur_port);
               FAPI_SET_HWP_ERROR(rc, RC_MSS_EFF_CONFIG_RANK_GROUP_NUM_RANKS_NEQ1);
               return rc;
            }
         } else if ((num_ranks_per_dimm_u8array[cur_port][0] == 0) && (num_ranks_per_dimm_u8array[cur_port][1] == 0)) {
            primary_rank_group0_u8array[cur_port] = INVALID;
            primary_rank_group1_u8array[cur_port] = INVALID;
            primary_rank_group2_u8array[cur_port] = INVALID;
            primary_rank_group3_u8array[cur_port] = INVALID;
            secondary_rank_group0_u8array[cur_port] = INVALID;
            secondary_rank_group1_u8array[cur_port] = INVALID;
            secondary_rank_group2_u8array[cur_port] = INVALID;
            secondary_rank_group3_u8array[cur_port] = INVALID;
         } else {
            FAPI_ERR("%s: FAILED!", PROCEDURE_NAME);
            FAPI_ERR("Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0], num_ranks_per_dimm_u8array[cur_port][1], i_target_mba.toEcmdString(), cur_port);
            FAPI_SET_HWP_ERROR(rc, RC_MSS_EFF_CONFIG_RANK_GROUP_NO_MATCH);
            return rc;
         }
         tertiary_rank_group0_u8array[cur_port] = INVALID;
         tertiary_rank_group1_u8array[cur_port] = INVALID;
         tertiary_rank_group2_u8array[cur_port] = INVALID;
         tertiary_rank_group3_u8array[cur_port] = INVALID;
         quanternary_rank_group0_u8array[cur_port] = INVALID;
         quanternary_rank_group1_u8array[cur_port] = INVALID;
         quanternary_rank_group2_u8array[cur_port] = INVALID;
         quanternary_rank_group3_u8array[cur_port] = INVALID;
      }
      FAPI_INF("P[%02d][%02d][%02d][%02d],S[%02d][%02d][%02d][%02d],T[%02d][%02d][%02d][%02d],Q[%02d][%02d][%02d][%02d] on %s PORT%d.", primary_rank_group0_u8array[cur_port], primary_rank_group1_u8array[cur_port], primary_rank_group2_u8array[cur_port], primary_rank_group3_u8array[cur_port], secondary_rank_group0_u8array[cur_port], secondary_rank_group1_u8array[cur_port], secondary_rank_group2_u8array[cur_port], secondary_rank_group3_u8array[cur_port], tertiary_rank_group0_u8array[cur_port], tertiary_rank_group1_u8array[cur_port], tertiary_rank_group2_u8array[cur_port], tertiary_rank_group3_u8array[cur_port], quanternary_rank_group0_u8array[cur_port], quanternary_rank_group1_u8array[cur_port], quanternary_rank_group2_u8array[cur_port], quanternary_rank_group3_u8array[cur_port], i_target_mba.toEcmdString(), cur_port);
   }
   rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP0, &i_target_mba, primary_rank_group0_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP1, &i_target_mba, primary_rank_group1_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP2, &i_target_mba, primary_rank_group2_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP3, &i_target_mba, primary_rank_group3_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP0, &i_target_mba, secondary_rank_group0_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP1, &i_target_mba, secondary_rank_group1_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP2, &i_target_mba, secondary_rank_group2_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP3, &i_target_mba, secondary_rank_group3_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP0, &i_target_mba, tertiary_rank_group0_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP1, &i_target_mba, tertiary_rank_group1_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP2, &i_target_mba, tertiary_rank_group2_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP3, &i_target_mba, tertiary_rank_group3_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP0, &i_target_mba, quanternary_rank_group0_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP1, &i_target_mba, quanternary_rank_group1_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP2, &i_target_mba, quanternary_rank_group2_u8array); if(rc) return rc;
   rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP3, &i_target_mba, quanternary_rank_group3_u8array); if(rc) return rc;

   FAPI_INF("%s on %s COMPLETE", PROCEDURE_NAME, i_target_mba.toEcmdString());
   return rc;
}
fapi2::ReturnCode
p9_rng_init_phase1(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    FAPI_INF("Start");

    fapi2::buffer<uint64_t> l_rng_cfg_data;
    fapi2::buffer<uint64_t> l_rng_st0_data;
    fapi2::buffer<uint64_t> l_rng_st1_data;
    fapi2::buffer<uint64_t> l_rng_st2_data;
    fapi2::buffer<uint64_t> l_rng_st3_data;
    fapi2::buffer<uint64_t> l_rng_rdelay_data;

    uint8_t l_rng_adaptest_dd1 = 0;
    uint8_t l_HW403701 = 0;

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_RNG_ADAPTEST_SETTINGS,
                           i_target,
                           l_rng_adaptest_dd1),
             "Error from FAPI_ATTR_GET (ATTR_CHIP_EC_FEATURE_RNG_ADAPTEST_SETTINGS");

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_HW403701,
                           i_target,
                           l_HW403701),
             "Error from FAPI_ATTR_GET (ATTR_CHIP_EC_FEATURE_HW403701");

    // 1. RNG will start running with FIFO write / self tests disabled (enable
    // doesn't gate the osc; it turns off FIFO writes and self test fails);
    // rng_enable = 0.

    // 2. RNG Conditioner Startup Test runs and reports status.
    // Host boot reads Conditioner Startup Test Fail status. If a fail is
    // detected then RNG is declared broken.

    // read conditioner startup test fail status, exit if failure has been
    // reported to declare RNG broken/unusable
    FAPI_TRY(fapi2::getScom(i_target, PU_NX_RNG_CFG, l_rng_cfg_data),
             "Error from getScom (NX RNG Status and Control Register)");

    FAPI_ASSERT(!l_rng_cfg_data.getBit<PU_NX_RNG_CFG_COND_STARTUP_TEST_FAIL>(),
                fapi2::P9_RNG_INIT_CONDITIONER_STARTUP_TEST_FAILED_ERR().
                set_TARGET(i_target).
                set_RNG_CFG(l_rng_cfg_data),
                "Conditioner startup test failed");

    // 3. Host boot programs window sizes, pace, self test enables and
    // parameters, read delay parameters.  program window sizes, pace, self test
    // enables/parameters, and read delay parameters get values from self test
    // registers
    FAPI_TRY(fapi2::getScom(i_target, PU_NX_RNG_ST0, l_rng_st0_data),
             "Error from getScom (NX RNG Self Test Register 0)");
    FAPI_TRY(fapi2::getScom(i_target, PU_NX_RNG_ST1, l_rng_st1_data),
             "Error from getScom (NX RNG Self Test Register 1)");
    FAPI_TRY(fapi2::getScom(i_target, PU_NX_RNG_ST3, l_rng_st3_data),
             "Error from getScom (NX RNG Self Test Register 3)");
    FAPI_TRY(fapi2::getScom(i_target, PU_NX_RNG_RDELAY, l_rng_rdelay_data),
             "Error from putScom (NX RNG Read Delay Parameters Register)");

    if (l_rng_adaptest_dd1)
    {
        FAPI_INF("Configuring Self Test Registers for P9N DD1");
        // configure RNG Self Test Register 0
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_REPTEST_MATCH_TH,
                                       PU_NX_RNG_ST0_REPTEST_MATCH_TH_LEN>
                                       (NX_RNG_ST0_REPTEST_MATCH_TH_DD1);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_SAMPLE_SIZE,
                                       PU_NX_RNG_ST0_ADAPTEST_SAMPLE_SIZE_LEN>
                                       (NX_RNG_ST0_ADAPTEST_SAMPLE_SIZE_DD1);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_WINDOW_SIZE,
                                       PU_NX_RNG_ST0_ADAPTEST_WINDOW_SIZE_LEN>
                                       (NX_RNG_ST0_ADAPTEST_WINDOW_SIZE_DD1);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_RRN_RNG0_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_RRN_RNG0_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_RRN_RNG0_MATCH_TH_DD1);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_RRN_RNG1_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_RRN_RNG1_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_RRN_RNG1_MATCH_TH_DD1);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_CRN_RNG0_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_CRN_RNG0_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_CRN_RNG0_MATCH_TH_DD1);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_CRN_RNG1_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_CRN_RNG1_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_CRN_RNG1_MATCH_TH_DD1);

        // configure RNG Self Test Register 1
        l_rng_st1_data.insertFromRight<PU_NX_RNG_ST1_ADAPTEST_SOFT_FAIL_TH,
                                       PU_NX_RNG_ST1_ADAPTEST_SOFT_FAIL_TH_LEN>
                                       (NX_RNG_ST1_ADAPTEST_SOFT_FAIL_TH_DD1);
        l_rng_st1_data.insertFromRight<PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MIN,
                                       PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MIN_LEN>
                                       (NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MIN_DD1);
        l_rng_st1_data.insertFromRight<PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MAX,
                                       PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MAX_LEN>
                                       (NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MAX_DD1);

        // configure RNG Self Test Register 3
        l_rng_st3_data.writeBit<PU_NX_RNG_ST3_SAMPTEST_RRN_ENABLE>
        (NX_RNG_ST3_SAMPTEST_RRN_ENABLE_DD1);
        l_rng_st3_data.insertFromRight<PU_NX_RNG_ST3_SAMPTEST_WINDOW_SIZE,
                                       PU_NX_RNG_ST3_SAMPTEST_WINDOW_SIZE_LEN>
                                       (NX_RNG_ST3_SAMPTEST_WINDOW_SIZE_DD1);
        l_rng_st3_data.insertFromRight<PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MIN,
                                       PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MIN_LEN>
                                       (NX_RNG_ST3_SAMPTEST_MATCH_TH_MIN_DD1);
        l_rng_st3_data.insertFromRight<PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MAX,
                                       PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MAX_LEN>
                                       (NX_RNG_ST3_SAMPTEST_MATCH_TH_MAX_DD1);

        // configure RNG Read Delay Parameters Register
        l_rng_rdelay_data.insertFromRight<PU_NX_RNG_RDELAY_CQ_READ_RTY_RATIO,
                                          PU_NX_RNG_RDELAY_CQ_READ_RTY_RATIO_LEN>
                                          (NX_RNG_CQ_RDELAY_READ_RTY_RATIO_DD1);
    }
    else
    {
        FAPI_INF("Configuring Self Test Registers (non P9N DD1)");
        // configure RNG Self Test Register 0
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_REPTEST_MATCH_TH,
                                       PU_NX_RNG_ST0_REPTEST_MATCH_TH_LEN>
                                       (NX_RNG_ST0_REPTEST_MATCH_TH_DD2);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_SAMPLE_SIZE,
                                       PU_NX_RNG_ST0_ADAPTEST_SAMPLE_SIZE_LEN>
                                       (NX_RNG_ST0_ADAPTEST_SAMPLE_SIZE_DD2);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_WINDOW_SIZE,
                                       PU_NX_RNG_ST0_ADAPTEST_WINDOW_SIZE_LEN>
                                       (NX_RNG_ST0_ADAPTEST_WINDOW_SIZE_DD2);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_RRN_RNG0_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_RRN_RNG0_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_RRN_RNG0_MATCH_TH_DD2);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_RRN_RNG1_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_RRN_RNG1_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_RRN_RNG1_MATCH_TH_DD2);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_CRN_RNG0_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_CRN_RNG0_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_CRN_RNG0_MATCH_TH_DD2);
        l_rng_st0_data.insertFromRight<PU_NX_RNG_ST0_ADAPTEST_CRN_RNG1_MATCH_TH,
                                       PU_NX_RNG_ST0_ADAPTEST_CRN_RNG1_MATCH_TH_LEN>
                                       (NX_RNG_ST0_ADAPTEST_CRN_RNG1_MATCH_TH_DD2);

        // configure RNG Self Test Register 1
        l_rng_st1_data.insertFromRight<PU_NX_RNG_ST1_ADAPTEST_SOFT_FAIL_TH,
                                       PU_NX_RNG_ST1_ADAPTEST_SOFT_FAIL_TH_LEN>
                                       (NX_RNG_ST1_ADAPTEST_SOFT_FAIL_TH_DD2);
        l_rng_st1_data.insertFromRight<PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MIN,
                                       PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MIN_LEN>
                                       (NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MIN_DD2);
        l_rng_st1_data.insertFromRight<PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MAX,
                                       PU_NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MAX_LEN>
                                       (NX_RNG_ST1_ADAPTEST_1BIT_MATCH_TH_MAX_DD2);

        // configure RNG Self Test Register 3
        l_rng_st3_data.writeBit<PU_NX_RNG_ST3_SAMPTEST_RRN_ENABLE>
        (NX_RNG_ST3_SAMPTEST_RRN_ENABLE_DD2);
        l_rng_st3_data.insertFromRight<PU_NX_RNG_ST3_SAMPTEST_WINDOW_SIZE,
                                       PU_NX_RNG_ST3_SAMPTEST_WINDOW_SIZE_LEN>
                                       (NX_RNG_ST3_SAMPTEST_WINDOW_SIZE_DD2);
        l_rng_st3_data.insertFromRight<PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MIN,
                                       PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MIN_LEN>
                                       (NX_RNG_ST3_SAMPTEST_MATCH_TH_MIN_DD2);
        l_rng_st3_data.insertFromRight<PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MAX,
                                       PU_NX_RNG_ST3_SAMPTEST_MATCH_TH_MAX_LEN>
                                       (NX_RNG_ST3_SAMPTEST_MATCH_TH_MAX_DD2);

        // configure RNG Read Delay Parameters Register
        l_rng_rdelay_data.writeBit<PU_NX_RNG_RDELAY_CQ_LFSR_RESEED_EN>
        (NX_RNG_CQ_RDELAY_LFSR_RESEED_EN_DD2);
        l_rng_rdelay_data.insertFromRight<PU_NX_RNG_RDELAY_CQ_READ_RTY_RATIO,
                                          PU_NX_RNG_RDELAY_CQ_READ_RTY_RATIO_LEN>
                                          (NX_RNG_CQ_RDELAY_READ_RTY_RATIO_DD2);

    }

    FAPI_TRY(fapi2::putScom(i_target, PU_NX_RNG_ST0, l_rng_st0_data),
             "Error from putScom (NX RNG Self Test Register 0)");

    FAPI_TRY(fapi2::putScom(i_target, PU_NX_RNG_ST1, l_rng_st1_data),
             "Error from putScom (NX RNG Self Test Register 1)");

    FAPI_TRY(fapi2::putScom(i_target, PU_NX_RNG_ST3, l_rng_st3_data),
             "Error from putScom (NX RNG Self Test Register 3)");

    FAPI_TRY(fapi2::putScom(i_target, PU_NX_RNG_RDELAY, l_rng_rdelay_data),
             "Error from putScom (NX RNG Read Delay Parameters Register)");

    // 4. If RNG is not broken then host boot sets rng_enable =1.
    // update RNG Status and Control Register to engage initialization test
    FAPI_TRY(fapi2::getScom(i_target, PU_NX_RNG_CFG, l_rng_cfg_data),
             "Error from getScom (NX RNG Status and Control Register)");

    l_rng_cfg_data.setBit<PU_NX_RNG_CFG_ENABLE>();
    l_rng_cfg_data.writeBit<PU_NX_RNG_CFG_MASK_TOGGLE_ENABLE>
    (NX_RNG_CFG_CONDITIONER_MASK_TOGGLE);
    l_rng_cfg_data.writeBit<PU_NX_RNG_CFG_SAMPTEST_ENABLE>
    (NX_RNG_CFG_SAMPLE_RATE_TEST_ENABLE);
    l_rng_cfg_data.writeBit<PU_NX_RNG_CFG_REPTEST_ENABLE>
    (NX_RNG_CFG_REPTEST_ENABLE);
    l_rng_cfg_data.writeBit<PU_NX_RNG_CFG_ADAPTEST_1BIT_ENABLE>
    (NX_RNG_CFG_ADAPTEST_1BIT_ENABLE);
    l_rng_cfg_data.writeBit<PU_NX_RNG_CFG_ADAPTEST_ENABLE>
    (NX_RNG_CFG_ADAPTEST_ENABLE);
    l_rng_cfg_data.insertFromRight<PU_NX_RNG_CFG_ST2_RESET_PERIOD,
                                   PU_NX_RNG_CFG_ST2_RESET_PERIOD_LEN>
                                   (NX_RNG_CFG_ST2_RESET_PERIOD);

    if (l_HW403701 != 0)
    {
        l_rng_cfg_data.insertFromRight<PU_NX_RNG_CFG_PACE_RATE,
                                       PU_NX_RNG_CFG_PACE_RATE_LEN>
                                       (NX_RNG_CFG_PACE_RATE_HW403701);
    }
    else
    {
        l_rng_cfg_data.insertFromRight<PU_NX_RNG_CFG_PACE_RATE,
                                       PU_NX_RNG_CFG_PACE_RATE_LEN>
                                       (NX_RNG_CFG_PACE_RATE);
    }

    FAPI_TRY(fapi2::putScom(i_target, PU_NX_RNG_CFG, l_rng_cfg_data),
             "Error from putScom (NX RNG Status and Control Register)");

fapi_try_exit:
    FAPI_INF("End");
    return fapi2::current_err;
}