diff options
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/dimm')
13 files changed, 2008 insertions, 1035 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C index c1f3622e9..f41505858 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C @@ -22,3 +22,214 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs00.C +/// @brief Run and manage the DDR4 MRS00 loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief mrs0_data ctor +/// @param[in] a fapi2::TARGET_TYPE_DIMM target +/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +mrs00_data::mrs00_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): + iv_burst_length(0), + iv_read_burst_type(0), + iv_dll_reset(0), + iv_test_mode(0), + iv_write_recovery(0), + iv_cas_latency(0) +{ + FAPI_TRY( mss::eff_dram_bl(i_target, iv_burst_length) ); + FAPI_TRY( mss::eff_dram_rbt(i_target, iv_read_burst_type) ); + FAPI_TRY( mss::eff_dram_cl(i_target, iv_cas_latency) ); + FAPI_TRY( mss::eff_dram_dll_reset(i_target, iv_dll_reset) ); + FAPI_TRY( mss::eff_dram_tm(i_target, iv_test_mode) ); + FAPI_TRY( mss::eff_dram_twr(i_target, iv_write_recovery) ); + + FAPI_INF("MR0 Attributes: BL: 0x%x, RBT: 0x%x, CL: 0x%x, TM: 0x%x, DLL_RESET: 0x%x, WR: 0x%x", + iv_burst_length, iv_read_burst_type, iv_cas_latency, iv_test_mode, iv_dll_reset, iv_write_recovery); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + FAPI_ERR("unable to get attributes for mrs0"); + return; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs00 +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs00(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Check to make sure our ctor worked ok + mrs00_data l_data( i_target, fapi2::current_err ); + FAPI_TRY( fapi2::current_err, "Unable to construct MRS00 data from attributes"); + FAPI_TRY( mrs00(i_target, l_data, io_inst, i_rank) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs00, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs00_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs00(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs00_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Map from Write Recovery attribute value to bits in the MRS. + // Bit 4 is A13, bits 5:7 are A11:A9 + constexpr uint64_t LOWEST_WR = 10; + constexpr uint64_t WR_COUNT = 17; + constexpr uint8_t wr_map[WR_COUNT] = + { + // 10 12 14 16 18 20 22 24 26 + 0b0000, 0, 0b0001, 0, 0b0001, 0, 0b0011, 0, 0b0100, 0, 0b0101, 0, 0b0111, 0, 0b0110, 0, 0b1000 + }; + + // Map from the CAS Latency attribute to the bits in the MRS + constexpr uint64_t LOWEST_CL = 9; + constexpr uint64_t CL_COUNT = 25; + constexpr uint8_t cl_map[CL_COUNT] = + { + // 9 10 11 12 13 14 15 16 + 0b00000, 0b00001, 0b00010, 0b00011, 0b00100, 0b00101, 0b00110, 0b00111, + // 17, 18 19 20 21 22 23 24 + 0b01101, 0b01000, 0b01110, 0b01001, 0b01111, 0b01010, 0b01100, 0b01011, + // 25 26 27 28 29 30 31 32 33 + 0b10000, 0b10001, 0b10010, 0b10011, 0b10100, 0b10101, 0b10110, 0b10111, 0b11000 + }; + + fapi2::buffer<uint8_t> l_cl; + fapi2::buffer<uint8_t> l_wr; + + FAPI_ASSERT((i_data.iv_write_recovery >= LOWEST_WR) && (i_data.iv_write_recovery < (LOWEST_WR + WR_COUNT)), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(0) + .set_PARAMETER(WRITE_RECOVERY) + .set_PARAMETER_VALUE(i_data.iv_write_recovery) + .set_DIMM_IN_ERROR(i_target), + "Bad value for Write Recovery: %d (%s)", i_data.iv_write_recovery, mss::c_str(i_target)); + + FAPI_ASSERT((i_data.iv_cas_latency >= LOWEST_CL) && (i_data.iv_cas_latency < (LOWEST_CL + CL_COUNT)), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(0) + .set_PARAMETER(CAS_LATENCY) + .set_PARAMETER_VALUE(i_data.iv_cas_latency) + .set_DIMM_IN_ERROR(i_target), + "Bad value for CAS Latency: %d (%s)", i_data.iv_cas_latency, mss::c_str(i_target)); + + io_inst.arr0.insertFromRight<A0, 2>(i_data.iv_burst_length); + io_inst.arr0.writeBit<A3>(i_data.iv_read_burst_type); + io_inst.arr0.writeBit<A7>(i_data.iv_test_mode); + io_inst.arr0.writeBit<A8>(i_data.iv_dll_reset); + + // CAS Latency takes a little effort - the bits aren't contiguous + l_cl = cl_map[i_data.iv_cas_latency - LOWEST_CL]; + io_inst.arr0.writeBit<A12>(l_cl.getBit<3>()); + io_inst.arr0.writeBit<A6>(l_cl.getBit<4>()); + io_inst.arr0.writeBit<A5>(l_cl.getBit<5>()); + io_inst.arr0.writeBit<A4>(l_cl.getBit<6>()); + io_inst.arr0.writeBit<A2>(l_cl.getBit<7>()); + + // Write Recovery/Read to Precharge is not contiguous either. + l_wr = wr_map[i_data.iv_write_recovery - LOWEST_WR]; + io_inst.arr0.writeBit<A13>(l_wr.getBit<4>()); + io_inst.arr0.writeBit<A11>(l_wr.getBit<5>()); + io_inst.arr0.writeBit<A10>(l_wr.getBit<6>()); + io_inst.arr0.writeBit<A9>(l_wr.getBit<7>()); + + FAPI_INF("MR0: 0x%016llx", uint64_t(io_inst.arr0)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS0, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode mrs00_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank) +{ + static const uint8_t wr_map[9] = { 10, 12, 14, 16, 18, 20, 24, 22, 26 }; + + uint8_t l_burst_length = 0; + uint8_t l_read_burst_type = 0; + uint8_t l_dll_reset = 0; + uint8_t l_test_mode = 0; + + fapi2::buffer<uint8_t> l_wr_index; + fapi2::buffer<uint8_t> l_cas_latency; + + i_inst.arr0.extractToRight<A0, 2>(l_burst_length); + l_read_burst_type = i_inst.arr0.getBit<A3>(); + l_test_mode = i_inst.arr0.getBit<A7>(); + l_dll_reset = i_inst.arr0.getBit<A8>(); + + // CAS Latency takes a little effort - the bits aren't contiguous + l_cas_latency.writeBit<3>(i_inst.arr0.getBit<A12>()); + l_cas_latency.writeBit<4>(i_inst.arr0.getBit<A6>()); + l_cas_latency.writeBit<5>(i_inst.arr0.getBit<A5>()); + l_cas_latency.writeBit<6>(i_inst.arr0.getBit<A4>()); + l_cas_latency.writeBit<7>(i_inst.arr0.getBit<A2>()); + + // Write Recovery/Read to Precharge is not contiguous either. + l_wr_index.writeBit<4>(i_inst.arr0.getBit<A13>()); + l_wr_index.writeBit<5>(i_inst.arr0.getBit<A11>()); + l_wr_index.writeBit<6>(i_inst.arr0.getBit<A10>()); + l_wr_index.writeBit<7>(i_inst.arr0.getBit<A9>()); + + FAPI_INF("MR0 Decode BL: 0x%x, RBT: 0x%x, CL: 0x%x, TM: 0x%x, DLL_RESET: 0x%x, WR: (0x%x)0x%x", + l_burst_length, l_read_burst_type, uint8_t(l_cas_latency), l_test_mode, l_dll_reset, + wr_map[uint8_t(l_wr_index)], uint8_t(l_wr_index)); + + return FAPI2_RC_SUCCESS; +} + +} // ns ddr4 + +} // ns mss + diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs01.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs01.C index 5f83649f1..8e58fddb7 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs01.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs01.C @@ -22,3 +22,185 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs01.C +/// @brief Run and manage the DDR4 MRS01 loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief mrs01_data ctor +/// @param[in] a fapi2::TARGET_TYPE_DIMM target +/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +mrs01_data::mrs01_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): + iv_dll_enable(0), + iv_odic(0), + iv_additive_latency(0), + iv_wl_enable(0), + iv_tdqs(0), + iv_qoff(0) +{ + FAPI_TRY( mss::eff_dram_dll_enable(i_target, iv_dll_enable) ); + FAPI_TRY( mss::eff_dram_ron(i_target, iv_odic) ); + FAPI_TRY( mss::eff_dram_al(i_target, iv_additive_latency) ); + FAPI_TRY( mss::eff_dram_wr_lvl_enable(i_target, iv_wl_enable) ); + FAPI_TRY( mss::eff_dram_rtt_nom(i_target, &(iv_rtt_nom[0])) ); + FAPI_TRY( mss::eff_dram_tdqs(i_target, iv_tdqs) ); + FAPI_TRY( mss::eff_dram_output_buffer(i_target, iv_qoff) ); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + FAPI_ERR("unable to get attributes for mrs0"); + return; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs01 +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs01(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Check to make sure our ctor worked ok + mrs01_data l_data( i_target, fapi2::current_err ); + FAPI_TRY( fapi2::current_err, "Unable to construct MRS01 data from attributes"); + FAPI_TRY( mrs01(i_target, l_data, io_inst, i_rank) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs01, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs01_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs01(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs01_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Little table to map Output Driver Imepdance Control. 34Ohm is index 0, + // 48Ohm is index 1 + // Left bit is A2, right bit is A1 + constexpr uint8_t odic_map[2] = { 0b00, 0b01 }; + + // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking + // for index 1. So this doesn't correspond directly with the table in the JEDEC spec, + // as that's not in "denominator order." + // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 + constexpr uint8_t rtt_nom_map[8] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; + + size_t l_rtt_nom_index = 0; + + fapi2::buffer<uint8_t> l_additive_latency; + fapi2::buffer<uint8_t> l_odic_buffer; + fapi2::buffer<uint8_t> l_rtt_nom_buffer; + + FAPI_ASSERT( ((i_data.iv_odic == fapi2::ENUM_ATTR_EFF_DRAM_RON_OHM34) || + (i_data.iv_odic == fapi2::ENUM_ATTR_EFF_DRAM_RON_OHM48)), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(1) + .set_PARAMETER(OUTPUT_IMPEDANCE) + .set_PARAMETER_VALUE(i_data.iv_odic) + .set_DIMM_IN_ERROR(i_target), + "Bad value for output driver impedance: %d (%s)", i_data.iv_odic, mss::c_str(i_target)); + + // Map from impedance to bits in MRS1 + l_odic_buffer = (i_data.iv_odic == fapi2::ENUM_ATTR_EFF_DRAM_RON_OHM34) ? odic_map[0] : odic_map[1]; + + // We have to be careful about 0 + l_rtt_nom_index = (i_data.iv_rtt_nom[mss::index(i_rank)] == 0) ? + 0 : fapi2::ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM240 / i_data.iv_rtt_nom[mss::index(i_rank)]; + + // Map from RTT_NOM array to the value in the map + l_rtt_nom_buffer = rtt_nom_map[l_rtt_nom_index]; + + // Print this here as opposed to the MRS01 ctor as we want to see the specific rtt now information + FAPI_INF("MR1 rank %d attributes: DLL_ENABLE: 0x%x, ODIC: 0x%x(0x%x), AL: 0x%x, WLE: 0x%x, " + "RTT_NOM: 0x%x(0x%x), TDQS: 0x%x, QOFF: 0x%x", i_rank, + i_data.iv_dll_enable, i_data.iv_odic, uint8_t(l_odic_buffer), uint8_t(l_additive_latency), i_data.iv_wl_enable, + i_data.iv_rtt_nom[mss::index(i_rank)], uint8_t(l_rtt_nom_buffer), i_data.iv_tdqs, i_data.iv_qoff); + + io_inst.arr0.writeBit<A0>(i_data.iv_dll_enable); + mss::swizzle<A1, 2, 7>(l_odic_buffer, io_inst.arr0); + mss::swizzle<A3, 2, 7>(fapi2::buffer<uint8_t>(i_data.iv_additive_latency), io_inst.arr0); + io_inst.arr0.writeBit<A7>(i_data.iv_wl_enable); + mss::swizzle<A8, 3, 7>(l_rtt_nom_buffer, io_inst.arr0); + io_inst.arr0.writeBit<A11>(i_data.iv_tdqs); + io_inst.arr0.writeBit<A12>(i_data.iv_qoff); + + FAPI_INF("MR1: 0x%016llx", uint64_t(io_inst.arr0)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS1, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode mrs01_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank) +{ + fapi2::buffer<uint8_t> l_odic; + fapi2::buffer<uint8_t> l_additive_latency; + fapi2::buffer<uint8_t> l_rtt_nom; + + uint8_t l_dll_enable = i_inst.arr0.getBit<A0>(); + uint8_t l_wrl_enable = i_inst.arr0.getBit<A7>(); + uint8_t l_tdqs = i_inst.arr0.getBit<A11>(); + uint8_t l_qoff = i_inst.arr0.getBit<A12>(); + + mss::swizzle<6, 2, A2>(i_inst.arr0, l_odic); + mss::swizzle<6, 2, A4>(i_inst.arr0, l_additive_latency); + mss::swizzle<5, 3, A10>(i_inst.arr0, l_rtt_nom); + + FAPI_INF("MR1 rank %d decode: DLL_ENABLE: 0x%x, ODIC: 0x%x, AL: 0x%x, WLE: 0x%x, " + "RTT_NOM: 0x%x, TDQS: 0x%x, QOFF: 0x%x", i_rank, + l_dll_enable, uint8_t(l_odic), uint8_t(l_additive_latency), l_wrl_enable, uint8_t(l_rtt_nom), + l_tdqs, l_qoff); + + return FAPI2_RC_SUCCESS; +} + +} // ns ddr4 + +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs02.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs02.C index fafcd9780..1d6ecbf44 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs02.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs02.C @@ -22,3 +22,185 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs02.C +/// @brief Run and manage the DDR4 MRS02 loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief mrs02_data ctor +/// @param[in] a fapi2::TARGET_TYPE_DIMM target +/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +mrs02_data::mrs02_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): + iv_lpasr(0), + iv_cwl(0), + iv_write_crc(0) +{ + FAPI_TRY( mss::eff_dram_lpasr(i_target, iv_lpasr) ); + FAPI_TRY( mss::eff_dram_cwl(i_target, iv_cwl) ); + FAPI_TRY( mss::eff_dram_rtt_wr(i_target, &(iv_dram_rtt_wr[0])) ); + FAPI_TRY( mss::eff_write_crc(i_target, iv_write_crc) ); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + FAPI_ERR("unable to get attributes for mrs0"); + return; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs02 +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs02(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Check to make sure our ctor worked ok + mrs02_data l_data( i_target, fapi2::current_err ); + FAPI_TRY( fapi2::current_err, "Unable to construct MRS02 data from attributes"); + FAPI_TRY( mrs02(i_target, l_data, io_inst, i_rank) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs02, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs02_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs02(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs02_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Index this by subtracting 9 from the CWL attribute value. The table maps CWL attribute value + // (in clks) to the bit setting in MR2. See the table in the JEDEC spec for the mapping. + constexpr uint64_t LOWEST_CWL = 9; + constexpr uint64_t CWL_COUNT = 12; + // 9 10 11 12 14 16 18 20 + constexpr uint8_t cwl_map[CWL_COUNT] = { 0b000, 0b001, 0b010, 0b011, 0, 0b100, 0, 0b101, 0, 0b110, 0, 0b111 }; + + fapi2::buffer<uint8_t> l_cwl_buffer; + fapi2::buffer<uint8_t> l_rtt_wr_buffer; + + FAPI_ASSERT((i_data.iv_cwl >= LOWEST_CWL) && (i_data.iv_cwl < (LOWEST_CWL + CWL_COUNT)), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(0) + .set_PARAMETER(CAS_WRITE_LATENCY) + .set_PARAMETER_VALUE(i_data.iv_cwl) + .set_DIMM_IN_ERROR(i_target), + "Bad value for CWL: %d (%s)", i_data.iv_cwl, mss::c_str(i_target)); + + l_cwl_buffer = cwl_map[i_data.iv_cwl - LOWEST_CWL]; + + switch (i_data.iv_dram_rtt_wr[i_rank]) + { + case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_DISABLE: + l_rtt_wr_buffer = 0b000; + break; + + case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_HIGHZ: + l_rtt_wr_buffer = 0b011; + break; + + case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM240: + l_rtt_wr_buffer = 0b010; + break; + + case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM120: + l_rtt_wr_buffer = 0b001; + break; + + case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM60: + l_rtt_wr_buffer = 0b100; + break; + + default: + FAPI_ERR("unknown RTT_WR 0x%x (%s rank %d), dynamic odt off", + i_data.iv_dram_rtt_wr[i_rank], mss::c_str(i_target), i_rank); + l_rtt_wr_buffer = 0b000; + break; + }; + + // Printed here as opposed to the ctor as it uses the rank information + FAPI_INF("MR2 rank %d attributes: LPASR: 0x%x, CWL: 0x%x(0x%x), RTT_WR: 0x%x(0x%x), WRITE_CRC: 0x%x", i_rank, + uint8_t(i_data.iv_lpasr), i_data.iv_cwl, uint8_t(l_cwl_buffer), + i_data.iv_dram_rtt_wr[i_rank], uint8_t(l_rtt_wr_buffer), i_data.iv_write_crc); + + mss::swizzle<A3, 3, 7>(l_cwl_buffer, io_inst.arr0); + + mss::swizzle<A6, 2, 7>(fapi2::buffer<uint8_t>(i_data.iv_lpasr), io_inst.arr0); + + mss::swizzle<A9, 3, 7>(l_rtt_wr_buffer, io_inst.arr0); + + io_inst.arr0.writeBit<A12>(i_data.iv_write_crc); + + FAPI_INF("MR2: 0x%016llx", uint64_t(io_inst.arr0)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS2, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode mrs02_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank) +{ + fapi2::buffer<uint8_t> l_lpasr; + fapi2::buffer<uint8_t> l_cwl; + fapi2::buffer<uint8_t> l_rtt_wr; + + uint8_t l_write_crc = i_inst.arr0.getBit<A12>(); + mss::swizzle<5, 3, A5>(i_inst.arr0, l_cwl); + mss::swizzle<6, 2, A7>(i_inst.arr0, l_lpasr); + mss::swizzle<5, 3, A11>(i_inst.arr0, l_rtt_wr); + + FAPI_INF("MR2 rank %d deocode: LPASR: 0x%x, CWL: 0x%x, RTT_WR: 0x%x, WRITE_CRC: 0x%x", i_rank, + uint8_t(l_lpasr), uint8_t(l_cwl), uint8_t(l_rtt_wr), l_write_crc); + + return FAPI2_RC_SUCCESS; +} + +} // ns ddr4 + +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs03.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs03.C index 52bf96fb3..31a1e323a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs03.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs03.C @@ -22,3 +22,172 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs03.C +/// @brief Run and manage the DDR4 DDR4 loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief mrs03_data ctor +/// @param[in] a fapi2::TARGET_TYPE_DIMM target +/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +mrs03_data::mrs03_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): + iv_mpr_mode(0), + iv_mpr_page(0), + iv_geardown(0), + iv_pda(0), + iv_crc_wr_latency(0), + iv_temp_readout(0), + iv_fine_refresh(0), + iv_read_format(0) +{ + FAPI_TRY( mss::eff_mpr_mode(i_target, iv_mpr_mode) ); + FAPI_TRY( mss::eff_mpr_page(i_target, iv_mpr_page) ); + FAPI_TRY( mss::eff_geardown_mode(i_target, iv_geardown) ); + FAPI_TRY( mss::eff_per_dram_access(i_target, iv_pda) ); + FAPI_TRY( mss::eff_temp_readout(i_target, iv_temp_readout) ); + FAPI_TRY( mss::mrw_fine_refresh_mode(iv_fine_refresh) ); + FAPI_TRY( mss::eff_crc_wr_latency(i_target, iv_crc_wr_latency) ); + FAPI_TRY( mss::eff_mpr_rd_format(i_target, iv_read_format) ); + + FAPI_INF("MR3 attributes: MPR_MODE: 0x%x, MPR_PAGE: 0x%x, GD: 0x%x, PDA: 0x%x, " + "TEMP: 0x%x FR: 0x%x, CRC_WL: 0x%x, RF: 0x%x", + iv_mpr_mode, iv_mpr_page, iv_geardown, iv_pda, iv_temp_readout, + iv_fine_refresh, iv_crc_wr_latency, iv_read_format); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + FAPI_ERR("unable to get attributes for mrs0"); + return; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs03 +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs03(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Check to make sure our ctor worked ok + mrs03_data l_data( i_target, fapi2::current_err ); + FAPI_TRY( fapi2::current_err, "Unable to construct MRS03 data from attributes"); + FAPI_TRY( mrs03(i_target, l_data, io_inst, i_rank) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs03, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs00_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs03(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs03_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + constexpr uint64_t LOWEST_WL = 4; + constexpr uint64_t WL_COUNT = 3; + // 4 5 6 + constexpr uint8_t crc_wr_latency_map[WL_COUNT] = { 1, 2, 3 }; + + fapi2::buffer<uint8_t> l_crc_wr_latency_buffer; + + FAPI_ASSERT((i_data.iv_crc_wr_latency >= LOWEST_WL) && (i_data.iv_crc_wr_latency < (LOWEST_WL + WL_COUNT)), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(3) + .set_PARAMETER(WRITE_CMD_LATENCY) + .set_PARAMETER_VALUE(i_data.iv_crc_wr_latency) + .set_DIMM_IN_ERROR(i_target), + "Bad value for Write CMD Latency: %d (%s)", i_data.iv_crc_wr_latency, mss::c_str(i_target)); + + l_crc_wr_latency_buffer = crc_wr_latency_map[i_data.iv_crc_wr_latency - LOWEST_WL]; + + mss::swizzle<A0, 2, 7>(fapi2::buffer<uint8_t>(i_data.iv_mpr_mode), io_inst.arr0); + io_inst.arr0.writeBit<A2>(i_data.iv_mpr_page); + io_inst.arr0.writeBit<A3>(i_data.iv_geardown); + io_inst.arr0.writeBit<A4>(i_data.iv_pda); + io_inst.arr0.writeBit<A5>(i_data.iv_temp_readout); + + mss::swizzle<A6 , 3, 7>(fapi2::buffer<uint8_t>(i_data.iv_fine_refresh), io_inst.arr0); + mss::swizzle<A9 , 2, 7>(l_crc_wr_latency_buffer, io_inst.arr0); + mss::swizzle<A11, 2, 7>(fapi2::buffer<uint8_t>(i_data.iv_read_format), io_inst.arr0); + + FAPI_INF("MR3: 0x%016llx", uint64_t(io_inst.arr0)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS3, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs03_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank) +{ + fapi2::buffer<uint8_t> l_mpr_mode; + + fapi2::buffer<uint8_t> l_fine_refresh; + fapi2::buffer<uint8_t> l_crc_wr_latency_buffer; + fapi2::buffer<uint8_t> l_read_format; + + uint8_t l_mpr_page = i_inst.arr0.getBit<A2>(); + uint8_t l_geardown = i_inst.arr0.getBit<A3>(); + uint8_t l_pda = i_inst.arr0.getBit<A4>(); + uint8_t l_temp_readout = i_inst.arr0.getBit<A5>(); + + mss::swizzle<6, 2, A1>(i_inst.arr0, l_mpr_mode); + mss::swizzle<5, 3, A7>(i_inst.arr0, l_fine_refresh); + mss::swizzle<6, 2, A10>(i_inst.arr0, l_crc_wr_latency_buffer); + mss::swizzle<6, 2, A12>(i_inst.arr0, l_read_format); + + FAPI_INF("MR3 rank %d decode: MPR_MODE: 0x%x, MPR_PAGE: 0x%x, GD: 0x%x, PDA: 0x%x, " + "TEMP: 0x%x FR: 0x%x, CRC_WL: 0x%x, RF: 0x%x", i_rank, + uint8_t(l_mpr_mode), l_mpr_page, l_geardown, l_pda, uint8_t(l_temp_readout), + uint8_t(l_fine_refresh), uint8_t(l_crc_wr_latency_buffer), uint8_t(l_read_format)); + + return FAPI2_RC_SUCCESS; +} + +} // ns ddr4 +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs04.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs04.C index da3efde0b..aeb0b8c9e 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs04.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs04.C @@ -22,3 +22,180 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs04.C +/// @brief Run and manage the DDR4 MRS04 loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief mrs04_data ctor +/// @param[in] a fapi2::TARGET_TYPE_DIMM target +/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +mrs04_data::mrs04_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): + iv_max_pd_mode(0), + iv_temp_refresh_range(0), + iv_temp_ref_mode(0), + iv_vref_mon(0), + iv_cs_cmd_latency(0), + iv_ref_abort(0), + iv_rd_pre_train_mode(0), + iv_rd_preamble(0), + iv_wr_preamble(0), + iv_ppr(0) +{ + FAPI_TRY( mss::eff_max_powerdown_mode(i_target, iv_max_pd_mode) ); + FAPI_TRY( mss::mrw_temp_refresh_range(iv_temp_refresh_range) ); + FAPI_TRY( mss::eff_temp_refresh_mode(i_target, iv_temp_ref_mode) ); + FAPI_TRY( mss::eff_internal_vref_monitor(i_target, iv_vref_mon) ); + FAPI_TRY( mss::eff_cs_cmd_latency(i_target, iv_cs_cmd_latency) ); + FAPI_TRY( mss::eff_self_ref_abort(i_target, iv_ref_abort) ); + FAPI_TRY( mss::eff_rd_preamble_train(i_target, iv_rd_pre_train_mode) ); + FAPI_TRY( mss::eff_rd_preamble(i_target, iv_rd_preamble) ); + FAPI_TRY( mss::eff_wr_preamble(i_target, iv_wr_preamble) ); + FAPI_TRY( mss::eff_dram_ppr(i_target, iv_ppr) ); + + FAPI_INF("MR4 attributes: MAX_PD: 0x%x, TEMP_REFRESH_RANGE: 0x%x, TEMP_REF_MODE: 0x%x " + "VREF_MON: 0x%x, CSL: 0x%x, REF_ABORT: 0x%x, RD_PTM: 0x%x, RD_PRE: 0x%x, " + "WR_PRE: 0x%x, PPR: 0x%x", + iv_max_pd_mode, iv_temp_refresh_range, iv_temp_ref_mode, iv_vref_mon, + iv_cs_cmd_latency, iv_ref_abort, + iv_rd_pre_train_mode, iv_rd_preamble, iv_wr_preamble, iv_ppr); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + FAPI_ERR("unable to get attributes for mrs0"); + return; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs04 +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank thes rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs04(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Check to make sure our ctor worked ok + mrs04_data l_data( i_target, fapi2::current_err ); + FAPI_TRY( fapi2::current_err, "Unable to construct MRS04 data from attributes"); + FAPI_TRY( mrs04(i_target, l_data, io_inst, i_rank) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs04, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs04_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs04(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs04_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + constexpr uint64_t CS_CMD_COUNT = 9; + // 0 3 4 5 6 8 + constexpr uint8_t cs_cmd_latency_map[CS_CMD_COUNT] = { 0b000, 0, 0, 0b001, 0b010, 0b011, 0b100, 0, 0b101 }; + + fapi2::buffer<uint8_t> l_cs_cmd_latency_buffer; + + FAPI_ASSERT( (i_data.iv_cs_cmd_latency < CS_CMD_COUNT), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(4) + .set_PARAMETER(CS_CMD_LATENCY) + .set_PARAMETER_VALUE(i_data.iv_cs_cmd_latency) + .set_DIMM_IN_ERROR(i_target), + "Bad value for CS to CMD/ADDR Latency: %d (%s)", i_data.iv_cs_cmd_latency, mss::c_str(i_target)); + + l_cs_cmd_latency_buffer = cs_cmd_latency_map[i_data.iv_cs_cmd_latency]; + + io_inst.arr0.writeBit<A1>(i_data.iv_max_pd_mode); + io_inst.arr0.writeBit<A2>(i_data.iv_temp_refresh_range); + io_inst.arr0.writeBit<A3>(i_data.iv_temp_ref_mode); + io_inst.arr0.writeBit<A4>(i_data.iv_vref_mon); + + mss::swizzle<A6, 3, 7>(l_cs_cmd_latency_buffer, io_inst.arr0); + io_inst.arr0.writeBit<A9>(i_data.iv_ref_abort); + io_inst.arr0.writeBit<A10>(i_data.iv_rd_pre_train_mode); + io_inst.arr0.writeBit<A11>(i_data.iv_rd_preamble); + io_inst.arr0.writeBit<A12>(i_data.iv_wr_preamble); + io_inst.arr0.writeBit<A13>(i_data.iv_ppr); + + FAPI_INF("MR4: 0x%016llx", uint64_t(io_inst.arr0)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS4, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs04_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank) +{ + uint8_t l_max_pd_mode = i_inst.arr0.getBit<A1>(); + uint8_t l_temp_refresh_range = i_inst.arr0.getBit<A2>(); + uint8_t l_temp_ref_mode = i_inst.arr0.getBit<A3>(); + uint8_t l_vref_mon = i_inst.arr0.getBit<A4>(); + + fapi2::buffer<uint8_t> l_cs_cmd_latency_buffer; + mss::swizzle<5, 3, A8>(i_inst.arr0, l_cs_cmd_latency_buffer); + + uint8_t l_ref_abort = i_inst.arr0.getBit<A9>(); + uint8_t l_rd_pre_train_mode = i_inst.arr0.getBit<A10>(); + uint8_t l_rd_preamble = i_inst.arr0.getBit<A11>(); + uint8_t l_wr_preamble = i_inst.arr0.getBit<A12>(); + uint8_t l_ppr = i_inst.arr0.getBit<A13>(); + + FAPI_INF("MR4 rank %d decode: MAX_PD: 0x%x, TEMP_REFRESH_RANGE: 0x%x, TEMP_REF_MODE: 0x%x " + "VREF_MON: 0x%x, CSL: 0x%x, REF_ABORT: 0x%x, RD_PTM: 0x%x, RD_PRE: 0x%x, " + "WR_PRE: 0x%x, PPR: 0x%x", i_rank, + l_max_pd_mode, l_temp_refresh_range, l_temp_ref_mode, l_vref_mon, + uint8_t(l_cs_cmd_latency_buffer), l_ref_abort, + l_rd_pre_train_mode, l_rd_preamble, l_wr_preamble, l_ppr); + + return FAPI2_RC_SUCCESS; +} + + +} // ns ddr4 +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs05.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs05.C index 966e225fa..5f647d1c1 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs05.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs05.C @@ -22,3 +22,199 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs05.C +/// @brief Run and manage the DDR4 MRS05 loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief mrs05_data ctor +/// @param[in] a fapi2::TARGET_TYPE_DIMM target +/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +mrs05_data::mrs05_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): + iv_ca_parity_latency(0), + iv_crc_error_clear(0), + iv_ca_parity_error_status(0), + iv_odt_input_buffer(0), + iv_ca_parity(0), + iv_data_mask(0), + iv_write_dbi(0), + iv_read_dbi(0) +{ + FAPI_TRY( mss::eff_ca_parity_latency(i_target, iv_ca_parity_latency) ); + FAPI_TRY( mss::eff_crc_error_clear(i_target, iv_crc_error_clear) ); + FAPI_TRY( mss::eff_ca_parity_error_status(i_target, iv_ca_parity_error_status) ); + FAPI_TRY( mss::eff_odt_input_buff(i_target, iv_odt_input_buffer) ); + FAPI_TRY( mss::eff_rtt_park(i_target, &(iv_rtt_park[0])) ); + FAPI_TRY( mss::eff_ca_parity(i_target, iv_ca_parity) ); + FAPI_TRY( mss::eff_data_mask(i_target, iv_data_mask) ); + FAPI_TRY( mss::eff_write_dbi(i_target, iv_write_dbi) ); + FAPI_TRY( mss::eff_read_dbi(i_target, iv_read_dbi) ); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + FAPI_ERR("unable to get attributes for mrs0"); + return; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs05 +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs05(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Check to make sure our ctor worked ok + mrs05_data l_data( i_target, fapi2::current_err ); + FAPI_TRY( fapi2::current_err, "Unable to construct MRS05 data from attributes"); + FAPI_TRY( mrs05(i_target, l_data, io_inst, i_rank) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs05, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs05_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs05(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs05_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + constexpr uint64_t CA_PARITY_COUNT = 9; + // 0 4 5 6 8 + constexpr uint8_t ca_parity_latency_map[CA_PARITY_COUNT] = { 0b000, 0, 0, 0, 0b001, 0b010, 0b011, 0, 0b100 }; + + // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking + // for index 1. So this doesn't correspond directly with the table in the JEDEC spec, + // as that's not in "denominator order." + constexpr uint64_t RTT_PARK_COUNT = 8; + // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 + constexpr uint8_t rtt_park_map[RTT_PARK_COUNT] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; + + uint8_t l_rtt_park_index = 0; + + fapi2::buffer<uint8_t> l_ca_parity_latency_buffer; + fapi2::buffer<uint8_t> l_rtt_park_buffer; + + FAPI_ASSERT( (i_data.iv_ca_parity_latency < CA_PARITY_COUNT), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(5) + .set_PARAMETER(CA_PARITY_LATENCY) + .set_PARAMETER_VALUE(i_data.iv_ca_parity_latency) + .set_DIMM_IN_ERROR(i_target), + "Bad value for CA parity latency: %d (%s)", i_data.iv_ca_parity_latency, mss::c_str(i_target)); + + FAPI_ASSERT( (i_rank < RTT_PARK_COUNT), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(5) + .set_PARAMETER(RTT_PARK) + .set_PARAMETER_VALUE(i_rank) + .set_DIMM_IN_ERROR(i_target), + "Bad value for RTT park: %d (%s)", i_rank, mss::c_str(i_target)); + + l_ca_parity_latency_buffer = ca_parity_latency_map[i_data.iv_ca_parity_latency]; + + // We have to be careful about 0 + l_rtt_park_index = (i_data.iv_rtt_park[mss::index(i_rank)] == 0) ? + 0 : fapi2::ENUM_ATTR_EFF_RTT_PARK_240OHM / i_data.iv_rtt_park[mss::index(i_rank)]; + + // Map from RTT_NOM array to the value in the map + l_rtt_park_buffer = rtt_park_map[l_rtt_park_index]; + + FAPI_INF("MR5 rank %d attributes: CAPL: 0x%x(0x%x), CRC_EC: 0x%x, CA_PES: 0x%x, ODT_IB: 0x%x " + "RTT_PARK: 0x%x(0x%x), CAP: 0x%x, DM: 0x%x, WDBI: 0x%x, RDBI: 0x%x", i_rank, + i_data.iv_ca_parity_latency, uint8_t(l_ca_parity_latency_buffer), i_data.iv_crc_error_clear, + i_data.iv_ca_parity_error_status, i_data.iv_odt_input_buffer, + i_data.iv_rtt_park[mss::index(i_rank)], uint8_t(l_rtt_park_buffer), i_data.iv_ca_parity, + i_data.iv_data_mask, i_data.iv_write_dbi, i_data.iv_read_dbi); + + mss::swizzle<A0, 3, 7>(l_ca_parity_latency_buffer, io_inst.arr0); + io_inst.arr0.writeBit<A3>(i_data.iv_crc_error_clear); + io_inst.arr0.writeBit<A4>(i_data.iv_ca_parity_error_status); + io_inst.arr0.writeBit<A5>(i_data.iv_odt_input_buffer); + mss::swizzle<A6, 3, 7>(l_rtt_park_buffer, io_inst.arr0); + io_inst.arr0.writeBit<A9>(i_data.iv_ca_parity); + io_inst.arr0.writeBit<A10>(i_data.iv_data_mask); + io_inst.arr0.writeBit<A11>(i_data.iv_write_dbi); + io_inst.arr0.writeBit<A12>(i_data.iv_read_dbi); + + FAPI_INF("MR5: 0x%016llx", uint64_t(io_inst.arr0)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS5, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs05_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank) +{ + fapi2::buffer<uint8_t> l_ca_parity_latency_buffer; + fapi2::buffer<uint8_t> l_rtt_park_buffer; + + mss::swizzle<5, 3, A2>(i_inst.arr0, l_ca_parity_latency_buffer); + mss::swizzle<5, 3, A8>(i_inst.arr0, l_rtt_park_buffer); + + uint8_t l_crc_error_clear = i_inst.arr0.getBit<A3>(); + uint8_t l_ca_parity_error_status = i_inst.arr0.getBit<A4>(); + uint8_t l_odt_input_buffer = i_inst.arr0.getBit<A5>(); + + uint8_t l_ca_parity = i_inst.arr0.getBit<A9>(); + uint8_t l_data_mask = i_inst.arr0.getBit<A10>(); + uint8_t l_write_dbi = i_inst.arr0.getBit<A11>(); + uint8_t l_read_dbi = i_inst.arr0.getBit<A12>(); + + FAPI_INF("MR5 rank %d decode: CAPL: 0x%x, CRC_EC: 0x%x, CA_PES: 0x%x, ODT_IB: 0x%x " + "RTT_PARK: 0x%x, CAP: 0x%x, DM: 0x%x, WDBI: 0x%x, RDBI: 0x%x", i_rank, + uint8_t(l_ca_parity_latency_buffer), l_crc_error_clear, l_ca_parity_error_status, + l_odt_input_buffer, uint8_t(l_rtt_park_buffer), l_ca_parity, l_data_mask, + l_write_dbi, l_read_dbi); + + return FAPI2_RC_SUCCESS; +} + +} // ns ddr4 +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs06.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs06.C index d8a285d91..3829d2ef0 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs06.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs06.C @@ -22,3 +22,149 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs06.C +/// @brief Run and manage the DDR4 MRS06 loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief mrs06_data ctor +/// @param[in] a fapi2::TARGET_TYPE_DIMM target +/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +mrs06_data::mrs06_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): + iv_tccd_l(0) +{ + FAPI_TRY( mss::eff_vref_dq_train_value(i_target, &(iv_vrefdq_train_value[0])) ); + FAPI_TRY( mss::eff_vref_dq_train_range(i_target, &(iv_vrefdq_train_range[0])) ); + FAPI_TRY( mss::eff_vref_dq_train_enable(i_target, &(iv_vrefdq_train_enable[0])) ); + FAPI_TRY( mss::eff_dram_tccd_l(i_target, iv_tccd_l) ); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + FAPI_ERR("unable to get attributes for mrs0"); + return; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs06 +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs06(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + // Check to make sure our ctor worked ok + mrs06_data l_data( i_target, fapi2::current_err ); + FAPI_TRY( fapi2::current_err, "Unable to construct MRS06 data from attributes"); + FAPI_TRY( mrs06(i_target, l_data, io_inst, i_rank) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Configure the ARR0 of the CCS instruction for mrs06, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs06_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank the rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs06(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs06_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank) +{ + constexpr uint64_t LOWEST_TCCD = 4; + constexpr uint64_t TCCD_COUNT = 5; + // 4 5 6 7 8 + constexpr uint8_t tccd_l_map[TCCD_COUNT] = { 0b000, 0b001, 0b010, 0b011, 0b100 }; + + fapi2::buffer<uint8_t> l_tccd_l_buffer; + fapi2::buffer<uint8_t> l_vrefdq_train_value_buffer; + + FAPI_ASSERT((i_data.iv_tccd_l >= LOWEST_TCCD) && (i_data.iv_tccd_l < (LOWEST_TCCD + TCCD_COUNT)), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(6) + .set_PARAMETER(TCCD) + .set_PARAMETER_VALUE(i_data.iv_tccd_l) + .set_DIMM_IN_ERROR(i_target), + "Bad value for TCCD: %d (%s)", i_data.iv_tccd_l, mss::c_str(i_target)); + + l_tccd_l_buffer = tccd_l_map[i_data.iv_tccd_l - LOWEST_TCCD]; + l_vrefdq_train_value_buffer = i_data.iv_vrefdq_train_value[mss::index(i_rank)]; + + FAPI_INF("MR6 rank %d attributes: TRAIN_V: 0x%x(0x%x), TRAIN_R: 0x%x, TRAIN_E: 0x%x, TCCD_L: 0x%x(0x%x)", i_rank, + i_data.iv_vrefdq_train_value[mss::index(i_rank)], uint8_t(l_vrefdq_train_value_buffer), + i_data.iv_vrefdq_train_range[mss::index(i_rank)], + i_data.iv_vrefdq_train_enable[mss::index(i_rank)], i_data.iv_tccd_l, uint8_t(l_tccd_l_buffer)); + + mss::swizzle<A0, 6, 7>(l_vrefdq_train_value_buffer, io_inst.arr0); + io_inst.arr0.writeBit<A6>(i_data.iv_vrefdq_train_range[mss::index(i_rank)]); + io_inst.arr0.writeBit<A7>(i_data.iv_vrefdq_train_enable[mss::index(i_rank)]); + mss::swizzle<A10, 3, 7>(l_tccd_l_buffer, io_inst.arr0); + + FAPI_INF("MR6: 0x%016llx", uint64_t(io_inst.arr0)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS6, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs06_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank) +{ + fapi2::buffer<uint8_t> l_tccd_l_buffer; + fapi2::buffer<uint8_t> l_vrefdq_train_value_buffer; + + mss::swizzle<2, 6, A5>(i_inst.arr0, l_vrefdq_train_value_buffer); + uint8_t l_vrefdq_train_range = i_inst.arr0.getBit<A6>(); + uint8_t l_vrefdq_train_enable = i_inst.arr0.getBit<A7>(); + mss::swizzle<5, 3, A12>(i_inst.arr0, l_tccd_l_buffer); + + FAPI_INF("MR6 rank %d decode: TRAIN_V: 0x%x, TRAIN_R: 0x%x, TRAIN_E: 0x%x, TCCD_L: 0x%x", i_rank, + uint8_t(l_vrefdq_train_value_buffer), l_vrefdq_train_range, + l_vrefdq_train_enable, uint8_t(l_tccd_l_buffer)); + + return FAPI2_RC_SUCCESS; +} + +} // ns ddr4 +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C new file mode 100644 index 000000000..166246dde --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C @@ -0,0 +1,125 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs_load_ddr4.C +/// @brief Run and manage the DDR4 mrs loading +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> + +#include <mss.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> + +using fapi2::TARGET_TYPE_MCBIST; +using fapi2::TARGET_TYPE_DIMM; + +using fapi2::FAPI2_RC_SUCCESS; + +namespace mss +{ + +namespace ddr4 +{ + +/// +/// @brief Perform the mrs_load DDR4 operations - TARGET_TYPE_DIMM specialization +/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> +/// @param[in] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, + std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst) +{ + FAPI_INF("ddr4::mrs_load %s", mss::c_str(i_target)); + + // Per DDR4MRS02 table 104 - timing requirements + static const uint64_t tMRD = 8; + + static std::vector< mrs_data<TARGET_TYPE_MCBIST> > l_mrs_data = + { + // JEDEC ordering of MRS per DDR4 power on sequence + { 3, mrs03, mrs03_decode, tMRD }, { 6, mrs06, mrs06_decode, tMRD }, + { 5, mrs05, mrs05_decode, tMRD }, { 4, mrs04, mrs04_decode, tMRD }, + { 2, mrs02, mrs02_decode, tMRD }, { 1, mrs01, mrs01_decode, tMRD }, + { 0, mrs00, mrs00_decode, tMRD }, + }; + + std::vector< uint64_t > l_ranks; + FAPI_TRY( mss::ranks(i_target, l_ranks) ); + + for (const auto& d : l_mrs_data) + { + for (const auto& r : l_ranks) + { + // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS + ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_a_side = + ccs::mrs_command<TARGET_TYPE_MCBIST>(i_target, r, d.iv_mrs); + ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_b_side; + + // Thou shalt send 2 MRS, one for the a-side and the other inverted for the b-side. + // If we're on an odd-rank then we need to mirror + // So configure the A-side, mirror if necessary and invert for the B-side + FAPI_TRY( d.iv_func(i_target, l_inst_a_side, r) ); + + FAPI_TRY( mss::address_mirror(i_target, r, l_inst_a_side) ); + l_inst_b_side = mss::address_invert(l_inst_a_side); + + // Not sure if we can get tricky here and only delay after the b-side MR. The question is whether the delay + // is needed/assumed by the register or is purely a DRAM mandated delay. We know we can't go wrong having + // both delays but if we can ever confirm that we only need one we can fix this. BRS + l_inst_a_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, + MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay); + l_inst_b_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, + MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay); + + // Dump out the 'decoded' MRS and trace the CCS instructions. + if (d.iv_dumper != nullptr) + { + FAPI_TRY( d.iv_dumper(l_inst_a_side, r) ); + } + + FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d a-side", uint8_t(d.iv_mrs), d.iv_delay, + l_inst_a_side.arr0, l_inst_a_side.arr1, mss::c_str(i_target), r); + FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d b-side", uint8_t(d.iv_mrs), d.iv_delay, + l_inst_b_side.arr0, l_inst_b_side.arr1, mss::c_str(i_target), r); + + // Add both to the CCS program + io_inst.push_back(l_inst_a_side); + io_inst.push_back(l_inst_b_side); + } + } + +fapi_try_exit: + return fapi2::current_err; +} + +} // ns ddr4 +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H new file mode 100644 index 000000000..cfbe96e5a --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H @@ -0,0 +1,579 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/// +/// @file mrs_load_ddr4.H +/// @brief Code to support mrs_load_ddr4 +/// +// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 1 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_MRS_LOAD_DDR4_H_ +#define _MSS_MRS_LOAD_DDR4_H_ + +#include <vector> +#include <fapi2.H> +#include <lib/utils/c_str.H> +#include <lib/dimm/mrs_load.H> + +namespace mss +{ + +namespace ddr4 +{ + +// +// Each MRS has it's attributes encapsulated in it's little struct. +// + +/// +/// @brief Data structure for MRS0 data +/// +struct mrs00_data +{ + /// + /// @brief mrs00_data ctor + /// @param[in] a fapi2::TARGET_TYPE_DIMM target + /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok + /// + mrs00_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ); + + uint8_t iv_burst_length; + uint8_t iv_read_burst_type; + uint8_t iv_dll_reset; + uint8_t iv_test_mode; + uint8_t iv_write_recovery; + uint8_t iv_cas_latency; +}; + +/// +/// @brief Data structure for MRS1 data +/// +struct mrs01_data +{ + /// + /// @brief mrs01_data ctor + /// @param[in] a fapi2::TARGET_TYPE_DIMM target + /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok + /// + mrs01_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ); + + uint8_t iv_dll_enable; + uint8_t iv_odic; + uint8_t iv_additive_latency; + uint8_t iv_wl_enable; + uint8_t iv_tdqs; + uint8_t iv_qoff; + uint8_t iv_rtt_nom[MAX_RANK_PER_DIMM]; +}; + +/// +/// @brief Data structure for MRS2 data +/// +struct mrs02_data +{ + /// + /// @brief mrs03_data ctor + /// @param[in] a fapi2::TARGET_TYPE_DIMM target + /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok + /// + mrs02_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ); + + uint8_t iv_lpasr; + uint8_t iv_cwl; + uint8_t iv_write_crc; + uint8_t iv_dram_rtt_wr[MAX_RANK_PER_DIMM]; +}; + + +/// +/// @brief Data structure for MRS3 data +/// +struct mrs03_data +{ + /// + /// @brief mrs03_data ctor + /// @param[in] a fapi2::TARGET_TYPE_DIMM target + /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok + /// + mrs03_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ); + + uint8_t iv_mpr_mode; + uint8_t iv_mpr_page; + uint8_t iv_geardown; + uint8_t iv_pda; + uint8_t iv_crc_wr_latency; + uint8_t iv_temp_readout; + uint8_t iv_fine_refresh; + uint8_t iv_read_format; +}; + +/// +/// @brief Data structure for MRS4 data +/// +struct mrs04_data +{ + /// + /// @brief mrs04_data ctor + /// @param[in] a fapi2::TARGET_TYPE_DIMM target + /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok + /// + mrs04_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ); + + uint8_t iv_max_pd_mode; + uint8_t iv_temp_refresh_range; + uint8_t iv_temp_ref_mode; + uint8_t iv_vref_mon; + uint8_t iv_cs_cmd_latency; + uint8_t iv_ref_abort; + uint8_t iv_rd_pre_train_mode; + uint8_t iv_rd_preamble; + uint8_t iv_wr_preamble; + uint8_t iv_ppr; +}; + +/// +/// @brief Data structure for MRS5 data +/// +struct mrs05_data +{ + /// + /// @brief mrs05_data ctor + /// @param[in] a fapi2::TARGET_TYPE_DIMM target + /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok + /// + mrs05_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ); + + uint8_t iv_ca_parity_latency; + uint8_t iv_crc_error_clear; + uint8_t iv_ca_parity_error_status; + uint8_t iv_odt_input_buffer; + uint8_t iv_ca_parity; + uint8_t iv_data_mask; + uint8_t iv_write_dbi; + uint8_t iv_read_dbi; + uint8_t iv_rtt_park[MAX_RANK_PER_DIMM]; +}; + +/// +/// @brief Data structure for MRS6 data +/// +struct mrs06_data +{ + /// + /// @brief mrs06_data ctor + /// @param[in] a fapi2::TARGET_TYPE_DIMM target + /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok + /// + mrs06_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ); + + uint8_t iv_vrefdq_train_value[MAX_RANK_PER_DIMM]; + uint8_t iv_vrefdq_train_range[MAX_RANK_PER_DIMM]; + uint8_t iv_vrefdq_train_enable[MAX_RANK_PER_DIMM]; + uint8_t iv_tccd_l; +}; + +/// +/// @defgroup setup-ccs +/// @addtogroyp setup-ccs +/// API which setup CCS instructions. +/// @{ + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs00 +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs00(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs01 +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs01(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs02 +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs02(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs03 +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs03(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs04 +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs04(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs05 +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs05(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs06 +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs06(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// }@ + +/// +/// @defgroup setup-ccs-overloads +/// @addtogroyp setup-ccs-overloads +/// API which setup CCS instructions, but take an MRS data object as input +/// @{ + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs00, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs00_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs00(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs00_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs01, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs01_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs01(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs01_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs02, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs02_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs02(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs02_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs03, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs00_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs03(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs03_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs04, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs04_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs04(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs04_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs05, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs05_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs05(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs05_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// +/// @brief Configure the ARR0 of the CCS isntruction for mrs06, data object as input +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] i_data an mrs06_data object, filled in +/// @param[in,out] io_inst the instruction to fixup +/// @param[in] i_rank ths rank in question +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode mrs06(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const mrs06_data& i_data, + ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst, + const uint64_t i_rank); + +/// }@ + +/// +/// @defgroup ccs-decode +/// @addtogroyccs-decode +/// API which decode CCS instructions. +/// @{ + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS00, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs00_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank); + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS01, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs01_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank); + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS02, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs02_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank); + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS03, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs03_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank); + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS04, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs04_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank); + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS05, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs05_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank); + +/// +/// @brief Given a CCS instruction which contains address bits with an encoded MRS06, +/// decode and trace the contents +/// @param[in] i_inst the CCS instruction +/// @param[in] i_rank ths rank in question +/// @return void +/// +fapi2::ReturnCode mrs06_decode(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst, + const uint64_t i_rank); + + +/// +/// @brief Perform the mrs_load DDR4 operations - TARGET_TYPE_DIMM specialization +/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM> +/// @param[in] io_inst a vector of CCS instructions we should add to +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +fapi2::ReturnCode mrs_load( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst); + +/// @} + +} // ns ddr4 + +// Map bits in the ARR0 register(s) to MRS address bits. Should be traits related to ARR0. BRS +enum address_bits +{ + A0 = 0, + A1 = 1, + A2 = 2, + A3 = 3, + A4 = 4, + A5 = 5, + A6 = 6, + A7 = 7, + A8 = 8, + A9 = 9, + A10 = 10, + A11 = 11, + A12 = 12, + A13 = 13, + A14 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_14, + A15 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_15, + A16 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_16, + A17 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_17, + + // Only kind of address bits ... <shrug> + BA0 = 17, + BA1 = 18, + BG0 = 19, + BG1 = 15, +}; + +/// +/// @brief Mirror (front to back) the ADR bits of a CCS instruction - implementation +/// @tparam T typename of the ccs::instruction_t +/// @param[in, out] io_inst reference to a CCS instruction to be mirrored +/// @return FAPI2_RC_SUCESS iff ok +/// @note written this way so this is easier to test +/// +template<fapi2::TargetType T> +void address_mirror_impl(ccs::instruction_t<T>& io_inst) +{ + // Nothing fancy here, just mirror the bits we're told to mirror in Table 14 — Address Mirroring and Inversion + mss::template swap<A3, A4>(io_inst.arr0); + mss::template swap<A5, A6>(io_inst.arr0); + mss::template swap<A7, A8>(io_inst.arr0); + mss::template swap<A11, A13>(io_inst.arr0); + mss::template swap<BA0, BA1>(io_inst.arr0); + mss::template swap<BG0, BG1>(io_inst.arr0); +} + +/// +/// @brief Mirror (front to back) the ADR bits of a CCS instruction +/// @tparam T typename of the ccs::instruction_t +/// @param[in] i_target target to use to get mirroring attribute +/// @param[in] i_rank the rank in question +/// @param[in, out] io_inst reference to a CCS instruction to be mirrored +/// @return FAPI2_RC_SUCESS iff ok +/// @note assumes the input is from an even number rank +/// +template<fapi2::TargetType T> +fapi2::ReturnCode address_mirror(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const uint64_t i_rank, ccs::instruction_t<T>& io_inst) +{ + // We only mirror if the mirroring attribute is set. + uint8_t l_mirror = 0; + FAPI_TRY( eff_dimm_rcd_mirror_mode(i_target, l_mirror) ); + + // We only mirror odd ranks. + if ((l_mirror == fapi2::ENUM_ATTR_EFF_DIMM_RCD_MIRROR_MODE_ON) && (i_rank & 0x1)) + { + address_mirror_impl(io_inst); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Invert (side to side) the ADR bits of a CCS instruction +/// @param[in] i_inst const reference to a CCS instruction. +/// @return[out] ccs instruction with the ADR bits inverted (side-to-side) +/// +template<fapi2::TargetType T> +ccs::instruction_t<T> address_invert(const ccs::instruction_t<T>& i_inst) +{ + // Copy the input as the output doesn't all change. + ccs::instruction_t<T> i_out(i_inst); + + // Nothing fancy here, just negate the bits we're told to negate in Table 14 — Address Mirroring and Inversion + mss::template negate<A3>(i_out.arr0); + mss::template negate<A4>(i_out.arr0); + mss::template negate<A5>(i_out.arr0); + mss::template negate<A6>(i_out.arr0); + mss::template negate<A7>(i_out.arr0); + mss::template negate<A8>(i_out.arr0); + mss::template negate<A9>(i_out.arr0); + + mss::template negate<A11>(i_out.arr0); + mss::template negate<A13>(i_out.arr0); + mss::template negate<A17>(i_out.arr0); + + mss::template negate<BA0>(i_out.arr0); + mss::template negate<BA1>(i_out.arr0); + mss::template negate<BG0>(i_out.arr0); + mss::template negate<BG1>(i_out.arr0); + + return i_out; +} + +} // namespace +#endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C index 9ea3415a8..1ece04fd4 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C @@ -38,7 +38,7 @@ #include <mss.H> #include <lib/dimm/mrs_load.H> -#include <lib/dimm/mrs_load_ddr4.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_DIMM; @@ -84,12 +84,12 @@ fapi_try_exit: /// /// @brief Perform the mrs_load operations - unknown DIMM case /// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in] i_inst a vector of CCS instructions we should add to (unused) +/// @param[in] io_inst a vector of CCS instructions we should add to (unused) /// @return FAPI2_RC_SUCCESS if and only if ok /// template<> fapi2::ReturnCode perform_mrs_load<DEFAULT_KIND>( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& i_inst) + std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst) { uint8_t l_type = 0; uint8_t l_gen = 0; @@ -114,15 +114,15 @@ fapi_try_exit: /// /// @brief Perform the mrs_load operations - RDIMM DDR4 /// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in] i_inst a vector of CCS instructions we should add to +/// @param[in] io_inst a vector of CCS instructions we should add to /// @return FAPI2_RC_SUCCESS if and only if ok /// template<> fapi2::ReturnCode perform_mrs_load<KIND_RDIMM_DDR4>( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& i_inst) + std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst) { FAPI_DBG("perform mrs_load for %s [expecting rdimm (ddr4)]", mss::c_str(i_target)); - FAPI_TRY( mrs_load_ddr4(i_target, i_inst) ); + FAPI_TRY( ddr4::mrs_load(i_target, io_inst) ); fapi_try_exit: return fapi2::current_err; @@ -131,15 +131,15 @@ fapi_try_exit: /// /// @brief Perform the mrs_load operations - LRDIMM DDR4 /// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in] i_inst a vector of CCS instructions we should add to +/// @param[in] io_inst a vector of CCS instructions we should add to /// @return FAPI2_RC_SUCCESS if and only if ok /// template<> fapi2::ReturnCode perform_mrs_load<KIND_LRDIMM_DDR4>( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& i_inst) + std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst) { FAPI_DBG("perform mrs_load for %s [expecting lrdimm (ddr4)]", mss::c_str(i_target)); - FAPI_TRY( mrs_load_ddr4(i_target, i_inst) ); + FAPI_TRY( ddr4::mrs_load(i_target, io_inst) ); fapi_try_exit: return fapi2::current_err; @@ -149,12 +149,12 @@ fapi_try_exit: /// /// @brief Perform the mrs_load operations - start the dispatcher /// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in] i_inst a vector of CCS instructions we should add to +/// @param[in] io_inst a vector of CCS instructions we should add to /// @return FAPI2_RC_SUCCESS if and only if ok /// template<> fapi2::ReturnCode perform_mrs_load<FORCE_DISPATCH>( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& i_inst) + std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst) { uint8_t l_type = 0; uint8_t l_gen = 0; @@ -162,7 +162,7 @@ fapi2::ReturnCode perform_mrs_load<FORCE_DISPATCH>( const fapi2::Target<TARGET_T FAPI_TRY( mss::eff_dimm_type(i_target, l_type) ); FAPI_TRY( mss::eff_dram_gen(i_target, l_gen) ); - return perform_mrs_load_dispatch<FORCE_DISPATCH>(dimm_kind( l_type, l_gen ), i_target, i_inst); + return perform_mrs_load_dispatch<FORCE_DISPATCH>(dimm_kind( l_type, l_gen ), i_target, io_inst); fapi_try_exit: FAPI_ERR("couldn't get dimm type, dram gen: %s", mss::c_str(i_target)); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H index 076b57c86..d7108dad3 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H @@ -46,6 +46,25 @@ namespace mss { /// +/// @brief MR Parameter Error Values +/// A set of enumerations allowing one error xml/code to represent all bad parameters +/// for MR encoding. The error info will take which MR has bad encoding, one of these +/// enumerations to indicate which field was incorrect, and then the incorrect value. +/// +enum mrs_bad_field +{ + WRITE_CMD_LATENCY = 0, + WRITE_RECOVERY = 1, + CAS_LATENCY = 2, + OUTPUT_IMPEDANCE = 3, + CAS_WRITE_LATENCY = 4, + CS_CMD_LATENCY = 5, + CA_PARITY_LATENCY = 6, + RTT_PARK = 7, + TCCD = 8, +}; + +/// /// @brief A structure to represent an MRS operation /// @tparam T, the target type of the CCS engine chiplet /// @@ -64,10 +83,10 @@ struct mrs_data // The delay needed after this MRS word is written uint64_t iv_delay; - mrs_data( uint64_t i_mrs, + mrs_data( const uint64_t i_mrs, fapi2::ReturnCode (*i_func)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, ccs::instruction_t<T>&, const uint64_t), fapi2::ReturnCode (*i_dumper)(const ccs::instruction_t<T>&, const uint64_t), - uint64_t i_delay ): + const uint64_t i_delay ): iv_mrs(i_mrs), iv_func(i_func), iv_dumper(i_dumper), @@ -142,7 +161,7 @@ struct perform_mrs_load_overload< KIND_LRDIMM_DDR4 > template< mss::kind_t K = FORCE_DISPATCH > typename std::enable_if< perform_mrs_load_overload<DEFAULT_KIND>::available, fapi2::ReturnCode>::type perform_mrs_load( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& i_inst); + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst); // // We know we registered overloads for perform_mrs_load, so we need the entry point to @@ -151,11 +170,11 @@ perform_mrs_load( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, // template<> fapi2::ReturnCode perform_mrs_load<FORCE_DISPATCH>( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& i_inst); + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst); template<> fapi2::ReturnCode perform_mrs_load<DEFAULT_KIND>( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& i_inst); + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst); // // Boilerplate dispatcher @@ -163,27 +182,27 @@ fapi2::ReturnCode perform_mrs_load<DEFAULT_KIND>( const fapi2::Target<fapi2::TAR template< kind_t K, bool B = perform_mrs_load_overload<K>::available > inline fapi2::ReturnCode perform_mrs_load_dispatch( const kind_t& i_kind, const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& i_inst) + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst) { // We dispatch to another kind if: // We don't have an overload defined (B == false) // Or, if we do have an overload (B == true) and this is not out kind. if ((B == false) || ((B == true) && (K != i_kind))) { - return perform_mrs_load_dispatch < (kind_t)(K - 1) > (i_kind, i_target, i_inst); + return perform_mrs_load_dispatch < (kind_t)(K - 1) > (i_kind, i_target, io_inst); } // Otherwise, we call the overload. - return perform_mrs_load<K>(i_target, i_inst); + return perform_mrs_load<K>(i_target, io_inst); } // DEFAULT_KIND is 0 so this is the end of the recursion template<> inline fapi2::ReturnCode perform_mrs_load_dispatch<DEFAULT_KIND>(const kind_t&, const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& i_inst) + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst) { - return perform_mrs_load<DEFAULT_KIND>(i_target, i_inst); + return perform_mrs_load<DEFAULT_KIND>(i_target, io_inst); } } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.C deleted file mode 100644 index 5632c05dd..000000000 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.C +++ /dev/null @@ -1,850 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -/// -/// @file mrs_load_ddr4.C -/// @brief Run and manage the DDR4 mrs loading -/// -// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> -// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> -// *HWP FW Owner: Bill Hoffa <wghoffa@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 1 -// *HWP Consumed by: FSP:HB - -#include <fapi2.H> - -#include <mss.H> -#include <lib/dimm/mrs_load_ddr4.H> - -using fapi2::TARGET_TYPE_MCBIST; -using fapi2::TARGET_TYPE_DIMM; - -using fapi2::FAPI2_RC_SUCCESS; - -namespace mss -{ - -// -// Each MRS has it's attributes encapsulated in it's little setter function. -// - -/// -/// @brief Configure the ARR0 of the CCS isntruction for mrs00 -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in,out] io_inst the instruction to fixup -/// @param[in] i_rank ths rank in question -/// @return FAPI2_RC_SUCCESS iff OK -/// -static fapi2::ReturnCode ddr4_mrs00(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, - const uint64_t i_rank) -{ - // Map from Write Recovery attribute value to bits in the MRS. - // Bit 4 is A13, bits 5:7 are A11:A9 - static const uint8_t wr_map[27] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0b0000, 0, 0b0001, 0, 0b0001, 0, 0b0011, - 0, 0b0100, 0, 0b0101, 0, 0b0111, 0, 0b0110, 0, 0b1000 - }; - - // Map from the CAS Latency attribute to the bits in the MRS - static const uint8_t cl_map[34] = - { - // 0 1 2 3 4 5 6 7 8 - 0, 0, 0, 0, 0, 0, 0, 0, 0, - // 9 10 11 12 13 14 15 16 - 0b00000, 0b00001, 0b00010, 0b00011, 0b00100, 0b00101, 0b00110, 0b00111, - // 17, 18 19 20 21 22 23 24 - 0b01101, 0b01000, 0b01110, 0b01001, 0b01111, 0b01010, 0b01100, 0b01011, - // 25 26 27 28 29 30 31 32 33 - 0b10000, 0b10001, 0b10010, 0b10011, 0b10100, 0b10101, 0b10110, 0b10111, 0b11000 - }; - - uint8_t l_burst_length = 0; - uint8_t l_read_burst_type = 0; - uint8_t l_dll_reset = 0; - uint8_t l_test_mode = 0; - uint8_t l_write_recovery = 0; - uint8_t l_cas_latency = 0; - - fapi2::buffer<uint8_t> l_cl; - fapi2::buffer<uint8_t> l_wr; - - FAPI_TRY( mss::eff_dram_bl(i_target, l_burst_length) ); - FAPI_TRY( mss::eff_dram_rbt(i_target, l_read_burst_type) ); - FAPI_TRY( mss::eff_dram_cl(i_target, l_cas_latency) ); - FAPI_TRY( mss::eff_dram_dll_reset(i_target, l_dll_reset) ); - FAPI_TRY( mss::eff_dram_tm(i_target, l_test_mode) ); - FAPI_TRY( mss::eff_dram_twr(i_target, l_write_recovery) ); - - FAPI_DBG("MR0 Attributes: BL: 0x%x, RBT: 0x%x, CL: 0x%x(0x%x), TM: 0x%x, DLL_RESET: 0x%x, WR: 0x%x(0x%x)", - l_burst_length, l_read_burst_type, l_cas_latency, cl_map[l_cas_latency], - l_test_mode, l_dll_reset, l_write_recovery, wr_map[l_write_recovery]); - - io_inst.arr0.insertFromRight<A0, 2>(l_burst_length); - io_inst.arr0.writeBit<A3>(l_read_burst_type); - io_inst.arr0.writeBit<A7>(l_test_mode); - io_inst.arr0.writeBit<A8>(l_dll_reset); - - // CAS Latency takes a little effort - the bits aren't contiguous - l_cl = cl_map[l_cas_latency]; - io_inst.arr0.writeBit<A12>(l_cl.getBit<3>()); - io_inst.arr0.writeBit<A6>(l_cl.getBit<4>()); - io_inst.arr0.writeBit<A5>(l_cl.getBit<5>()); - io_inst.arr0.writeBit<A4>(l_cl.getBit<6>()); - io_inst.arr0.writeBit<A2>(l_cl.getBit<7>()); - - // Write Recovery/Read to Precharge is not contiguous either. - l_wr = wr_map[l_write_recovery]; - io_inst.arr0.writeBit<A13>(l_wr.getBit<4>()); - io_inst.arr0.writeBit<A11>(l_wr.getBit<5>()); - io_inst.arr0.writeBit<A10>(l_wr.getBit<6>()); - io_inst.arr0.writeBit<A9>(l_wr.getBit<7>()); - - FAPI_DBG("MR0: 0x%016llx", uint64_t(io_inst.arr0)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Given a CCS instruction which contains address bits with an encoded MRS0, -/// decode and trace the contents -/// @param[in] i_inst the CCS instruction -/// @param[in] i_rank ths rank in question -/// @return void -/// -static fapi2::ReturnCode ddr4_mrs00_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, - const uint64_t i_rank) -{ - static const uint8_t wr_map[9] = { 10, 12, 14, 16, 18, 20, 24, 22, 26 }; - - uint8_t l_burst_length = 0; - uint8_t l_read_burst_type = 0; - uint8_t l_dll_reset = 0; - uint8_t l_test_mode = 0; - - fapi2::buffer<uint8_t> l_wr_index; - fapi2::buffer<uint8_t> l_cas_latency; - - i_inst.arr0.extractToRight<A0, 2>(l_burst_length); - l_read_burst_type = i_inst.arr0.getBit<A3>(); - l_test_mode = i_inst.arr0.getBit<A7>(); - l_dll_reset = i_inst.arr0.getBit<A8>(); - - // CAS Latency takes a little effort - the bits aren't contiguous - l_cas_latency.writeBit<3>(i_inst.arr0.getBit<A12>()); - l_cas_latency.writeBit<4>(i_inst.arr0.getBit<A6>()); - l_cas_latency.writeBit<5>(i_inst.arr0.getBit<A5>()); - l_cas_latency.writeBit<6>(i_inst.arr0.getBit<A4>()); - l_cas_latency.writeBit<7>(i_inst.arr0.getBit<A2>()); - - // Write Recovery/Read to Precharge is not contiguous either. - l_wr_index.writeBit<4>(i_inst.arr0.getBit<A13>()); - l_wr_index.writeBit<5>(i_inst.arr0.getBit<A11>()); - l_wr_index.writeBit<6>(i_inst.arr0.getBit<A10>()); - l_wr_index.writeBit<7>(i_inst.arr0.getBit<A9>()); - - FAPI_DBG("MR0 Decode BL: 0x%x, RBT: 0x%x, CL: 0x%x, TM: 0x%x, DLL_RESET: 0x%x, WR: (0x%x)0x%x", - l_burst_length, l_read_burst_type, uint8_t(l_cas_latency), l_test_mode, l_dll_reset, - wr_map[uint8_t(l_wr_index)], uint8_t(l_wr_index)); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Configure the ARR0 of the CCS isntruction for mrs01 -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in,out] io_inst the instruction to fixup -/// @param[in] i_rank ths rank in question -/// @return FAPI2_RC_SUCCESS iff OK -/// -static fapi2::ReturnCode ddr4_mrs01(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, - const uint64_t i_rank) -{ - // Little table to map Output Driver Imepdance Control. 34Ohm is index 0, - // 48Ohm is index 1 and we expect eff_config to make sure there's nothing - // else used here. - // Left bit is A2, right bit is A1 - static const uint8_t odic_map[2] = { 0b00, 0b01 }; - - // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking - // for index 1. So this doesn't correspond directly with the table in the JEDEC spec, - // as that's not in "denominator order." - // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 - static const uint8_t rtt_nom_map[8] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; - - uint8_t l_dll_enable = 0; - uint8_t l_odic = 0; - uint8_t l_wl_enable = 0; - uint8_t l_tdqs = 0; - uint8_t l_qoff = 0; - uint8_t l_rtt_nom[MAX_RANK_PER_DIMM] = {0}; - - size_t l_rtt_nom_index = 0; - - fapi2::buffer<uint8_t> l_additive_latency; - fapi2::buffer<uint8_t> l_odic_buffer; - fapi2::buffer<uint8_t> l_rtt_nom_buffer; - - FAPI_TRY( mss::eff_dram_dll_enable(i_target, l_dll_enable) ); - FAPI_TRY( mss::eff_dram_ron(i_target, l_odic) ); - FAPI_TRY( mss::eff_dram_al(i_target, l_additive_latency) ); - FAPI_TRY( mss::eff_dram_wr_lvl_enable(i_target, l_wl_enable) ); - FAPI_TRY( mss::eff_dram_rtt_nom(i_target, &(l_rtt_nom[0])) ); - FAPI_TRY( mss::eff_dram_tdqs(i_target, l_tdqs) ); - FAPI_TRY( mss::eff_dram_output_buffer(i_target, l_qoff) ); - - // Map from impedance to bits in MRS1 - l_odic_buffer = (l_odic == fapi2::ENUM_ATTR_EFF_DRAM_RON_OHM34) ? odic_map[0] : odic_map[1]; - - // We have to be careful about 0 - l_rtt_nom_index = (l_rtt_nom[mss::index(i_rank)] == 0) ? - 0 : fapi2::ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM240 / l_rtt_nom[mss::index(i_rank)]; - - // Map from RTT_NOM array to the value in the map - l_rtt_nom_buffer = rtt_nom_map[l_rtt_nom_index]; - - FAPI_INF("MR1 rank %d attributes: DLL_ENABLE: 0x%x, ODIC: 0x%x(0x%x), AL: 0x%x, WLE: 0x%x, " - "RTT_NOM: 0x%x(0x%x), TDQS: 0x%x, QOFF: 0x%x", i_rank, - l_dll_enable, l_odic, uint8_t(l_odic_buffer), uint8_t(l_additive_latency), l_wl_enable, - l_rtt_nom[mss::index(i_rank)], uint8_t(l_rtt_nom_buffer), l_tdqs, l_qoff); - - io_inst.arr0.writeBit<A0>(l_dll_enable); - mss::swizzle<A1, 2, 7>(l_odic_buffer, io_inst.arr0); - mss::swizzle<A3, 2, 7>(l_additive_latency, io_inst.arr0); - io_inst.arr0.writeBit<A7>(l_wl_enable); - mss::swizzle<A8, 3, 7>(l_rtt_nom_buffer, io_inst.arr0); - io_inst.arr0.writeBit<A11>(l_tdqs); - io_inst.arr0.writeBit<A12>(l_qoff); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Given a CCS instruction which contains address bits with an encoded MRS1, -/// decode and trace the contents -/// @param[in] i_inst the CCS instruction -/// @param[in] i_rank ths rank in question -/// @return void -/// -static fapi2::ReturnCode ddr4_mrs01_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, - const uint64_t i_rank) -{ - fapi2::buffer<uint8_t> l_odic; - fapi2::buffer<uint8_t> l_additive_latency; - fapi2::buffer<uint8_t> l_rtt_nom; - - uint8_t l_dll_enable = i_inst.arr0.getBit<A0>(); - uint8_t l_wrl_enable = i_inst.arr0.getBit<A7>(); - uint8_t l_tdqs = i_inst.arr0.getBit<A11>(); - uint8_t l_qoff = i_inst.arr0.getBit<A12>(); - - mss::swizzle<6, 2, A2>(i_inst.arr0, l_odic); - mss::swizzle<6, 2, A4>(i_inst.arr0, l_additive_latency); - mss::swizzle<5, 3, A10>(i_inst.arr0, l_rtt_nom); - - FAPI_INF("MR1 rank %d decode: DLL_ENABLE: 0x%x, ODIC: 0x%x, AL: 0x%x, WLE: 0x%x, " - "RTT_NOM: 0x%x, TDQS: 0x%x, QOFF: 0x%x", i_rank, - l_dll_enable, uint8_t(l_odic), uint8_t(l_additive_latency), l_wrl_enable, uint8_t(l_rtt_nom), - l_tdqs, l_qoff); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Given a uint32_t, which contains address bits with an encoded MRS1, -/// decode and trace the contents -/// @param[in] i_value ADR 17:0 -/// @return void -/// -fapi2::ReturnCode ddr4_mrs01_decode(const uint32_t i_value) -{ - fapi2::buffer<uint32_t> l_data(i_value); - // Flip l_data so bit 0 is bit 0, bit 17 is bit 17 ... - reverse(l_data); - - fapi2::buffer<uint8_t> l_odic; - fapi2::buffer<uint8_t> l_additive_latency; - fapi2::buffer<uint8_t> l_rtt_nom; - - uint8_t l_dll_enable = l_data.getBit<A0>(); - uint8_t l_wrl_enable = l_data.getBit<A7>(); - uint8_t l_tdqs = l_data.getBit<A11>(); - uint8_t l_qoff = l_data.getBit<A12>(); - - mss::swizzle<6, 2, A2>(l_data, l_odic); - mss::swizzle<6, 2, A4>(l_data, l_additive_latency); - mss::swizzle<5, 3, A10>(l_data, l_rtt_nom); - - FAPI_INF("MR1 buffer decode: DLL_ENABLE: 0x%x, ODIC: 0x%x, AL: 0x%x, WLE: 0x%x, " - "RTT_NOM: 0x%x, TDQS: 0x%x, QOFF: 0x%x", - l_dll_enable, uint8_t(l_odic), uint8_t(l_additive_latency), l_wrl_enable, uint8_t(l_rtt_nom), - l_tdqs, l_qoff); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Configure the ARR0 of the CCS isntruction for mrs02 -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in,out] io_inst the instruction to fixup -/// @param[in] i_rank ths rank in question -/// @return FAPI2_RC_SUCCESS iff OK -/// -static fapi2::ReturnCode ddr4_mrs02(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, - const uint64_t i_rank) -{ - // Index this by subtracting 9 from the CWL attribute value. - static const uint64_t LOWEST_CWL = 9; - // 9 10 11 12 14 16 18 20 - static const uint8_t cwl_map[12] = { 0b000, 0b001, 0b010, 0b011, 0, 0b100, 0, 0b101, 0, 0b110, 0, 0b111 }; - - fapi2::buffer<uint8_t> l_lpasr; - uint8_t l_cwl = 0; - uint8_t l_dram_rtt_wr[MAX_RANK_PER_DIMM] = {0}; - uint8_t l_write_crc = 0; - - fapi2::buffer<uint8_t> l_cwl_buffer; - fapi2::buffer<uint8_t> l_rtt_wr_buffer; - - FAPI_TRY( mss::eff_dram_lpasr(i_target, l_lpasr) ); - FAPI_TRY( mss::eff_dram_cwl(i_target, l_cwl) ); - FAPI_TRY( mss::eff_dram_rtt_wr(i_target, &(l_dram_rtt_wr[0])) ); - FAPI_TRY( mss::eff_write_crc(i_target, l_write_crc) ); - - l_cwl_buffer = cwl_map[l_cwl - LOWEST_CWL]; - - // Arg. Change this. BRS - switch (l_dram_rtt_wr[i_rank]) - { - case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_DISABLE: - l_rtt_wr_buffer = 0b000; - break; - - case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_HIGHZ: - l_rtt_wr_buffer = 0b011; - break; - - case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM240: - l_rtt_wr_buffer = 0b010; - break; - - case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM120: - l_rtt_wr_buffer = 0b001; - break; - - case fapi2::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM60: - l_rtt_wr_buffer = 0b100; - break; - - default: - FAPI_ERR("unknown RTT_WR 0x%x (%s rank %d), dynamic odt off", - l_dram_rtt_wr[i_rank], mss::c_str(i_target), i_rank); - l_rtt_wr_buffer = 0b000; - break; - }; - - FAPI_INF("MR2 rank %d attributes: LPASR: 0x%x, CWL: 0x%x(0x%x), RTT_WR: 0x%x(0x%x), WRITE_CRC: 0x%x", i_rank, - uint8_t(l_lpasr), l_cwl, uint8_t(l_cwl_buffer), - l_dram_rtt_wr[i_rank], uint8_t(l_rtt_wr_buffer), l_write_crc); - - mss::swizzle<A3, 3, 7>(l_cwl_buffer, io_inst.arr0); - - mss::swizzle<A6, 2, 7>(l_lpasr, io_inst.arr0); - - mss::swizzle<A9, 3, 7>(l_rtt_wr_buffer, io_inst.arr0); - - io_inst.arr0.writeBit<A12>(l_write_crc); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Given a CCS instruction which contains address bits with an encoded MRS2, -/// decode and trace the contents -/// @param[in] i_inst the CCS instruction -/// @param[in] i_rank ths rank in question -/// @return void -/// -static fapi2::ReturnCode ddr4_mrs02_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, - const uint64_t i_rank) -{ - fapi2::buffer<uint8_t> l_lpasr; - fapi2::buffer<uint8_t> l_cwl; - fapi2::buffer<uint8_t> l_rtt_wr; - - uint8_t l_write_crc = i_inst.arr0.getBit<A12>(); - mss::swizzle<5, 3, A5>(i_inst.arr0, l_cwl); - mss::swizzle<6, 2, A7>(i_inst.arr0, l_lpasr); - mss::swizzle<5, 3, A11>(i_inst.arr0, l_rtt_wr); - - FAPI_INF("MR2 rank %d deocode: LPASR: 0x%x, CWL: 0x%x, RTT_WR: 0x%x, WRITE_CRC: 0x%x", i_rank, - uint8_t(l_lpasr), uint8_t(l_cwl), uint8_t(l_rtt_wr), l_write_crc); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Configure the ARR0 of the CCS isntruction for mrs03 -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in,out] io_inst the instruction to fixup -/// @param[in] i_rank ths rank in question -/// @return FAPI2_RC_SUCCESS iff OK -/// -static fapi2::ReturnCode ddr4_mrs03(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, - const uint64_t i_rank) -{ - // 4 5 6 R - static const uint8_t crc_wr_latency_map[8] = { 0, 0, 0, 0, 0, 1, 2, 3 }; - - uint8_t l_mpr_page = 0; - uint8_t l_geardown = 0; - uint8_t l_pda = 0; - uint8_t l_crc_wr_latency = 0; - uint8_t l_temp_readout = 0; - uint8_t l_fine_refresh; - - fapi2::buffer<uint8_t> l_mpr_mode; - fapi2::buffer<uint8_t> l_crc_wr_latency_buffer; - fapi2::buffer<uint8_t> l_read_format; - - FAPI_TRY( mss::eff_mpr_mode(i_target, l_mpr_mode) ); - FAPI_TRY( mss::eff_mpr_page(i_target, l_mpr_page) ); - FAPI_TRY( mss::eff_geardown_mode(i_target, l_geardown) ); - FAPI_TRY( mss::eff_per_dram_access(i_target, l_pda) ); - FAPI_TRY( mss::eff_temp_readout(i_target, l_temp_readout) ); - FAPI_TRY( mss::mrw_fine_refresh_mode(l_fine_refresh) ); - FAPI_TRY( mss::eff_crc_wr_latency(i_target, l_crc_wr_latency) ); - FAPI_TRY( mss::eff_mpr_rd_format(i_target, l_read_format) ); - - l_crc_wr_latency_buffer = crc_wr_latency_map[l_crc_wr_latency]; - - FAPI_INF("MR3 rank %d attributes: MPR_MODE: 0x%x, MPR_PAGE: 0x%x, GD: 0x%x, PDA: 0x%x, " - "TEMP: 0x%x FR: 0x%x, CRC_WL: 0x%x(0x%x), RF: 0x%x", i_rank, - uint8_t(l_mpr_mode), l_mpr_page, l_geardown, l_pda, l_temp_readout, - uint8_t(l_fine_refresh), l_crc_wr_latency, uint8_t(l_crc_wr_latency_buffer), - uint8_t(l_read_format)); - - mss::swizzle<A0, 2, 7>(l_mpr_mode, io_inst.arr0); - io_inst.arr0.writeBit<A2>(l_mpr_page); - io_inst.arr0.writeBit<A3>(l_geardown); - io_inst.arr0.writeBit<A4>(l_pda); - io_inst.arr0.writeBit<A5>(l_temp_readout); - - mss::swizzle<A6 , 3, 7>(fapi2::buffer<uint8_t>(l_fine_refresh), io_inst.arr0); - mss::swizzle<A9 , 2, 7>(l_crc_wr_latency_buffer, io_inst.arr0); - mss::swizzle<A11, 2, 7>(l_read_format, io_inst.arr0); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Given a CCS instruction which contains address bits with an encoded MRS3, -/// decode and trace the contents -/// @param[in] i_inst the CCS instruction -/// @param[in] i_rank ths rank in question -/// @return void -/// -static fapi2::ReturnCode ddr4_mrs03_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, - const uint64_t i_rank) -{ - fapi2::buffer<uint8_t> l_mpr_mode; - - fapi2::buffer<uint8_t> l_fine_refresh; - fapi2::buffer<uint8_t> l_crc_wr_latency_buffer; - fapi2::buffer<uint8_t> l_read_format; - - uint8_t l_mpr_page = i_inst.arr0.getBit<A2>(); - uint8_t l_geardown = i_inst.arr0.getBit<A3>(); - uint8_t l_pda = i_inst.arr0.getBit<A4>(); - uint8_t l_temp_readout = i_inst.arr0.getBit<A5>(); - - mss::swizzle<6, 2, A1>(i_inst.arr0, l_mpr_mode); - mss::swizzle<5, 3, A7>(i_inst.arr0, l_fine_refresh); - mss::swizzle<6, 2, A10>(i_inst.arr0, l_crc_wr_latency_buffer); - mss::swizzle<6, 2, A12>(i_inst.arr0, l_read_format); - - FAPI_INF("MR3 rank %d decode: MPR_MODE: 0x%x, MPR_PAGE: 0x%x, GD: 0x%x, PDA: 0x%x, " - "TEMP: 0x%x FR: 0x%x, CRC_WL: 0x%x, RF: 0x%x", i_rank, - uint8_t(l_mpr_mode), l_mpr_page, l_geardown, l_pda, uint8_t(l_temp_readout), - uint8_t(l_fine_refresh), uint8_t(l_crc_wr_latency_buffer), uint8_t(l_read_format)); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Configure the ARR0 of the CCS isntruction for mrs04 -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in,out] io_inst the instruction to fixup -/// @param[in] i_rank ths rank in question -/// @return FAPI2_RC_SUCCESS iff OK -/// -static fapi2::ReturnCode ddr4_mrs04(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, - const uint64_t i_rank) -{ - // 0 3 4 5 6 8 - static const uint8_t cs_cmd_latency_map[9] = { 0b000, 0, 0, 0b001, 0b010, 0b011, 0b100, 0, 0b101 }; - - uint8_t l_max_pd_mode = 0; - uint8_t l_temp_refresh_range = 0; - uint8_t l_temp_ref_mode = 0; - uint8_t l_vref_mon = 0; - uint8_t l_cs_cmd_latency = 0; - uint8_t l_ref_abort = 0; - uint8_t l_rd_pre_train_mode = 0; - uint8_t l_rd_preamble = 0; - uint8_t l_wr_preamble = 0; - uint8_t l_ppr = 0; - - fapi2::buffer<uint8_t> l_cs_cmd_latency_buffer; - - FAPI_TRY( mss::eff_max_powerdown_mode(i_target, l_max_pd_mode) ); - FAPI_TRY( mss::mrw_temp_refresh_range(l_temp_refresh_range) ); - FAPI_TRY( mss::eff_temp_refresh_mode(i_target, l_temp_ref_mode) ); - FAPI_TRY( mss::eff_internal_vref_monitor(i_target, l_vref_mon) ); - FAPI_TRY( mss::eff_cs_cmd_latency(i_target, l_cs_cmd_latency) ); - FAPI_TRY( mss::eff_self_ref_abort(i_target, l_ref_abort) ); - FAPI_TRY( mss::eff_rd_preamble_train(i_target, l_rd_pre_train_mode) ); - FAPI_TRY( mss::eff_rd_preamble(i_target, l_rd_preamble) ); - FAPI_TRY( mss::eff_wr_preamble(i_target, l_wr_preamble) ); - FAPI_TRY( mss::eff_dram_ppr(i_target, l_ppr) ); - - l_cs_cmd_latency_buffer = cs_cmd_latency_map[l_cs_cmd_latency]; - - FAPI_INF("MR4 rank %d attributes: MAX_PD: 0x%x, TEMP_REFRESH_RANGE: 0x%x, TEMP_REF_MODE: 0x%x " - "VREF_MON: 0x%x, CSL: 0x%x(0x%x), REF_ABORT: 0x%x, RD_PTM: 0x%x, RD_PRE: 0x%x, " - "WR_PRE: 0x%x, PPR: 0x%x", i_rank, - l_max_pd_mode, l_temp_refresh_range, l_temp_ref_mode, l_vref_mon, - l_cs_cmd_latency, uint8_t(l_cs_cmd_latency_buffer), l_ref_abort, - l_rd_pre_train_mode, l_rd_preamble, l_wr_preamble, l_ppr); - - io_inst.arr0.writeBit<A1>(l_max_pd_mode); - io_inst.arr0.writeBit<A2>(l_temp_refresh_range); - io_inst.arr0.writeBit<A3>(l_temp_ref_mode); - io_inst.arr0.writeBit<A4>(l_vref_mon); - - mss::swizzle<A6, 3, 7>(l_cs_cmd_latency_buffer, io_inst.arr0); - io_inst.arr0.writeBit<A9>(l_ref_abort); - io_inst.arr0.writeBit<A10>(l_rd_pre_train_mode); - io_inst.arr0.writeBit<A11>(l_rd_preamble); - io_inst.arr0.writeBit<A12>(l_wr_preamble); - io_inst.arr0.writeBit<A13>(l_ppr); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Given a CCS instruction which contains address bits with an encoded MRS4, -/// decode and trace the contents -/// @param[in] i_inst the CCS instruction -/// @param[in] i_rank ths rank in question -/// @return void -/// -static fapi2::ReturnCode ddr4_mrs04_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, - const uint64_t i_rank) -{ - uint8_t l_max_pd_mode = i_inst.arr0.getBit<A1>(); - uint8_t l_temp_refresh_range = i_inst.arr0.getBit<A2>(); - uint8_t l_temp_ref_mode = i_inst.arr0.getBit<A3>(); - uint8_t l_vref_mon = i_inst.arr0.getBit<A4>(); - - fapi2::buffer<uint8_t> l_cs_cmd_latency_buffer; - mss::swizzle<5, 3, A8>(i_inst.arr0, l_cs_cmd_latency_buffer); - - uint8_t l_ref_abort = i_inst.arr0.getBit<A9>(); - uint8_t l_rd_pre_train_mode = i_inst.arr0.getBit<A10>(); - uint8_t l_rd_preamble = i_inst.arr0.getBit<A11>(); - uint8_t l_wr_preamble = i_inst.arr0.getBit<A12>(); - uint8_t l_ppr = i_inst.arr0.getBit<A13>(); - - FAPI_INF("MR4 rank %d decode: MAX_PD: 0x%x, TEMP_REFRESH_RANGE: 0x%x, TEMP_REF_MODE: 0x%x " - "VREF_MON: 0x%x, CSL: 0x%x, REF_ABORT: 0x%x, RD_PTM: 0x%x, RD_PRE: 0x%x, " - "WR_PRE: 0x%x, PPR: 0x%x", i_rank, - l_max_pd_mode, l_temp_refresh_range, l_temp_ref_mode, l_vref_mon, - uint8_t(l_cs_cmd_latency_buffer), l_ref_abort, - l_rd_pre_train_mode, l_rd_preamble, l_wr_preamble, l_ppr); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Configure the ARR0 of the CCS isntruction for mrs05 -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in,out] io_inst the instruction to fixup -/// @param[in] i_rank ths rank in question -/// @return FAPI2_RC_SUCCESS iff OK -/// -static fapi2::ReturnCode ddr4_mrs05(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, - const uint64_t i_rank) -{ - // 0 4 5 6 8 - static const uint8_t ca_parity_latency_map[9] = { 0b000, 0, 0, 0, 0b001, 0b010, 0b011, 0, 0b100 }; - - // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking - // for index 1. So this doesn't correspond directly with the table in the JEDEC spec, - // as that's not in "denominator order." - // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 - static const uint8_t rtt_park_map[8] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; - - uint8_t l_ca_parity_latency = 0; - uint8_t l_crc_error_clear = 0; - uint8_t l_ca_parity_error_status = 0; - uint8_t l_odt_input_buffer = 0; - uint8_t l_rtt_park[MAX_RANK_PER_DIMM] = {0}; - uint8_t l_ca_parity = 0; - uint8_t l_data_mask = 0; - uint8_t l_write_dbi = 0; - uint8_t l_read_dbi = 0; - - uint8_t l_rtt_park_index = 0; - - fapi2::buffer<uint8_t> l_ca_parity_latency_buffer; - fapi2::buffer<uint8_t> l_rtt_park_buffer; - - FAPI_TRY( mss::eff_ca_parity_latency(i_target, l_ca_parity_latency) ); - FAPI_TRY( mss::eff_crc_error_clear(i_target, l_crc_error_clear) ); - FAPI_TRY( mss::eff_ca_parity_error_status(i_target, l_ca_parity_error_status) ); - FAPI_TRY( mss::eff_odt_input_buff(i_target, l_odt_input_buffer) ); - - FAPI_TRY( mss::eff_rtt_park(i_target, &(l_rtt_park[0])) ); - - FAPI_TRY( mss::eff_ca_parity(i_target, l_ca_parity) ); - FAPI_TRY( mss::eff_data_mask(i_target, l_data_mask) ); - FAPI_TRY( mss::eff_write_dbi(i_target, l_write_dbi) ); - FAPI_TRY( mss::eff_read_dbi(i_target, l_read_dbi) ); - - l_ca_parity_latency_buffer = ca_parity_latency_map[l_ca_parity_latency]; - - // We have to be careful about 0 - l_rtt_park_index = (l_rtt_park[mss::index(i_rank)] == 0) ? - 0 : fapi2::ENUM_ATTR_EFF_RTT_PARK_240OHM / l_rtt_park[mss::index(i_rank)]; - - // Map from RTT_NOM array to the value in the map - l_rtt_park_buffer = rtt_park_map[l_rtt_park_index]; - - FAPI_INF("MR5 rank %d attributes: CAPL: 0x%x(0x%x), CRC_EC: 0x%x, CA_PES: 0x%x, ODT_IB: 0x%x " - "RTT_PARK: 0x%x(0x%x), CAP: 0x%x, DM: 0x%x, WDBI: 0x%x, RDBI: 0x%x", i_rank, - l_ca_parity_latency, uint8_t(l_ca_parity_latency_buffer), l_crc_error_clear, - l_ca_parity_error_status, l_odt_input_buffer, - l_rtt_park[mss::index(i_rank)], uint8_t(l_rtt_park_buffer), l_ca_parity, - l_data_mask, l_write_dbi, l_read_dbi); - - mss::swizzle<A0, 3, 7>(l_ca_parity_latency_buffer, io_inst.arr0); - io_inst.arr0.writeBit<A3>(l_crc_error_clear); - io_inst.arr0.writeBit<A4>(l_ca_parity_error_status); - io_inst.arr0.writeBit<A5>(l_odt_input_buffer); - mss::swizzle<A6, 3, 7>(l_rtt_park_buffer, io_inst.arr0); - io_inst.arr0.writeBit<A9>(l_ca_parity); - io_inst.arr0.writeBit<A10>(l_data_mask); - io_inst.arr0.writeBit<A11>(l_write_dbi); - io_inst.arr0.writeBit<A12>(l_read_dbi); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Given a CCS instruction which contains address bits with an encoded MRS5, -/// decode and trace the contents -/// @param[in] i_inst the CCS instruction -/// @param[in] i_rank ths rank in question -/// @return void -/// -static fapi2::ReturnCode ddr4_mrs05_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, - const uint64_t i_rank) -{ - fapi2::buffer<uint8_t> l_ca_parity_latency_buffer; - fapi2::buffer<uint8_t> l_rtt_park_buffer; - - mss::swizzle<5, 3, A2>(i_inst.arr0, l_ca_parity_latency_buffer); - mss::swizzle<5, 3, A8>(i_inst.arr0, l_rtt_park_buffer); - - uint8_t l_crc_error_clear = i_inst.arr0.getBit<A3>(); - uint8_t l_ca_parity_error_status = i_inst.arr0.getBit<A4>(); - uint8_t l_odt_input_buffer = i_inst.arr0.getBit<A5>(); - - uint8_t l_ca_parity = i_inst.arr0.getBit<A9>(); - uint8_t l_data_mask = i_inst.arr0.getBit<A10>(); - uint8_t l_write_dbi = i_inst.arr0.getBit<A11>(); - uint8_t l_read_dbi = i_inst.arr0.getBit<A12>(); - - FAPI_INF("MR5 rank %d decode: CAPL: 0x%x, CRC_EC: 0x%x, CA_PES: 0x%x, ODT_IB: 0x%x " - "RTT_PARK: 0x%x, CAP: 0x%x, DM: 0x%x, WDBI: 0x%x, RDBI: 0x%x", i_rank, - uint8_t(l_ca_parity_latency_buffer), l_crc_error_clear, l_ca_parity_error_status, - l_odt_input_buffer, uint8_t(l_rtt_park_buffer), l_ca_parity, l_data_mask, - l_write_dbi, l_read_dbi); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Configure the ARR0 of the CCS isntruction for mrs06 -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in,out] io_inst the instruction to fixup -/// @param[in] i_rank ths rank in question -/// @return FAPI2_RC_SUCCESS iff OK -/// -static fapi2::ReturnCode ddr4_mrs06(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst, - const uint64_t i_rank) -{ - // 4 5 6 7 8 - static const uint8_t tccd_l_map[9] = { 0, 0, 0, 0, 0b000, 0b001, 0b010, 0b011, 0b100 }; - - uint8_t l_vrefdq_train_value[MAX_RANK_PER_DIMM] = {0}; - uint8_t l_vrefdq_train_range[MAX_RANK_PER_DIMM] = {0}; - uint8_t l_vrefdq_train_enable[MAX_RANK_PER_DIMM] = {0}; - uint8_t l_tccd_l = 0; - - fapi2::buffer<uint8_t> l_tccd_l_buffer; - fapi2::buffer<uint8_t> l_vrefdq_train_value_buffer; - - FAPI_TRY( mss::eff_vref_dq_train_value(i_target, l_vrefdq_train_value) ); - FAPI_TRY( mss::eff_vref_dq_train_range(i_target, l_vrefdq_train_range) ); - FAPI_TRY( mss::eff_vref_dq_train_enable(i_target, l_vrefdq_train_enable) ); - FAPI_TRY( mss::eff_dram_tccd_l(i_target, l_tccd_l) ); - - l_tccd_l_buffer = tccd_l_map[l_tccd_l]; - l_vrefdq_train_value_buffer = l_vrefdq_train_value[mss::index(i_rank)]; - - FAPI_INF("MR6 rank %d attributes: TRAIN_V: 0x%x(0x%x), TRAIN_R: 0x%x, TRAIN_E: 0x%x, TCCD_L: 0x%x(0x%x)", i_rank, - l_vrefdq_train_value[mss::index(i_rank)], uint8_t(l_vrefdq_train_value_buffer), - l_vrefdq_train_range[mss::index(i_rank)], - l_vrefdq_train_enable[mss::index(i_rank)], l_tccd_l, uint8_t(l_tccd_l_buffer)); - - mss::swizzle<A0, 6, 7>(l_vrefdq_train_value_buffer, io_inst.arr0); - io_inst.arr0.writeBit<A6>(l_vrefdq_train_range[mss::index(i_rank)]); - io_inst.arr0.writeBit<A7>(l_vrefdq_train_enable[mss::index(i_rank)]); - mss::swizzle<A10, 3, 7>(l_tccd_l_buffer, io_inst.arr0); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Given a CCS instruction which contains address bits with an encoded MRS6, -/// decode and trace the contents -/// @param[in] i_inst the CCS instruction -/// @param[in] i_rank ths rank in question -/// @return void -/// -static fapi2::ReturnCode ddr4_mrs06_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst, - const uint64_t i_rank) -{ - fapi2::buffer<uint8_t> l_tccd_l_buffer; - fapi2::buffer<uint8_t> l_vrefdq_train_value_buffer; - - mss::swizzle<2, 6, A5>(i_inst.arr0, l_vrefdq_train_value_buffer); - uint8_t l_vrefdq_train_range = i_inst.arr0.getBit<A6>(); - uint8_t l_vrefdq_train_enable = i_inst.arr0.getBit<A7>(); - mss::swizzle<5, 3, A12>(i_inst.arr0, l_tccd_l_buffer); - - FAPI_INF("MR6 rank %d decode: TRAIN_V: 0x%x, TRAIN_R: 0x%x, TRAIN_E: 0x%x, TCCD_L: 0x%x", i_rank, - uint8_t(l_vrefdq_train_value_buffer), l_vrefdq_train_range, - l_vrefdq_train_enable, uint8_t(l_tccd_l_buffer)); - - return FAPI2_RC_SUCCESS; -} - -/// -/// @brief Perform the mrs_load_ddr4 operations - TARGET_TYPE_DIMM specialization -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in] i_inst a vector of CCS instructions we should add to -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -fapi2::ReturnCode mrs_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& i_inst) -{ - FAPI_INF("mrs_load_ddr4 %s", mss::c_str(i_target)); - - // Per DDR4MRS02 table 104 - timing requirements - static const uint64_t tMRD = 8; - - static std::vector< mrs_data<TARGET_TYPE_MCBIST> > l_mrs_data = - { - { 0, ddr4_mrs00, ddr4_mrs00_decode, tMRD }, { 1, ddr4_mrs01, ddr4_mrs01_decode, tMRD }, - { 2, ddr4_mrs02, ddr4_mrs02_decode, tMRD }, { 3, ddr4_mrs03, ddr4_mrs03_decode, tMRD }, - { 4, ddr4_mrs04, ddr4_mrs04_decode, tMRD }, { 5, ddr4_mrs05, ddr4_mrs05_decode, tMRD }, - { 6, ddr4_mrs06, ddr4_mrs06_decode, tMRD }, - }; - - std::vector< uint64_t > l_ranks; - FAPI_TRY( mss::ranks(i_target, l_ranks) ); - - for (auto d : l_mrs_data) - { - for (auto r : l_ranks) - { - // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS - ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_a_side = ccs::mrs_command<TARGET_TYPE_MCBIST>(i_target, r, d.iv_mrs); - ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_b_side; - - // Thou shalt send 2 MRS, one for the a-side and the other inverted for the b-side. - // If we're on an odd-rank then we need to mirror - // So configure the A-side, mirror if necessary and invert for the B-side - FAPI_TRY( d.iv_func(i_target, l_inst_a_side, r) ); - - FAPI_TRY( mss::address_mirror(i_target, r, l_inst_a_side) ); - l_inst_b_side = mss::address_invert(l_inst_a_side); - - // Not sure if we can get tricky here and only delay after the b-side MR. The question is whether the delay - // is needed/assumed by the register or is purely a DRAM mandated delay. We know we can't go wrong having - // both delays but if we can ever confirm that we only need one we can fix this. BRS - l_inst_a_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay); - l_inst_b_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(d.iv_delay); - - // Dump out the 'decoded' MRS and trace the CCS instructions. - if (d.iv_dumper != NULL) - { - FAPI_TRY( d.iv_dumper(l_inst_a_side, r) ); - } - - FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d a-side", uint8_t(d.iv_mrs), d.iv_delay, - l_inst_a_side.arr0, l_inst_a_side.arr1, mss::c_str(i_target), r); - FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d b-side", uint8_t(d.iv_mrs), d.iv_delay, - l_inst_b_side.arr0, l_inst_b_side.arr1, mss::c_str(i_target), r); - - // Add both to the CCS program - i_inst.push_back(l_inst_a_side); - i_inst.push_back(l_inst_b_side); - } - } - -fapi_try_exit: - return fapi2::current_err; -} - -} // namespace diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.H deleted file mode 100644 index 1878864c4..000000000 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.H +++ /dev/null @@ -1,163 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load_ddr4.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -/// -/// @file mrs_load_ddr4.H -/// @brief Code to support mrs_load_ddr4 -/// -// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> -// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> -// *HWP FW Owner: Bill Hoffa <wghoffa@us.ibm.com> -// *HWP Team: Memory -// *HWP Level: 1 -// *HWP Consumed by: HB:FSP - -#ifndef _MSS_MRS_LOAD_DDR4_H_ -#define _MSS_MRS_LOAD_DDR4_H_ - -#include <fapi2.H> -#include <mss.H> - -namespace mss -{ - -// Map bits in the ARR0 register(s) to MRS address bits. Should be traits related to ARR0. BRS -enum address_bits -{ - A0 = 0, - A1 = 1, - A2 = 2, - A3 = 3, - A4 = 4, - A5 = 5, - A6 = 6, - A7 = 7, - A8 = 8, - A9 = 9, - A10 = 10, - A11 = 11, - A12 = 12, - A13 = 13, - A14 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_14, - A15 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_15, - A16 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_16, - A17 = MCBIST_CCS_INST_ARR0_00_DDR_ADDRESS_17, - - // Only kind of address bits ... <shrug> - BA0 = 17, - BA1 = 18, - BG0 = 19, - BG1 = 15, -}; - -/// -/// @brief Perform the mrs_load_ddr4 operations - TARGET_TYPE_DIMM specialization -/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM> -/// @param[in] i_inst a vector of CCS instructions we should add to -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -fapi2::ReturnCode mrs_load_ddr4( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& i_inst); - -/// -/// @brief Mirror (front to back) the ADR bits of a CCS instruction - implementation -/// @tparam T typename of the ccs::instruction_t -/// @param[in, out] io_inst reference to a CCS instruction to be mirrored -/// @return FAPI2_RC_SUCESS iff ok -/// @note written this way so this is easier to test -/// -template<fapi2::TargetType T> -void address_mirror_impl(ccs::instruction_t<T>& io_inst) -{ - // Nothing fancy here, just mirror the bits we're told to mirror in Table 14 — Address Mirroring and Inversion - mss::template swap<A3, A4>(io_inst.arr0); - mss::template swap<A5, A6>(io_inst.arr0); - mss::template swap<A7, A8>(io_inst.arr0); - mss::template swap<A11, A13>(io_inst.arr0); - mss::template swap<BA0, BA1>(io_inst.arr0); - mss::template swap<BG0, BG1>(io_inst.arr0); -} - -/// -/// @brief Mirror (front to back) the ADR bits of a CCS instruction -/// @tparam T typename of the ccs::instruction_t -/// @param[in] i_target target to use to get mirroring attribute -/// @param[in] i_rank the rank in question -/// @param[in, out] io_inst reference to a CCS instruction to be mirrored -/// @return FAPI2_RC_SUCESS iff ok -/// @note assumes the input is from an even number rank -/// -template<fapi2::TargetType T> -fapi2::ReturnCode address_mirror(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const uint64_t i_rank, ccs::instruction_t<T>& io_inst) -{ - // We only mirror if the mirroring attribute is set. - uint8_t l_mirror = 0; - FAPI_TRY( eff_dimm_rcd_mirror_mode(i_target, l_mirror) ); - - // We only mirror odd ranks. - if ((l_mirror == fapi2::ENUM_ATTR_EFF_DIMM_RCD_MIRROR_MODE_ON) && (i_rank & 0x1)) - { - address_mirror_impl(io_inst); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Invert (side to side) the ADR bits of a CCS instruction -/// @param[in] i_inst const reference to a CCS instruction. -/// @return[out] ccs instruction with the ADR bits inverted (side-to-side) -/// -template<fapi2::TargetType T> -ccs::instruction_t<T> address_invert(const ccs::instruction_t<T>& i_inst) -{ - // Copy the input as the output doesn't all change. - ccs::instruction_t<T> i_out(i_inst); - - // Nothing fancy here, just negate the bits we're told to negate in Table 14 — Address Mirroring and Inversion - mss::template negate<A3>(i_out.arr0); - mss::template negate<A4>(i_out.arr0); - mss::template negate<A5>(i_out.arr0); - mss::template negate<A6>(i_out.arr0); - mss::template negate<A7>(i_out.arr0); - mss::template negate<A8>(i_out.arr0); - mss::template negate<A9>(i_out.arr0); - - mss::template negate<A11>(i_out.arr0); - mss::template negate<A13>(i_out.arr0); - mss::template negate<A17>(i_out.arr0); - - mss::template negate<BA0>(i_out.arr0); - mss::template negate<BA1>(i_out.arr0); - mss::template negate<BG0>(i_out.arr0); - mss::template negate<BG1>(i_out.arr0); - - return i_out; -} - -} // namespace -#endif |