summaryrefslogtreecommitdiffstats
path: root/src/import/chips
diff options
context:
space:
mode:
authorLouis Stermole <stermole@us.ibm.com>2019-07-08 10:19:55 -0400
committerRaja Das <rajadas2@in.ibm.com>2019-07-26 00:59:14 -0500
commit03efd4591c9031e8ed28b6a39ccc00e27e773814 (patch)
treedfc89f92ab4531e55d377e6e4231f236ca0f4163 /src/import/chips
parentab24d3119eb3b84ed028e4ac9aa3ec9b6f04f625 (diff)
downloadtalos-sbe-03efd4591c9031e8ed28b6a39ccc00e27e773814.tar.gz
talos-sbe-03efd4591c9031e8ed28b6a39ccc00e27e773814.zip
Fix polling timeouts for exp_omi_train and exp_check_for_ready
Change-Id: I35d3068e6f44a048ccf06a69919d4a17397400b5 Original-Change-Id: Ifb260bb167dc254405884b12bf55246826d6b3bb Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/80152 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Mark Pizzutillo <mark.pizzutillo@ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: RYAN P. KING <rpking@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Dev-Ready: Louis Stermole <stermole@us.ibm.com> Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Diffstat (limited to 'src/import/chips')
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H182
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H34
2 files changed, 156 insertions, 60 deletions
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H
index 5c0667a0..8e30c3f3 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H
@@ -60,6 +60,7 @@ namespace check
/// @param[in] i_cmd_id the command ID
/// @param[in] i_data data to check from EXP_FW_STATUS
/// @param[out] o_busy true if explorer returns FW_BUSY status, false otherwise
+/// @return FAPI2_RC_SUCCESS iff okay
///
inline fapi2::ReturnCode status_code( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const uint8_t i_cmd_id,
@@ -96,33 +97,6 @@ fapi_try_exit:
return fapi2::current_err;
}
-///
-/// @brief Checks the I2c explorer boot stage for FUNTIME_FW
-/// @param[in] i_target the OCMB target
-/// @param[in] i_data data to check from EXP_FW_STATUS
-///
-inline fapi2::ReturnCode runtime_boot_stage( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const std::vector<uint8_t>& i_data )
-{
- constexpr uint8_t EXPECTED_BOOT_STAGE = boot_stages::RUNTIME_FW;
- uint8_t l_boot_stage = 0;
- FAPI_TRY( status::get_boot_stage(i_target, i_data, l_boot_stage) );
-
- // Check that Explorer is in the RUNTIME_FW boot stage
- FAPI_ASSERT( (l_boot_stage == EXPECTED_BOOT_STAGE),
- fapi2::MSS_EXP_I2C_WRONG_BOOT_STAGE().
- set_TARGET(i_target).
- set_BOOT_STAGE(l_boot_stage).
- set_EXPECTED_BOOT_STAGE(EXPECTED_BOOT_STAGE),
- "FW_STATUS command returned wrong boot stage (0x%01x, expected 0x%01x) for %s",
- l_boot_stage, EXPECTED_BOOT_STAGE, mss::c_str(i_target) );
-
- return fapi2::FAPI2_RC_SUCCESS;
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
}// check
///
@@ -139,8 +113,19 @@ inline void fw_status_setup(size_t& o_size,
}
///
+/// @brief EXP_FW_BYPASS_4SEC_TIMEOUT setup helper function
+/// @param[out] o_cmd_id the explorer command ID
+///
+inline void fw_bypass_download_window_setup(std::vector<uint8_t>& o_cmd_id)
+{
+ o_cmd_id.clear();
+ o_cmd_id.push_back(FW_BYPASS_4SEC_TIMEOUT);
+}
+
+///
/// @brief get EXP_FW_STATUS bytes
/// @param[in] i_target the OCMB target
+/// @param[out] o_data the return data from FW_STATUS command
/// @return FAPI2_RC_SUCCESS iff okay
///
inline fapi2::ReturnCode get_fw_status(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
@@ -160,37 +145,73 @@ fapi_try_exit:
}
///
+/// @brief Helper function to check FW_STATUS loop termination, for unit testing
+/// @param[in] i_target the OCMB target
+/// @param[in] i_busy busy flag from check::status_code
+/// @param[in] i_boot_stage boot_stage output from status::get_boot_stage
+/// @return true if we should break out of the loop, false otherwise
+///
+inline bool fw_status_loop_done(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const bool i_busy,
+ const uint8_t i_boot_stage)
+{
+ constexpr uint8_t EXPECTED_BOOT_STAGE = boot_stages::RUNTIME_FW;
+
+ if (i_busy)
+ {
+ FAPI_DBG( "%s reutrned FW_BUSY status. Retrying...", mss::c_str(i_target) );
+ return false;
+ }
+
+ if (i_boot_stage != EXPECTED_BOOT_STAGE)
+ {
+ FAPI_DBG( "%s reutrned non-RUNTIME boot stage (0x%02x). Retrying...",
+ mss::c_str(i_target), i_boot_stage );
+ return false;
+ }
+
+ return true;
+}
+
+///
/// @brief EXP_FW_STATUS
/// @param[in] i_target the OCMB target
+/// @param[in] i_delay delay between polls
+/// @param[in] i_loops number of polling loops to perform
/// @return FAPI2_RC_SUCCESS iff okay
///
-inline fapi2::ReturnCode fw_status(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
+inline fapi2::ReturnCode fw_status(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint64_t i_delay,
+ const uint64_t i_loops)
{
- constexpr uint64_t NUM_LOOPS = 50;
+ constexpr uint8_t EXPECTED_BOOT_STAGE = boot_stages::RUNTIME_FW;
+
// So, why aren't we using the memory team's polling API?
// This is a base function that will be utilized by the platform code
// As such, we don't want to pull in more libraries than we need to: it would cause extra dependencies
// So, we're decomposing the polling library below
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
bool l_busy = true;
+ uint8_t l_boot_stage = 0;
uint64_t l_loop = 0;
- // Loop until we max our our loop count or get a doorbell response
- for(; l_loop < NUM_LOOPS && l_busy; ++l_loop)
+ // Loop until we max our our loop count or get a non-busy response
+ for(; l_loop < i_loops; ++l_loop)
{
std::vector<uint8_t> l_data;
FAPI_TRY( get_fw_status(i_target, l_data) );
FAPI_TRY( check::status_code(i_target, FW_STATUS, l_data, l_busy) );
- FAPI_TRY( check::runtime_boot_stage(i_target, l_data) );
+ FAPI_TRY( status::get_boot_stage(i_target, l_data, l_boot_stage) );
- if (l_busy)
+ if (fw_status_loop_done(i_target, l_busy, l_boot_stage))
{
- FAPI_INF( "%s reutrned FW_BUSY status. Retrying...", mss::c_str(i_target) );
- FAPI_TRY( fapi2::delay( DELAY_100NS, 200) );
+ break;
}
+
+ FAPI_TRY( fapi2::delay( i_delay, 200) );
}
- FAPI_DBG("%s stopped on loop%u/%u. %s",
- mss::c_str(i_target), l_loop, NUM_LOOPS, (l_busy ? "FW_BUSY" : "SUCCESS"));
+ FAPI_DBG("%s stopped on loop %u/%u", mss::c_str(i_target), l_loop, i_loops);
// Check that Explorer is not still in FW_BUSY state
FAPI_ASSERT( !l_busy,
@@ -199,6 +220,15 @@ inline fapi2::ReturnCode fw_status(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_C
"Polling timeout on FW_STATUS command (still FW_BUSY) for %s",
mss::c_str(i_target) );
+ // Check that Explorer is in RUNTIME_FW boot stage
+ FAPI_ASSERT( (l_boot_stage == EXPECTED_BOOT_STAGE),
+ fapi2::MSS_EXP_I2C_WRONG_BOOT_STAGE().
+ set_TARGET(i_target).
+ set_BOOT_STAGE(l_boot_stage).
+ set_EXPECTED_BOOT_STAGE(EXPECTED_BOOT_STAGE),
+ "Polling timeout on FW_STATUS command (wrong boot stage: 0x%01x, expected 0x%01x) for %s",
+ l_boot_stage, EXPECTED_BOOT_STAGE, mss::c_str(i_target) );
+
fapi_try_exit:
return fapi2::current_err;
}
@@ -239,9 +269,19 @@ inline fapi2::ReturnCode boot_config(const fapi2::Target<fapi2::TARGET_TYPE_OCMB
std::vector<uint8_t> l_configured_data(i_data);
boot_config_setup(l_configured_data);
- // Get data and check for errors
+ // Send the command
FAPI_TRY(fapi2::putI2c(i_target, l_configured_data));
- FAPI_TRY(fw_status(i_target));
+
+ // Wait a bit for the command (DLL lock and OMI training) to complete
+ // Value based on initial Explorer hardware.
+ // 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;
@@ -260,23 +300,40 @@ inline fapi2::ReturnCode is_ready(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CH
std::vector<uint8_t> l_cmd_id;
fw_status_setup(l_size, l_cmd_id);
- // We just ignore the data. We'll see FAPI2_RC_SUCCESS if
- // the I2C returns an ACK.
+ // We'll see FAPI2_RC_SUCCESS if the I2C returns an ACK.
+ // We just ignore the data
std::vector<uint8_t> l_data;
return fapi2::getI2c(i_target, l_size, l_cmd_id, l_data);
}
///
+/// @brief EXP_FW_BYPASS_4SEC_TIMEOUT
+/// @param[in] i_target the OCMB target
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+inline fapi2::ReturnCode fw_bypass_download_window(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
+{
+ std::vector<uint8_t> l_cmd_id;
+ fw_bypass_download_window_setup(l_cmd_id);
+
+ // We'll see FAPI2_RC_SUCCESS if the I2C returns an ACK.
+ return fapi2::putI2c(i_target, l_cmd_id);
+}
+
+///
/// @brief Helper function for exp_check_for_ready
/// @param[in] i_target the controller
-/// @param[in] i_poll_count the number of times to run the fw_status command (default = 50)
-/// @param[in] i_delay delay in ns between fw_status command attempts (default = 200ns)
+/// @param[in] i_poll_count the number of times to run the fw_status command (default = 200)
+/// @param[in] i_delay delay in ns between fw_status command attempts (default = 1ms)
/// @return FAPI2_RC_SUCCESS iff ok
///
inline fapi2::ReturnCode exp_check_for_ready_helper(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const uint64_t i_poll_count = DEFAULT_POLL_LIMIT,
- const uint64_t i_delay = 200)
+ const uint64_t i_poll_count = 200,
+ const uint64_t i_delay = DELAY_1MS)
{
+ std::vector<uint8_t> l_data;
+ uint8_t l_boot_stage = 0;
+
// Using using default parameters from class, with overrides for delay and poll_count
mss::poll_parameters l_poll_params(DELAY_10NS,
200,
@@ -296,16 +353,37 @@ inline fapi2::ReturnCode exp_check_for_ready_helper(const fapi2::Target<fapi2::T
"Failed to see an ACK from I2C -- polling timeout on %s",
mss::c_str(i_target) );
- // We send the EXP_FW_STATUS command as a sanity check to see if it returns SUCCESS
+ // If we're already in RUNTIME_FW stage, due to fuse settings or running procedures manually,
+ // we can (and should) skip the bypass and polling here
+ FAPI_TRY( get_fw_status(i_target, l_data) );
+ FAPI_TRY( status::get_boot_stage(i_target, l_data, l_boot_stage) );
+
+ if (l_boot_stage == boot_stages::RUNTIME_FW)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // MSCC explorer firmware arch spec 4.1.6.5
+ // Boot ROM will wait 4 secs and will proceed for normal boot operation. During this time,
+ // I2C channel will be disabled and Host will see NACK on the bus for subsequent EXP_FW_STATUS
+ // command.
+ // Sending FW_BYPASS_4SEC_TIMEOUT command will bypass the 4 secs
+ // and immediately load the runtime firmware.
+ FAPI_TRY(fw_bypass_download_window(i_target));
+
+ // Loop again until we get an ACK from i2c
FAPI_ASSERT( mss::poll(i_target, l_poll_params, [i_target]()->bool
{
- return mss::exp::i2c::fw_status(i_target) == fapi2::FAPI2_RC_SUCCESS;
+ return mss::exp::i2c::is_ready(i_target) == fapi2::FAPI2_RC_SUCCESS;
}),
- fapi2::MSS_EXP_STATUS_POLLING_TIMEOUT().
+ fapi2::MSS_EXP_I2C_POLLING_TIMEOUT().
set_TARGET(i_target),
- "Failed to see a successful return code -- polling timeout on %s",
+ "Failed to see an ACK from I2C -- polling timeout on %s",
mss::c_str(i_target) );
+ // Now poll the EXP_FW_STATUS command until it returns SUCCESS and RUNTIME_FW
+ FAPI_TRY(fw_status(i_target, i_delay, i_poll_count));
+
return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
@@ -352,7 +430,7 @@ inline fapi2::ReturnCode fw_reg_write(const fapi2::Target<fapi2::TARGET_TYPE_OC
i_addr, mss::fapi_pos(i_target));
// Check status of operation
- FAPI_TRY(fw_status(i_target),
+ FAPI_TRY(fw_status(i_target, DELAY_1MS, 100),
"Invalid Status after FW_REG_WRITE operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X",
i_addr, mss::fapi_pos(i_target));
@@ -398,7 +476,7 @@ inline fapi2::ReturnCode fw_reg_read(const fapi2::Target<fapi2::TARGET_TYPE_OCMB
i_addr, mss::fapi_pos(i_target));
// Check i2c status after operation
- FAPI_TRY(fw_status(i_target),
+ FAPI_TRY(fw_status(i_target, DELAY_1MS, 100),
"Invalid Status after FW_REG_ADDR_LATCH operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X",
i_addr, mss::fapi_pos(i_target));
@@ -434,7 +512,7 @@ inline fapi2::ReturnCode fw_reg_read(const fapi2::Target<fapi2::TARGET_TYPE_OCMB
FW_REG_ADDR_LATCH_SIZE, l_tmp_vector[0] );
// Check i2c status after operation
- FAPI_TRY(fw_status(i_target),
+ FAPI_TRY(fw_status(i_target, DELAY_1MS, 100),
"Invalid Status after FW_REG_READ operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X",
i_addr, mss::fapi_pos(i_target));
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H
index 1b437d91..a2d77405 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H
@@ -182,14 +182,32 @@ namespace i2c
///
enum cmd_id : uint8_t
{
- FW_BOOT_CONFIG = 0x01,
- FW_STATUS = 0x02,
- FW_REG_ADDR_LATCH = 0x03,
- FW_REG_READ = 0x04,
- FW_REG_WRITE = 0x05,
- FW_DOWNLOAD = 0x06,
- FW_CONT_REG_READ = 0x07,
- FW_CONT_REG_WRITE = 0x08,
+ FW_BOOT_CONFIG = 0x01,
+ FW_STATUS = 0x02,
+ FW_REG_ADDR_LATCH = 0x03,
+ FW_REG_READ = 0x04,
+ FW_REG_WRITE = 0x05,
+ FW_DOWNLOAD = 0x06,
+ FW_CONT_REG_READ = 0x07,
+ FW_CONT_REG_WRITE = 0x08,
+ FW_BYPASS_4SEC_TIMEOUT = 0x09,
+ FW_PQM_LANE_SET = 0x0A,
+ FW_PQM_LANE_GET = 0x0B,
+ FW_PQM_FREQ_SET = 0x0C,
+ FW_PQM_FREQ_GET = 0x0D,
+ FW_PQM_LANE_TRAINING = 0x0E,
+ FW_PQM_TRAINING_RESET = 0x0F,
+ FW_PQM_RX_ADAPTATION_OBJ_READ = 0x10,
+ FW_PQM_RX_CALIBRATION_VALUE_READ = 0x11,
+ FW_PQM_CSU_CALIBRATION_VALUE_STATUS_READ = 0x12,
+ FW_PQM_PRBS_PATTERN_MODE_SET = 0x13,
+ FW_PQM_PRBS_USER_DEFINED_PATTERN_SET = 0x14,
+ FW_PQM_PRBS_MONITOR_CONTROL = 0x15,
+ FW_PQM_PRBS_GENERATOR_CONTROL = 0x16,
+ FW_PQM_PRBS_ERR_COUNT_READ = 0x17,
+ FW_PQM_HORIZONTAL_BATHTUB_GET = 0x18,
+ FW_PQM_VERTICAL_BATHTUB_GET = 0x19,
+ FW_PQM_2D_BATHTUB_GET = 0x1A,
};
///
OpenPOWER on IntegriCloud