diff options
author | Chris Steffen <cwsteffen@us.ibm.com> | 2016-03-11 09:11:27 -0600 |
---|---|---|
committer | Stephen Cprek <smcprek@us.ibm.com> | 2016-04-21 13:51:26 -0500 |
commit | b8c969e821c73378e71dbcddb1c23343b269072e (patch) | |
tree | 7068e07e1c1e964684b468e0288457fd77f1107c | |
parent | d2c95191a40d8ed37a7f8ab57ac4ce1c57d0255d (diff) | |
download | talos-hostboot-b8c969e821c73378e71dbcddb1c23343b269072e.tar.gz talos-hostboot-b8c969e821c73378e71dbcddb1c23343b269072e.zip |
Update xbus dccal
Change-Id: Ia59cb3b28adaeb013905e4e6fe27b2edea18ec24
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22311
Tested-by: Jenkins Server
Reviewed-by: Richard J. Knight <rjknight@us.ibm.com>
Reviewed-by: Gary A. Peterson <garyp@us.ibm.com>
Tested-by: Hostboot CI
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22312
Tested-by: FSP CI Jenkins
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
3 files changed, 445 insertions, 374 deletions
diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.C b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.C index a448387eb..ee73a779d 100644 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.C +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.C @@ -7,7 +7,7 @@ /* */ /* EKB Project */ /* */ -/* COPYRIGHT 2015 */ +/* COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -34,7 +34,7 @@ /// Run Dccal /// /// Dccal is completed on all thin/thick PHYs: -/// - XBUS(EDIP), DMI(EDIP), OBUS(OPT), ABUS(OPT) +/// - XBUS(EDIP) /// /// Procedure Prereq: /// - System clocks are running. @@ -47,34 +47,89 @@ // Includes //----------------------------------------------------------------------------- #include <p9_io_xbus_dccal.H> -#include <p9_io_gcr.H> +#include <p9_io_scom.H> #include <p9_io_regs.H> //----------------------------------------------------------------------------- // Function Declarations //----------------------------------------------------------------------------- -fapi2::ReturnCode txZCal(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target); -fapi2::ReturnCode txZCalGetResults(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target, - float& i_pval, - float& i_nval); +/** + * @brief Tx Z Impedance Calibration + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @param[in] i_flags Dccal Attribute Flags + * @retval ReturnCode + */ +fapi2::ReturnCode tx_z_cal( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group, + const uint8_t& i_flags ); -fapi2::ReturnCode txZCalSetParms(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target, - const uint8_t i_group, - const float i_pval, - const float i_nval); +/** + * @brief Tx Z Impedance Calibration State Machine + * @param[in] i_target FAPI2 Target + * @retval ReturnCode + */ +fapi2::ReturnCode tx_z_cal_run_sm( const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target ); -fapi2::ReturnCode rxDccal(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target); +/** + * @brief Tx Z Impedance Calibration Verify Results + * @param[in] i_target FAPI2 Target + * @param[in] io_pval Tx Zcal P-value + * @param[in] io_nval Tx Zcal N-value + * @retval ReturnCode + */ +fapi2::ReturnCode tx_z_cal_get_results( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + uint32_t& io_pval, + uint32_t& io_nval ); -fapi2::ReturnCode rxDccalPoll(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target, - const uint8_t i_group); +/** + * @brief Tx Z Impedance Calibration Apply Segments + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @param[in] i_pval Tx Zcal P-value + * @param[in] i_nval Tx Zcal N-value + * @retval ReturnCode + */ +fapi2::ReturnCode tx_z_cal_apply_segments( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group, + const uint32_t& i_pval, + const uint32_t& i_nval ); -fapi2::ReturnCode setLaneInvalid(fapi2::Target<fapi2::TARGET_TYPE_XBUS> i_target, - uint8_t i_group, - uint8_t data); +/** + * @brief Rx Dc Calibration + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @retval ReturnCode + */ +fapi2::ReturnCode rx_dc_cal( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group ); -uint32_t round(const float input, const uint32_t width2r); +/** + * @brief Rx Dc Calibration Poll + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @retval ReturnCode + */ +fapi2::ReturnCode rx_dc_cal_poll( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group ); +/** + * @brief Rx Dc Calibration Set Lanes Invalid + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @param[in] i_data Data to Set Lanes Invalid + * @retval ReturnCode + */ +fapi2::ReturnCode set_lanes_invalid( + const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& i_target, + const uint8_t& i_group, + const uint8_t& i_data ); //----------------------------------------------------------------------------- // Function Definitions //----------------------------------------------------------------------------- @@ -84,499 +139,512 @@ uint32_t round(const float input, const uint32_t width2r); * @brief A I/O EDI+ Procedure that runs Rx Dccal and Tx Z Impedance calibration * on every instance of the XBUS. * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group * @retval ReturnCode */ -fapi2::ReturnCode -p9_io_xbus_dccal(const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target) +fapi2::ReturnCode p9_io_xbus_dccal( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group ) { - FAPI_IMP("Entering..."); + FAPI_IMP( "p9_io_xbus_dccal: I/O EDI+ Xbus Entering" ); + uint8_t l_dccal_flags = 0x0; + // Check if Tx Impedance Calibration or Rx Dc Calibration has been run. + FAPI_TRY( FAPI_ATTR_GET( fapi2::ATTR_IO_XBUS_DCCAL_FLAGS, i_target, l_dccal_flags ) ); - // We cannot run tx impedance calibration while using broadside scoms. - // The request pulse is not a physical latch and get optimized out when - // using the broadside scoms. Once the pie driver ready, we can run - // realscoms and tx zcal will work. -#if 0 - FAPI_TRY(txZCal(i_target), "I/O Edi+ Xbus Tx Z Calibration Run Failed"); -#endif + FAPI_DBG( "p9_io_xbus_dccal: I/O EDI+ Xbus Dccal Flags Tx(%d) Rx(%d)", + ( l_dccal_flags & fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_TX ) ? 1 : 0, + ( l_dccal_flags & fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_RX ) ? 1 : 0 ); + + /////////////////////////////////////////////////////////////////////////// + // Tx Impedance Calibraiton + /////////////////////////////////////////////////////////////////////////// + FAPI_TRY( tx_z_cal( i_target, i_group, l_dccal_flags ), + "p9_io_xbus_dccal: I/O Edi+ Xbus Tx Z Calibration Run Failed" ); + + l_dccal_flags |= fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_TX; + FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_IO_XBUS_DCCAL_FLAGS, i_target, l_dccal_flags ) ); + + /////////////////////////////////////////////////////////////////////////// + // Rx DC Calibraiton + /////////////////////////////////////////////////////////////////////////// + FAPI_TRY( rx_dc_cal( i_target, i_group ), + "p9_io_xbus_dccal: I/O Edi+ Xbus Rx DC Calibration Run Failed" ); + + l_dccal_flags |= fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_RX; + FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_IO_XBUS_DCCAL_FLAGS, i_target, l_dccal_flags ) ); - FAPI_TRY(rxDccal(i_target), "I/O Edi+ Xbus Rx DC Calibration Run Failed"); fapi_try_exit: - FAPI_IMP("Exiting..."); + FAPI_IMP( "p9_io_xbus_dccal: I/O EDI+ Xbus Exiting" ); return fapi2::current_err; } /** - * @brief Runs Tx Impedance Calibration. + * @brief Tx Z Impedance Calibration * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @param[in] i_flags Dccal Attribute Flags * @retval ReturnCode */ -fapi2::ReturnCode txZCal(fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target) +fapi2::ReturnCode tx_z_cal( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group, + const uint8_t& i_flags ) { - FAPI_IMP("Entering..."); - const uint8_t TIMEOUT = 255; - const uint64_t POLL_NS = 500; - const uint64_t SIM_CYCLES = 50000000; - Register<EDIP_TX_IMPCAL_PB> tx_impcal_pb; - uint8_t l_poll_count = 0; - uint8_t l_dccal_flags = 0x0; - float l_zcalp = 25 * 2; // Nominal 2R Value - float l_zcaln = 25 * 2; // Nominal 2R Value + uint32_t l_pval = 25 * 4; // Nominal 25 Segments 1R * 4 = 4R + uint32_t l_nval = 25 * 4; // Nominal 25 Segments 1R * 4 = 4R - FAPI_INF("Checking I/O Xbus Dccal Flags."); - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_XBUS_DCCAL_FLAGS, i_target, l_dccal_flags)); + FAPI_IMP( "tx_z_cal: I/O EDI+ Xbus Entering" ); - if(l_dccal_flags & fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_TX) + if( !( i_flags & fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_TX ) ) { - FAPI_INF("I/O EDI+ Xbus Tx Impedance Calibration has been previously ran."); - } - else - { - FAPI_INF("I/O EDI+ Xbus Tx Impedance Calibration is Required."); + FAPI_INF( "tx_z_cal: I/O EDI+ Xbus Tx Impedance Calibration is Required." ); + + FAPI_TRY( tx_z_cal_run_sm( i_target ), "tx_z_cal: Tx Z Cal Run Failed" ); } + // If zCal ran successfully use the found values, else we will use the nominal default values. + // Also check to make sure the values are within the bounds of acceptable values. + FAPI_TRY( tx_z_cal_get_results( i_target, l_pval, l_nval ), + "tx_z_cal: Tx Z Cal Get Results Failed" ); + + // Convert the results of the zCal to actual segments. + FAPI_TRY( tx_z_cal_apply_segments( i_target, i_group, l_pval, l_nval ), + "tx_z_cal: Tx Z Cal Apply Segments Failed" ); + +fapi_try_exit: + FAPI_IMP( "tx_z_cal: I/O EDI+ Xbus Exiting" ); + return fapi2::current_err; +} + +/** + * @brief Tx Z Impedance Calibration State Machine + * @param[in] i_target FAPI2 Target + * @retval ReturnCode + */ +fapi2::ReturnCode tx_z_cal_run_sm( const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target ) +{ + const uint32_t TIMEOUT = 200; + const uint64_t POLL_NS = 500; + const uint64_t SIM_CYCLES = 1000000; + const uint8_t GROUP_00 = 0; + const uint8_t LANE_00 = 0; + uint32_t l_count = 0; + uint64_t l_data = 0; + + FAPI_IMP( "tx_z_cal_run_sm: I/O EDI+ Xbus Entering" ); + + +#if 0 //////////////////////////////////// + // To speed up simulation, xbus_unit model + pie driver + // without these settings: 50 million cycles + // with these settings: 13 million cycles + io::set( EDIP_TX_ZCAL_SM_MIN_VAL, 50, l_data ); + io::set( EDIP_TX_ZCAL_SM_MAX_VAL, 52, l_data ); + FAPI_TRY( io::write( EDIP_TX_IMPCAL_SWO2_PB, i_target, GROUP_00, LANE_00, l_data ) ); +#endif /////////////////////////////////// + // Request to start Tx Impedance Calibration - // The Done bit is read only - FAPI_TRY( tx_impcal_pb.read(i_target), "Read tx_impcal_pb Failed."); - tx_impcal_pb.set<EDIP_TX_ZCAL_REQ>(1); - FAPI_TRY(tx_impcal_pb.write(i_target), "Starting Tx Zcal Failed."); + // The Done bit is read only pulse, must use pie driver or system model in sim + FAPI_TRY( io::rmw( EDIP_TX_ZCAL_REQ, i_target, GROUP_00, LANE_00, 1 ), + "tx_z_cal_run_sm: RMW Tx Zcal Req Failed"); // Poll Until Tx Impedance Calibration is done or errors out - while( (l_poll_count < TIMEOUT) && !( tx_impcal_pb.get<EDIP_TX_ZCAL_DONE>() || - tx_impcal_pb.get<EDIP_TX_ZCAL_ERROR>() ) ) + FAPI_TRY( io::read( EDIP_TX_IMPCAL_PB, i_target, GROUP_00, LANE_00, l_data ), + "tx_z_cal_run_sm: Reading Tx Impcal Pb Failed" ); + + while( ( ++l_count < TIMEOUT ) && + !( io::get( EDIP_TX_ZCAL_DONE, l_data ) || io::get( EDIP_TX_ZCAL_ERROR, l_data ) ) ) { - FAPI_DBG("I/O EDI+ Xbus Tx Zcal Poll, Count(%d/%d).", l_poll_count, TIMEOUT); + FAPI_DBG( "tx_z_cal_run_sm: I/O EDI+ Xbus Tx Zcal Poll, Count(%d/%d).", l_count, TIMEOUT ); - FAPI_TRY(tx_impcal_pb.read(i_target), "Read tx_impcal_pb Failed.") + FAPI_TRY( fapi2::delay( POLL_NS, SIM_CYCLES ), + "tx_z_cal_run_sm: Fapi Delay Failed." ); - FAPI_TRY( fapi2::delay(POLL_NS, SIM_CYCLES), "Fapi Delay Failed."); - ++l_poll_count; + FAPI_TRY( io::read( EDIP_TX_IMPCAL_PB, i_target, GROUP_00, LANE_00, l_data ), + "tx_z_cal_run_sm: Reading Tx Impcal Pb Failed" ); } - if( (tx_impcal_pb.get<EDIP_TX_ZCAL_DONE>() == 0) || - (tx_impcal_pb.get<EDIP_TX_ZCAL_ERROR>() == 1) ) + if( io::get( EDIP_TX_ZCAL_DONE, l_data ) == 0 ) { - FAPI_ERR("Tx Zcal Timeout/Error. Attempting to use Nominal zCal values."); - l_zcalp = 25 * 2; // Nominal 2R Value - l_zcaln = 25 * 2; // Nominal 2R Value + FAPI_ERR( "tx_z_cal_run_sm: WARNING: Tx Z Calibration Timeout: Loops(%d)", l_count ); } - else - { - FAPI_TRY( txZCalGetResults(i_target, l_zcalp, l_zcaln), - "Get Tx Zcal Results Failed" ); - } - -#if 0 // Broadcast group scoms do not work with broadside scom loads - // We will now read the encoded values and do the floating - // point math to calculate the pre-cursor, margin, and total_en segments. - FAPI_TRY(txZCalSetParms(i_target, BROADCAST_GROUP, l_zcalp, l_zcaln), - "Calculate Tx FFE Parameters Failed"); -#else - for(uint8_t l_group = 0; l_group < 2; ++l_group) + if( io::get( EDIP_TX_ZCAL_ERROR, l_data ) == 1 ) { - FAPI_TRY(txZCalSetParms(i_target, l_group, l_zcalp, l_zcaln), - "Calculate Tx FFE Parameters Failed"); + FAPI_ERR( "tx_z_cal_run_sm: WARNING: Tx Z Calibration Error" ); } -#endif - - l_dccal_flags |= fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_TX; - FAPI_ATTR_SET(fapi2::ATTR_IO_XBUS_DCCAL_FLAGS, i_target, - l_dccal_flags); - - FAPI_ASSERT( (tx_impcal_pb.get<EDIP_TX_ZCAL_DONE>() == 1), - fapi2::IO_XBUS_TX_ZCAL_TIMEOUT().set_TARGET(i_target), - "Tx zCal Timeout: Loops(%d) delay(%d ns, %d cycles)", - l_poll_count, POLL_NS, SIM_CYCLES); - - FAPI_ASSERT( (tx_impcal_pb.get<EDIP_TX_ZCAL_ERROR>() != 1), - fapi2::IO_XBUS_TX_ZCAL_ERROR().set_TARGET(i_target), - "I/O EDI+ Xbus Tx Impedance Calibration Error."); - fapi_try_exit: - FAPI_IMP("Exiting..."); + FAPI_IMP( "tx_z_cal-run_sm: I/O EDI+ Xbus Exiting" ); return fapi2::current_err; } - /** - * @brief Calculate the total number of P segments and N segments (pre-cursor, - * post-cursor, magin, and main slice) based on the Tx Impedance Calibration - * results (tx_l_zcal_p and tx_l_zcal_n). - * @param[in] i_target Reference to the Current Target - * @param[in] i_group Clock Group - * @retval fapi2::current_err + * @brief Tx Z Impedance Calibration Get Results + * @param[in] i_target FAPI2 Target + * @param[in] io_pval Tx Zcal P-value + * @param[in] io_nval Tx Zcal N-value + * @retval ReturnCode */ -fapi2::ReturnCode txZCalGetResults(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target, - float& o_pval, - float& o_nval) +fapi2::ReturnCode tx_z_cal_get_results( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + uint32_t& io_pval, + uint32_t& io_nval ) { - FAPI_IMP("Entering..."); - // l_zcal_p and l_zcal_n are 9 bit registers // These are also 4x of a 1R segment - const uint32_t ZCAL_MIN = 0x40; // 16 segments * 4 = 64 (0x40) - const uint32_t ZCAL_MAX = 0x84; // 33 segments * 4 = 132(0x84) - - Register<EDIP_TX_IMPCAL_PVAL_PB> l_pval_reg; - Register<EDIP_TX_IMPCAL_NVAL_PB> l_nval_reg; + const uint32_t ZCAL_MIN = 16 * 4; // 16 segments * 4 = 64 (0x40) + const uint32_t ZCAL_MAX = 33 * 4; // 33 segments * 4 = 132(0x84) + const uint8_t GROUP_00 = 0; + const uint8_t LANE_00 = 0; + uint64_t l_data = 0; + FAPI_IMP( "tx_z_cal_get_results: I/O EDI+ Xbus Entering" ); + + // Read Tx Impedance Calibration Register to check if the zcal P & N values are valid + FAPI_TRY( io::read( EDIP_TX_IMPCAL_PB, i_target, GROUP_00, LANE_00, l_data ), + "tx_z_cal_get_results: Reading Tx Impcal Pb Failed" ); + + if( io::get( EDIP_TX_ZCAL_DONE, l_data ) == 1 && io::get( EDIP_TX_ZCAL_ERROR, l_data ) == 0 ) + { + FAPI_DBG( "tx_z_cal_get_results: Using zCal Results." ); - FAPI_TRY( l_pval_reg.read(i_target), "tx_impcal_pval_pb read fail"); - FAPI_TRY( l_nval_reg.read(i_target), "tx_impcal_nval_pb read fail"); + FAPI_TRY( io::read( EDIP_TX_ZCAL_P, i_target, GROUP_00, LANE_00, l_data ), + "tx_z_cal_get_results: tx_impcal_pval_pb read fail" ); + io_pval = io::get( EDIP_TX_ZCAL_P, l_data ); + FAPI_TRY( io::read( EDIP_TX_ZCAL_N, i_target, GROUP_00, LANE_00, l_data ), + "tx_z_cal_get_results: tx_impcal_nval_pb read fail" ); + io_nval = io::get( EDIP_TX_ZCAL_N, l_data ); + } + else + { + FAPI_DBG( "tx_z_cal_get_results: Using Default Segments." ); + io_pval = 25 * 4; // Nominal 25 Segments 1R * 4 = 4R + io_nval = 25 * 4; // Nominal 25 Segments 1R * 4 = 4R + } - FAPI_DBG("I/O EDI+ zCal: Min/Max Allowed(0x%X,0x%X) Read Pval/Nval(0x%X,0x%X)", - ZCAL_MIN, - ZCAL_MAX, - l_pval_reg.get<EDIP_TX_ZCAL_P>(), - l_nval_reg.get<EDIP_TX_ZCAL_N>()); + FAPI_DBG( "tx_z_cal_get_results: Min/Max Allowed(0x%X,0x%X) Read Pval/Nval(0x%X,0x%X)", + ZCAL_MIN, + ZCAL_MAX, + io_pval, + io_nval ); - o_pval = (float)l_pval_reg.get<EDIP_TX_ZCAL_P>() / 2; - o_nval = (float)l_nval_reg.get<EDIP_TX_ZCAL_N>() / 2; - if( l_pval_reg.get<EDIP_TX_ZCAL_P>() > ZCAL_MAX ) + if( io_pval > ZCAL_MAX ) { - // Convert from 4R to 2R - o_pval = (float)ZCAL_MAX / 2; - FAPI_ERR("Tx Zcal Pval(0x%X) > Max Allowed(0x%X)", - l_pval_reg.get<EDIP_TX_ZCAL_P>(), ZCAL_MAX); - fapi2::IO_XBUS_TX_ZCAL_OUT_OF_RANGE().set_TARGET(i_target) - .set_ZCAL_P(l_pval_reg.get<EDIP_TX_ZCAL_P>()) - .set_ZCAL_N(l_nval_reg.get<EDIP_TX_ZCAL_N>()) - .execute(); + io_pval = ZCAL_MAX; + FAPI_ERR( "tx_z_cal_get_results: Tx Zcal Pval(0x%X) > Max Allowed(0x%X)", + io_pval, ZCAL_MAX ); } - if( l_nval_reg.get<EDIP_TX_ZCAL_N>() > ZCAL_MAX ) + if( io_nval > ZCAL_MAX ) { - // Convert from 4R to 2R - o_nval = (float)ZCAL_MAX / 2; - FAPI_ERR("Tx Zcal Nval(0x%X) > Max Allowed(0x%X)", - l_nval_reg.get<EDIP_TX_ZCAL_N>(), ZCAL_MAX); - fapi2::IO_XBUS_TX_ZCAL_OUT_OF_RANGE().set_TARGET(i_target) - .set_ZCAL_P(l_pval_reg.get<EDIP_TX_ZCAL_P>()) - .set_ZCAL_N(l_nval_reg.get<EDIP_TX_ZCAL_N>()) - .execute(); + io_nval = ZCAL_MAX; + FAPI_ERR( "tx_z_cal_get_results: Tx Zcal Nval(0x%X) > Max Allowed(0x%X)", + io_nval, ZCAL_MAX ); } - if( l_pval_reg.get<EDIP_TX_ZCAL_P>() < ZCAL_MIN ) + if( io_pval < ZCAL_MIN ) { - // Convert from 4R to 2R - o_pval = (float)ZCAL_MIN / 2; - FAPI_ERR("Tx Zcal Pval(0x%X) < Min Allowed(0x%X)", - l_pval_reg.get<EDIP_TX_ZCAL_P>(), ZCAL_MIN); - fapi2::IO_XBUS_TX_ZCAL_OUT_OF_RANGE().set_TARGET(i_target) - .set_ZCAL_P(l_pval_reg.get<EDIP_TX_ZCAL_P>()) - .set_ZCAL_N(l_nval_reg.get<EDIP_TX_ZCAL_N>()) - .execute(); + io_pval = ZCAL_MIN; + FAPI_ERR( "tx_z_cal_get_results: Tx Zcal Pval(0x%X) < Min Allowed(0x%X)", + io_pval, ZCAL_MIN ); } - if( l_nval_reg.get<EDIP_TX_ZCAL_N>() < ZCAL_MIN ) + if( io_nval < ZCAL_MIN ) { - // Convert from 4R to 2R - o_nval = (float)ZCAL_MIN / 2; - FAPI_ERR("Tx Zcal Nval(0x%X) < Min Allowed(0x%X)", - l_nval_reg.get<EDIP_TX_ZCAL_N>(), ZCAL_MIN); - fapi2::IO_XBUS_TX_ZCAL_OUT_OF_RANGE().set_TARGET(i_target) - .set_ZCAL_P(l_pval_reg.get<EDIP_TX_ZCAL_P>()) - .set_ZCAL_N(l_nval_reg.get<EDIP_TX_ZCAL_N>()) - .execute(); + io_nval = ZCAL_MIN; + FAPI_ERR( "tx_z_cal_get_results: Tx Zcal Nval(0x%X) < Min Allowed(0x%X)", + io_nval, ZCAL_MIN ); } fapi_try_exit: - FAPI_IMP("Exiting..."); + FAPI_IMP( "tx_z_cal_get_results: I/O EDI+ Xbus Exiting" ); return fapi2::current_err; } /** - * @brief Calculate the total number of P segments and N segments (pre-cursor, - * post-cursor, magin, and main slice) based on the Tx Impedance Calibration - * results (tx_l_zcal_p and tx_l_zcal_n). - * @param[in] i_target Reference to the Current Target - * @param[in] i_group Clock Group - * @retval fapi2::current_err + * @brief Tx Z Impedance Calibration Apply Segments. The results of the Tx Impedance + * calibrationMargining and FFE Precursor + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @param[in] i_pval Tx Zcal P-value + * @param[in] i_nval Tx Zcal N-value + * @retval ReturnCode */ -fapi2::ReturnCode txZCalSetParms(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target, - const uint8_t i_group, - const float i_pval, - const float i_nval) +fapi2::ReturnCode tx_z_cal_apply_segments( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group, + const uint32_t& i_pval, + const uint32_t& i_nval ) { - FAPI_IMP("Entering..."); - - // BANK EDI+ OPT - // ---- 1R 2R 1R 2R - // PRE-BANK 4 1 4 1 - // POST-BANK 0 0 6 1 - // MARGIN PULL-UP 8 0 8 0 - // MARGIN PULL-DOWN 8 0 8 0 - // MAIN BANK 12 1 6 1 - - // 2R equivalent values. - const uint32_t PRE_1R = 4; - const uint32_t PRE_2R = 1; - const uint32_t PRE_BANK = ( PRE_1R * 2 ) + PRE_2R; - const uint32_t MARGIN_1R = 8; - const uint32_t MARGIN_2R = 0; - const uint32_t MARGIN_PD_BANK = (MARGIN_1R * 2) + MARGIN_2R; - const uint32_t MARGIN_PU_BANK = (MARGIN_1R * 2) + MARGIN_2R; - const uint32_t MAIN_1R = 12; - const uint32_t MAIN_2R = 1; - const uint32_t MAIN_BANK = ( MAIN_1R * 2 ) + MAIN_2R; - - // M = MARGIN RATIO, Range 0.5 - 1 - // M = 1 :: 0% Margining - // M = 0.5 :: 50% Margining - const float M = 1; - - // K0 = PRE-CURSOR COEFFICIENT, Range 0 - 0.115 - // K0 = 0 :: 0% Pre-Cursor - // K0 = 0.115 :: 11.5% Pre-Cursor - const float K0 = 0.115; - - Register<EDIP_TX_CTLSM_CNTL1_EO_PG> l_pseg_pre_reg; - Register<EDIP_TX_CTLSM_CNTL2_EO_PG> l_nseg_pre_reg; - Register<EDIP_TX_CTLSM_CNTL3_EO_PG> l_pseg_margin_reg; - Register<EDIP_TX_CTLSM_CNTL4_EO_PG> l_nseg_margin_reg; - Register<EDIP_TX_CTLSM_CNTL5_EO_PG> l_margin_reg; - Register<EDIP_TX_CTLSM_CNTL6_EO_PG> l_pseg_main_reg; - Register<EDIP_TX_CTLSM_CNTL7_EO_PG> l_nseg_main_reg; + FAPI_IMP( "tx_z_cal_apply_segments: I/O EDI+ Xbus Entering" ); + + //const uint32_t PRE_1R = 4; + //const uint32_t PRE_2R = 1; + const uint32_t MARGIN_1R = 8; + const uint32_t MARGIN_2R = 0; + const uint32_t MAIN_1R = 12; + const uint32_t MAIN_2R = 1; + //const uint32_t PRE_4R_TOTAL = ( PRE_1R * 4 ) + ( PRE_2R * 2 ); + const uint32_t MARGIN_4R_TOTAL = ( MARGIN_1R * 4 ) + ( MARGIN_2R * 2 ); + const uint32_t MAIN_4R_TOTAL = ( MAIN_1R * 4 ) + ( MAIN_2R * 2 ); + + // During normal opertation we will not use margining, we will use this during + // High Speed I/O Characterization. + const float MARGIN_RATIO = 0; // 0(0%) 0.5(50%) + + // Based on worst case channel simulations for Witherspoon, we will use + // -4.8% FFE Precursor Tap Weight + const float PRECURSOR_COEF = 0.048; // 0(0%) 0.115(11.5%) + const uint8_t LANE_00 = 0; // :: Set the Selected Bank Segments // Apply Calcualted Segments to margin/pre/main banks accordingly // 1. Apply Segments to Margining first // 2. Apply Segments to Pre-Cursor second // 3. Apply Segments to Main last - float l_margin_pu_sel = i_pval * ( 1 - M ); - float l_margin_pd_sel = i_nval * ( 1 - M ); - float l_pre_p_sel = ( i_pval - l_margin_pu_sel ) * K0; - float l_pre_n_sel = ( i_nval - l_margin_pd_sel ) * K0; - float l_main_p_en = i_pval - l_margin_pu_sel - l_pre_p_sel; - float l_main_n_en = i_nval - l_margin_pd_sel - l_pre_n_sel; + uint64_t l_data = 0; + + // i_pval will be promoted to a float, then the decimal bits will be truncated as the value + // is returned as a uint32_t. This is okay as we are already working in 4R steps. + uint32_t sel_margin_pu = (uint32_t)( i_pval * MARGIN_RATIO ); + + // To protect against selecting too many margining segments + if( sel_margin_pu > MARGIN_4R_TOTAL ) + { + sel_margin_pu = MARGIN_4R_TOTAL; + } + uint32_t sel_margin_pd = (uint32_t)( i_nval * MARGIN_RATIO ); - // :: Set the Enabled P Bank Segments - float l_pre_p_en = l_pre_p_sel; - float l_margin_p_pu_en = l_margin_pu_sel; - float l_margin_p_pd_en = l_margin_pd_sel; + // To protect against selecting too many margining segments + if( sel_margin_pd > MARGIN_4R_TOTAL ) + { + sel_margin_pd = MARGIN_4R_TOTAL; + } - // Check if the main bank is over the max segments. - if( l_main_p_en > MAIN_BANK) + // For the selects to work, we need to enable at least the amount of selected segments. + uint32_t p_en_margin_pu = sel_margin_pu; + uint32_t p_en_margin_pd = sel_margin_pd; + uint32_t n_en_margin_pu = sel_margin_pu; + uint32_t n_en_margin_pd = sel_margin_pd; + + // The result of i_pval and sel_margin_* will be promoeted to a float, then the decimal bits + // will be truncated as the value will be returned as a uint32_t. This is okay as we are + // working in 4R steps. + uint32_t p_sel_pre = (uint32_t)( ( i_pval - sel_margin_pu - sel_margin_pd ) * PRECURSOR_COEF ); + uint32_t n_sel_pre = (uint32_t)( ( i_nval - sel_margin_pu - sel_margin_pd ) * PRECURSOR_COEF ); + uint32_t p_en_pre = p_sel_pre; + uint32_t n_en_pre = n_sel_pre; + + // Apply the leftover segments that are not used fro the selects to the main segment bank + uint32_t p_en_main = i_pval - sel_margin_pu - sel_margin_pd - p_sel_pre; + uint32_t n_en_main = i_nval - sel_margin_pu - sel_margin_pd - n_sel_pre; + + // Apply the segments across the main, margin, and pre banks to ensure we have the appropriate + // number of segments applied. + if( p_en_main > MAIN_4R_TOTAL) { - l_pre_p_en += (l_main_p_en - MAIN_BANK); - l_main_p_en = MAIN_BANK; + p_en_margin_pu += ( p_en_main - MAIN_4R_TOTAL ); + p_en_main = MAIN_4R_TOTAL; - if( l_pre_p_en > PRE_BANK ) + if( p_en_margin_pu > MARGIN_4R_TOTAL ) { - l_margin_p_pu_en += (l_pre_p_en - PRE_BANK); - l_pre_p_en = PRE_BANK; + p_en_margin_pd += ( p_en_margin_pu - MARGIN_4R_TOTAL ); + p_en_margin_pu = MARGIN_4R_TOTAL; - if( l_margin_p_pu_en > MARGIN_PU_BANK ) + if( p_en_margin_pd > MARGIN_4R_TOTAL ) { - l_margin_p_pd_en += (l_margin_p_pu_en - MARGIN_PU_BANK); - l_margin_p_pu_en = MARGIN_PU_BANK; + // p_en_pre is garanteed to be in range as we have checked the range of the + // results in tx_z_cal_get_results + p_en_pre += ( p_en_margin_pd - MARGIN_4R_TOTAL ); + p_en_margin_pd = MARGIN_4R_TOTAL; } } } - // :: Set the Enabled N Bank Segments - float l_pre_n_en = l_pre_n_sel; - float l_margin_n_pu_en = l_margin_pu_sel; - float l_margin_n_pd_en = l_margin_pd_sel; - - // Check if the main bank is over the max segments. - if( l_main_n_en > MAIN_BANK) + // Apply the segments across the main, margin, and pre banks to ensure we have the appropriate + // number of segments applied. + if( n_en_main > MAIN_4R_TOTAL ) { - l_pre_n_en += (l_main_n_en - MAIN_BANK); - l_main_n_en = MAIN_BANK; + n_en_margin_pd += ( n_en_main - MAIN_4R_TOTAL ); + n_en_main = MAIN_4R_TOTAL; - if( l_pre_n_en > PRE_BANK ) + if( n_en_margin_pd > MARGIN_4R_TOTAL ) { - l_margin_n_pd_en += (l_pre_n_en - PRE_BANK); - l_pre_n_en = PRE_BANK; + n_en_margin_pu += ( n_en_margin_pd - MARGIN_4R_TOTAL ); + n_en_margin_pd = MARGIN_4R_TOTAL; - if( l_margin_n_pd_en > MARGIN_PD_BANK ) + if( n_en_margin_pu > MARGIN_4R_TOTAL ) { - l_margin_n_pu_en += (l_margin_n_pd_en - MARGIN_PU_BANK); - l_margin_n_pd_en = MARGIN_PU_BANK; + // n_en_pre is garanteed to be in range as we have checked the range of the + // results in tx_z_cal_get_results + n_en_pre += ( n_en_margin_pu - MARGIN_4R_TOTAL ); + n_en_margin_pu = MARGIN_4R_TOTAL; } } } // We can write these registers without reading, since we are writing - // the entire register. - l_pseg_pre_reg.set<EDIP_TX_PSEG_PRE_SEL>(round(l_pre_p_sel, PRE_2R)); - l_pseg_pre_reg.set<EDIP_TX_PSEG_PRE_EN>(round(l_pre_p_en, PRE_2R)); - FAPI_TRY(l_pseg_pre_reg.write(i_target, i_group), "Pseg Pre Write Fail"); - - l_nseg_pre_reg.set<EDIP_TX_NSEG_PRE_SEL>(round(l_pre_n_sel, PRE_2R)); - l_nseg_pre_reg.set<EDIP_TX_NSEG_PRE_EN>(round(l_pre_n_en, PRE_2R)); - FAPI_TRY(l_nseg_pre_reg.write(i_target, i_group), "Nseg Pre Write Fail"); - - l_pseg_margin_reg.set<EDIP_TX_PSEG_MARGINPD_EN>(round(l_margin_p_pd_en, MARGIN_2R)); - l_pseg_margin_reg.set<EDIP_TX_PSEG_MARGINPU_EN>(round(l_margin_p_pu_en, MARGIN_2R)); - FAPI_TRY(l_pseg_margin_reg.write(i_target, i_group), "Pseg Margin Write Fail"); - - l_nseg_margin_reg.set<EDIP_TX_NSEG_MARGINPD_EN>(round(l_margin_n_pd_en, MARGIN_2R)); - l_nseg_margin_reg.set<EDIP_TX_NSEG_MARGINPU_EN>(round(l_margin_n_pu_en, MARGIN_2R)); - FAPI_TRY(l_nseg_margin_reg.write(i_target, i_group), "Nseg Margin Write Fail"); - - l_margin_reg.set<EDIP_TX_MARGINPD_SEL>(round(l_margin_pd_sel, MARGIN_2R)); - l_margin_reg.set<EDIP_TX_MARGINPU_SEL>(round(l_margin_pu_sel, MARGIN_2R)); - FAPI_TRY(l_margin_reg.write(i_target, i_group), "Margin Write Fail"); - - l_pseg_main_reg.set<EDIP_TX_PSEG_MAIN_EN>(round(l_main_p_en, MAIN_2R)); - FAPI_TRY(l_pseg_main_reg.write(i_target, i_group), "Pseg Main Write Fail"); - - l_nseg_main_reg.set<EDIP_TX_NSEG_MAIN_EN>(round(l_main_n_en, MAIN_2R)); - FAPI_TRY(l_nseg_main_reg.write(i_target, i_group), "Nseg Main Write Fail"); + // the entire register. To convert the 4R values to needed register values, + // we will add the appropriate amount and shift to convert to 1R or + // 1R + a 2R. + l_data = 0; + io::set( EDIP_TX_PSEG_PRE_SEL, ( p_sel_pre + 1 ) >> 1, l_data ); + io::set( EDIP_TX_PSEG_PRE_EN, ( p_en_pre + 1 ) >> 1, l_data ); + FAPI_TRY( io::write( EDIP_TX_CTLSM_CNTL1_EO_PG, i_target, i_group, LANE_00, l_data ), + "tx_z_cal_apply_segments: Pseg Pre Write Fail" ); + + l_data = 0; + io::set( EDIP_TX_NSEG_PRE_SEL, ( n_sel_pre + 1 ) >> 1, l_data ); + io::set( EDIP_TX_NSEG_PRE_EN, ( n_en_pre + 1 ) >> 1, l_data ); + FAPI_TRY( io::write( EDIP_TX_CTLSM_CNTL2_EO_PG, i_target, i_group, LANE_00, l_data ), + "tx_z_cal_apply_segments: Nseg Pre Write Fail" ); + + l_data = 0; + io::set( EDIP_TX_PSEG_MARGINPD_EN, ( p_en_margin_pd + 2 ) >> 2, l_data ); + io::set( EDIP_TX_PSEG_MARGINPU_EN, ( p_en_margin_pu + 2 ) >> 2, l_data ); + FAPI_TRY( io::write( EDIP_TX_CTLSM_CNTL3_EO_PG, i_target, i_group, LANE_00, l_data ), + "tx_z_cal_apply_segments: Pseg Margin Write Fail" ); + + l_data = 0; + io::set( EDIP_TX_NSEG_MARGINPD_EN, ( n_en_margin_pd + 2 ) >> 2, l_data ); + io::set( EDIP_TX_NSEG_MARGINPU_EN, ( n_en_margin_pu + 2 ) >> 2, l_data ); + FAPI_TRY( io::write( EDIP_TX_CTLSM_CNTL4_EO_PG, i_target, i_group, LANE_00, l_data ), + "tx_z_cal_apply_segments: Nseg Margin Write Fail" ); + + l_data = 0; + io::set( EDIP_TX_MARGINPD_SEL, ( sel_margin_pd + 2 ) >> 2, l_data ); + io::set( EDIP_TX_MARGINPU_SEL, ( sel_margin_pu + 2 ) >> 2, l_data ); + FAPI_TRY( io::write( EDIP_TX_CTLSM_CNTL5_EO_PG, i_target, i_group, LANE_00, l_data ), + "tx_z_cal_apply_segments: Margin Write Fail" ); + + l_data = 0; + io::set( EDIP_TX_PSEG_MAIN_EN, ( p_en_main + 1 ) >> 1, l_data ); + FAPI_TRY( io::write( EDIP_TX_CTLSM_CNTL6_EO_PG, i_target, i_group, LANE_00, l_data ), + "tx_z_cal_apply_segments: Pseg Main Write Fail" ); + + l_data = 0; + io::set( EDIP_TX_NSEG_MAIN_EN, ( n_en_main + 1 ) >> 1, l_data ); + FAPI_TRY( io::write( EDIP_TX_CTLSM_CNTL7_EO_PG, i_target, i_group, LANE_00, l_data ), + "tx_z_cal_apply_segments: Nseg Main Write Fail" ); fapi_try_exit: - FAPI_IMP("Exiting..."); + FAPI_IMP( "tx_z_cal_apply_segments: I/O EDI+ Xbus Exiting" ); return fapi2::current_err; } - /** - * @brief Runs Rx Dccal on an EDI+ Xbus Target + * @brief Rx Dc Calibration * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group * @retval ReturnCode */ -fapi2::ReturnCode rxDccal (const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target ) +fapi2::ReturnCode rx_dc_cal ( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group ) { - FAPI_IMP("Entering..."); - Register<EDIP_RX_CTL_CNTL1_E_PG> l_dccal_reg; - Register<EDIP_RX_CTL_STAT1_E_PG> l_cal_done_reg; - const uint8_t XBUS_GROUPS = 2; - uint8_t l_dccal_flags = 0x0; - - FAPI_INF("Checking I/O Xbus Dccal Flags."); - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_XBUS_DCCAL_FLAGS, i_target, l_dccal_flags)); - - if(l_dccal_flags & fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_RX) - { - FAPI_INF("I/O EDI+ Xbus Rx DC Calibration has been previously ran."); - } - else - { - FAPI_INF("I/O EDI+ Xbus Rx DC Calibration is Required."); - } + FAPI_IMP( "rx_dc_cal: I/O EDI+ Xbus Entering" ); + const uint8_t LANE_00 = 0; - for(uint8_t group = 0; group < XBUS_GROUPS; ++group) - { - FAPI_INF("I/O EDI+ Xbus Rx Dccal Group(%d).", group); - - // Must set lane invalid bit to 0 to run rx dccal - FAPI_TRY(setLaneInvalid(i_target, group, 0), "Error Setting Lane Invalid to 0"); + // Must set lane invalid bit to 0 to run rx dccal + FAPI_TRY( set_lanes_invalid( i_target, i_group, 0 ), + "rx_dc_cal: Error Setting Lane Invalid to 0" ); - // Clearing the Rx Dccal Done bit. - FAPI_TRY( l_cal_done_reg.read(i_target, group), "Read Dccal Done Failed"); - l_cal_done_reg.set<EDIP_RX_DC_CALIBRATE_DONE>(0); - FAPI_TRY( l_cal_done_reg.write(i_target, group), "Write Dccal Done Failed"); + // Clear the rx dccal done bit in case rx dccal was previously run. + FAPI_TRY( io::rmw( EDIP_RX_DC_CALIBRATE_DONE, i_target, i_group, LANE_00, 0), + "rx_dc_cal: RMW Dccal Done Failed" ); - // Start DC Calibrate - FAPI_TRY(l_dccal_reg.read(i_target, group), "Reading Start Dccal Failed"); - l_dccal_reg.set<EDIP_RX_START_DC_CALIBRATE>(1); - FAPI_TRY(l_dccal_reg.write(i_target, group), "Starting Dccal Failed"); + // Start DC Calibrate, this iniates the rx dccal state machine + FAPI_TRY( io::rmw( EDIP_RX_START_DC_CALIBRATE, i_target, i_group, LANE_00, 1 ), + "rx_dc_cal: RMW Start Dccal Failed" ); - // Check each lane in the group. - FAPI_TRY(rxDccalPoll(i_target, group), "Poll Rx DcCal Failed"); + // Poll to see if rx dccal is done on the specified target / group. + FAPI_TRY( rx_dc_cal_poll( i_target, i_group ), "rx_dc_cal: Poll Rx DcCal Failed" ); - // Stop DC Calibrate - l_dccal_reg.set<EDIP_RX_START_DC_CALIBRATE>(0); - FAPI_TRY(l_dccal_reg.write(i_target, group), "Stopping Dccal Failed"); + // Stop DC Calibrate + FAPI_TRY( io::rmw( EDIP_RX_START_DC_CALIBRATE, i_target, i_group, LANE_00, 0 ), + "rx_dc_cal: Stopping Dccal Failed" ); - // Restore the invalid bits, Wiretest will modify these as training is run. - FAPI_TRY(setLaneInvalid(i_target, group, 1), "Error Setting Lane Invalid to 1"); + // Restore the invalid bits, Wiretest will modify these as training is run. + FAPI_TRY( set_lanes_invalid( i_target, i_group, 1 ), + "rx_dc_cal: Error Setting Lane Invalid to 1" ); - FAPI_DBG("I/O EDI+ Xbus Rx Dccal Complete on Group(%d)", group); - } + FAPI_DBG( "rx_dc_cal: I/O EDI+ Xbus Rx Dccal Complete on Group(%d)", i_group ); - l_dccal_flags |= fapi2::ENUM_ATTR_IO_XBUS_DCCAL_FLAGS_RX; - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_IO_XBUS_DCCAL_FLAGS, i_target, - l_dccal_flags)); fapi_try_exit: - FAPI_IMP("Exiting..."); + FAPI_IMP( "rx_dc_cal: I/O EDI+ Xbus Exiting" ); return fapi2::current_err; } - /** - * @brief Polls Rx Dccal status on an EDI+ Xbus Target - * @param[in] i_target FAPI2 Target - * @param[in] i_group Clock Group + * @brief Rx Dc Calibration Poll + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group * @retval ReturnCode */ -fapi2::ReturnCode -rxDccalPoll(const fapi2::Target < fapi2::TARGET_TYPE_XBUS > i_target, const uint8_t i_group) +fapi2::ReturnCode rx_dc_cal_poll( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group ) { - FAPI_IMP("Entering..."); - const uint8_t TIMEOUT = 200; - const uint64_t POLL_NS = 500; - const uint64_t SIM_CYCLES = 25000000; - Register<EDIP_RX_CTL_STAT1_E_PG> l_cal_done_reg; - uint8_t l_poll_count = 0; - - FAPI_TRY( l_cal_done_reg.read(i_target, i_group), "Read Dccal Done Failed"); - - while( (l_poll_count < TIMEOUT) && !l_cal_done_reg.get<EDIP_RX_DC_CALIBRATE_DONE>() ) + FAPI_IMP( "rx_dc_cal_poll: I/O EDI+ Xbus Entering" ); + const uint8_t TIMEOUT = 200; + const uint64_t POLL_NS = 500; + const uint64_t SIM_CYCLES = 25000000; + const uint8_t LANE_00 = 0; + uint8_t l_poll_count = 0; + uint64_t l_data = 0; + + do { - FAPI_DBG("I/O EDI+ Xbus Rx Dccal Polling Count(%d/%d).", l_poll_count, TIMEOUT); + FAPI_DBG( "rx_dc_cal_poll: I/O EDI+ Xbus Rx Dccal Polling Count(%d/%d).", + l_poll_count, TIMEOUT ); - FAPI_TRY( l_cal_done_reg.read(i_target, i_group), "Read Dccal Done Failed"); + FAPI_TRY( fapi2::delay( POLL_NS, SIM_CYCLES ), "rx_dc_cal_poll: Fapi Delay Failed." ); - FAPI_TRY( fapi2::delay(POLL_NS, SIM_CYCLES), "Fapi Delay Failed."); - ++l_poll_count; + FAPI_TRY( io::read( EDIP_RX_DC_CALIBRATE_DONE, i_target, i_group, LANE_00, l_data ), + "rx_dc_cal_poll: Read Dccal Done Failed" ); } + while( ( ++l_poll_count < TIMEOUT ) && !io::get( EDIP_RX_DC_CALIBRATE_DONE, l_data ) ); - FAPI_ASSERT( (l_cal_done_reg.get<EDIP_RX_DC_CALIBRATE_DONE>() == 1), - fapi2::IO_XBUS_RX_DCCAL_TIMEOUT().set_TARGET(i_target).set_GROUP(i_group), - "Rx Dccal Timeout: Loops(%d) delay(%d ns, %d cycles)", - l_poll_count, POLL_NS, SIM_CYCLES); + FAPI_ASSERT( ( io::get( EDIP_RX_DC_CALIBRATE_DONE, l_data ) == 1 ), + fapi2::IO_XBUS_RX_DCCAL_TIMEOUT().set_TARGET( i_target ).set_GROUP( i_group ), + "rx_dc_cal_poll: Rx Dccal Timeout: Loops(%d) delay(%d ns, %d cycles)", + l_poll_count, POLL_NS, SIM_CYCLES ); fapi_try_exit: - FAPI_IMP("Exiting..."); + FAPI_IMP( "rx_dc_cal_poll: I/O EDI+ Xbus Exiting" ); return fapi2::current_err; } /** - * @brief This function sets the lane invalid field to the value of the data passed in - * @param[in] i_target FAPI2 Target - * @param[in] i_group Clock Group - * @param[in] i_data Value to set rx lane invalid field to. - * @return fapi2::ReturnCode + * @brief Rx Dc Calibration Set Lanes Invalid + * @param[in] i_target FAPI2 Target + * @param[in] i_group Clock Group + * @param[in] i_data Data to Set Lanes Invalid + * @retval ReturnCode */ -fapi2::ReturnCode -setLaneInvalid(const fapi2::Target<fapi2::TARGET_TYPE_XBUS> i_target, - const uint8_t i_group, - const uint8_t i_data) +fapi2::ReturnCode set_lanes_invalid( + const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& i_target, + const uint8_t& i_group, + const uint8_t& i_data ) { - FAPI_IMP("Entering..."); - fapi2::ReturnCode rc; - Register<EDIP_RX_BIT_CNTLX1_EO_PL> l_lane_invalid_reg; const uint8_t XBUS_LANES = 17; - for(uint8_t lane = 0; lane < XBUS_LANES; ++lane) + FAPI_IMP( "set_lanes_invalid: I/O EDI+ Xbus Entering" ); + + for( uint8_t lane = 0; lane < XBUS_LANES; ++lane ) { - FAPI_TRY(l_lane_invalid_reg.read(i_target, i_group, lane), "Reading Invalid Lane Failed") - l_lane_invalid_reg.set<EDIP_RX_LANE_INVALID>(i_data); - FAPI_TRY(l_lane_invalid_reg.write(i_target, i_group, lane), "Reading Invalid Lane Failed") + FAPI_TRY( io::rmw( EDIP_RX_LANE_INVALID, i_target, i_group, lane, i_data ), + "set_lanes_invalid: RMW Invalid Lane Failed" ); } fapi_try_exit: - FAPI_IMP("Exiting..."); - return rc; + FAPI_IMP( "set_lanes_invalid: I/O EDI+ Xbus: Exiting" ); + return fapi2::current_err; } - -/** - * @brief The function assumes that the Tx ZCal FFE 2r width will be between 0-1 - * @param[in] i_data data in 2r format - * @param[in] i_width2r If the segment contains a 2r field, Range of 0-1 - * @return data in 1r format - */ -uint32_t round(const float i_data, const uint32_t i_width2r) -{ - return (i_width2r == 1) ? uint32_t( i_data ) : (uint32_t(i_data + 0.5) >> 1); -} diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.H b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.H index 086383791..fba338ae0 100644 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.H +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.H @@ -7,7 +7,7 @@ /* */ /* EKB Project */ /* */ -/* COPYRIGHT 2015 */ +/* COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,7 +38,8 @@ typedef fapi2::ReturnCode (*p9_io_xbus_dccal_FP_t) -(const fapi2::Target < fapi2::TARGET_TYPE_XBUS>&); +( const fapi2::Target < fapi2::TARGET_TYPE_XBUS>&, + const uint8_t& ); extern "C" { @@ -50,7 +51,9 @@ extern "C" * @retval ReturnCode */ fapi2::ReturnCode - p9_io_xbus_dccal(const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target); + p9_io_xbus_dccal( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_group ); } // extern "C" diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.mk b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.mk index 62a1d4f85..c8ac7ed0a 100644 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.mk +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_dccal.mk @@ -7,7 +7,7 @@ # # EKB Project # -# COPYRIGHT 2015 +# COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # |