Example #1
0
fapi2::ReturnCode ppe_resume(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const uint64_t i_base_address)
{
    fapi2::buffer<uint64_t> l_data64;

    static const uint32_t RESUME_TRIES = 10;
    uint32_t l_timeout_count = RESUME_TRIES;
    //Before reume always clear debug status (Michael's comment)
    FAPI_INF("   Clear debug status via XCR...");
    l_data64.flush<0>();
    FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to clear dbg status");

    FAPI_INF("   Send RESUME command via XCR...");
    l_data64.flush<0>().insertFromRight(p9hcd::RESUME, 1, 3);

    FAPI_TRY(putScom(i_target, i_base_address + PPE_XIXCR, l_data64), "Error in PUTSCOM in XCR to resume condition");

    do
    {
        FAPI_TRY(getScom(i_target, i_base_address + PPE_XIRAMEDR, l_data64));
        FAPI_DBG("   Poll content:  XSR: 0x%16llX", l_data64);
    }
    while((l_data64.getBit<p9hcd::HALTED_STATE>() != 0) && (--l_timeout_count != 0));

fapi_try_exit:
    return fapi2::current_err;
}
Example #2
0
///
/// @brief Equalize the throttles among OCMB chips
/// @param[in] i_targets vector of OCMB chips
/// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
///
fapi2::ReturnCode equalize_throttles( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >& i_targets,
                                      const mss::throttle_type i_throttle_type)
{
    FAPI_INF("Start equalize_throttles for %s type throttling",
             (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER"));

    std::vector< fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> > l_exceeded_power;

    // Set all of the throttles to the lowest value per port for performance reasons
    FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, i_throttle_type, l_exceeded_power));

    // Report any port that exceeded the max power limit, and return a failing RC if we have any
    for (const auto& l_port : l_exceeded_power)
    {
        FAPI_ERR(" MEM_PORT %s estimated power exceeded the maximum allowed", mss::c_str(l_port) );
        fapi2::current_err = fapi2::FAPI2_RC_FALSE;
    }

    FAPI_INF("End equalize_throttles");
    return fapi2::current_err;

fapi_try_exit:
    FAPI_ERR("Error calculating equalize_throttles using %s throttling",
             ((i_throttle_type == mss::throttle_type::POWER) ? "power" : "thermal"));
    return fapi2::current_err;
}
Example #3
0
//------------------------------------------------------------------------------
// function: apply PBCQ/AIB customization via SCOM initfile
// parameters: i_target => processor chip target
// returns: FAPI_RC_SUCCESS if initfile evaluation is successful,
//          else error
//------------------------------------------------------------------------------
fapi::ReturnCode proc_pcie_config_pbcq(
    const fapi::Target & i_target)
{
    fapi::ReturnCode rc;
    std::vector<fapi::Target> targets;

    // mark function entry
    FAPI_INF("proc_pcie_config_pbcq: Start");

    do
    {
        // execute Phase2 SCOM initfile
        targets.push_back(i_target);
        FAPI_INF("proc_pcie_config_pbcq: Executing %s on %s",
                 PROC_PCIE_CONFIG_PHASE2_IF, i_target.toEcmdString());
        FAPI_EXEC_HWP(
            rc,
            fapiHwpExecInitFile,
            targets,
            PROC_PCIE_CONFIG_PHASE2_IF);
        if (!rc.ok())
        {
            FAPI_ERR("proc_pcie_config_pbcq: Error from fapiHwpExecInitfile executing %s on %s",
                     PROC_PCIE_CONFIG_PHASE2_IF,
                     i_target.toEcmdString());
            break;
        }
    } while(0);

    // mark function exit
    FAPI_INF("proc_pcie_config_pbcq: End");
    return rc;
}
Example #4
0
    ///
    /// @brief Scominit for Explorer
    /// @param[in] i_target the OCMB target to operate on
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode exp_scominit( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
    {
        mss::display_git_commit_info("exp_scominit");

        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping mss_scominit %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // We need to make sure we hit all ports
        const auto& l_port_targets = mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target);

        fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
        const auto& l_mc = i_target.getParent<fapi2::TARGET_TYPE_OMI>()
                           .getParent<fapi2::TARGET_TYPE_MCC>()
                           .getParent<fapi2::TARGET_TYPE_MI>()
                           .getParent<fapi2::TARGET_TYPE_MC>();

        for(const auto& l_port : l_port_targets)
        {
            fapi2::ReturnCode l_rc;
            FAPI_INF("phy scominit for %s", mss::c_str(l_port));
            FAPI_EXEC_HWP(l_rc, explorer_scom, i_target, l_port, FAPI_SYSTEM, l_mc);

            FAPI_TRY(l_rc, "Error from explorer.scom.initfile %s", mss::c_str(l_port));
        }

        return fapi2::FAPI2_RC_SUCCESS;

    fapi_try_exit:
        FAPI_INF("End MSS SCOM init");
        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;
    }
