Skip to content

Commit

Permalink
Add code and workarounds for *_omi_setup and *_omi_train for Swift
Browse files Browse the repository at this point in the history
Change-Id: I139357a553e621b25b46bee6303357c712b67be2
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/83848
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Dev-Ready: Steven B Janssen <janssens@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Christian R Geddes <crgeddes@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/83905
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
Tested-by: Daniel M Crowell <dcrowell@us.ibm.com>
  • Loading branch information
markypizz authored and dcrowell77 committed Oct 17, 2019
1 parent 70b54e6 commit 8f549e7
Show file tree
Hide file tree
Showing 21 changed files with 771 additions and 154 deletions.
Expand Up @@ -34,6 +34,7 @@
// *HWP Consumed by: Memory

#include <fapi2.H>
#include <exp_omi_setup.H>
#include <generic/memory/lib/utils/c_str.H>
#include <lib/exp_attribute_accessors_manual.H>
#include <lib/omi/exp_omi_utils.H>
Expand All @@ -42,6 +43,7 @@
#include <generic/memory/mss_git_data_helper.H>
#include <generic/memory/lib/mss_generic_attribute_getters.H>
#include <generic/memory/lib/mss_generic_system_attribute_getters.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>

extern "C"
{
Expand All @@ -54,17 +56,14 @@ extern "C"
fapi2::ReturnCode exp_omi_setup( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
{
mss::display_git_commit_info("exp_omi_setup");
uint8_t l_gem_menterp_workaround = 0;

// Declares variables
fapi2::buffer<uint64_t> l_data;
fapi2::buffer<uint64_t> dlx_config1_data;
uint8_t l_edpl_disable = 0;
bool l_is_enterprise = false;
bool l_is_half_dimm = false;
bool l_workaround_required = false;
std::vector<uint8_t> l_boot_config_data;

// BOOT CONFIG 0
uint8_t l_dl_layer_boot_mode = fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_DL_LAYER_BOOT_MODE_NON_DL_TRAINING;
uint8_t l_gem_menterp_workaround = 0;

// Gets the data setup
FAPI_TRY(mss::exp::omi::train::setup_fw_boot_config(i_target, l_boot_config_data));

Expand All @@ -75,12 +74,27 @@ extern "C"
// Note: This does not kick off OMI training
FAPI_TRY(mss::exp::i2c::boot_config(i_target, l_boot_config_data));

// Check FW status for success
FAPI_TRY(mss::exp::i2c::fw_status(i_target, mss::DELAY_1MS, 100));

FAPI_TRY(mss::exp::workarounds::omi::gem_menterp(i_target, l_gem_menterp_workaround));

// If no workaround, we can perform menterp reads/writes (explorer)
// If workaround (gem). we need to bypass menterp. Can also bypass dlx_config1 since it's a noop
if (!l_gem_menterp_workaround)
// If no workaround (explorer), we can perform menterp reads/writes
// If workaround (gemini). we need to bypass menterp. Can also bypass dlx_config1 too since it's a noop
if (l_gem_menterp_workaround)
{
return fapi2::FAPI2_RC_SUCCESS;
}

// Set up DLX_CONFIG1
{
fapi2::buffer<uint64_t> l_data;
fapi2::buffer<uint64_t> l_dlx_config1_data;

uint8_t l_edpl_disable = 0;
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));
Expand All @@ -102,24 +116,15 @@ extern "C"
FAPI_TRY(mss::exp::omi::check_enterprise_mode(i_target, l_is_enterprise, l_data));

// Set the EDPL according the attribute
FAPI_TRY(mss::exp::omi::read_dlx_config1(i_target, dlx_config1_data));
mss::exp::omi::set_edpl_enable_bit(dlx_config1_data, l_edpl_disable);
FAPI_TRY(mss::exp::omi::write_dlx_config1(i_target, dlx_config1_data));
FAPI_TRY(mss::exp::omi::read_dlx_config1(i_target, l_dlx_config1_data));
mss::exp::omi::set_edpl_enable_bit(l_dlx_config1_data, !l_edpl_disable);
FAPI_TRY(mss::exp::omi::write_dlx_config1(i_target, l_dlx_config1_data));
FAPI_INF("%s EDPL enable: %s", mss::c_str(i_target), l_edpl_disable ? "false" : "true");
}

// Run the workaround if it's needed
FAPI_TRY(mss::exp::workarounds::omi::is_prbs_ocmb_required(i_target, l_workaround_required));

if (l_workaround_required)
{
uint8_t l_dl_x4_backoff_en = 0;

FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_OMI_DL_X4_BACKOFF_ENABLE, i_target, l_dl_x4_backoff_en),
"Error getting ATTR_CHIP_EC_FEATURE_OMI_DL_X4_BACKOFF_ENABLE");

FAPI_TRY(mss::exp::workarounds::omi::prbs_ocmb(i_target, l_dl_x4_backoff_en));
}
// Perform p9a workaround
// Train mode 6 (state 3)
FAPI_TRY(mss::exp::workarounds::omi::pre_training_prbs(i_target));

