summaryrefslogtreecommitdiffstats
path: root/src/import
diff options
context:
space:
mode:
authorMark Pizzutillo <Mark.Pizzutillo@ibm.com>2019-07-29 17:41:16 -0500
committerChristian R Geddes <crgeddes@us.ibm.com>2019-10-28 13:33:51 -0500
commit4921bf245e22bccc84c60a2030801ec6ee48dcd6 (patch)
tree5d4c27d65a451d7e7ed28a5499d2502dc29f4ca6 /src/import
parent333d66b55815428a6fff9be13f5cfc5a7d420b15 (diff)
downloadtalos-hostboot-4921bf245e22bccc84c60a2030801ec6ee48dcd6.tar.gz
talos-hostboot-4921bf245e22bccc84c60a2030801ec6ee48dcd6.zip
Update exp_draminit results display for new response structs
Change-Id: I65df040404585fd5cb3b9b79258e697333079dd8 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/81318 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@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: Louis Stermole <stermole@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/82252 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import')
-rw-r--r--src/import/chips/ocmb/explorer/common/include/exp_data_structs.H137
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C64
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C271
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H123
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C272
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H311
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C86
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H245
-rw-r--r--src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml16
-rw-r--r--src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml13
-rw-r--r--src/import/generic/memory/lib/utils/mss_bad_bits.H28
11 files changed, 1231 insertions, 335 deletions
diff --git a/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H b/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H
index dbd1c8d75..2e5fcf906 100644
--- a/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H
+++ b/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H
@@ -68,6 +68,10 @@ enum exp_struct_sizes
TRAINING_RESPONSE_NUM_RC = 27,
TRAINING_RESPONSE_MR6_SIZE = TRAINING_RESPONSE_NUM_RANKS * TRAINING_RESPONSE_NUM_DRAM,
RCW_8BIT_CUTOFF = 16,
+ EYE_MIN_MAX_SIZE = 31,
+ DBYTE_N_SIZE = 10,
+ NIBBLE_N_SIZE = 20,
+ BIT_N_SIZE = 8,
};
///
@@ -78,19 +82,20 @@ enum exp_struct_sizes
typedef struct __attribute__((packed))
{
// Command Header
- uint8_t cmd_id; // Command type
- uint8_t cmd_flags; // Various flags associated with the command
- uint16_t request_identifier; // The request identifier of this transport request
- uint32_t cmd_length; // Number of bytes following the UI header
- uint32_t cmd_crc; // CRC of command data buffer, if used
- uint32_t host_work_area; // Scratchpad area for Host, FW returns this value as a reponse
- uint32_t cmd_work_area; // Scratchpad area for Firmware, can be used for tracking command progress etc.
- uint32_t padding[CMD_PADDING_SIZE]; // Fill up to the size of one cache line
- uint8_t command_argument[ARGUMENT_SIZE]; // Additional parameters associated with the command
- uint32_t cmd_header_crc; // CRC of 64 bytes of command header
+ uint8_t cmd_id; // Command type
+ uint8_t cmd_flags; // Various flags associated with the command
+ uint16_t request_identifier; // The request identifier of this transport request
+ uint32_t cmd_length; // Number of bytes following the UI header
+ uint32_t cmd_crc; // CRC of command data buffer, if used
+ uint32_t host_work_area; // Scratchpad area for Host, FW returns this value as a reponse
+ uint32_t cmd_work_area; // Scratchpad area for Firmware, can be used for tracking command progress etc.
+ uint32_t padding[CMD_PADDING_SIZE]; // Fill up to the size of one cache line
+ uint8_t command_argument[ARGUMENT_SIZE]; // Additional parameters associated with the command
+ uint32_t cmd_header_crc; // CRC of 64 bytes of command header
}
host_fw_command_struct;
+
///
/// @class host_fw_response_struct
/// @brief The firmware response structure
@@ -745,6 +750,88 @@ typedef struct __attribute__((packed)) user_response_rc_msdg_t
} user_response_rc_msdg_t;
///
+/// @class train_2d_eye_min_max_msdg_t
+/// @brief Microchip response structure
+///
+typedef struct __attribute__((packed)) train_2d_eye_min_max_msdg
+{
+ //2D training has to run with 1D training results in the delay registers. Horizontally it takes 1D
+ //centered value as starting position and only sweep half of a UI to left and right (1 UI in total).
+ //Vertically it takes preset vref value as starting position and sweep until bit error is detected.
+ //The assumption is that data eye will be enclosed in that range.
+ //eye_max/min contain the max/min VrefDAC0/VrefDQ value which passes test with the Nth step shift
+ //within the 1UI range. The 1D centered RxClkDly/TxDqDly is always normalized to index 15 of the
+ //array.
+ //In train_2d_read_eye_msdg, eye_max/min value represents VrefDAC0 (PHY DQ receiver Vref setting)
+ //Vref = (0.510 + VrefDAC0[6:0] * 0.00385) * VDDQ
+ //In train_2d_write_eye_msdg, eye_max/min value represents VrefDQ (Dram DQ receiver Vref setting)
+ //Vref = (0.450 + VrefDQ[6:0] * 0.0065) * VDDQ
+ uint16_t eye_min[EYE_MIN_MAX_SIZE];
+ uint16_t eye_max[EYE_MIN_MAX_SIZE];
+} train_2d_eye_min_max_msdg_t;
+
+///
+/// @class train_2d_read_eye_msdg_t
+/// @brief Microchip response structure
+///
+typedef struct __attribute__((packed)) train_2d_read_eye_msdg
+{
+ //train_2d_read_eye_msdg_t returns the read eye diagram from point of view of 2D training firmware.
+ //1D training center RxClkDly (per nibble) horizontally (left and right search), 2D training does
+ //sweep on horizontal (RxClkDly) and vertical (VrefDAC0) directions, then decide the center.
+ //2D training has to run with 1D training results in the delay registers. Horizontally it takes 1D
+ //centered value as starting position and only sweep half of a UI to left and right (1 UI in total).
+ //Vertically it takes preset vref value as starting position and sweep until bit error is detected.
+ //The assumption is that data eye will be enclosed in that range.
+ //VrefDAC0[*][*][*] contains the max/min VrefDAC0 value which passes test with the Nth step shift
+ //within the 1UI range. The 1D centered RxClkDly is always normalized to index 15 of the
+ //array.
+ //With both arrays, 2D read eye diagram can be plotted on debug host.
+
+ // VrefDAC0[RANKi][DBYTEn][BITn] Maximum
+ // and minimum passing VrefDAC0 in 2D read training
+ train_2d_eye_min_max_msdg_t VrefDAC0[TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][BIT_N_SIZE];
+
+ // VrefDAC0_Center[DBYTEn][BITn] Centered
+ // VrefDAC0 value after 2D read training
+ uint16_t VrefDAC0_Center[DBYTE_N_SIZE][BIT_N_SIZE];
+
+ // RxClkDly_Center[RANKi][NIBBLEn] Centered
+ // RxClkDly location (w.r.t. eye diagram) after 2D
+ // read training
+ uint16_t RxClkDly_Center[TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE];
+} train_2d_read_eye_msdg_t;
+
+typedef struct __attribute__((packed)) train_2d_write_eye_msdg
+{
+ //train_2d_write_eye_msdg_t returns the write eye diagram from point of view of 2D training
+ //firmware.
+ //1D training center TxDqDly (per DQ) horizontally (left and right search), 2D training does sweep
+ //on horizontal (TxDqDly) and vertical (VrefDQ) directions, then decide the center.
+ //2D training has to run with 1D training results in the delay registers. Horizontally it takes 1D
+ //centered value as starting position and only sweep half of a UI to left and right (1 UI in total).
+ //Vertically it takes preset vref value as starting position and sweep until bit error is detected.
+ //The assumption is that data eye will be enclosed in that range.
+ //VrefDQ[*][*][*] contains the max/min VrefDQ value which passes test with the Nth step shift within
+ //the 1UI range. The 1D centered TxDqDly is always normalized to index 15 of the array.
+ //With both arrays, 2D read eye diagram can be plotted on debug host.
+
+ // VrefDQ[RANKi][DBYTEn][BITn] Maximum and
+ // minimum passing VrefDQ in 2D write training
+ train_2d_eye_min_max_msdg_t VrefDQ[TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][BIT_N_SIZE];
+
+ // VrefDQ_Center[RANKi][NIBBLEn] Centered VrefDQ
+ // value after 2D write training
+ uint16_t VrefDQ_Center[TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE];
+
+ // TxDqDly_Center[RANKi][DBYTEn][BITn] Centered
+ // TxDqDly location (w.r.t. eye diagram) after 2D
+ // write training
+ uint16_t TxDqDly_Center[TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][BIT_N_SIZE];
+
+} train_2d_write_eye_msdg_t;
+
+///
/// @class user_response_msdg_t
/// @brief Microchip response structure
///
@@ -758,4 +845,34 @@ typedef struct __attribute__((packed)) user_response_msdg
} user_response_msdg_t;
+///
+/// @class user_2d_eye_response_1_msdg_t
+/// @brief Microchip response structure
+///
+typedef struct __attribute__((packed)) user_2d_eye_response_1_msdg
+{
+ uint32_t version_number;
+ train_2d_read_eye_msdg_t read_2d_eye_resp;
+ user_response_timing_msdg_t tm_resp;
+ user_response_error_msdg_t err_resp;
+ user_response_mrs_msdg_t mrs_resp;
+ user_response_rc_msdg_t rc_resp;
+
+} user_2d_eye_response_1_msdg_t;
+
+///
+/// @class user_2d_eye_response_2_msdg_t
+/// @brief Microchip response structure
+///
+typedef struct __attribute__((packed)) user_2d_eye_response_2_msdg
+{
+ uint32_t version_number;
+ train_2d_write_eye_msdg_t write_2d_eye_resp;
+ user_response_timing_msdg_t tm_resp;
+ user_response_error_msdg_t err_resp;
+ user_response_mrs_msdg_t mrs_resp;
+ user_response_rc_msdg_t rc_resp;
+
+} user_2d_eye_response_2_msdg_t;
+
#endif
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C
index ce9137db9..67ddf14d5 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C
@@ -55,7 +55,7 @@ extern "C"
mss::display_git_commit_info("exp_draminit");
uint32_t l_crc = 0;
- host_fw_command_struct l_cmd;
+ uint8_t l_phy_init_mode = 0;
user_input_msdg l_phy_params;
FAPI_TRY(mss::exp::setup_phy_params(i_target, l_phy_params),
@@ -65,54 +65,28 @@ extern "C"
FAPI_TRY( mss::exp::ib::putUserInputMsdg(i_target, l_phy_params, l_crc),
"Failed putUserInputMsdg() for %s", mss::c_str(i_target) );
- {
- // Issue full boot mode cmd though EXP-FW REQ buffer
- FAPI_TRY( mss::exp::setup_cmd_params(i_target,
- l_crc,
- sizeof(l_phy_params),
- l_cmd) );
- FAPI_TRY( mss::exp::ib::putCMD(i_target, l_cmd),
- "Failed putCMD() for %s", mss::c_str(i_target) );
- }
+ // Get phy init mode attribute
+ FAPI_TRY(mss::attr::get_exp_phy_init_mode(i_target, l_phy_init_mode));
- // Wait a bit for the command (and training) to complete
- // Value based on initial Explorer hardware in Cronus in i2c mode.
- // Training takes ~10ms with no trace, ~450ms with Explorer UART debug
- FAPI_TRY( fapi2::delay( (mss::DELAY_1MS * 8), 200) );
+ // Make sure we're in range
+ FAPI_ASSERT((l_phy_init_mode <= fapi2::ENUM_ATTR_MSS_OCMB_PHY_INIT_MODE_WITH_EYE_CAPTURE),
+ fapi2::MSS_EXP_UNKNOWN_PHY_INIT_MODE()
+ .set_TARGET(i_target)
+ .set_VALUE(l_phy_init_mode),
+ "%s Value for phy init mode for exp_draminit is unknown: %u expected 0 (NORMAL), 1 (WITH_EYE_CAPTURE)",
+ mss::c_str(i_target), l_phy_init_mode);
- // Read the response message from EXP-FW RESP buffer
+ // Call appropriate init function
+ if (l_phy_init_mode == fapi2::ENUM_ATTR_MSS_OCMB_PHY_INIT_MODE_NORMAL)
{
- host_fw_response_struct l_response;
- user_response_msdg l_train_response;
-
- std::vector<uint8_t> l_rsp_data;
- fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS);
-
- FAPI_TRY( mss::exp::ib::getRSP(i_target, l_response, l_rsp_data),
- "Failed getRSP() for %s", mss::c_str(i_target) );
-
- // Proccesses the response data
- FAPI_TRY( mss::exp::read_training_response(i_target, l_rsp_data, l_train_response),
- "Failed read_training_response for %s", mss::c_str(i_target));
-
- // Displays the training response
- FAPI_TRY( mss::exp::train::display_info(i_target, l_train_response));
-
- // Check if cmd was successful
- l_rc = mss::exp::check::response(i_target, l_response, l_cmd);
-
- // If not, then we need to process the bad bitmap
- if(l_rc != fapi2::FAPI2_RC_SUCCESS)
- {
- mss::exp::bad_bit_interface l_interface(l_train_response);
-
- // Record bad bits should only fail if we have an attributes issue - that's a major issue
- FAPI_TRY(mss::record_bad_bits<mss::mc_type::EXPLORER>(i_target, l_interface));
-
- // Now, go to our true error handling procedure
- FAPI_TRY(l_rc, "mss::exp::check::response failed for %s", mss::c_str(i_target));
- }
+ FAPI_TRY(mss::exp::host_fw_phy_normal_init(i_target, l_crc));
}
+ else
+ {
+ FAPI_TRY(mss::exp::host_fw_phy_init_with_eye_capture(i_target, l_crc, l_phy_params));
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
FAPI_INF("Draminit training - %s %s",
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C
index 843675d6e..de8d0cfad 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.C
@@ -34,6 +34,9 @@
#include <generic/memory/lib/utils/c_str.H>
#include <lib/exp_draminit_utils.H>
+#include <lib/phy/exp_train_display.H>
+#include <lib/phy/exp_train_handler.H>
+#include <exp_inband.H>
namespace mss
{
@@ -41,34 +44,285 @@ namespace exp
{
///
-/// @brief host_fw_command_struct structure setup
-/// @param[in] i_target the OCMB being acted upon
+/// @brief Perform normal host FW phy init
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_crc CRC value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode host_fw_phy_normal_init(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint32_t i_crc)
+{
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
+ host_fw_command_struct l_cmd;
+ std::vector<uint8_t> l_rsp_data;
+
+ // Issue full boot mode cmd though EXP-FW REQ buffer
+ FAPI_TRY(send_host_phy_init_cmd(i_target, i_crc, phy_init_mode::NORMAL, l_cmd));
+ FAPI_TRY(mss::exp::check_host_fw_response(i_target, l_cmd, l_rsp_data, l_rc));
+ FAPI_TRY(mss::exp::read_and_display_normal_training_repsonse(i_target, l_rsp_data, l_rc));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Perform host FW phy init with eye capture
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_crc CRC value
+/// @param[in] i_phy_params PHY params struct
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success
+/// @note the goal here is to attempt to send both phy_inits even in the event of a bad return code from the read & display
+///
+fapi2::ReturnCode host_fw_phy_init_with_eye_capture(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint32_t i_crc,
+ const user_input_msdg& i_phy_params)
+{
+ fapi2::ReturnCode l_check_response_1_rc = fapi2::FAPI2_RC_SUCCESS;
+ fapi2::ReturnCode l_read_display_response_1_rc = fapi2::FAPI2_RC_SUCCESS;
+ fapi2::ReturnCode l_check_response_2_rc = fapi2::FAPI2_RC_SUCCESS;
+ fapi2::ReturnCode l_read_display_response_2_rc = fapi2::FAPI2_RC_SUCCESS;
+
+ user_2d_eye_response_1_msdg l_response_1;
+ user_2d_eye_response_2_msdg l_response_2;
+
+ std::vector<uint8_t> l_rsp_data;
+
+ // First, step 1
+ {
+ host_fw_command_struct l_cmd;
+ FAPI_TRY(send_host_phy_init_cmd(i_target, i_crc, phy_init_mode::EYE_CAPTURE_STEP_1, l_cmd));
+
+ // Return code output param is that of check::response
+ // A fail of getRSP will go to fapi_try_exit
+ FAPI_TRY(mss::exp::check_host_fw_response(i_target, l_cmd, l_rsp_data, l_check_response_1_rc));
+ l_read_display_response_1_rc = mss::exp::read_and_display_user_2d_eye_response(i_target, l_rsp_data, l_response_1);
+ }
+ l_rsp_data.clear();
+
+ // Next, step 2
+ {
+ host_fw_command_struct l_cmd;
+ uint32_t l_crc = 0;
+
+ // Put user_input_msdg again for step 2 (overwritten by data buffer from step 1)
+ FAPI_TRY( mss::exp::ib::putUserInputMsdg(i_target, i_phy_params, l_crc),
+ "Failed putUserInputMsdg() for %s", mss::c_str(i_target) );
+
+ // Send cmd
+ FAPI_TRY(send_host_phy_init_cmd(i_target, l_crc, phy_init_mode::EYE_CAPTURE_STEP_2, l_cmd));
+
+ // Return code output param is that of check::response
+ // A fail of getRSP will go to fapi_try_exit
+ FAPI_TRY(mss::exp::check_host_fw_response(i_target, l_cmd, l_rsp_data, l_check_response_2_rc));
+
+ l_read_display_response_2_rc = mss::exp::read_and_display_user_2d_eye_response(i_target, l_rsp_data, l_response_2);
+ }
+
+ // Check the return codes
+ FAPI_TRY(process_eye_capture_return_codes(i_target,
+ l_response_1,
+ l_response_2,
+ l_check_response_1_rc,
+ l_check_response_2_rc));
+
+ // Finally, check the display response return codes
+ FAPI_TRY(l_read_display_response_1_rc, "Error ocurred reading/displaying eye capture response 1 of %s",
+ mss::c_str(i_target));
+ FAPI_TRY(l_read_display_response_2_rc, "Error ocurred reading/displaying eye capture response 2 of %s",
+ mss::c_str(i_target));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Process return codes from PHY init with eye capture operations
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_response_1 response struct for EYE_CAPTURE_STEP_1
+/// @param[in] i_response_2 response struct for EYE_CAPTURE_STEP_2
+/// @param[in] i_response_1_rc response from check_host_fw_response from EYE_CAPTURE_STEP_1
+/// @param[in] i_response_2_rc response from check_host_fw_response from EYE_CAPTURE_STEP_2
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else an error from above as defined in the function algorithm
+/// @note return codes are passed by value, caller should not expect these to change
+///
+fapi2::ReturnCode process_eye_capture_return_codes(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_1_msdg& i_response_1,
+ const user_2d_eye_response_2_msdg& i_response_2,
+ fapi2::ReturnCode i_response_1_rc,
+ fapi2::ReturnCode i_response_2_rc)
+{
+ const bool l_response_1_failed = i_response_1_rc != fapi2::FAPI2_RC_SUCCESS;
+ const bool l_response_2_failed = i_response_2_rc != fapi2::FAPI2_RC_SUCCESS;
+
+ if (l_response_2_failed)
+ {
+ FAPI_ERR("%s check_fw_host_response() for %s returned error code 0x%016llu",
+ mss::c_str(i_target), "EYE_CAPTURE_STEP_2", uint64_t(i_response_2_rc));
+
+ mss::exp::bad_bit_interface<user_2d_eye_response_2_msdg> l_interface_2(i_response_2);
+ FAPI_TRY(mss::record_bad_bits<mss::mc_type::EXPLORER>(i_target, l_interface_2));
+
+ if (l_response_1_failed)
+ {
+ // Log response 2's error, and let's return response 1
+ fapi2::logError(i_response_2_rc, fapi2::FAPI2_ERRL_SEV_RECOVERED);
+
+ // logError sets the return code& to NULL. Set to FAPI2_RC_SUCCESS in case of use
+ i_response_2_rc = fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ FAPI_TRY(i_response_2_rc);
+ }
+
+ if (l_response_1_failed)
+ {
+ FAPI_ERR("%s check_fw_host_response() for %s returned error code 0x%016llu",
+ mss::c_str(i_target), "EYE_CAPTURE_STEP_1", uint64_t(i_response_1_rc));
+
+ mss::exp::bad_bit_interface<user_2d_eye_response_1_msdg> l_interface_1(i_response_1);
+ FAPI_TRY(mss::record_bad_bits<mss::mc_type::EXPLORER>(i_target, l_interface_1));
+
+ return i_response_1_rc;
+ }
+
+ // Else, we did not see errors!
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Send PHY init command given the provided phy mode and CRC
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_crc CRC field
+/// @param[in] i_phy_init_mode normal / eye capture step 1 or 2
+/// @param[out] host_fw_command_struct used for initialization
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode send_host_phy_init_cmd(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint32_t i_crc,
+ const uint8_t i_phy_init_mode,
+ host_fw_command_struct& o_cmd)
+{
+ host_fw_command_struct l_cmd;
+
+ // Issue full boot mode cmd though EXP-FW REQ buffer
+ FAPI_TRY(setup_cmd_params(i_target, i_crc, sizeof(user_input_msdg), i_phy_init_mode, l_cmd));
+ FAPI_TRY(mss::exp::ib::putCMD(i_target, l_cmd),
+ "Failed putCMD() for %s", mss::c_str(i_target));
+
+ // Wait a bit for the command (and training) to complete
+ // Value based on initial Explorer hardware in Cronus in i2c mode.
+ // Training takes ~10ms with no trace, ~450ms with Explorer UART debug
+ FAPI_TRY(fapi2::delay((mss::DELAY_1MS * 8), 200));
+
+ o_cmd = l_cmd;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get and check the host fw response from the explorer
+///
+/// @param[in] i_target OCMB chip
+/// @param[in] i_cmd host_fw_command_struct used to generate the response
+/// @param[out] o_rsp_data response data
+/// @param[out] o_rc return code from mss::exp::check::response()
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code
+///
+fapi2::ReturnCode check_host_fw_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ host_fw_command_struct& i_cmd,
+ std::vector<uint8_t>& o_rsp_data,
+ fapi2::ReturnCode& o_rc)
+{
+ host_fw_response_struct l_response;
+
+ FAPI_TRY(mss::exp::ib::getRSP(i_target, l_response, o_rsp_data),
+ "Failed getRSP() for %s", mss::c_str(i_target));
+
+ o_rc = mss::exp::check::response(i_target, l_response, i_cmd);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Reads and displays the normal draminit training response
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_resp_data RESP data
+/// @param[in] i_rc return code from checking response
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode read_and_display_normal_training_repsonse(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const std::vector<uint8_t> i_resp_data,
+ const fapi2::ReturnCode i_rc)
+{
+ user_response_msdg l_train_response;
+
+ // Proccesses the response data
+ FAPI_TRY( mss::exp::read_normal_training_response(i_target, i_resp_data, l_train_response),
+ "Failed read_training_response for %s", mss::c_str(i_target));
+
+ // Displays the training response
+ FAPI_INF("%s displaying user response data version %u", mss::c_str(i_target), l_train_response.version_number)
+ FAPI_TRY( mss::exp::train::display_normal_info(i_target, l_train_response));
+
+ if(i_rc != fapi2::FAPI2_RC_SUCCESS)
+ {
+ mss::exp::bad_bit_interface<user_response_msdg> l_interface(l_train_response);
+ FAPI_TRY(mss::record_bad_bits<mss::mc_type::EXPLORER>(i_target, l_interface));
+ FAPI_TRY(i_rc, "mss::exp::check::response failed for %s", mss::c_str(i_target));
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief host_fw_phy_init_command_struct structure setup
+///
+/// @param[in] i_target OCMB target
/// @param[in] i_cmd_data_crc the command data CRC
/// @param[in] i_cmd_length the length of the command present in the data buffer (if any)
+/// @param[in] i_phy_init_mode PHY init mode
/// @param[out] o_cmd the command parameters to set
///
fapi2::ReturnCode setup_cmd_params(
const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const uint32_t i_cmd_data_crc,
- const uint8_t i_cmd_length,
+ const uint32_t i_cmd_length,
+ const uint8_t i_phy_init_mode,
host_fw_command_struct& o_cmd)
{
+ static constexpr uint8_t EYE_CAPTURE_STEP_1 = 1;
memset(&o_cmd, 0, sizeof(host_fw_command_struct));
// Issue full boot mode cmd though EXP-FW REQ buffer
// Explicit with all of these (including 0 values) to avoid ambiguity
o_cmd.cmd_id = mss::exp::omi::EXP_FW_DDR_PHY_INIT;
- o_cmd.cmd_flags = 0;
// Retrieve a unique sequence id for this transaction
uint32_t l_counter = 0;
FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_OCMB_COUNTER, i_target, l_counter));
-
o_cmd.request_identifier = l_counter;
+
+ // STEP_1 = 1, STEP_2 = 0 as defined in MCHP spec section 5.4.3 Eye Capture
+ o_cmd.cmd_flags = i_phy_init_mode == EYE_CAPTURE_STEP_1 ? 1 : 0;
+
o_cmd.cmd_length = i_cmd_length;
o_cmd.cmd_crc = i_cmd_data_crc;
o_cmd.host_work_area = 0;
o_cmd.cmd_work_area = 0;
- memset(o_cmd.padding, 0, sizeof(o_cmd.padding));
+
+ // According to the spec Table 5-2, phy_init_mode takes the place of command_argument[0]
+ o_cmd.command_argument[0] = i_phy_init_mode;
fapi_try_exit:
return fapi2::current_err;
@@ -184,8 +438,9 @@ fapi2::ReturnCode response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_
set_ERROR_CODE(i_rsp.response_argument[1]).
set_EXPECTED_REQID(i_cmd.request_identifier).
set_ACTUAL_REQID(i_rsp.request_identifier),
- "Failed to initialize the PHY for %s, response=0x%X",
- mss::c_str(i_target), i_rsp.response_argument[0]);
+ "Failed to initialize the PHY for %s, response=0x%X "
+ "RSP RQ ID: %u CMD RQ ID: %u",
+ mss::c_str(i_target), i_rsp.response_argument[0], i_rsp.request_identifier, i_cmd.request_identifier);
return fapi2::FAPI2_RC_SUCCESS;
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H
index 88d814ede..39598303d 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/exp_draminit_utils.H
@@ -46,6 +46,9 @@
#include <generic/memory/lib/utils/c_str.H>
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/utils/mss_buffer_utils.H>
+#include <lib/phy/exp_train_display.H>
+#include <lib/phy/exp_train_handler.H>
+#include <exp_data_structs.H>
#include <stdio.h>
namespace mss
@@ -54,6 +57,16 @@ namespace exp
{
///
+/// @brief Phy init mode for host_fw_command struct
+///
+enum phy_init_mode
+{
+ NORMAL = 0,
+ EYE_CAPTURE_STEP_1 = 1,
+ EYE_CAPTURE_STEP_2 = 2,
+};
+
+///
/// @brief defines the supported DIMM types in Explorer
///
enum msdg_dimm_types
@@ -149,17 +162,125 @@ enum odt_fields
};
///
+/// @brief Perform normal host FW phy init
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_crc CRC value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode host_fw_phy_normal_init(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint32_t i_crc);
+
+///
+/// @brief Perform host FW phy init with eye capture
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_crc CRC value
+/// @param[in] i_phy_params PHY params struct
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success
+/// @note the goal here is to attempt to send both phy_inits even in the event of a bad return code from the read & display
+///
+fapi2::ReturnCode host_fw_phy_init_with_eye_capture(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint32_t i_crc,
+ const user_input_msdg& i_phy_params);
+
+///
+/// @brief Process return codes from PHY init with eye capture operations
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_response_1 response struct for EYE_CAPTURE_STEP_1
+/// @param[in] i_response_2 response struct for EYE_CAPTURE_STEP_2
+/// @param[in] i_response_1_rc response from check_host_fw_response from EYE_CAPTURE_STEP_1
+/// @param[in] i_response_2_rc response from check_host_fw_response from EYE_CAPTURE_STEP_2
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else an error from above as defined in the function algorithm
+/// @note return codes are passed by value, caller should not expect these to change
+///
+fapi2::ReturnCode process_eye_capture_return_codes(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_1_msdg& i_response_1,
+ const user_2d_eye_response_2_msdg& i_response_2,
+ fapi2::ReturnCode i_response_1_rc,
+ fapi2::ReturnCode i_response_2_rc);
+
+///
+/// @brief Send PHY init command given the provided phy mode and CRC
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_crc CRC field
+/// @param[in] i_phy_init_mode normal / eye capture step 1 or 2
+/// @param[out] host_fw_command_struct used for initialization
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode send_host_phy_init_cmd(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint32_t i_crc,
+ const uint8_t i_phy_init_mode,
+ host_fw_command_struct& o_cmd);
+
+///
+/// @brief Get and check the host fw response from the explorer
+/// @param[in] i_target OCMB chip
+/// @param[in] i_cmd host_fw_command_struct used to generate the response
+/// @param[out] o_rsp_data response data
+/// @param[out] o_rc return code from mss::exp::check::response()
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code
+///
+fapi2::ReturnCode check_host_fw_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ host_fw_command_struct& i_cmd,
+ std::vector<uint8_t>& o_rsp_data,
+ fapi2::ReturnCode& o_rc);
+
+///
+/// @brief Reads and displays the normal draminit training response
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_resp_data RESP data
+/// @param[in] i_rc return code from checking response
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode read_and_display_normal_training_repsonse(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const std::vector<uint8_t> i_resp_data,
+ const fapi2::ReturnCode i_rc);
+
+///
+/// @brief Reads and displays the user 2d eye response 1
+///
+/// @tparam T response struct
+/// @param[in] i_target OCMB target
+/// @param[in] i_resp_data RESP data
+/// @param[out] o_rc return code from checking response
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success
+///
+template <typename T>
+inline fapi2::ReturnCode read_and_display_user_2d_eye_response(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const std::vector<uint8_t> i_resp_data,
+ T& o_train_response)
+{
+ // Proccesses the response data
+ FAPI_TRY(mss::exp::read_user_2d_eye_response<T>(i_target, i_resp_data, o_train_response),
+ "Failed read_training_response for %s", mss::c_str(i_target));
+
+ // Displays the training response
+ FAPI_TRY(mss::exp::train::display_user_2d_eye_info<T>(i_target, o_train_response));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
/// @brief host_fw_command_struct structure setup
/// @param[in] i_target the OCMB being acted upon
/// @param[in] i_cmd_data_crc the command data CRC
/// @param[in] i_cmd_length the length of the command present in the data buffer (if any)
+/// @param[in] i_phy_init_mode PHY init mode
/// @param[out] o_cmd the command parameters to set
/// @return FAPI2_RC_SUCCESS iff okay
///
fapi2::ReturnCode setup_cmd_params(
const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const uint32_t i_cmd_data_crc,
- const uint8_t i_cmd_length,
+ const uint32_t i_cmd_length,
+ const uint8_t i_phy_init_mode,
host_fw_command_struct& o_cmd);
///
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C
index fa39f9e5c..f7fbad41a 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C
@@ -35,15 +35,11 @@
#include <fapi2.H>
#include <lib/shared/exp_consts.H>
-#include <lib/shared/exp_defaults.H>
-#include <lib/dimm/exp_rank.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <generic/memory/lib/utils/index.H>
#include <generic/memory/lib/utils/c_str.H>
-#include <generic/memory/lib/utils/find.H>
#include <exp_data_structs.H>
#include <lib/phy/exp_train_display.H>
-#include <generic/memory/lib/mss_generic_attribute_getters.H>
namespace mss
{
@@ -75,10 +71,10 @@ void display_lane_results(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_t
constexpr uint16_t CLEAN = 0;
- // If we passed, display the information as only as debug - we don't want to clutter the screen with too much information
+ // If we passed, display the information as only as MFG - we don't want to clutter the screen with too much information
if(CLEAN == i_data)
{
- FAPI_DBG("%s lane: %u PASSING R0:%u R1:%u R2:%u R3:%u",
+ FAPI_MFG("%s lane: %u PASSING R0:%u R1:%u R2:%u R3:%u",
mss::c_str(i_target), i_lane,
l_rank0, l_rank1, l_rank2, l_rank3);
}
@@ -93,211 +89,128 @@ void display_lane_results(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_t
}
///
-/// @brief Displays lane failure information after training
-/// @param[in] i_target the OCMB target
-/// @param[in] i_training_info the training information to display
+/// @brief Display train_2d_read_eye_msdg_t response struct
///
-void display_lane_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info)
-{
- for(uint8_t l_lane = 0; l_lane < exp_struct_sizes::TRAINING_RESPONSE_NUM_LANES; ++l_lane)
- {
- display_lane_results( i_target, l_lane, i_training_info.err_resp.Failure_Lane[l_lane]);
- }
-}
-
-///
-/// @brief Displays MR information
-/// @param[in] i_target the OCMB target
-/// @param[in] i_training_info the training information to display
+/// @param[in] i_target OCMB target
+/// @param[in] i_training_info training info struct
///
-fapi2::ReturnCode display_mrs_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info)
+void display_train_2d_read_eye(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_1_msdg_t& i_training_info)
{
- // Loop through all DIMM's
- for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
- {
- // Rank info object for
- std::vector<mss::rank::info<>> l_rank_info_vect;
- uint8_t l_dram_width = 0;
- FAPI_TRY(mss::rank::ranks_on_dimm<>(l_dimm, l_rank_info_vect));
- FAPI_TRY(mss::attr::get_dram_width(l_dimm, l_dram_width));
+ FAPI_MFG("%s %s (EYE MIN/MAX):", mss::c_str(i_target), "VrefDAC0");
- // Loops through all of the ranks
- for (const auto& l_rank_info : l_rank_info_vect)
+ for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank)
+ {
+ for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte)
{
- const uint8_t l_phy_rank = l_rank_info.get_phy_rank();
- // MR0->5 are easy, just display the value
- FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 0, i_training_info.mrs_resp.MR0);
- FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 1, i_training_info.mrs_resp.MR1[l_phy_rank]);
- FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 2, i_training_info.mrs_resp.MR2[l_phy_rank]);
- FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 3, i_training_info.mrs_resp.MR3);
- FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 4, i_training_info.mrs_resp.MR4);
- FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 5, i_training_info.mrs_resp.MR5[l_phy_rank]);
-
- // The number of the DRAM's and the position to access each DRAM changes based upon x4 vs x8
- const auto l_num_dram = l_dram_width == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ?
- mss::exp::generic_consts::EXP_NUM_DRAM_X4 :
- mss::exp::generic_consts::EXP_NUM_DRAM_X8;
- // The correction factor is used to determine the correct DRAM position, as x8 DRAM's take up two entries
- const auto l_correction_factor = l_dram_width == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ?
- 1 : 2;
-
- for(uint64_t l_dram = 0; l_dram < l_num_dram; ++l_dram)
+ for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit)
{
- const auto l_dram_pos = l_correction_factor * l_dram;
- FAPI_DBG("%s rank%u MR6 dram%u 0x%04x", mss::c_str(i_target), l_phy_rank, l_dram,
- i_training_info.mrs_resp.MR6[l_phy_rank][l_dram_pos]);
+ for (uint8_t l_eye_index = 0; l_eye_index < EYE_MIN_MAX_SIZE; ++l_eye_index)
+ {
+ const auto l_eye_min = i_training_info.read_2d_eye_resp.VrefDAC0[l_rank][l_dbyte][l_bit].eye_min[l_eye_index];
+ const auto l_eye_max = i_training_info.read_2d_eye_resp.VrefDAC0[l_rank][l_dbyte][l_bit].eye_max[l_eye_index];
+
+ FAPI_MFG("%s %s RANK %u, DBYTE %u BIT %u EYE INDEX %u -- MIN: %u MAX: %u",
+ mss::c_str(i_target), "VrefDAC0", l_rank, l_dbyte, l_bit, l_eye_index, l_eye_min, l_eye_max);
+ }
}
}
}
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- return fapi2::current_err;
-}
+ FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "VrefDAC0");
-///
-/// @brief Displays all RCW information
-/// @param[in] i_target the OCMB target
-/// @param[in] i_training_info the training information to display
-///
-void display_rcw_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info)
-{
- constexpr uint64_t FUNC_SPACE0 = 0;
- constexpr uint64_t FUNC_SPACE1 = 1;
-
- // Only display the DIMM's that exist
- const auto& l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target);
-
- // Display DIMM0
- if(l_dimms.size() >= 1)
+ for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte)
{
- // Display all of function space 0
- // Display all 4-bit numbers
- for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
- {
- display_rcw_4bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]);
- }
-
- // Display all 8-bit numbers
- for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit)
{
- display_rcw_8bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]);
+ const auto l_vref_dac0_center = i_training_info.read_2d_eye_resp.VrefDAC0_Center[l_dbyte][l_bit];
+ FAPI_MFG("%s %s DBYTE %u, BIT %u: %u", mss::c_str(i_target), "VrefDAC0_Center", l_dbyte, l_bit, l_vref_dac0_center);
}
+ }
- // Display all of function space 1
- // Display all 4-bit numbers
- for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
- {
- display_rcw_4bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]);
- }
+ FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "RxClkDly");
- // Display all 8-bit numbers
- for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank)
+ {
+ for (uint8_t l_nibble = 0; l_nibble < NIBBLE_N_SIZE; ++l_nibble)
{
- display_rcw_8bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]);
+ const auto l_rxclkdly_center = i_training_info.read_2d_eye_resp.RxClkDly_Center[l_rank][l_nibble];
+ FAPI_MFG("%s %s RANK %u, NIBBLE %u: %u", mss::c_str(i_target), "RxClkDly_Center", l_rank, l_nibble, l_rxclkdly_center);
}
}
+}
+
+///
+/// @brief Display train_2d_write_eye_msdg_t response struct
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_training_info training info struct
+///
+void display_train_2d_write_eye(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_2_msdg_t& i_training_info)
+{
+ FAPI_MFG("%s %s (EYE MIN/MAX):", mss::c_str(i_target), "VrefDQ");
- // Display DIMM1
- if(l_dimms.size() == 2)
+ for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank)
{
- // Display all of function space 0
- // Display all 4-bit numbers
- for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte)
{
- display_rcw_4bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]);
+ for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit)
+ {
+ for (uint8_t l_eye_index = 0; l_eye_index < EYE_MIN_MAX_SIZE; ++l_eye_index)
+ {
+ const auto l_eye_min = i_training_info.write_2d_eye_resp.VrefDQ[l_rank][l_dbyte][l_bit].eye_min[l_eye_index];
+ const auto l_eye_max = i_training_info.write_2d_eye_resp.VrefDQ[l_rank][l_dbyte][l_bit].eye_max[l_eye_index];
+
+ FAPI_MFG("%s %s RANK %u, DBYTE %u BIT %u EYE INDEX %u -- MIN: %u MAX: %u",
+ mss::c_str(i_target), "VrefDQ", l_rank, l_dbyte, l_bit, l_eye_index, l_eye_min, l_eye_max);
+ }
+ }
}
+ }
- // Display all 8-bit numbers
- for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
- {
- display_rcw_8bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]);
- }
+ FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "VrefDQ");
- // Display all of function space 1
- // Display all 4-bit numbers
- for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank)
+ {
+ for (uint8_t l_nibble = 0; l_nibble < NIBBLE_N_SIZE; ++l_nibble)
{
- display_rcw_4bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]);
+ const auto l_vrefdq_center = i_training_info.write_2d_eye_resp.VrefDQ_Center[l_rank][l_nibble];
+ FAPI_MFG("%s %s RANK %u, NIBBLE %u: %u", mss::c_str(i_target), "VrefDQ_Center", l_rank, l_nibble, l_vrefdq_center);
}
+ }
- // Display all 8-bit numbers
- for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ FAPI_MFG("%s %s_Center:", mss::c_str(i_target), "TxDqDly");
+
+ for (uint8_t l_rank = 0; l_rank < TRAINING_RESPONSE_NUM_RANKS; ++l_rank)
+ {
+ for (uint8_t l_dbyte = 0; l_dbyte < DBYTE_N_SIZE; ++l_dbyte)
{
- display_rcw_8bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]);
+ for (uint8_t l_bit = 0; l_bit < BIT_N_SIZE; ++l_bit)
+ {
+ const auto l_txdqdly_center = i_training_info.write_2d_eye_resp.TxDqDly_Center[l_rank][l_dbyte][l_bit];
+ FAPI_MFG("%s %s RANK %u, DBYTE %u BIT %u: %u", mss::c_str(i_target), "TxDqDly_Center", l_rank, l_dbyte, l_bit,
+ l_txdqdly_center);
+ }
}
}
}
///
-/// @brief Displays command to command response timing
+/// @brief Displays all training information
/// @param[in] i_target the OCMB target
/// @param[in] i_training_info the training information to display
-/// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully
+/// @return fapi2::FAPI2_RC_SUCCESS iff success
///
-fapi2::ReturnCode display_response_timing(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info)
+template <>
+fapi2::ReturnCode display_user_2d_eye_info<user_2d_eye_response_1_msdg_t>(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_1_msdg_t& i_training_info)
{
- uint8_t l_num_rank_per_ocmb = 0;
-
- // Loop through all DIMM's
- for(const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
- {
- // Gets the number of DIMM's and x4 vs x8 DRAM
- // TK update ranks to use rank API
- uint8_t l_num_master_ranks = 0;
-
- FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(l_dimm, l_num_master_ranks));
- l_num_rank_per_ocmb += l_num_master_ranks;
- }
-
- // DFIMRL_DDRCLK_trained training result
- FAPI_INF("%s DFIMRL_DDRCLK_trained: %u", mss::c_str(i_target), i_training_info.tm_resp.DFIMRL_DDRCLK_trained);
-
- // RD to RD
- FAPI_DBG("%s RD-to-RD : 0 1 2 3", mss::c_str(i_target));
-
- for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
- {
- FAPI_DBG("%s RD-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n,
- i_training_info.tm_resp.CDD_RR[l_rank_n][0], i_training_info.tm_resp.CDD_RR[l_rank_n][1],
- i_training_info.tm_resp.CDD_RR[l_rank_n][2], i_training_info.tm_resp.CDD_RR[l_rank_n][3]);
- }
-
- // WR to WR
- FAPI_DBG("%s WR-to-WR : 0 1 2 3", mss::c_str(i_target));
-
- for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
- {
- FAPI_DBG("%s WR-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n,
- i_training_info.tm_resp.CDD_WW[l_rank_n][0], i_training_info.tm_resp.CDD_WW[l_rank_n][1],
- i_training_info.tm_resp.CDD_WW[l_rank_n][2], i_training_info.tm_resp.CDD_WW[l_rank_n][3]);
- }
-
- // WR to RD
- FAPI_DBG("%s WR-to-RD : 0 1 2 3", mss::c_str(i_target));
-
- for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
- {
- FAPI_DBG("%s WR-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n,
- i_training_info.tm_resp.CDD_WR[l_rank_n][0], i_training_info.tm_resp.CDD_WR[l_rank_n][1],
- i_training_info.tm_resp.CDD_WR[l_rank_n][2], i_training_info.tm_resp.CDD_WR[l_rank_n][3]);
- }
-
- // RD to WR
- FAPI_DBG("%s RD-to-WR : 0 1 2 3", mss::c_str(i_target));
-
- for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
- {
- FAPI_DBG("%s RD-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_rank_n,
- i_training_info.tm_resp.CDD_RW[l_rank_n][0], i_training_info.tm_resp.CDD_RW[l_rank_n][1],
- i_training_info.tm_resp.CDD_RW[l_rank_n][2], i_training_info.tm_resp.CDD_RW[l_rank_n][3]);
- }
+ FAPI_INF("%s displaying user 2d eye response 1 data version %u", mss::c_str(i_target), i_training_info.version_number)
+ display_train_2d_read_eye(i_target, i_training_info);
+ FAPI_TRY(display_normal_info(i_target, i_training_info));
- return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
return fapi2::current_err;
}
@@ -306,15 +219,16 @@ fapi_try_exit:
/// @brief Displays all training information
/// @param[in] i_target the OCMB target
/// @param[in] i_training_info the training information to display
+/// @return fapi2::FAPI2_RC_SUCCESS iff success
///
-fapi2::ReturnCode display_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info)
+template <>
+fapi2::ReturnCode display_user_2d_eye_info<user_2d_eye_response_2_msdg_t>(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_2_msdg_t& i_training_info)
{
- FAPI_INF("%s displaying user response data version %u", mss::c_str(i_target), i_training_info.version_number)
- display_rcw_info(i_target, i_training_info);
- FAPI_TRY(display_mrs_info(i_target, i_training_info));
- display_lane_info(i_target, i_training_info);
- FAPI_TRY(display_response_timing(i_target, i_training_info));
+ FAPI_INF("%s displaying user 2d eye response 2 data version %u", mss::c_str(i_target), i_training_info.version_number)
+ display_train_2d_write_eye(i_target, i_training_info);
+ FAPI_TRY(display_normal_info(i_target, i_training_info));
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H
index a71bffce6..5905e1d4b 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H
@@ -37,10 +37,16 @@
#define _EXP_TRAIN_DISPLAY_H_
#include <fapi2.H>
+#include <lib/shared/exp_consts.H>
+#include <lib/shared/exp_defaults.H>
+#include <lib/dimm/exp_rank.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <generic/memory/lib/utils/index.H>
#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/find.H>
#include <exp_data_structs.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+
namespace mss
{
@@ -58,24 +64,6 @@ void display_lane_results(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_t
const uint64_t i_lane,
const uint16_t i_data);
-
-///
-/// @brief Displays lane failure information after training
-/// @param[in] i_target the OCMB target
-/// @param[in] i_training_info the training information to display
-///
-void display_lane_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info);
-
-///
-/// @brief Displays MRS information
-/// @param[in] i_target the OCMB target
-/// @param[in] i_training_info the training information to display
-/// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully
-///
-fapi2::ReturnCode display_mrs_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info);
-
///
/// @brief Displays RCW information for a single 8-bit RCW
/// @param[in] i_target the OCMB target
@@ -91,7 +79,7 @@ inline void display_rcw_8bit(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
const uint8_t i_data)
{
const uint64_t l_rcw_print_number = i_rcw_number - exp_struct_sizes::RCW_8BIT_CUTOFF;
- FAPI_DBG("%s DIMM%u F%uRC%xX: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, l_rcw_print_number, i_data);
+ FAPI_MFG("%s DIMM%u F%uRC%xX: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, l_rcw_print_number, i_data);
}
///
@@ -108,34 +96,305 @@ inline void display_rcw_4bit(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
const uint64_t i_rcw_number,
const uint8_t i_data)
{
- FAPI_DBG("%s DIMM%u F%uRC%02x: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, i_rcw_number, i_data);
+ FAPI_MFG("%s DIMM%u F%uRC%02x: 0x%02x", mss::c_str(i_target), i_dimm, i_func_space, i_rcw_number, i_data);
+}
+
+
+///
+/// @brief Displays lane failure information after training
+/// @tparam T response struct
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+///
+template <typename T>
+void display_lane_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const T& i_training_info)
+{
+ for(uint8_t l_lane = 0; l_lane < exp_struct_sizes::TRAINING_RESPONSE_NUM_LANES; ++l_lane)
+ {
+ display_lane_results( i_target, l_lane, i_training_info.err_resp.Failure_Lane[l_lane]);
+ }
+}
+
+///
+/// @brief Displays MR information
+/// @tparam T response struct
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+///
+template <typename T>
+fapi2::ReturnCode display_mrs_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const T& i_training_info)
+{
+ // Loop through all ports
+ for (const auto& l_port : mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target))
+ {
+ // Rank info object for
+ std::vector<mss::rank::info<>> l_rank_info_vect;
+ uint8_t l_dram_width[mss::exp::sizes::MAX_DIMM_PER_PORT] = {};
+ FAPI_TRY(mss::rank::ranks_on_port<>(l_port, l_rank_info_vect));
+ FAPI_TRY(mss::attr::get_dram_width(l_port, l_dram_width));
+
+ // Loops through all of the ranks
+ for (const auto& l_rank_info : l_rank_info_vect)
+ {
+ const uint8_t l_phy_rank = l_rank_info.get_phy_rank();
+ const uint8_t l_port_rank = l_rank_info.get_port_rank();
+ const uint8_t l_dram_width_for_dimm = l_dram_width[mss::index(l_rank_info.get_dimm_target())];
+ // MR0->5 are easy, just display the value
+ FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 0, i_training_info.mrs_resp.MR0);
+ FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 1, i_training_info.mrs_resp.MR1[l_phy_rank]);
+ FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 2, i_training_info.mrs_resp.MR2[l_phy_rank]);
+ FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 3, i_training_info.mrs_resp.MR3);
+ FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 4, i_training_info.mrs_resp.MR4);
+ FAPI_MFG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_port_rank, 5, i_training_info.mrs_resp.MR5[l_phy_rank]);
+
+ // The number of the DRAM's and the position to access each DRAM changes based upon x4 vs x8
+ const auto l_num_dram = l_dram_width_for_dimm == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ?
+ mss::exp::generic_consts::EXP_NUM_DRAM_X4 : mss::exp::generic_consts::EXP_NUM_DRAM_X8;
+ // The correction factor is used to determine the correct DRAM position, as x8 DRAM's take up two entries
+ const auto l_correction_factor = l_dram_width_for_dimm == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ? 1 : 2;
+
+ for (uint64_t l_dram = 0; l_dram < l_num_dram; ++l_dram)
+ {
+ const auto l_dram_pos = l_correction_factor * l_dram;
+ FAPI_MFG("%s rank%u MR6 dram%u 0x%04x", mss::c_str(i_target), l_port_rank, l_dram,
+ i_training_info.mrs_resp.MR6[l_phy_rank][l_dram_pos]);
+ }
+ }
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
/// @brief Displays all RCW information
+/// @tparam T response struct
/// @param[in] i_target the OCMB target
/// @param[in] i_training_info the training information to display
///
+template <typename T>
void display_rcw_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info);
+ const T& i_training_info)
+{
+ constexpr uint64_t FUNC_SPACE0 = 0;
+ constexpr uint64_t FUNC_SPACE1 = 1;
+
+ // Only display the DIMM's that exist
+ const auto& l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target);
+
+ // Display DIMM0
+ if(l_dimms.size() >= 1)
+ {
+ // Display all of function space 0
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]);
+ }
+
+ // Display all of function space 1
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]);
+ }
+ }
+
+ // Display DIMM1
+ if(l_dimms.size() == 2)
+ {
+ // Display all of function space 0
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]);
+ }
+
+ // Display all of function space 1
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]);
+ }
+ }
+}
///
/// @brief Displays command to command response timing
+/// @tparam T response struct
/// @param[in] i_target the OCMB target
/// @param[in] i_training_info the training information to display
/// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully
///
-fapi2::ReturnCode display_response_timing(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info);
+template <typename T>
+inline fapi2::ReturnCode display_response_timing(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const T& i_training_info)
+{
+ // Loop through all ports
+ for (const auto& l_port : mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target))
+ {
+ // Rank info object for
+ std::vector<mss::rank::info<>> l_rank_info_vect;
+ FAPI_TRY(mss::rank::ranks_on_port<>(l_port, l_rank_info_vect));
+
+ // DFIMRL_DDRCLK_trained training result
+ FAPI_INF("%s DFIMRL_DDRCLK_trained: %u", mss::c_str(i_target), i_training_info.tm_resp.DFIMRL_DDRCLK_trained);
+
+ // RD to RD
+ FAPI_MFG("%s RD-to-RD : 0 1 2 3", mss::c_str(i_target));
+
+ for(const auto& l_rank : l_rank_info_vect)
+ {
+ const auto l_phy_rank = l_rank.get_phy_rank();
+ const auto l_port_rank = l_rank.get_port_rank();
+ FAPI_MFG("%s RD-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank,
+ i_training_info.tm_resp.CDD_RR[l_phy_rank][0], i_training_info.tm_resp.CDD_RR[l_phy_rank][1],
+ i_training_info.tm_resp.CDD_RR[l_phy_rank][2], i_training_info.tm_resp.CDD_RR[l_phy_rank][3]);
+ }
+
+ // WR to WR
+ FAPI_MFG("%s WR-to-WR : 0 1 2 3", mss::c_str(i_target));
+
+ for(const auto& l_rank : l_rank_info_vect)
+ {
+ const auto l_phy_rank = l_rank.get_phy_rank();
+ const auto l_port_rank = l_rank.get_port_rank();
+ FAPI_MFG("%s WR-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank,
+ i_training_info.tm_resp.CDD_WW[l_phy_rank][0], i_training_info.tm_resp.CDD_WW[l_phy_rank][1],
+ i_training_info.tm_resp.CDD_WW[l_phy_rank][2], i_training_info.tm_resp.CDD_WW[l_phy_rank][3]);
+ }
+
+ // WR to RD
+ FAPI_MFG("%s WR-to-RD : 0 1 2 3", mss::c_str(i_target));
+
+ for(const auto& l_rank : l_rank_info_vect)
+ {
+ const auto l_phy_rank = l_rank.get_phy_rank();
+ const auto l_port_rank = l_rank.get_port_rank();
+ FAPI_MFG("%s WR-to-RD rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank,
+ i_training_info.tm_resp.CDD_WR[l_phy_rank][0], i_training_info.tm_resp.CDD_WR[l_phy_rank][1],
+ i_training_info.tm_resp.CDD_WR[l_phy_rank][2], i_training_info.tm_resp.CDD_WR[l_phy_rank][3]);
+ }
+
+ // RD to WR
+ FAPI_MFG("%s RD-to-WR : 0 1 2 3", mss::c_str(i_target));
+
+ for(const auto& l_rank : l_rank_info_vect)
+ {
+ const auto l_phy_rank = l_rank.get_phy_rank();
+ const auto l_port_rank = l_rank.get_port_rank();
+ FAPI_MFG("%s RD-to-WR rank%u: %2i %2i %2i %2i", mss::c_str(i_target), l_port_rank,
+ i_training_info.tm_resp.CDD_RW[l_phy_rank][0], i_training_info.tm_resp.CDD_RW[l_phy_rank][1],
+ i_training_info.tm_resp.CDD_RW[l_phy_rank][2], i_training_info.tm_resp.CDD_RW[l_phy_rank][3]);
+ }
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
///
-/// @brief Displays all training information
+/// @brief Display train_2d_read_eye_msdg_t response struct
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_training_info training info struct
+///
+void display_train_2d_read_eye(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_1_msdg_t& i_training_info);
+
+///
+/// @brief Display train_2d_write_eye_msdg_t response struct
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_training_info training info struct
+///
+void display_train_2d_write_eye(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_2_msdg_t& i_training_info);
+
+///
+/// @brief Displays all training information common to all response structs
+/// @tparam T response struct
/// @param[in] i_target the OCMB target
/// @param[in] i_training_info the training information to display
/// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully
///
-fapi2::ReturnCode display_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const user_response_msdg_t& i_training_info);
+template <typename T>
+inline fapi2::ReturnCode display_normal_info(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const T& i_training_info)
+{
+ // Target trace & FAPI_INF moved to the caller(s) such that we can call this from the eye capture functions
+ display_rcw_info(i_target, i_training_info);
+ FAPI_TRY(display_mrs_info(i_target, i_training_info));
+ display_lane_info(i_target, i_training_info);
+ FAPI_TRY(display_response_timing(i_target, i_training_info));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Displays all training information
+/// @tparam T response struct
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+/// @return fapi2::FAPI2_RC_SUCCESS iff success
+///
+template <typename T>
+fapi2::ReturnCode display_user_2d_eye_info(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const T& i_training_info);
+
+///
+/// @brief Displays all training information for eye response 1
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+/// @return fapi2::FAPI2_RC_SUCCESS iff success
+///
+template <>
+fapi2::ReturnCode display_user_2d_eye_info<user_2d_eye_response_1_msdg_t>(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_1_msdg_t& i_training_info);
+
+///
+/// @brief Displays all training information for eye response 2
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+/// @return fapi2::FAPI2_RC_SUCCESS iff success
+///
+template <>
+fapi2::ReturnCode display_user_2d_eye_info<user_2d_eye_response_2_msdg_t>(
+ const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_2d_eye_response_2_msdg_t& i_training_info);
} // ns train
} // ns exp
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C
index 14b6f5e36..8ca3b5f87 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C
@@ -46,17 +46,40 @@ namespace mss
{
///
-/// @brief A generic bad bits setter
-/// @tparam MC type memory controller type
+/// @brief Bad bit getter - Explorer specialization
/// @param[in] i_target the fapi2 target oon which training was conducted
-/// @param[in] i_array the bad bits to set
+/// @param[out] o_array the bad bits
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code
+///
+template <>
+fapi2::ReturnCode get_bad_dq_bitmap<mss::mc_type::EXPLORER>(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint8_t (&o_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT])
+{
+ return mss::attr::get_bad_dq_bitmap(i_target, o_array);
+}
+
+///
+/// @brief Bad bit setter - Explorer specialization
+/// @param[in] i_target the fapi2 target oon which training was conducted
+/// @param[in] i_array the bad bits to append
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired
///
template <>
fapi2::ReturnCode set_bad_dq_bitmap<mss::mc_type::EXPLORER>(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
uint8_t (&i_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT])
{
- return mss::attr::set_bad_dq_bitmap(i_target, i_array);
+ uint8_t l_current_data[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] = {};
+
+ // Get existing bad bits data
+ FAPI_TRY(mss::attr::get_bad_dq_bitmap(i_target, l_current_data));
+
+ // Now, or the new bits and any existing bits together
+ mss::combine_bad_bits(l_current_data, i_array);
+
+ FAPI_TRY(mss::attr::set_bad_dq_bitmap(i_target, i_array));
+
+fapi_try_exit:
+ return fapi2::current_err;
}
namespace check
@@ -94,68 +117,17 @@ namespace exp
/// @param[out] o_resp the processed training response class
/// @return FAPI2_RC_SUCCESS if ok
///
-fapi2::ReturnCode read_training_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+fapi2::ReturnCode read_normal_training_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const std::vector<uint8_t>& i_data,
user_response_msdg& o_resp)
{
-
- // True if we pass
// We assert at the end to avoid LOTS of fapi asserts
uint32_t l_idx = 0;
-
uint32_t l_version_number = 0;
bool l_pass = readLE(i_data, l_idx, l_version_number);
o_resp.version_number = l_version_number;
- uint16_t l_DFIMRL_DDRCLK_trained = 0;
-
- // Reads in the timing portion of the training response
- l_pass &= readLE(i_data, l_idx, l_DFIMRL_DDRCLK_trained);
- l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_RR[0][0]);
- l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_WW[0][0]);
- l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_RW[0][0]);
- l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_WR[0][0]);
-
- // Write to user_response_msdg
- o_resp.tm_resp.DFIMRL_DDRCLK_trained = l_DFIMRL_DDRCLK_trained;
-
- // Error response
- l_pass &= readLEArray(i_data, 80, l_idx, o_resp.err_resp.Failure_Lane);
-
- uint16_t l_MR0 = 0;
- uint16_t l_MR3 = 0;
- uint16_t l_MR4 = 0;
-
- // MRS response
- l_pass &= readLE(i_data, l_idx, l_MR0);
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR1);
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR2);
- l_pass &= readLE(i_data, l_idx, l_MR3);
- l_pass &= readLE(i_data, l_idx, l_MR4);
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR5);
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_MR6_SIZE, l_idx, &o_resp.mrs_resp.MR6[0][0]);
-
- o_resp.mrs_resp.MR0 = l_MR0;
- o_resp.mrs_resp.MR3 = l_MR3;
- o_resp.mrs_resp.MR4 = l_MR4;
-
- // Register Control Word (RCW) response
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F0RC_D0);
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F1RC_D0);
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F0RC_D1);
- l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F1RC_D1);
-
- // Check if we have errors
- FAPI_ASSERT( l_pass,
- fapi2::EXP_INBAND_LE_DATA_RANGE()
- .set_TARGET(i_target)
- .set_FUNCTION(mss::exp::READ_TRAINING_RESPONSE_STRUCT)
- .set_DATA_SIZE(i_data.size())
- .set_MAX_INDEX(sizeof(user_response_msdg)),
- "%s Failed to convert from data to host_fw_response_struct data size %u expected size %u",
- mss::c_str(i_target), i_data.size(), sizeof(user_response_msdg));
-
- return fapi2::FAPI2_RC_SUCCESS;
+ FAPI_TRY(read_tm_err_mrs_rc_response<user_response_msdg>(i_target, i_data, l_idx, l_pass, o_resp));
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H
index 8cd501d67..dc599616c 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H
@@ -41,6 +41,7 @@
#include <lib/shared/exp_defaults.H>
#include <lib/dimm/exp_rank.H>
#include <exp_data_structs.H>
+#include <generic/memory/lib/utils/endian_utils.H>
#include <generic/memory/lib/utils/mss_bad_bits.H>
#include <generic/memory/lib/mss_generic_attribute_setters.H>
#include <generic/memory/lib/mss_generic_attribute_getters.H>
@@ -51,20 +52,204 @@ namespace exp
{
///
-/// @brief Reads the training response structure
-/// @param[in] i_target the target associated with the response data
-/// @param[in] i_data the response data to read
-/// @param[out] o_resp the processed training response class
-/// @return FAPI2_RC_SUCCESS if ok
+/// @brief Read eye capture response data from explorer data buffer
+///
+/// @tparam T Response struct type
+/// @param[in] i_target OCMB target
+/// @param[in] i_data Raw data bytes
+/// @param[in,out] io_current_idx Current parsing index
+/// @param[in,out] io_pass any errors occurred during reading/endian-swapping
+/// @param[in,out] io_resp response struct
+/// @note this function expects io_current_index to be set correctly to the start of eye capture data
+///
+template <typename T>
+void read_eye_capture_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const std::vector<uint8_t>& i_data,
+ uint32_t& io_current_idx,
+ bool& io_pass,
+ T& io_resp);
+
+///
+/// @brief Read eye capture response data from explorer data buffer (eye capture step 1)
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_data Raw data bytes
+/// @param[in,out] io_current_idx Current parsing index
+/// @param[in,out] io_pass any errors occurred during reading/endian-swapping
+/// @param[in,out] io_resp train_2d_read_eye_msdg
+/// @note this function expects io_current_index to be set correctly to the start of eye capture data
///
-fapi2::ReturnCode read_training_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+template<>
+inline void read_eye_capture_response<user_2d_eye_response_1_msdg>(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
+ i_target,
const std::vector<uint8_t>& i_data,
- user_response_msdg& o_resp);
+ uint32_t& io_current_idx,
+ bool& io_pass,
+ user_2d_eye_response_1_msdg& io_resp)
+{
+ // Eye capture step 1 struct
+ uint32_t l_idx = io_current_idx;
+ bool l_pass = io_pass;
+
+ // VrefDAC0: 3D array of 2 1D arrays
+ for (uint8_t l_num_ranks = 0; l_num_ranks < TRAINING_RESPONSE_NUM_RANKS; ++l_num_ranks)
+ {
+ for (uint8_t l_dbyte_n_size = 0; l_dbyte_n_size < DBYTE_N_SIZE; ++ l_dbyte_n_size)
+ {
+ for (uint8_t l_bit_n_sze = 0; l_bit_n_sze < BIT_N_SIZE; ++ l_bit_n_sze)
+ {
+ l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx,
+ &io_resp.read_2d_eye_resp.VrefDAC0[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_min[0]);
+ l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx,
+ &io_resp.read_2d_eye_resp.VrefDAC0[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_max[0]);
+ }
+ }
+ }
+
+ // 2D array VrefDAC0_Center [DBYTE_N_SIZE][BIT_N_SIZE]
+ l_pass &= readLEArray(i_data, (DBYTE_N_SIZE * BIT_N_SIZE), l_idx,
+ &io_resp.read_2d_eye_resp.VrefDAC0_Center[0][0]);
+
+ // 2D array RxClkDly_Center [TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE]
+ l_pass &= readLEArray(i_data, (TRAINING_RESPONSE_NUM_RANKS * NIBBLE_N_SIZE), l_idx,
+ &io_resp.read_2d_eye_resp.RxClkDly_Center[0][0]);
+
+ io_pass = l_pass;
+ io_current_idx = l_idx;
+}
+
+///
+/// @brief Read eye capture response data from explorer data buffer (eye capture step 2)
+///
+/// @param[in] i_target OCMB target
+/// @param[in] i_data Raw data bytes
+/// @param[in,out] io_current_idx Current parsing index
+/// @param[in,out] io_pass any errors occurred during reading/endian-swapping
+/// @param[in,out] io_resp user_2d_eye_response_2_msdg
+/// @note this function expects io_current_index to be set correctly to the start of eye capture data
+///
+template<>
+inline void read_eye_capture_response<user_2d_eye_response_2_msdg>(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
+ i_target,
+ const std::vector<uint8_t>& i_data,
+ uint32_t& io_current_idx,
+ bool& io_pass,
+ user_2d_eye_response_2_msdg& io_resp)
+{
+
+ // Eye capture step 1 struct
+ uint32_t l_idx = io_current_idx;
+ bool l_pass = io_pass;
+
+ // VrefDQ: 3D array of 2 1D arrays
+ for (uint8_t l_num_ranks = 0; l_num_ranks < TRAINING_RESPONSE_NUM_RANKS; ++l_num_ranks)
+ {
+ for (uint8_t l_dbyte_n_size = 0; l_dbyte_n_size < DBYTE_N_SIZE; ++ l_dbyte_n_size)
+ {
+ for (uint8_t l_bit_n_sze = 0; l_bit_n_sze < BIT_N_SIZE; ++ l_bit_n_sze)
+ {
+ l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx,
+ &io_resp.write_2d_eye_resp.VrefDQ[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_min[0]);
+ l_pass &= readLEArray(i_data, EYE_MIN_MAX_SIZE, l_idx,
+ &io_resp.write_2d_eye_resp.VrefDQ[l_num_ranks][l_dbyte_n_size][l_bit_n_sze].eye_max[0]);
+ }
+ }
+ }
+
+ // 2D array VrefDQ_Center [TRAINING_RESPONSE_NUM_RANKS][NIBBLE_N_SIZE]
+ l_pass &= readLEArray(i_data, (TRAINING_RESPONSE_NUM_RANKS * NIBBLE_N_SIZE), l_idx,
+ &io_resp.write_2d_eye_resp.VrefDQ_Center[0][0]);
+
+ // 3D array TxDqDly_Center [TRAINING_RESPONSE_NUM_RANKS][DBYTE_N_SIZE][DBYTE_N_SIZE]
+ l_pass &= readLEArray(i_data, (TRAINING_RESPONSE_NUM_RANKS * DBYTE_N_SIZE * BIT_N_SIZE), l_idx,
+ &io_resp.write_2d_eye_resp.TxDqDly_Center[0][0][0]);
+
+ io_pass = l_pass;
+ io_current_idx = l_idx;
+
+ return;
+}
+
+///
+/// @brief Read the common block of fields from the training response structs
+///
+/// @tparam T training repsonse struct type
+/// @param[in] i_target OCMB chip
+/// @param[in] i_data response data
+/// @param[in] i_current_idx last index left off
+/// @param[in] i_pass response parsing success thus far
+/// @param[in,out] io_resp response struct
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success
+///
+template <typename T>
+fapi2::ReturnCode read_tm_err_mrs_rc_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const std::vector<uint8_t>& i_data,
+ const uint32_t i_current_idx,
+ const bool i_pass,
+ T& io_resp)
+{
+ uint32_t l_idx = i_current_idx;
+ bool l_pass = i_pass;
+
+ uint16_t l_DFIMRL_DDRCLK_trained = 0;
+
+ // Reads in the timing portion of the training response
+ l_pass &= readLE(i_data, l_idx, l_DFIMRL_DDRCLK_trained);
+ l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_RR[0][0]);
+ l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_WW[0][0]);
+ l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_RW[0][0]);
+ l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &io_resp.tm_resp.CDD_WR[0][0]);
+
+ // Write to user_response_msdg
+ io_resp.tm_resp.DFIMRL_DDRCLK_trained = l_DFIMRL_DDRCLK_trained;
+
+ // Error response
+ l_pass &= readLEArray(i_data, 80, l_idx, io_resp.err_resp.Failure_Lane);
+
+ uint16_t l_MR0 = 0;
+ uint16_t l_MR3 = 0;
+ uint16_t l_MR4 = 0;
+
+ // MRS response
+ l_pass &= readLE(i_data, l_idx, l_MR0);
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, io_resp.mrs_resp.MR1);
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, io_resp.mrs_resp.MR2);
+ l_pass &= readLE(i_data, l_idx, l_MR3);
+ l_pass &= readLE(i_data, l_idx, l_MR4);
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, io_resp.mrs_resp.MR5);
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_MR6_SIZE, l_idx, &io_resp.mrs_resp.MR6[0][0]);
+
+ io_resp.mrs_resp.MR0 = l_MR0;
+ io_resp.mrs_resp.MR3 = l_MR3;
+ io_resp.mrs_resp.MR4 = l_MR4;
+
+ // Register Control Word (RCW) response
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F0RC_D0);
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F1RC_D0);
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F0RC_D1);
+ l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, io_resp.rc_resp.F1RC_D1);
+
+ // Check if we have errors
+ FAPI_ASSERT( l_pass,
+ fapi2::EXP_INBAND_LE_DATA_RANGE()
+ .set_TARGET(i_target)
+ .set_FUNCTION(mss::exp::READ_TRAINING_RESPONSE_STRUCT)
+ .set_DATA_SIZE(i_data.size())
+ .set_MAX_INDEX(sizeof(T)),
+ "%s Failed to convert from data to host_fw_response_struct data size %u expected size %u",
+ mss::c_str(i_target), i_data.size(), sizeof(T));
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
///
/// @brief Explorer's bad bit interface class
-/// @brief Explorer's bad bit interface class
+/// @tparam T user response struct type
///
+template <typename T>
class bad_bit_interface
{
public:
@@ -85,7 +270,7 @@ class bad_bit_interface
/// @brief Constructor
/// @param[in] i_response response data from training
///
- bad_bit_interface(const user_response_msdg_t& i_response )
+ bad_bit_interface(const T& i_response )
{
// First, clear everything
std::fill(&iv_bad_bits[0][0], &iv_bad_bits[0][0] + sizeof(iv_bad_bits), 0);
@@ -171,6 +356,48 @@ class bad_bit_interface
}
};
+
+///
+/// @brief Reads the training response structure
+/// @param[in] i_target the target associated with the response data
+/// @param[in] i_data the response data to read
+/// @param[out] o_resp the processed training response class
+/// @return FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode read_normal_training_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const std::vector<uint8_t>& i_data,
+ user_response_msdg& o_resp);
+
+///
+/// @brief Reads user 2d eye response 1
+/// @tparam T response struct
+/// @param[in] i_target the target associated with the response data
+/// @param[in] i_data the response data to read
+/// @param[out] o_resp the processed training response class
+/// @return FAPI2_RC_SUCCESS if ok
+///
+template <typename T>
+inline fapi2::ReturnCode read_user_2d_eye_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const std::vector<uint8_t>& i_data,
+ T& o_resp)
+{
+ // First let's erase the struct
+ memset(&o_resp, 0, sizeof(T));
+ // We assert at the end to avoid LOTS of fapi asserts
+ uint32_t l_idx = 0;
+ uint32_t l_version_number = 0;
+ bool l_pass = readLE(i_data, l_idx, l_version_number);
+ o_resp.version_number = l_version_number;
+
+ read_eye_capture_response<T>(i_target, i_data, l_idx, l_pass, o_resp);
+
+ FAPI_TRY(read_tm_err_mrs_rc_response<T>(i_target, i_data, l_idx, l_pass, o_resp));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
} // ns exp
} // ns mss
diff --git a/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml b/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml
index 9e655ee15..cdd22a559 100644
--- a/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml
+++ b/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_attributes.xml
@@ -410,4 +410,20 @@
<mssAccessorName>exp_atxdly_b</mssAccessorName>
</attribute>
+ <attribute>
+ <id>ATTR_MSS_OCMB_PHY_INIT_MODE</id>
+ <targetType>TARGET_TYPE_OCMB_CHIP</targetType>
+ <description>
+ Mode for PHY initialization.
+ </description>
+ <valueType>uint8</valueType>
+ <initToZero></initToZero>
+ <enum>
+ NORMAL = 0,
+ WITH_EYE_CAPTURE = 1
+ </enum>
+ <writeable/>
+ <mssAccessorName>exp_phy_init_mode</mssAccessorName>
+ </attribute>
+
</attributes>
diff --git a/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml b/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml
index ae2cf7f56..9172a516f 100644
--- a/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml
+++ b/src/import/chips/ocmb/explorer/procedures/xml/error_info/mss_exp_errors.xml
@@ -700,4 +700,17 @@
</gard>
</hwpError>
+ <hwpError>
+ <rc>RC_MSS_EXP_UNKNOWN_PHY_INIT_MODE</rc>
+ <description>
+ The PHY init mode attribute value was unknown. Valid: 0 (NORMAL), 1 (WITH_EYE_CAPTURE)
+ </description>
+ <ffdc>TARGET</ffdc>
+ <ffdc>VALUE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
+
</hwpErrors>
diff --git a/src/import/generic/memory/lib/utils/mss_bad_bits.H b/src/import/generic/memory/lib/utils/mss_bad_bits.H
index e6d2cdfa5..b39d84859 100644
--- a/src/import/generic/memory/lib/utils/mss_bad_bits.H
+++ b/src/import/generic/memory/lib/utils/mss_bad_bits.H
@@ -46,6 +46,17 @@ namespace mss
{
///
+/// @brief A generic bad bits getter
+/// @tparam MC type memory controller type
+/// @param[in] i_target the fapi2 target oon which training was conducted
+/// @param[out] o_array the bad bits array
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code
+///
+template <mss::mc_type MC>
+fapi2::ReturnCode get_bad_dq_bitmap(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint8_t (&o_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]);
+
+///
/// @brief A generic bad bits setter
/// @tparam MC type memory controller type
/// @param[in] i_target the fapi2 target oon which training was conducted
@@ -57,6 +68,23 @@ fapi2::ReturnCode set_bad_dq_bitmap(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>
uint8_t (&i_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]);
///
+/// @brief combine the two bad bits arrays into the io_bad_bits array
+/// @param[in] i_new_bad_bits bad bits to append
+/// @param[in,out] io_bad_bits will contain the bitwise or of the original io_bad_bits and i_new_bad_bits
+///
+inline void combine_bad_bits(const uint8_t (&i_new_bad_bits)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT],
+ uint8_t (&io_bad_bits)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT])
+{
+ for (uint8_t l_rank = 0; l_rank < BAD_BITS_RANKS; ++ l_rank)
+ {
+ for (uint8_t l_bad_dq_byte = 0; l_bad_dq_byte < BAD_DQ_BYTE_COUNT; ++l_bad_dq_byte)
+ {
+ io_bad_bits[l_rank][l_bad_dq_byte] |= i_new_bad_bits[l_rank][l_bad_dq_byte];
+ }
+ }
+}
+
+///
/// @brief Records bad bits into the bad bits attribute
/// @tparam MC MC type on which training was run
/// @tparam T fapi2::TargetType on which training was conducted
OpenPOWER on IntegriCloud