/// @brief Enable Drivers/Recievers of O, PCIE, MC chiplets
///
/// @param[in]     i_target_chiplet   Reference to TARGET_TYPE_PERV target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
static fapi2::ReturnCode p9_chiplet_enable_ridi_net_ctrl_action_function(
    const fapi2::Target<fapi2::TARGET_TYPE_PERV>& i_target_chiplet)
{
    bool l_read_reg = false;
    fapi2::buffer<uint64_t> l_data64;
    FAPI_DBG("Entering ...");

    FAPI_INF("Check for chiplet enable");
    //Getting NET_CTRL0 register value
    FAPI_TRY(fapi2::getScom(i_target_chiplet, PERV_NET_CTRL0, l_data64));
    l_read_reg = l_data64.getBit<0>();  //l_read_reg = NET_CTRL0.CHIPLET_ENABLE

    if ( l_read_reg )
    {
        FAPI_INF("Enable Recievers, Drivers DI1 & DI2");
        //Setting NET_CTRL0 register value
        l_data64.flush<0>();
        l_data64.setBit<19>();  //NET_CTRL0.RI_N = 1
        l_data64.setBit<20>();  //NET_CTRL0.DI1_N = 1
        l_data64.setBit<21>();  //NET_CTRL0.DI2_N = 1
        FAPI_TRY(fapi2::putScom(i_target_chiplet, PERV_NET_CTRL0_WOR, l_data64));
    }

    FAPI_DBG("Exiting ...");

fapi_try_exit:
    return fapi2::current_err;

}
Example #7
0
fapi2::ReturnCode p9_i2ctest_puti2c_fail(
               fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
    // This will fail because PROC_CHIP not supported type
    FAPI_INF("Entering p9_i2ctest_puti2c_fail...");

    std::vector<uint8_t> l_i2cdata;
    l_i2cdata.push_back(1);
    l_i2cdata.push_back(2);
    l_i2cdata.push_back(3);
    l_i2cdata.push_back(4);
    l_i2cdata.push_back(5);


    FAPI_INF( "Do putI2c on proc target" );
    FAPI_TRY(fapi2::putI2c(i_target,
                           l_i2cdata));

 fapi_try_exit:

    FAPI_INF( "Exiting p9_i2ctest_puti2c_fail... rc = 0x%.8X",
              (uint64_t)fapi2::current_err );

    return fapi2::current_err;

}
Example #8
0
fapi2::ReturnCode p9_i2ctest_puti2c_pass(
               fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
{
    FAPI_INF("Entering p9_i2ctest_puti2c_pass...");
/*
    std::vector<uint8_t> l_i2cdata;

    // purposely truncate address to the last 2 bytes
    uint16_t offsetAddr = (uint16_t)SBE::SBE_VERSION_SEEPROM_ADDRESS;
    uint8_t * pOffset = (uint8_t*)&offsetAddr;

    l_i2cdata.push_back(pOffset[0]);
    l_i2cdata.push_back(pOffset[1]);
    l_i2cdata.push_back('P');
    l_i2cdata.push_back('U');
    l_i2cdata.push_back('T');
    l_i2cdata.push_back('I');
    l_i2cdata.push_back('2');
    l_i2cdata.push_back('C');
    l_i2cdata.push_back('-');
    l_i2cdata.push_back('P');
    l_i2cdata.push_back('A');
    l_i2cdata.push_back('S');
    l_i2cdata.push_back('S');

    FAPI_INF("Do putI2c on proc target");
    FAPI_TRY(fapi2::putI2c(i_target,
                           l_i2cdata));
 fapi_try_exit:
*/
    FAPI_INF("Exiting p9_i2ctest_puti2c_pass...");

    return fapi2::current_err;
}
Example #9
0
/// @brief check clocks status
///
/// @param[in]     i_regions            regions from upper level input
/// @param[in]     i_clock_status       clock status
/// @param[in]     i_reg                bit status
/// @param[in]     i_clock_cmd          clock command
/// @param[out]    o_exp_clock_status   expected clock status
/// @return  FAPI2_RC_SUCCESS if success, else error code.
fapi2::ReturnCode p9_sbe_common_check_status(const fapi2::buffer<uint64_t>
        i_regions,
        const fapi2::buffer<uint64_t> i_clock_status,
        const bool i_reg,
        const fapi2::buffer<uint8_t> i_clock_cmd,
        fapi2::buffer<uint64_t>& o_exp_clock_status)
{
    FAPI_INF("p9_sbe_common_check_status: Entering ...");

    if ( (i_reg) && (i_clock_cmd == 0b01) )
    {
        o_exp_clock_status = i_clock_status & (~(i_regions << 49));
    }
    else
    {
        if ( (i_reg) && (i_clock_cmd == 0b10) )
        {
            o_exp_clock_status = i_clock_status | (i_regions << 49);
        }
        else
        {
            o_exp_clock_status = i_clock_status;
        }
    }

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

    return fapi2::FAPI2_RC_SUCCESS;

}
Example #10
0
//------------------------------------------------------------------------------
// function: proc_tod_init
//
// parameters: i_tod_node  Reference to TOD topology (FAPI targets included within)
//
// returns: FAPI_RC_SUCCESS if TOD topology is successfully initialized
//          else FAPI or ECMD error is sent through
//------------------------------------------------------------------------------
fapi::ReturnCode proc_tod_init(const tod_topology_node* i_tod_node)
{
    fapi::ReturnCode rc;

    FAPI_INF("proc_tod_init: Start");
    do
    {
        if (i_tod_node == NULL)
        {
            FAPI_ERR("proc_tod_setup: null node passed into function!");
            FAPI_SET_HWP_ERROR(rc, RC_PROC_TOD_NULL_NODE);
            break;
        }

        rc = proc_tod_clear_error_reg(i_tod_node);
        if (!rc.ok())
        {
            FAPI_ERR("proc_tod_setup: Failure clearing TOD error registers!");
            break;
        }

        //Start configuring each node; (init_tod_node will recurse on each child)
        rc = init_tod_node(i_tod_node);
        if (!rc.ok())
        {
            FAPI_ERR("proc_tod_setup: Failure initializing TOD!");
            break;
        }

    } while (0);

    FAPI_INF("proc_tod_init: End");
    return rc;
}
Example #11
0
///
/// @brief Checks that the starting port/dimm address is in range for broadcast mode - helper for testing
/// @param[in] i_targets a vector of MCA targets
/// @param[in] i_start_addr the starting port_dimm select address
/// @return FAPI2_RC_SUCCESS iff okay
///
fapi2::ReturnCode broadcast_mode_start_address_check_helper(
    const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> >& i_targets,
    const uint64_t i_start_addr)
{
    if( i_targets.size() == 0 )
    {
        // Programming bug, multi_port_init check assures we shouldn't get here
        FAPI_INF("No ports passed in");
        fapi2::Assert(false);
    }

    // The check makes for bugs of not hitting the first port or hitting the middle dimm's multiple times
    // since multi_port_init loops through all valid DIMM's and plops the addresses in
    const auto l_first_configured_mca = i_targets[0];
    const auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_first_configured_mca);
    const auto l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(l_first_configured_mca);
    const size_t l_dimms_under_mca = mss::count_dimm(l_first_configured_mca);

    if( l_dimms.size() == 0)
    {
        FAPI_INF("No DIMMs under %s", mss::c_str(l_first_configured_mca));
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_INF("%d DIMMs under %s", l_dimms_under_mca, mss::c_str(l_first_configured_mca));

    // Bomb out if we have incorrect addresses
    // The following assert catches the error incorrect address error earlier
    // It also keeps the error meaningful with an invalid address callout rather than a generic MCBIST error callout

    // Note: we are guaranteed to have at least one DIMM, as we are not broadcast capable without DIMM's
    // The ports are also required to have the same number and type of DIMM's to be broadcast capable
    // As such, we can be guaranteed that we have at least one DIMM below
    const uint64_t l_port_dimm_offset = l_dimms_under_mca - 1;
    const uint64_t l_portdimm_this_dimm_min = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(l_dimms[0]);
    const uint64_t l_portdimm_this_dimm_max = l_portdimm_this_dimm_min + l_port_dimm_offset;

    FAPI_INF("Start port_dimm address %d, %s first configured mca start address %d",
             i_start_addr,
             mss::c_str(l_first_configured_mca),
             l_portdimm_this_dimm_min);


    // Checking that we are received a valid address (port_dimm) that is no less than the first configured port_dimm
    // on this MCBIST. This vector is sorted to make sure this is true.
    // Note: cronus always passes in a 0 address, so we need to support an address that is on or before this port
    FAPI_ASSERT( i_start_addr <= l_portdimm_this_dimm_max,
                 fapi2::MSS_MEMDIAGS_BCMODE_INVALID_ADDRESS()
                 .set_MCA_TARGET(l_first_configured_mca)
                 .set_START_ADDRESS(i_start_addr)
                 .set_MCA_START_ADDRESS(l_portdimm_this_dimm_min),
                 "%s address (%lu) is not the MCBIST's first configured port address (%lu)",
                 mss::c_str(l_mcbist), i_start_addr, l_portdimm_this_dimm_min);

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}
Example #12
0
///
/// @brief Calcuate the throttle values based on throttle type
/// @param[in] i_target
/// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Called in p9_mss_bulk_pwr_throttles
/// @note determines the throttle levels based off of the port's power curve,
/// sets the slot throttles to the same
/// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles
/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
///
fapi2::ReturnCode pwr_throttles( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
                                 const mss::throttle_type i_throttle_type)
{
    FAPI_INF("Start exp_bulk_pwr_throttle for %s type throttling for %s",
             (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER"), mss::c_str(i_target));

    if (mss::count_dimm (i_target) == 0)
    {
        return fapi2::FAPI2_RC_SUCCESS;
    }

    uint16_t l_slot = 0;
    uint16_t l_port  = 0;
    uint32_t l_power = 0;

    for (const auto& l_port_target : mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target))
    {
        fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;

        //Don't run if there are no dimms on the port
        if (mss::count_dimm(l_port_target) == 0)
        {
            continue;
        }

        mss::power_thermal::throttle<> l_pwr_struct(l_port_target, l_rc);
        FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s",
                 mss::c_str(l_port_target));

        //Let's do the actual work now
        if ( i_throttle_type == mss::throttle_type::THERMAL)
        {
            FAPI_TRY (l_pwr_struct.thermal_throttles());
        }
        else
        {
            FAPI_TRY (l_pwr_struct.power_regulator_throttles());
        }

        l_slot = l_pwr_struct.iv_n_slot;
        l_port = l_pwr_struct.iv_n_port;
        l_power = l_pwr_struct.iv_calc_port_maxpower;

        FAPI_INF("For target %s Calculated power is %d, throttle per slot is %d, throttle per port is %d",
                 mss::c_str(l_port_target), l_power, l_slot, l_port);

        FAPI_TRY(mss::attr::set_port_maxpower( l_port_target, l_power));
        FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_slot( l_port_target, l_slot));
        FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_port( l_port_target, l_port));
    }

    FAPI_INF("End bulk_pwr_throttles for %s", mss::c_str(i_target));
    return fapi2::current_err;