fapi_try_exit:
return fapi2::current_err;
Expand Down
Expand Up @@ -37,8 +37,12 @@
#include <generic/memory/lib/utils/c_str.H>
#include <lib/omi/exp_omi_utils.H>
#include <lib/i2c/exp_i2c.H>
#include <lib/exp_attribute_accessors_manual.H>
#include <lib/workarounds/exp_omi_workarounds.H>
#include <exp_omi_train.H>
#include <generic/memory/mss_git_data_helper.H>
#include <generic/memory/lib/mss_generic_attribute_getters.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>

extern "C"
{
Expand All @@ -52,18 +56,41 @@ extern "C"
{
mss::display_git_commit_info("exp_omi_train");

std::vector<uint8_t> l_data;
uint8_t l_dl_layer_boot_mode = fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_DL_LAYER_BOOT_MODE_ONLY_DL_TRAINING;
// Perform p9a workaround
// Train mode 1 (PATTERN_A)
FAPI_TRY(mss::exp::workarounds::omi::training_prbs(i_target));

// Gets the data setup
FAPI_TRY(mss::exp::omi::train::setup_fw_boot_config(i_target, l_data));
// BOOT CONFIG 1
{
bool l_ocmb_is_explorer = false;

// Sets DL_TRAIN field
FAPI_TRY(mss::exp::i2c::boot_cfg::set_dl_layer_boot_mode( i_target, l_data, l_dl_layer_boot_mode ));
std::vector<uint8_t> l_data;
uint8_t l_dl_layer_boot_mode = fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_DL_LAYER_BOOT_MODE_ONLY_DL_TRAINING;

// Issues the command and checks for completion
// Note: the status check also checks for the OMI training completion, so after we run this command, we're good to go
FAPI_TRY(mss::exp::i2c::boot_config(i_target, l_data));
// Gets the data setup
FAPI_TRY(mss::exp::omi::train::setup_fw_boot_config(i_target, l_data));

// Sets DL_TRAIN field
FAPI_TRY(mss::exp::i2c::boot_cfg::set_dl_layer_boot_mode( i_target, l_data, l_dl_layer_boot_mode ));

// Issues the command and checks for completion
FAPI_TRY(mss::exp::i2c::boot_config(i_target, l_data));

// Check for expected busy status (this won't work for gemini)
FAPI_TRY(mss::exp::workarounds::omi::ocmb_is_explorer(i_target, l_ocmb_is_explorer));

if (l_ocmb_is_explorer)
{
// Explorer & P9A environment should see a busy status until auto train is kicked off from both sides
FAPI_TRY(mss::exp::i2c::check_fw_status_busy(i_target));
}
else
{
// Gemini should return success code
FAPI_TRY(mss::exp::i2c::fw_status(i_target, mss::DELAY_1MS, 100));
}

}

fapi_try_exit:
return fapi2::current_err;
Expand Down
Expand Up @@ -22,3 +22,118 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */

/// @file exp_omi_train_check.C
/// @brief Check that omi training was successful from explorer side
///
/// *HWP HWP Owner: Mark Pizzutillo <Mark.Pizzutillo@ibm.com>
/// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
/// *HWP Team: Memory
/// *HWP Level: 2
/// *HWP Consumed by: HB

#include <fapi2.H>
#include <exp_omi_train_check.H>
#include <lib/omi/exp_omi_utils.H>
#include <generic/memory/mss_git_data_helper.H>
#include <lib/shared/exp_consts.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/i2c/exp_i2c.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>

///
/// @brief Check that the OCMB's omi state machine is in its expected state after OMI training
/// @param[in] i_target the OCMB target to check
/// @return FAPI2_RC_SUCCESS iff ok
/// @note the functionality of this procedure was made to match that of p9a_omi_train_check
///
fapi2::ReturnCode exp_omi_train_check(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
{
mss::display_git_commit_info("exp_omi_train_check");

FAPI_INF("%s Start exp_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 = 10; // Retry times
const auto& l_omi = mss::find_target<fapi2::TARGET_TYPE_OMI>(i_target);
const auto& l_proc = mss::find_target<fapi2::TARGET_TYPE_PROC_CHIP>(i_target);

// Declares variables
fapi2::buffer<uint64_t> l_omi_status;
fapi2::buffer<uint64_t> l_omi_training_status;
fapi2::buffer<uint64_t> l_dl0_error_hold;
fapi2::buffer<uint64_t> l_expected_dl0_error_hold;
fapi2::buffer<uint64_t> l_dl0_config1;
uint8_t l_state_machine_state = 0;
uint8_t l_tries = 0;
uint32_t l_omi_freq = 0;

do
{
// Delay
fapi2::delay(500 * mss::DELAY_1MS, 10 * mss::DELAY_1MS);

// Check OMI training status
FAPI_TRY(mss::exp::omi::train::omi_train_status(i_target, l_state_machine_state, l_omi_status));
l_tries++;

}
while (l_tries < MAX_LOOP_COUNT && l_state_machine_state != STATE_MACHINE_SUCCESS);

// Note: this is very useful debug information while trying to debug training during polling
FAPI_TRY(fapi2::getScom(i_target, EXPLR_DLX_DL0_TRAINING_STATUS, l_omi_training_status));
FAPI_TRY(fapi2::getScom(i_target, EXPLR_DLX_DL0_CONFIG1, l_dl0_config1));
FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_OMI_MHZ, l_proc, l_omi_freq));


FAPI_ASSERT(l_state_machine_state == STATE_MACHINE_SUCCESS,
fapi2::EXP_OMI_TRAIN_ERR()
.set_OCMB_TARGET(i_target)
.set_OMI_TARGET(l_omi)
.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)
.set_DL0_CONFIG1(l_dl0_config1)
.set_OMI_FREQ(l_omi_freq),
"%s EXP OMI Training Failure, expected state:%d/actual state:%d",
mss::c_str(i_target),
STATE_MACHINE_SUCCESS,
l_state_machine_state
);

// Finally, make sure fw_status is good
FAPI_TRY(mss::exp::i2c::fw_status(i_target, mss::common_timings::DELAY_1MS, 100));

// Check for errors in ERROR_HOLD until we get a proper FIR API setup
FAPI_TRY(fapi2::getScom(i_target, EXPLR_DLX_DL0_ERROR_HOLD, l_dl0_error_hold));

// Training done bit
l_expected_dl0_error_hold.setBit<EXPLR_DLX_DL0_ERROR_HOLD_CERR_39>();

if (l_dl0_error_hold != l_expected_dl0_error_hold)
{
// To get to this point, we had to have completed training, so these errors are not catastrophic
// We don't need to assert out, but let's make sure we print them out
FAPI_INF("%s EXPLR_DLX_DL0_ERROR_HOLD REG 0x%016llx "
"did not match expected value. REG contents: 0x%016llx Expected: 0x%016llx",
mss::c_str(i_target),
EXPLR_DLX_DL0_ERROR_HOLD,
l_dl0_error_hold,
l_expected_dl0_error_hold);
}

FAPI_INF("%s End exp_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;

}// exp_omi_train_check
Expand Up @@ -22,3 +22,32 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */

/// @file exp_omi_train_check.C
/// @brief Check that omi training was successful from explorer side
///
/// *HWP HWP Owner: Mark Pizzutillo <Mark.Pizzutillo@ibm.com>
/// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
/// *HWP Team: Memory
/// *HWP Level: 2
/// *HWP Consumed by: HB

#ifndef _EXP_OMI_TRAIN_CHECK_H_
#define _EXP_OMI_TRAIN_CHECK_H_

#include <fapi2.H>

typedef fapi2::ReturnCode (*exp_omi_train_check_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&);

extern "C"
{

///
/// @brief Check that the OCMB's omi state machine is in its expected state after OMI training
/// @param[in] i_target the OCMB target to check
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode exp_omi_train_check(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target);
}

#endif
Expand Up @@ -22,3 +22,8 @@
# permissions and limitations under the License.
#
# IBM_PROLOG_END_TAG
-include 00exp_common.mk

PROCEDURE=exp_omi_train_check
$(eval $(call ADD_EXP_MEMORY_INCDIRS,$(PROCEDURE)))
$(call BUILD_PROCEDURE)
Expand Up @@ -295,11 +295,39 @@ inline fapi2::ReturnCode boot_config(const fapi2::Target<fapi2::TARGET_TYPE_OCMB
// The command takes ~300ms and we poll for around 100ms, so wait 250ms here
FAPI_TRY( fapi2::delay( (mss::DELAY_1MS * 250), 200) );

// Poll for status response
// Note: the EXP_FW_BOOT_CONFIG command trains the OMI, which takes a
// significant amount of time. We're waiting 1ms between polls, and poll for 100 loops,
// which totals at least 100ms
FAPI_TRY(fw_status(i_target, DELAY_1MS, 100));
fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Check that the FW status code returns a busy status (expected for exp_omi_train)
///
/// @param[in] i_target OCMB
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff busy and no error code, else, error code
///
inline fapi2::ReturnCode check_fw_status_busy(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
{
uint8_t l_status = ~(0);

std::vector<uint8_t> l_data;
FAPI_TRY(get_fw_status(i_target, l_data));

FAPI_TRY(status::get_status_code(i_target, l_data, l_status));

// Post bootconfig1, we should see a busy status until p9a_omi_train is kicked off (setting axone to AUTO_TRAIN)
// explorer will return busy status until then. if we have another status, then we may not have executed bootconfig1
// or some previous command correctly, so we should check it here
// After p9a_omi_train, exp_omi_train_check will check fw_status for success (in addition to checking training completion)
// to make sure things went smoothly
FAPI_ASSERT( l_status == status_codes::FW_BUSY,
fapi2::MSS_EXP_I2C_FW_BOOT_CONFIG_STATUS_CODE_INVALID().
set_TARGET(i_target).
set_STATUS_CODE(l_status).
set_CMD_ID(FW_STATUS),
"Status code did not return BUSY (%d) as expected post BOOT_CONFIG1, received (%d) for " TARGIDFORMAT ,
status_codes::FW_BUSY, l_status, TARGID );

return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
Expand Down

0 comments on commit 8f549e7

Please sign in to comment.