diff options
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.C')
-rw-r--r-- | src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.C | 137 |
1 files changed, 136 insertions, 1 deletions
diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.C b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.C index a7a5151dd..ab8927381 100644 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.C +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_xbus_clear_firs.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -48,9 +48,13 @@ // Includes //----------------------------------------------------------------------------- #include <p9_io_xbus_clear_firs.H> +#include <p9_io_xbus_read_erepair.H> #include <p9_io_scom.H> #include <p9_io_regs.H> +#include <p9_xbus_scom_addresses.H> +#include <p9_xbus_scom_addresses_fld.H> + //----------------------------------------------------------------------------- // Definitions //----------------------------------------------------------------------------- @@ -147,3 +151,134 @@ fapi2::ReturnCode io_tx_fir_reset( fapi_try_exit: return fapi2::current_err; } + +/** + * @brief This function reads the bad lane data of a EDI+ Xbus + * @param[in] i_target FAPI2 Target + * @param[in] i_clock_group Clock Group + * @param[out] o_bad_lane_data Bit representation of each lane in the clock group + * @retval ReturnCode + */ +fapi2::ReturnCode p9_io_xbus_get_bad_lane_data( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + const uint8_t& i_clock_group, + uint32_t& o_bad_lane_data) +{ + FAPI_IMP("I/O EDI+ Xbus Get Current Bad Lane Data :: Start"); + const uint8_t LN0 = 0; + uint64_t l_data = 0; + std::vector<uint8_t> l_bad_lanes; + + FAPI_DBG("Read Bad Lane Vector 0 15"); + FAPI_TRY(io::read(EDIP_RX_LANE_BAD_VEC_0_15, i_target, i_clock_group, LN0, l_data), + "rmw to edip_rx_lane_bad_vec_0_15 failed."); + + o_bad_lane_data = (io::get(EDIP_RX_LANE_BAD_VEC_0_15, l_data) << 8) & 0x00FFFF00; + + FAPI_DBG("Read Bad Lane Vector 16 23"); + FAPI_TRY(io::read(EDIP_RX_LANE_BAD_VEC_16_23, i_target, i_clock_group, LN0, l_data), + "rmw to edip_rx_lane_bad_vec_16_23 failed."); + + o_bad_lane_data |= (io::get(EDIP_RX_LANE_BAD_VEC_16_23, l_data) & 0x000000FF); + + + FAPI_DBG("Call xbus read erepair"); + FAPI_TRY(p9_io_xbus_read_erepair(i_target, i_clock_group, l_bad_lanes)); + + for(auto bad_lane : l_bad_lanes) + { + o_bad_lane_data |= (0x1 << (23 - bad_lane)); + } + +fapi_try_exit: + FAPI_IMP("I/O EDI+ Xbus Get Current Bad Lane Data :: Exit"); + return fapi2::current_err; +} + +/** + * @brief Clears PHY Rx/Tx FIRs on the XBUS(EDI+) specified target. The FIRs + * are cleared by toggling a rx & tx fir reset bit. + * @param[in] i_target FAPI2 Target + * @retval ReturnCode + */ +fapi2::ReturnCode p9_io_xbus_erepair_cleanup( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target) +{ + const uint8_t MAX_CLOCK_GROUPS = 2; + bool l_clear_pb_spare_deployed = true; + uint32_t l_grp0_pre_bad_lane_data = 0; + uint32_t l_grp1_pre_bad_lane_data = 0; + uint32_t l_pre_bad_lane_data = 0; + uint32_t l_post_bad_lane_data = 0; + FAPI_IMP("I/O Start Xbus Clear FIRs"); + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_XBUS_GRP0_PRE_BAD_LANE_DATA, + i_target, l_grp0_pre_bad_lane_data)); + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IO_XBUS_GRP1_PRE_BAD_LANE_DATA, + i_target, l_grp1_pre_bad_lane_data)); + + for (uint8_t l_group = 0; l_group < MAX_CLOCK_GROUPS; ++l_group) + { + // Get attribute of pre bad lane data + FAPI_IMP("Get Pre Bad Lane Data"); + + if (l_group == 0) + { + l_pre_bad_lane_data = l_grp0_pre_bad_lane_data; + } + else + { + l_pre_bad_lane_data = l_grp1_pre_bad_lane_data; + } + + + // Get current bad lane data + // - bad_lane_vector AND bad_lane_code + FAPI_IMP("Get Current Bad Lane Data"); + FAPI_TRY(p9_io_xbus_get_bad_lane_data(i_target, l_group, l_post_bad_lane_data)); + + FAPI_IMP("Compare Bad Lane Data"); + + if (l_pre_bad_lane_data == l_post_bad_lane_data) + { + FAPI_DBG("I/O EDI+ Xbus Pre/Post Bad Lane Data Match"); + + // If the entire bad lane vector equals 0, then we don't need to clear + // any firs. + if (l_pre_bad_lane_data != 0) + { + FAPI_DBG("I/O EDI+ Xbus Clearing PG Firs"); + + FAPI_TRY(io_tx_fir_reset(i_target, l_group), "Tx Reset Failed"); + FAPI_TRY(io_rx_fir_reset(i_target, l_group), "Rx Reset Failed"); + + } + } + else + { + FAPI_DBG("Bad lane data does NOT match."); + l_clear_pb_spare_deployed = false; + } + } + + // Clearing of the Spare Lane Deployed FIR when: + // - the pre/post bad lane data match on both groups. (l_clear_pb_spare_deployed) + // - AND if either groups have nonzero bad lane data + if (l_clear_pb_spare_deployed && + ((l_grp0_pre_bad_lane_data != 0x0) || (l_grp1_pre_bad_lane_data != 0x0)) ) + { + fapi2::buffer<uint64_t> l_data; + fapi2::buffer<uint64_t> l_mask; + + // Clear BUS0_SPARE_DEPLOYED (Bit 9). + l_data.clearBit<XBUS_1_FIR_REG_RX_BUS0_SPARE_DEPLOYED>(); + l_mask.setBit<XBUS_1_FIR_REG_RX_BUS0_SPARE_DEPLOYED>(); + FAPI_TRY(fapi2::putScomUnderMask(i_target, XBUS_FIR_REG, l_data, l_mask)); + + } + +fapi_try_exit: + FAPI_IMP("I/O End Xbus Clear FIRs"); + return fapi2::current_err; +} |