fapi_try_exit:
    FAPI_ERR("Error calculating bulk_pwr_throttles using %s throttling",
             ((i_throttle_type == mss::throttle_type::POWER) ? "power" : "thermal"));
    return fapi2::current_err;
}
Example #13
0
///
/// @brief Check the omi status in Axone side
/// @param[in] i_target the OMIC target to operate on
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode p9a_omi_train_check( const fapi2::Target<fapi2::TARGET_TYPE_OMI>& i_target)
{
    mss::display_git_commit_info("p9a_omi_train_check");

    FAPI_INF("%s Start p9a_omi_train_check", mss::c_str(i_target));

    // Const
    constexpr uint8_t STATE_MACHINE_SUCCESS = 0b111;  // This value is from Lonny Lambrecht
    constexpr uint8_t MAX_LOOP_COUNT = 20;  // Retry times

    // Declares variables
    fapi2::buffer<uint64_t> l_omi_status;
    fapi2::buffer<uint64_t> l_omi_training_status;
    uint8_t l_state_machine_state = 0;
    uint8_t l_tries = 0;

    FAPI_TRY(mss::mc::omi_train_status(i_target, l_state_machine_state, l_omi_status));

    while (l_tries < MAX_LOOP_COUNT && l_state_machine_state != STATE_MACHINE_SUCCESS)
    {
        // Delay
        fapi2::delay(mss::DELAY_100US, 10 * mss::DELAY_1MS);

        // Check OMI training status
        FAPI_TRY(mss::mc::omi_train_status(i_target, l_state_machine_state, l_omi_status));
        // Note: this is very useful debug information while trying to debug training during polling
        FAPI_TRY(mss::getScom(i_target, P9A_MC_REG2_DL0_TRAINING_STATUS, l_omi_training_status));
        l_tries++;
    }

    FAPI_TRY(mss::getScom(i_target, P9A_MC_REG2_DL0_TRAINING_STATUS, l_omi_training_status));
    FAPI_ASSERT(l_state_machine_state == STATE_MACHINE_SUCCESS,
                fapi2::P9A_OMI_TRAIN_ERR()
                .set_TARGET(i_target)
                .set_EXPECTED_SM_STATE(STATE_MACHINE_SUCCESS)
                .set_ACTUAL_SM_STATE(l_state_machine_state)
                .set_DL0_STATUS(l_omi_status)
                .set_DL0_TRAINING_STATUS(l_omi_training_status),
                "%s OMI Training Failure, expected state:%d/actual state:%d",
                mss::c_str(i_target),
                STATE_MACHINE_SUCCESS,
                l_state_machine_state
               );

    FAPI_INF("%s End p9a_omi_train_check, expected state:%d/actual state:%d, DL0_STATUS:0x%016llx, DL0_TRAINING_STATUS:0x%016llx",
             mss::c_str(i_target),
             STATE_MACHINE_SUCCESS,
             l_state_machine_state,
             l_omi_status,
             l_omi_training_status);
    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;

}// p9a_omi_train_check
Example #14
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
Example #15
0
//------------------------------------------------------------------------------
// function: proc_tod_clear_error_reg
//
// parameters: i_tod_node  Reference to TOD topology (FAPI targets included within)
//
// returns: FAPI_RC_SUCCESS if every TOD node is cleared of errors
//          else FAPI or ECMD error is sent through
//------------------------------------------------------------------------------
fapi::ReturnCode proc_tod_clear_error_reg(const tod_topology_node* i_tod_node)
{
    fapi::ReturnCode rc;
    ecmdDataBufferBase data(64);
    uint32_t rc_ecmd = 0;
    fapi::Target* target = i_tod_node->i_target;

    FAPI_INF("proc_tod_clear_error_reg: Start");
    do
    {
        if (i_tod_node == NULL)
        {
            FAPI_ERR("proc_tod_clear_error_reg: null node passed into function!");
            FAPI_SET_HWP_ERROR(rc, RC_PROC_TOD_NULL_NODE);
            break;
        }

        FAPI_DBG("proc_tod_clear_error_reg: Clear any previous errors from TOD_ERROR_REG_00040030");
        rc_ecmd |= data.flushTo1();
        if (rc_ecmd)
        {
            FAPI_ERR("proc_tod_clear_error_reg: Error 0x%08X in ecmdDataBuffer setup for TOD_ERROR_REG_00040030.",  rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }
        rc = fapiPutScom(*target, TOD_ERROR_REG_00040030, data);
        if (!rc.ok())
        {
            FAPI_ERR("proc_tod_clear_error_reg: Could not write TOD_ERROR_REG_00040030.");
            break;
        }

        for (std::list<tod_topology_node*>::const_iterator child = (i_tod_node->i_children).begin();
             child != (i_tod_node->i_children).end();
             ++child)
        {
            tod_topology_node* tod_node = *child;
            rc = proc_tod_clear_error_reg(tod_node);
            if (!rc.ok())
            {
                FAPI_ERR("proc_tod_clear_error_reg: Failure clearing errors from downstream node!");
                break;
            }
        }
        if (!rc.ok())
        {
            break;  // error in above for loop
        }
    } while (0);

    FAPI_INF("proc_tod_clear_error_reg: End");
    return rc;
}
Example #16
0
fapi2::ReturnCode p9_i2ctest_write_read_pass(
               fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
{
    FAPI_INF("Entering p9_i2ctest_write_read_pass...");
/*
    std::vector<uint8_t> l_i2cdata;
    std::vector<uint8_t> l_read_i2cdata;
    std::vector<uint8_t> l_read_offset;

    const uint8_t l_data[] = {0xFE,0xD9,
                              0x49,0x4E,0x56,0x41,0x4C,0x49,0x44,0x00,0x8C,
                              0x49,0x4E,0x56,0x41,0x4C,0x49,0x44,0x00,0x8C,
                              0x49,0x4E,0x56,0x41,0x4C,0x49,0x44,0x00,0x8C,
                              0x49,0x4E,0x56,0x41,0x4C,0x49,0x44,0x00,0x8C};
    const size_t l_read_size = sizeof(l_data) - 2;
    l_i2cdata.insert( l_i2cdata.end(), &l_data[0], &l_data[sizeof(l_data)] );
    l_read_offset.insert( l_read_offset.end(), &l_data[0], &l_data[2]);

    FAPI_INF("Calling putI2c on the target");
    FAPI_TRY(fapi2::putI2c(i_target,
                           l_i2cdata));

    // now read it out and verify it was written correctly
    FAPI_INF("Now read the just written data");
    FAPI_TRY(fapi2::getI2c(i_target,
                           l_read_size,
                           l_read_offset,
                           l_read_i2cdata));

    // remove 2-byte address part at beginning
    l_i2cdata.clear();
    l_i2cdata.insert( l_i2cdata.end(), &l_data[2], &l_data[sizeof(l_data)] );
    if (l_i2cdata == l_read_i2cdata)
    {
        FAPI_INF("Data found matches what was written");
    }
    else
    {
        FAPI_ERR( "Data found (%d) does NOT match written values (%d)",
            l_read_i2cdata.size(), l_i2cdata.size() );
        TRACFBIN(g_fapiTd, "getI2c returned", l_read_i2cdata.data(), l_read_i2cdata.size());
        TRACFBIN(g_fapiTd, "putI2c wrote", l_i2cdata.data(), l_i2cdata.size());
    }

 fapi_try_exit:
*/
    FAPI_INF("Exiting p9_i2ctest_write_read_pass...");

    return fapi2::current_err;
}
Example #17
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;

}
Example #18
0
// HWP entry point, comments in header
fapi2::ReturnCode p9_io_obus_scominit( const fapi2::Target<fapi2::TARGET_TYPE_OBUS>& i_target )
{
    // mark HWP entry
    FAPI_INF("p9_io_obus_scominit: Entering...");
    const uint8_t GROUP_00 = 0;
    const uint8_t LANE_00  = 0;
    const uint8_t SET_RESET = 1;
    const uint8_t CLEAR_RESET = 0;
    fapi2::ReturnCode rc = fapi2::FAPI2_RC_SUCCESS;

    // get system target
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_system_target;

    // get a proc target
    fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_proc_target = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    // assert IO reset to power-up bus endpoint logic
    FAPI_TRY( io::rmw( OPT_IORESET_HARD_BUS0, i_target, GROUP_00, LANE_00, SET_RESET ) );

    // Bus Reset is relatively fast, only needing < a hundred cycles to allow the signal to propogate.
    FAPI_TRY( fapi2::delay( 10, 1000 ) );

    FAPI_TRY( io::rmw( OPT_IORESET_HARD_BUS0, i_target, GROUP_00, LANE_00, CLEAR_RESET ) );

    FAPI_INF("Invoke FAPI procedure core: input_target");
    FAPI_EXEC_HWP(rc, p9_obus_scom, i_target, l_system_target, l_proc_target);

    // configure FIR
    {
        FAPI_TRY(fapi2::putScom(i_target,
                                OBUS_FIR_ACTION0_REG,
                                OBUS_PHY_FIR_ACTION0),
                 "Error from putScom (OBUS_FIR_ACTION0_REG)");
        FAPI_TRY(fapi2::putScom(i_target,
                                OBUS_FIR_ACTION1_REG,
                                OBUS_PHY_FIR_ACTION1),
                 "Error from putScom (OBUS_FIR_ACTION1_REG)");
        FAPI_TRY(fapi2::putScom(i_target,
                                OBUS_FIR_MASK_REG,
                                OBUS_PHY_FIR_MASK),
                 "Error from putScom (OBUS_FIR_MASK_REG)");
    }

    // mark HWP exit
    FAPI_INF("p9_io_obus_scominit: ...Exiting");

fapi_try_exit:
    return fapi2::current_err;
}
Example #19
0
///
/// @brief Helper function for mrs05_decode
/// @param[in] i_inst the CCS instruction
/// @param[in] i_rank the rank in question
/// @param[out] o_crc_error_clear the crc error clear setting
/// @param[out] o_ca_parity_error_status the c/a parity error status
/// @param[out] o_odt_input_buffer the odt input buffer during power down mode setting
/// @param[out] o_ca_parity the c/a parity persistent error setting
/// @param[out] o_data_mask the data mask setting
/// @param[out] o_write_dbi the write dbi setting
/// @param[out] o_read_dbi the read dbi setting
/// @param[out] o_ca_parity_latency_buffer the c/a parity latency mode setting
/// @param[out] o_rtt_park_buffer the rtt_park setting
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode mrs05_decode_helper(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst,
                                      const uint64_t i_rank,
                                      uint8_t& o_crc_error_clear,
                                      uint8_t& o_ca_parity_error_status,
                                      uint8_t& o_odt_input_buffer,
                                      uint8_t& o_ca_parity,
                                      uint8_t& o_data_mask,
                                      uint8_t& o_write_dbi,
                                      uint8_t& o_read_dbi,
                                      fapi2::buffer<uint8_t>& o_ca_parity_latency_buffer,
                                      fapi2::buffer<uint8_t>& o_rtt_park_buffer)
{
    o_ca_parity_latency_buffer = 0;
    o_rtt_park_buffer = 0;

    mss::swizzle<5, 3, A2>(i_inst.arr0, o_ca_parity_latency_buffer);
    mss::swizzle<5, 3, A8>(i_inst.arr0, o_rtt_park_buffer);

    o_crc_error_clear = i_inst.arr0.getBit<A3>();
    o_ca_parity_error_status = i_inst.arr0.getBit<A4>();
    o_odt_input_buffer = i_inst.arr0.getBit<A5>();

    o_ca_parity = i_inst.arr0.getBit<A9>();
    o_data_mask = i_inst.arr0.getBit<A10>();
    o_write_dbi = i_inst.arr0.getBit<A11>();
    o_read_dbi = i_inst.arr0.getBit<A12>();

    FAPI_INF("MR5 rank %d decode: CAPL: 0x%x, CRC_EC: 0x%x, CA_PES: 0x%x, ODT_IB: 0x%x "
             "RTT_PARK: 0x%x, CAP: 0x%x, DM: 0x%x, WDBI: 0x%x, RDBI: 0x%x",
             i_rank, uint8_t(o_ca_parity_latency_buffer), o_crc_error_clear, o_ca_parity_error_status,
             o_odt_input_buffer, uint8_t(o_rtt_park_buffer), o_ca_parity, o_data_mask,
             o_write_dbi, o_read_dbi);

    return FAPI2_RC_SUCCESS;
}
Example #20
0
    ///
    /// @brief Setup the OCMB for enterprise and half-DIMM modes as desired
    /// @param[in] i_target the OCMB target to operate on
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode exp_omi_setup( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
    {
        mss::display_git_commit_info("exp_omi_setup");

        // Declares variables
        fapi2::buffer<uint64_t> l_data;
        bool l_is_enterprise = false;
        bool l_is_half_dimm = false;

        // Gets the configuration information from attributes
        FAPI_TRY(mss::enterprise_mode(i_target, l_is_enterprise));
        FAPI_TRY(mss::half_dimm_mode(i_target, l_is_half_dimm));

        // Prints out the data
        FAPI_INF("%s %s enterprise mode %s-DIMM mode", mss::c_str(i_target), l_is_enterprise ? "is" : "isn't",
                 l_is_half_dimm ? "half" : "full");

        // Sets up the register
        mss::exp::omi::set_enterprise_set_bit(l_data, l_is_enterprise);
        mss::exp::omi::set_half_dimm_mode(l_data, l_is_half_dimm);

        // Writes the data to the register
        FAPI_TRY(mss::exp::omi::write_enterprise_config(i_target, l_data));

        // Checks that the chip is configured correctly
        FAPI_TRY(mss::exp::omi::read_enterprise_config(i_target, l_data));
        FAPI_TRY(mss::exp::omi::check_enterprise_mode(i_target, l_is_enterprise, l_data));

    fapi_try_exit:
        return fapi2::current_err;
    }
Example #21
0
//******************************************************************************
// fapiUnloadInitFile
//******************************************************************************
fapi::ReturnCode fapiUnloadInitFile(const char * i_file, const char *& io_addr,
    size_t & io_size)
{
#ifndef __HOSTBOOT_RUNTIME
    fapi::ReturnCode l_rc = fapi::FAPI_RC_SUCCESS;
    errlHndl_t l_pError = NULL;

    FAPI_INF("fapiUnloadInitFile: %s", i_file);

    l_pError = VFS::module_unload(i_file);
    if(l_pError)
    {
        // Add the error log pointer as data to the ReturnCode
        FAPI_ERR("fapiUnloadInitFile: module_unload failed %s", i_file);
        l_rc.setPlatError(reinterpret_cast<void *> (l_pError));
    }
    else
    {
        io_addr = NULL;
        io_size = 0;
    }
#else
    fapi::ReturnCode l_rc = fapi::FAPI_RC_PLAT_NOT_SUPPORTED_AT_RUNTIME;
#endif

    return l_rc;
}
Example #22
0
fapi2::ReturnCode p9_pm_cme_firinit(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const p9pm::PM_FLOW_MODE i_mode)
{
    FAPI_IMP("p9_pm_cme_firinit start");

    if(i_mode == p9pm::PM_RESET)
    {
        FAPI_TRY(pm_cme_fir_reset(i_target),
                 "ERROR: Failed to reset the CME FIRs");
    }
    else if(i_mode == p9pm::PM_INIT)
    {
        FAPI_TRY(pm_cme_fir_init(i_target),
                 "ERROR: Failed to initialize the CME FIRs");
    }
    else
    {
        FAPI_ASSERT(false, fapi2::PM_CME_FIRINIT_BAD_MODE().set_BADMODE(i_mode),
                    "ERROR; Unknown mode passed to p9_pm_cme_firinit. Mode %x",
                    i_mode);
    }

fapi_try_exit:
    FAPI_INF("p9_pm_cme_firinit end");
    return fapi2::current_err;
}
Example #23
0
///
/// @brief Helper function to set DAC_COARSE reg
/// @param[in] i_target the fapi2 target
/// @param[in] i_failed_dll_dac failed DLL VREG COARSE
/// @param[in] i_value the value to set
/// @return FAPI2_RC_SUCCESS iff ok
///
static fapi2::ReturnCode dll_dac_helper(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
                                        const fapi2::buffer<uint64_t>& i_failed_dll_dac,
                                        const uint64_t i_value)
{
    constexpr uint64_t SOURCE_START = dll_map::REGS_RXDLL_VREG;

    // Read DAC coarse from failed DLL
    fapi2::buffer<uint64_t> l_data;

    FAPI_TRY( mss::getScom(i_target, i_failed_dll_dac, l_data),
              "Failed getScom() operation on %s reg 0x%016llx",
              mss::c_str(i_target), i_failed_dll_dac );


    l_data.insert<dll_map::REGS_RXDLL_VREG,
                  dll_map::REGS_RXDLL_VREG_LEN,
                  SOURCE_START>(i_value);

    FAPI_INF("%s Writing to DAC_REG 0x%016llx, data 0x%016llx, value 0x%llx",
             mss::c_str(i_target), i_failed_dll_dac, l_data, i_value);

    // Write DAC coarse from failed DLL with DAC coarse from neighboring DLL
    FAPI_TRY( mss::putScom(i_target, i_failed_dll_dac, l_data),
              "Failed putScom() operation on %s reg 0x%016llx",
              mss::c_str(i_target), i_failed_dll_dac );

fapi_try_exit:
    return fapi2::current_err;
}
Example #24
0
///
/// @brief Change VREG_COARSE for failed DLLs
/// @param[in] i_target the fapi2 target
/// @param[in] i_failed_dll_map failed DLL VREG COARSE map
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode change_vreg_coarse(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
                                     const std::map< fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> >& i_failed_dll_map)
{
    for( const auto& map : i_failed_dll_map)
    {
        // Little renaming to help clarify map fields
        const auto FAILING_COARSE_REG = map.first;
        const auto NEIGHBOR_DATA = map.second;

        fapi2::buffer<uint64_t> l_data;

        // Read DAC coarse from failed DLL
        FAPI_TRY( mss::getScom(i_target, FAILING_COARSE_REG, l_data),
                  "Failed getScom() operation on %s reg 0x%016llx",
                  mss::c_str(i_target), FAILING_COARSE_REG );


        FAPI_DBG("%s Read DLL_VREG_COARSE reg 0x%016llx, data 0x%016llx",
                 mss::c_str(i_target), FAILING_COARSE_REG, l_data);

        l_data.insertFromRight< dll_map::REGS_RXDLL_DAC_COARSE,
                                dll_map::REGS_RXDLL_DAC_COARSE_LEN>(NEIGHBOR_DATA);

        FAPI_INF("%s Writing to DLL_VREG_COARSE reg 0x%016llx, data 0x%016llx, value 0x%llx",
                 mss::c_str(i_target), FAILING_COARSE_REG, l_data, NEIGHBOR_DATA);

        // Write DAC coarse from failed DLL with DAC coarse from neighboring DLL
        FAPI_TRY( mss::putScom(i_target, FAILING_COARSE_REG, l_data),
                  "Failed putScom() operation on %s reg 0x%016llx",
                  mss::c_str(i_target), FAILING_COARSE_REG );
    }

fapi_try_exit:
    return fapi2::current_err;
}
Example #25
0
//******************************************************************************
// targetTest1
//******************************************************************************
uint32_t targetTest1()
{
    uint32_t l_result = 0;

    // Create Target using default constructor
    Target l_target;

    // Ensure that the handle pointer is NULL
    void * l_pHandle = l_target.get();

    if (l_pHandle != NULL)
    {
        FAPI_ERR("targetTest1. Handle is not NULL");
        l_result = 1;
    }
    else
    {
        // Ensure that the type is TARGET_TYPE_NONE
        TargetType l_type = l_target.getType();

        if (l_type != TARGET_TYPE_NONE)
        {
            FAPI_ERR("targetTest1. Type is 0x%x, expected NONE", l_type);
            l_result = 2;
        }
        else
        {
            FAPI_INF("targetTest1. Success!");
        }
    }

    return l_result;
}
Example #26
0
//******************************************************************************
// targetTest8
//******************************************************************************
uint32_t targetTest8()
{
    uint32_t l_result = 0;
    uint8_t l_handle = 7;
    void * l_pHandle = reinterpret_cast<void *>(&l_handle);

    // Create Target
    Target l_target(TARGET_TYPE_L4, l_pHandle);

    // an L4 Target is not a chip
    if ( l_target.isChip() )
    {
        FAPI_ERR("targetTest8. L4 target incorrectly"
                                " identified itself as a chip");
        l_result = 1;
    }
    else
    {

        if ( !l_target.isChiplet() )
        {
            FAPI_ERR("targetTest8. L4 target failed to identify as a chiplett" );
            l_result = 2;
        }
        else
        {
            FAPI_INF("targetTest8. Success!");
        }
    }

    // Set the handle pointer to NULL to prevent any problem on destruction
    l_target.set(NULL);

    return l_result;
}
Example #27
0
///
/// @brief Helper to evaluate the unsupported rank config override attribute
/// @param[in] i_dimm0_ranks count of the ranks on DIMM in slot 0
/// @param[in] i_dimm1_ranks count of the ranks on DIMM in slot 1
/// @param[in] i_attr value of the attribute containing the unsupported rank configs
/// @return true iff this rank config is supported according to the unsupported attribute
/// @note not to be used to enforce populated/unpopulated - e.g., 0 ranks in both slots is ignored
///
bool unsupported_rank_helper(const uint64_t i_dimm0_ranks, const uint64_t i_dimm1_ranks,
                             const fapi2::buffer<uint64_t>& i_attr)
{
    // Quick - if the attribute is 0 (typically is) then we're out.
    if (i_attr == 0)
    {
        FAPI_INF("(%d, %d) is supported, override empty", i_dimm0_ranks, i_dimm1_ranks);
        return true;
    }

    // Quick - if both rank configs are 0 (no ranks seen in any slots) we return true. This is always OK.
    if ((i_dimm0_ranks == 0) && (i_dimm1_ranks == 0))
    {
        FAPI_INF("(%d, %d) is always supported", i_dimm0_ranks, i_dimm1_ranks);
        return true;
    }

    // We use 8 bits to represent a config in the unsupported ranks attribute. Each 'config' is a byte in
    // the attribute. The left nibble is the count of ranks on DIMM0, right nibble is the count of unsupported
    // ranks on DIMM1. Total ranks so we need the bits to represent stacks too.
    uint64_t l_current_byte  = 0;

    do
    {
        uint8_t  l_config = 0;
        uint64_t l_current_dimm0 = 0;
        uint64_t l_current_dimm1 = 0;

        i_attr.extractToRight(l_config, l_current_byte * BITS_PER_BYTE, BITS_PER_BYTE);

        fapi2::buffer<uint8_t>(l_config).extractToRight<0,               BITS_PER_NIBBLE>(l_current_dimm0);
        fapi2::buffer<uint8_t>(l_config).extractToRight<BITS_PER_NIBBLE, BITS_PER_NIBBLE>(l_current_dimm1);

        FAPI_INF("Seeing 0x%x for unsupported rank config (%d, %d)", l_config, l_current_dimm0, l_current_dimm1);

        if ((l_current_dimm0 == i_dimm0_ranks) && (l_current_dimm1 == i_dimm1_ranks))
        {
            FAPI_INF("(%d, %d) is unsupported", i_dimm0_ranks, i_dimm1_ranks);
            return false;
        }

    }
    while (++l_current_byte < sizeof(uint64_t));

    FAPI_INF("(%d, %d) is supported", i_dimm0_ranks, i_dimm1_ranks);
    return true;
}
Example #28
0
void platSetOpMode(const OpModes i_mode)
{
    FAPI_INF("Setting fapi2::opMode to be 0x%x", i_mode);
    opMode = static_cast<OpModes>(
                static_cast<uint8_t>(opMode) | static_cast<uint8_t>(i_mode)
                );
    return;
}
Example #29
0
// -----------------------------------------------------------------------------
//  pba_reset  -- mode = PM_RESET
// -----------------------------------------------------------------------------
fapi2::ReturnCode pba_reset(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{

    std::vector<uint64_t> v_pba_reset_regs =
    {
        PU_BCDE_PBADR_SCOM,
        PU_BCDE_OCIBAR_SCOM,
        PU_BCUE_CTL_SCOM,
        PU_BCUE_SET_SCOM,
        PU_BCUE_PBADR_SCOM,
        PU_BCUE_OCIBAR_SCOM,
        PU_PBAXSHBR0_SCOM,
        PU_PBAXSHBR1_SCOM,
        PU_PBAXSHCS0_SCOM,
        PU_PBAXSHCS1_SCOM,
        PU_PBASLVCTL0_SCOM,
        PU_PBASLVCTL1_SCOM,
        PU_PBASLVCTL2_SCOM,
        PU_PBAFIR,
        PU_PBACFG,
        PU_PBAERRRPT0
    };

    FAPI_IMP(">> pba_reset ...");

    fapi2::buffer<uint64_t> l_data64;

    // Stop the  BCDE and BCUE
    FAPI_TRY(pba_bc_stop(i_target), "pba_bc_stop() detected an error");

    // Reset each slave and wait for completion.
    FAPI_TRY(pba_slave_reset(i_target), "pba_slave_reset() failed.");

    for (auto it : v_pba_reset_regs)
    {
        FAPI_DBG("Resetting PBA register 0x%08llX", it);
        FAPI_TRY(fapi2::putScom(i_target, it, 0),
                 "Failed to reset register 0x%08llX",  it);
    }

    // Perform non-zero reset operations
    // Reset PBAX errors via Configuration Register
    //     Bit 2: PBAXCFG_SND_RESET
    //     Bit 3: PBAXCFG_RCV_RESET
    l_data64.setBit<2, 2>();
    FAPI_INF("Resetting PBAX errors via PBAX config register 0x%08llX with "
             "value = 0x%16llX", PU_PBAXCFG_SCOM, uint64_t(l_data64));
    FAPI_TRY(fapi2::putScom(i_target, PU_PBAXCFG_SCOM, l_data64));

    // Perform PBA Slave setup to prepare for the boot phase.
    FAPI_TRY(pba_slave_setup_boot_phase(i_target),
             "pba_slave_setup_boot_phase() failed. ");

fapi_try_exit:
    FAPI_IMP("<< pba_reset ...");
    return fapi2::current_err;
}
Example #30
0
///
/// @brief End of rank work around
/// For Nimbus DD1 the MCBIST engine doesn't detect the end of rank properly
/// for a 1R DIMM during a super-fast read. To work around this, we check the
/// MCBIST to see if any port has a 1R DIMM on it and if so we change our stop
/// conditions to immediate. However, because that doesn't work (by design) with
/// read, we also must change all reads to displays (slow read.)
/// @param[in] i_target the fapi2 target of the mcbist
/// @param[in,out] io_program the mcbist program to check
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode end_of_rank( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
                               mss::mcbist::program<TARGET_TYPE_MCBIST>& io_program )
{
    using TT = mss::mcbistTraits<TARGET_TYPE_MCBIST>;

    // If we don't need the mcbist work-around, we're done.
    if (! mss::chip_ec_feature_mcbist_end_of_rank(i_target) )
    {
        return FAPI2_RC_SUCCESS;
    }

    // First things first - lets find out if we have an 1R DIMM on our side of the chip.
    const auto l_dimm_kinds = dimm::kind::vector( mss::find_targets<TARGET_TYPE_DIMM>(i_target) );
    const auto l_kind = std::find_if(l_dimm_kinds.begin(), l_dimm_kinds.end(), [](const dimm::kind & k) -> bool
    {
        // If total ranks are 1, we have a 1R DIMM, SDP. This is the fellow of concern
        return k.iv_total_ranks == 1;
    });

    // If we don't find the fellow of concern, we can get outta here
    if (l_kind == l_dimm_kinds.end())
    {
        FAPI_INF("no 1R SDP DIMM on this MCBIST (%s), we're ok", mss::c_str(i_target));
        return FAPI2_RC_SUCCESS;
    }

    // Keep in mind that pause-on-error-mode is two bits and it doesn't encode master/slave. The
    // end_boundary enums are constructed such that STOP_AFTER_MASTER_RANK is really stop on
    // either master or slave for the purposes of this field. So, checking stop-after-master-rank
    // will catch both master and slave pauses which is correct for this work-around.
    uint64_t l_pause_mode = 0;
    io_program.iv_config.extractToRight<TT::CFG_PAUSE_ON_ERROR_MODE, TT::CFG_PAUSE_ON_ERROR_MODE_LEN>(l_pause_mode);

    if( l_pause_mode != mss::mcbist::end_boundary::STOP_AFTER_MASTER_RANK )
    {
        FAPI_INF("not checking rank boundaries on this MCBIST (%s), we're ok", mss::c_str(i_target));
        return FAPI2_RC_SUCCESS;
    }

    // If we're here, we need to fix up our program. We need to set our stop to stop immediate, which implies
    // we don't do broadcasts and we can't do read, we have to do display.
    replace_read_helper(io_program);

    return fapi2::FAPI2_RC_SUCCESS;
}