diff options
author | Andre Marin <aamarin@us.ibm.com> | 2016-09-01 19:23:05 -0500 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2016-09-21 16:39:30 -0400 |
commit | 142582dcca86c52698662aec925495bac8dc7059 (patch) | |
tree | 127123c92d7e8200809aaff28766f10b0077d3d5 /src/import/chips | |
parent | 92fbd675918101f1b5ab446c061ea33881b3c62b (diff) | |
download | talos-hostboot-142582dcca86c52698662aec925495bac8dc7059.tar.gz talos-hostboot-142582dcca86c52698662aec925495bac8dc7059.zip |
Add LRDIMM decoder and unit tests
Change-Id: Ic213fe7883b4090aef8afc3d481bb63d5cdc49fe
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/29811
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Brian R. Silver <bsilver@us.ibm.com>
Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/29812
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips')
7 files changed, 2887 insertions, 52 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H index cec0698b9..b737d196b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H @@ -65,13 +65,11 @@ class dimm_module_decoder virtual ~dimm_module_decoder() = default; /// - /// @brief Decodes module nominal height max, in mm + /// @brief Decodes module nominal height max /// @param[out] o_output height range encoding from SPD /// @return FAPI2_RC_SUCCESS if okay /// @note SPD Byte 128 (Bits 4~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 48 /// virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) { @@ -80,13 +78,24 @@ class dimm_module_decoder } /// - /// @brief Decodes front module maximum thickness max, in mm + /// @brief Decodes raw card extension + /// @param[out] o_output height range encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 128 (Bits 7~5) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes front module maximum thickness max /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay /// @note SPD Byte 129 (Bits 3~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 48 /// virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) { @@ -95,13 +104,11 @@ class dimm_module_decoder } /// - /// @brief Decodes back module maximum thickness max, in mm + /// @brief Decodes back module maximum thickness max /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay /// @note SPD Byte 129 (Bits 7~4) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 48 /// virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) { @@ -115,8 +122,6 @@ class dimm_module_decoder /// @return FAPI2_RC_SUCCESS if okay /// @note SPD Byte 131 (Bits 1~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 50 /// virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) { @@ -130,8 +135,6 @@ class dimm_module_decoder /// @return FAPI2_RC_SUCCESS if okay /// @note SPD Byte 131 (Bits 3~2) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 50 /// virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) { @@ -140,16 +143,28 @@ class dimm_module_decoder } /// + /// @brief Decodes number of rows of DRAMs on RDIMM + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 7~4) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// /// @brief Decodes heat spreader thermal characteristics /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCEawSS if okay /// @note SPD Byte 132 (Bits 6~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 51 /// virtual fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_output) { + // Undefined must be coded as 0x00 o_output = 0; return fapi2::FAPI2_RC_SUCCESS; } @@ -160,8 +175,6 @@ class dimm_module_decoder /// @return FAPI2_RC_SUCCESS if okay /// @note SPD Byte 132 (Bit 7) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 51 /// virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) { @@ -173,10 +186,8 @@ class dimm_module_decoder /// @brief Decodes number of continuation codes /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 133 (bit 6~0) + /// @note SPD Byte 133 (Bits 6~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 51 /// virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) { @@ -188,10 +199,8 @@ class dimm_module_decoder /// @brief Decodes manufacturer ID code /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 133 (bit 6~0) + /// @note SPD Byte 134 (Bits 7~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 51 /// virtual fapi2::ReturnCode manufacturer_id_code(uint8_t& o_output) { @@ -203,10 +212,8 @@ class dimm_module_decoder /// @brief Decodes register revision number /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 135 (bit 7~0) + /// @note SPD Byte 135 (Bits 7~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 51 /// virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) { @@ -218,10 +225,8 @@ class dimm_module_decoder /// @brief Decodes address mapping from register to dram /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 136 (bit 0) + /// @note SPD Byte 136 (Bit 0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 52 /// virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) { @@ -233,10 +238,8 @@ class dimm_module_decoder /// @brief Decodes register output drive strength for CKE signal /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (bit 1~0) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 + /// @note SPD Byte 137 (Bits 1~0) + /// @note Item JEDEC Standard No. 21-C /// virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) { @@ -248,10 +251,8 @@ class dimm_module_decoder /// @brief Decodes register output drive strength for ODT signal /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (bit 3~2) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 + /// @note SPD Byte 137 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C /// virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) { @@ -263,10 +264,8 @@ class dimm_module_decoder /// @brief Decodes register output drive strength for command/address (CA) signal /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (bit 5~4) + /// @note SPD Byte 137 (Bits 5~4) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 53 /// virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) { @@ -278,10 +277,8 @@ class dimm_module_decoder /// @brief Decodes register output drive strength for chip select (CS) signal /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 137 (bit 6~7) - /// @note Item JC-45-2220.01x - /// @note Page 76 - /// @note DDR4 SPD Document Release 4 + /// @note SPD Byte 137 (Bits 6~7) + /// @note Item JEDEC Standard No. 21-C /// virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) { @@ -293,10 +290,8 @@ class dimm_module_decoder /// @brief Decodes register output drive strength for clock (B side) /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (bit 1~0) + /// @note SPD Byte 138 (Bits 1~0) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 53 /// virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) { @@ -308,18 +303,322 @@ class dimm_module_decoder /// @brief Decodes register output drive strength for clock (A side) /// @param[out] o_output drive strength encoding from SPD /// @return FAPI2_RC_SUCCESS if okay - /// @note SPD Byte 138 (bit 3~2) + /// @note SPD Byte 138 (Bits 3~2) /// @note Item JEDEC Standard No. 21-C - /// @note DDR4 SPD Document Release 2 - /// @note Page 4.1.2.12 - 53 /// virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) { o_output = 0; return fapi2::FAPI2_RC_SUCCESS; } + + /// + /// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE) + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 4) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode bcom_bcke_bodt_drive_strength(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + + } + + /// + /// @brief Decodes register output drive strength for data buffer control (BCK) + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 5) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode bck_output_drive_strength(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes RCD output slew rate control + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 6) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode slew_rate_control(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes data buffer revision number + /// @param[out] o_output revision number + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 139 (Bits 7~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode data_buffer_rev(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 0 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 140 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_vref_dq_rank0(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 1 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 141 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_vref_dq_rank1(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 2 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 142 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_vref_dq_rank2(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 3 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 143 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_vref_dq_rank3(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes data buffer VrefDQ for DRAM interface + /// @param[out] o_output encoding of F5BC6x in DDR4DB01 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 144 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode data_buffer_vref_dq(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM interface MDQ Drive Strenth + /// of the data buffer component for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output encoding of F5BC6x in + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 145 - 147 (Bits 6~4) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM interface MDQ read termination strength + /// of the data buffer component for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output encoding of F5BC6x in + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 145 - 147 (Bits 2~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM drive strenth + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output DRAM drive strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 148 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM ODT for RTT_NOM + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 149 - 151 (Bits 2~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM ODT for RTT_WR + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 149 - 151 (Bits 5~3) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1 + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 152 - 154 (Bits 2~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3 + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 152 - 154 (Bits 5~3) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes VrefDQ range for DRAM interface range + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 155 (Bits 3~0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode dram_vref_dq_range(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes data buffer VrefDQ range for DRAM interface range + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 155 (Bit 4) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode data_buffer_vref_dq_range(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes data buffer gain adjustment + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 156 (Bit 0) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode data_buffer_gain_adjustment(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Decodes data buffer Decision Feedback Equalization (DFE) + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 156 (Bit 1) + /// @note Item JEDEC Standard No. 21-C + /// + virtual fapi2::ReturnCode data_buffer_dfe(uint8_t& o_output) + { + o_output = 0; + return fapi2::FAPI2_RC_SUCCESS; + } }; +/// +/// @brief data structure for byte fields +/// +struct field_t +{ + const uint64_t iv_byte; + const uint64_t iv_start; + const uint64_t iv_length; + + // default ctor deleted + constexpr field_t() = delete; + + /// + /// @brief ctor + /// @param[in] i_byte_index + /// @param[in] i_start_bit + /// @param[in] i_bit_length + /// + constexpr field_t(const uint64_t i_byte_index, + const uint64_t i_start_bit, + const uint64_t i_bit_length) + : iv_byte(i_byte_index), iv_start(i_start_bit), iv_length(i_bit_length) + {} + + /// + /// @brief default dtor + /// + ~field_t() = default; + +};// field_t + }// spd }// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H index 439821411..3bfcdc4ab 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.H @@ -45,7 +45,9 @@ #include <fapi2.H> // mss lib +#include <lib/spd/common/dimm_module_decoder.H> #include <lib/spd/rdimm/rdimm_decoder.H> +#include <lib/spd/lrdimm/lrdimm_decoder.H> #include <lib/spd/rdimm/raw_cards.H> #include <lib/utils/c_str.H> @@ -94,6 +96,8 @@ enum factory_byte_extract /// @tparam I Byte index /// @tparam S Start bit /// @tparam L Bit length +/// @param[in] i_target the dimm target +/// @param[in] i_spd_data the SPD data /// @return extracted byte (right aligned) /// template<uint8_t I, uint8_t S, uint8_t L> @@ -116,6 +120,56 @@ inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i } /// +/// @brief Helper function to extract byte information +/// @tparam F the SPD field to extract +/// @param[in] i_target the dimm target +/// @param[in] i_spd_data the SPD data +/// @return extracted byte (right aligned) +/// +template< const field_t& F > +inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data) +{ + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + F.iv_byte, + i_spd_data[F.iv_byte]); + + fapi2::buffer<uint8_t> l_buffer(i_spd_data[F.iv_byte]); + + // Extracting desired bits + uint8_t l_field_bits = 0; + l_buffer.extractToRight<F.iv_start, F.iv_length>(l_field_bits); + + return l_field_bits; +} + +/// +/// @brief Helper function to extract byte information +/// @param[in] i_target the dimm target +/// @param[in] i_field the SPD field +/// @param[in] i_spd_data the SPD data +/// @return extracted byte (right aligned) +/// +inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const field_t& i_field, + const std::vector<uint8_t>& i_spd_data) +{ + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(i_target), + i_field.iv_byte, + i_spd_data[i_field.iv_byte]); + + fapi2::buffer<uint8_t> l_buffer(i_spd_data[i_field.iv_byte]); + + // Extracting desired bits + uint8_t l_field_bits = 0; + l_buffer.extractToRight( l_field_bits, i_field.iv_start, i_field.iv_length ); + + return l_field_bits; +} + +/// /// @class decoder /// @brief Base SPD DRAM decoder /// @@ -1454,4 +1508,4 @@ class decoder_v1_1 : public decoder }// spd }// mss -#endif //_MSS_SPD_DECODER_H_ +#endif //_MSSS_PD_DECODER_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder.H index 0126e55eb..4e3c5694a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder.H @@ -32,3 +32,640 @@ // *HWP Team: Memory // *HWP Level: 2 // *HWP Consumed by: HB:FSP + + +#ifndef _MSS_LRDIMM_DECODER_H_ +#define _MSS_LRDIMM_DECODER_H_ + +#include <fapi2.H> +#include <vector> +#include <lib/spd/common/dimm_module_decoder.H> + +namespace mss +{ +namespace spd +{ +namespace lrdimm +{ + +/// +/// @brief LRDIMM module decoder for revision 1.0 +/// +class decoder_v1_0 : public dimm_module_decoder +{ + protected: + + const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target; + + constexpr static field_t MODULE_NOMINAL_HEIGHT{128, 3, 5}; + constexpr static field_t RAW_CARD_EXTENSION{128, 0, 3}; + + constexpr static field_t FRONT_MODULE_THICKNESS{129, 4, 4}; + constexpr static field_t BACK_MODULE_THICKNESS{129, 0, 4}; + + constexpr static field_t NUM_REGISTERS_USED{131, 6, 2}; + constexpr static field_t NUM_ROWS_OF_DRAMS{131, 4, 2}; + constexpr static field_t REGISTER_TYPE{131, 0, 4}; + + constexpr static field_t HEAT_SPREADER_THERM_CHAR{132, 1, 7}; + constexpr static field_t HEAT_SPREADER_SOLUTION{132, 0, 1}; + + constexpr static field_t CONTINUATION_CODES{133, 1, 7}; + constexpr static field_t ADDR_MAPPING{136, 7, 1}; + + constexpr static field_t CKE_DRIVE_STRENGTH{137, 6, 2}; + constexpr static field_t ODT_DRIVE_STRENGTH{137, 4, 2}; + constexpr static field_t CA_DRIVE_STRENGTH{137, 2, 2}; + constexpr static field_t CS_DRIVE_STRENGTH{137, 0, 2}; + + constexpr static field_t B_SIDE_DRIVE_STRENGTH{138, 6, 2}; + constexpr static field_t A_SIDE_DRIVE_STRENGTH{138, 4, 2}; + constexpr static field_t BCOM_BODT_BCKE_DRIVE_STRENGTH{138, 3, 1}; + constexpr static field_t BCK_DRIVE_STRENGTH{138, 2, 1}; + constexpr static field_t RCD_SLEW_CNTRL{138, 1, 1 }; + + constexpr static field_t VREF_DQ_RANK0{140, 2, 6}; + constexpr static field_t VREF_DQ_RANK1{141, 2, 6}; + constexpr static field_t VREF_DQ_RANK2{142, 2, 6}; + constexpr static field_t VREF_DQ_RANK3{143, 2, 6}; + + constexpr static field_t DATA_BUFFER_MDQ{145, 1, 3}; + + constexpr static field_t DRAM_VREF_DQ_RANGE{155, 4, 4}; + constexpr static field_t DATA_BUFFER_VREF_DQ{155, 3, 1}; + + constexpr static field_t DATA_BUFFER_GAIN_ADJUST{156, 7, 1}; + constexpr static field_t DATA_BUFFER_DFE{156, 6, 1}; + + public: + // Allows injection of errors for testing + // TK - Consider API change to use setter/getters + // for this instance variable, RDIMM decoder + // uses this interface so they have to match - AAM + std::vector<uint8_t> iv_spd_data; + + // deleted default ctor + decoder_v1_0() = delete; + + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data vector DIMM SPD data + /// + decoder_v1_0(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data) + : iv_target(i_target), iv_spd_data(i_spd_data) + {} + + /// + /// @brief default dtor + /// + virtual ~decoder_v1_0() = default; + + /// + /// @brief Decodes module nominal height max + /// @param[out] o_output height range encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 128 (Bits 4~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 55 + /// + virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) override; + + /// + /// @brief Decodes raw card extension + /// @param[out] o_output raw card rev. encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 128 (Bits 7~5) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 55 + /// + virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output) override; + + /// + /// @brief Decodes front module maximum thickness max + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 129 (Bits 3~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 55 + /// + virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) override; + + /// + /// @brief Decodes back module maximum thickness max + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 129 (Bits 7~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 55 + /// + virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) override; + + /// + /// @brief Decodes number of registers used on LRDIMM + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 57 + /// + virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) override; + + /// + /// @brief Decodes number of rows of DRAMs on LRDIMM + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 57 + /// + virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) override; + + /// + /// @brief Decodes heat spreader solution + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 132 (Bit 7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 58 + /// + virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) override; + + /// + /// @brief Decodes number of continuation codes + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 133 (Bits 6~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 58 + /// + virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) override; + + /// + /// @brief Decodes manufacturer ID code + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 134 (Bits 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 58 + /// + virtual fapi2::ReturnCode manufacturer_id_code(uint8_t& o_output) override; + + /// + /// @brief Decodes register revision number + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 135 (Bits 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 58 + /// + virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) override; + + /// + /// @brief Decodes address mapping from register to dram + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 136 (Bit 0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 59 + /// + virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for CKE signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 60 + /// + virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for ODT signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 60 + /// + virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for command/address (CA) signal + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (Bits 5~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 60 + /// + virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for chip select (CS) signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (Bits 6~7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 60 + /// + virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (B side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bits 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 60 + /// + virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (A side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 60 + /// + virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes data buffer revision number + /// @param[out] o_output revision number + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 139 (Bits 7~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 60 + /// + virtual fapi2::ReturnCode data_buffer_rev(uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 0 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 140 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 61 + /// + virtual fapi2::ReturnCode dram_vref_dq_rank0(uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 1 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 141 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 61 + /// + virtual fapi2::ReturnCode dram_vref_dq_rank1(uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 2 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 142 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 61 + /// + virtual fapi2::ReturnCode dram_vref_dq_rank2(uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM VrefDQ for Package Rank 3 + /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 143 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 61 + /// + virtual fapi2::ReturnCode dram_vref_dq_rank3(uint8_t& o_output) override; + + /// + /// @brief Decodes data buffer VrefDQ for DRAM interface + /// @param[out] o_output encoding of F5BC6x in DDR4DB01 spec + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 144 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 61 + /// + virtual fapi2::ReturnCode data_buffer_vref_dq(uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM interface MDQ Drive Strenth + /// of the data buffer component for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output encoding of F5BC6x in + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 145 - 147 (Bits 6~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 62 + /// + virtual fapi2::ReturnCode data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, + uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM interface MDQ read termination strength + /// of the data buffer component for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output encoding of F5BC6x in + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 145 - 147 (Bits 2~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 62 + /// + virtual fapi2::ReturnCode data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM drive strenth + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output DRAM drive strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 148 (Bits 5~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 63 + /// + virtual fapi2::ReturnCode dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM ODT for RTT_NOM + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 149 - 151 (Bits 2~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - (64 - 65) + /// + virtual fapi2::ReturnCode dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM ODT for RTT_WR + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 149 - 151 (Bits 5~3) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - (64 - 65) + /// + virtual fapi2::ReturnCode dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1 + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 152 - 154 (Bits 2~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 65 + /// + virtual fapi2::ReturnCode dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output) override; + + /// + /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3 + /// for a particular dimm speed + /// @param[in] i_dimm_speed the dimm speed in MT/s + /// @param[out] o_output ODT termination strength (in ohms) + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 152 - 154 (Bits 5~3) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 2 + /// @note Page 4.1.2.12.2 - 65 + /// + virtual fapi2::ReturnCode dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output) override; + +};//decoder + +/// +/// @brief LRDIMM module decoder for revision 1.1 +/// +class decoder_v1_1 : public decoder_v1_0 +{ + public: + + // deleted default ctor + decoder_v1_1() = delete; + + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data vector DIMM SPD data + /// + decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data) + : decoder_v1_0(i_target, i_spd_data) + {} + + /// + /// @brief default dtor + /// + virtual ~decoder_v1_1() = default; + + /// + /// @brief Decodes register and data buffer types + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 131 (Bits 7~4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 63 + /// + virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for CKE signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (Bits 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 65 + /// + virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for ODT signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 65 + /// + virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for chip select (CS) signal + /// @param[out] o_output encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 137 (Bits 6~7) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 65 + /// + virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (B side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bits 1~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 66 + /// + virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for clock (A side) + /// @param[out] o_output drive strength encoding from SPD + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bits 3~2) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 66 + /// + virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE) + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 66 + /// + virtual fapi2::ReturnCode bcom_bcke_bodt_drive_strength(uint8_t& o_output) override; + + /// + /// @brief Decodes register output drive strength for data buffer control (BCK) + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 5) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 3 + /// @note Page 4.1.2.12.3 - 66 + /// + virtual fapi2::ReturnCode bck_output_drive_strength(uint8_t& o_output) override; + +}; + +/// +/// @brief LRDIMM module decoder for revision 1.2 +/// +class decoder_v1_2 : public decoder_v1_1 +{ + public: + + // deleted default ctor + decoder_v1_2() = delete; + + /// + /// @brief ctor + /// @param[in] i_target dimm target + /// @param[in] i_spd_data vector DIMM SPD data + /// + decoder_v1_2(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<uint8_t>& i_spd_data) + : decoder_v1_1(i_target, i_spd_data) + {} + + /// + /// @brief default dtor + /// + virtual ~decoder_v1_2() = default; + + /// + /// @brief Decodes RCD output slew rate control + /// @param[out] o_output encoded drive strength + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 138 (Bit 6) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 4 + /// @note Page 4.1.2.L-4 - 70 + /// + virtual fapi2::ReturnCode slew_rate_control(uint8_t& o_output) override; + + /// + /// @brief Decodes VrefDQ range for DRAM interface range + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 155 (Bits 3~0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 4 + /// @note Page 4.1.2.L-4 - 76 + /// + virtual fapi2::ReturnCode dram_vref_dq_range(uint8_t& o_output) override; + + /// + /// @brief Decodes data buffer VrefDQ range for DRAM interface range + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 155 (Bit 4) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 4 + /// @note Page 4.1.2.L-4 - 76 + /// + virtual fapi2::ReturnCode data_buffer_vref_dq_range(uint8_t& o_output) override; + + /// + /// @brief Decodes data buffer gain adjustment + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 156 (Bit 0) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 4 + /// @note Page 4.1.2.L-4 - 77 + /// + virtual fapi2::ReturnCode data_buffer_gain_adjustment(uint8_t& o_output) override; + + /// + /// @brief Decodes data buffer Decision Feedback Equalization (DFE) + /// @param[out] o_output spd encoding + /// @return FAPI2_RC_SUCCESS if okay + /// @note SPD Byte 156 (Bit 1) + /// @note Item JEDEC Standard No. 21-C + /// @note DDR4 SPD Document Release 4 + /// @note Page 4.1.2.L-4 - 77 + /// + virtual fapi2::ReturnCode data_buffer_dfe(uint8_t& o_output) override; +}; + +}// lrdimm +}// spd +}// mss + +#endif //_MSS_LRDIMM_DECODER_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_0.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_0.C index c0eb14710..e46a09a50 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_0.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_0.C @@ -32,3 +32,1336 @@ // *HWP Team: Memory // *HWP Level: 2 // *HWP Consumed by: HB:FSP + +// std lib +#include <vector> + +// fapi2 +#include <fapi2.H> + +// mss lib +#include <lib/spd/lrdimm/lrdimm_decoder.H> +#include <lib/spd/common/spd_decoder.H> +#include <lib/utils/checker.H> +#include <lib/utils/c_str.H> +#include <lib/utils/find.H> + +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + + +namespace mss +{ +namespace spd +{ +namespace lrdimm +{ + +///////////////////////// +// Non-member helper functions +// For LRDIMM module rev 1.0 +///////////////////////// + +/// @brief Helper function to find SPD byte based on freq +/// @param[in] i_dimm_speed DIMM speed in MT/s +/// @param[out] o_byte byte to extract spd from +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, +/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values +/// so we use a simple case statement to get our results. +static fapi2::ReturnCode mdq_helper(const uint64_t i_dimm_speed, uint8_t& o_byte) +{ + switch(i_dimm_speed) + { + case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: + o_byte = 145; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: + case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: + o_byte = 146; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: + o_byte = 147; + break; + + default: + FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + break; + } + + return fapi2::FAPI2_RC_SUCCESS; +}; + +/// @brief Helper function to find start bit based on freq +/// @param[in] i_dimm_speed DIMM speed in MT/s +/// @param[out] o_start_bit start bit to extract SPD from +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, +/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values +/// so we use a simple case statement to get our results. +static fapi2::ReturnCode drive_strength_start_bit_finder(const uint64_t i_dimm_speed, size_t& o_start_bit) +{ + switch(i_dimm_speed) + { + case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: + o_start_bit = 6; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: + case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: + o_start_bit = 4; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: + o_start_bit = 2; + break; + + default: + FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + break; + } + + return fapi2::FAPI2_RC_SUCCESS; +} + +/// @brief Helper function to find SPD byte based on freq +/// @param[in] i_dimm_speed DIMM speed in MT/s +/// @param[out] o_byte byte to extract spd from +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, +/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values +/// so we use a simple case statement to get our results. +static fapi2::ReturnCode rtt_wr_and_nom_byte_finder(const uint64_t i_dimm_speed, size_t& o_byte) +{ + switch(i_dimm_speed) + { + case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: + o_byte = 149; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: + case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: + o_byte = 150; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: + o_byte = 151; + break; + + default: + FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + break; + } + + return fapi2::FAPI2_RC_SUCCESS; +} + +/// @brief Helper function to find SPD byte based on freq +/// @param[in] i_dimm_speed DIMM speed in MT/s +/// @param[out] o_byte byte to extract spd from +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400, +/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values +/// so we use a simple case statement to get our results. +static fapi2::ReturnCode rtt_park_byte_finder(const uint64_t i_dimm_speed, size_t& o_byte) +{ + switch(i_dimm_speed) + { + case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: + o_byte = 152; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: + case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: + o_byte = 153; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: + o_byte = 154; + break; + + default: + FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + break; + } + + return fapi2::FAPI2_RC_SUCCESS; +} + +///////////////////////// +// Member Method implementation +// For LRDIMM module rev 1.0 +///////////////////////// + +/// +/// @brief Decodes module nominal height max +/// @param[out] o_output height range encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 128 (Bits 4~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 55 +/// +fapi2::ReturnCode decoder_v1_0::max_module_nominal_height(uint8_t& o_output) +{ + uint8_t l_field_bits = extract_spd_field< MODULE_NOMINAL_HEIGHT >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b11111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + MODULE_NOMINAL_HEIGHT.iv_byte, + l_field_bits, + "Failed bound check for module nominal height max") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Max module nominal height: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes raw card extension +/// @param[out] o_output raw card rev. encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 128 (Bits 7~5) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 55 +/// +fapi2::ReturnCode decoder_v1_0::raw_card_extension(uint8_t& o_output) +{ + uint8_t l_field_bits = extract_spd_field< RAW_CARD_EXTENSION >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + RAW_CARD_EXTENSION.iv_byte, + l_field_bits, + "Failed bound check for raw card extension") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Raw card extension: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes front module maximum thickness max +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 129 (Bits 3~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 55 +/// +fapi2::ReturnCode decoder_v1_0::front_module_max_thickness(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< FRONT_MODULE_THICKNESS >(iv_target, iv_spd_data); + + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b1111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + FRONT_MODULE_THICKNESS.iv_byte, + l_field_bits, + "Failed bound check for front module max thickness") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Front module max thickness: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes back module maximum thickness max +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 129 (Bits 7~4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 55 +/// +fapi2::ReturnCode decoder_v1_0::back_module_max_thickness(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< BACK_MODULE_THICKNESS >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 0b1111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + BACK_MODULE_THICKNESS.iv_byte, + l_field_bits, + "Failed bound check for back module max thickness") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Back module max thickness: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes number of registers used on LRDIMM +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 131 (Bits 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 57 +/// +fapi2::ReturnCode decoder_v1_0::num_registers_used(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< NUM_REGISTERS_USED >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 0b10; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + NUM_REGISTERS_USED.iv_byte, + l_field_bits, + "Failed bound check for number of registers used on RDIMM ") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Number of registers used on LRDIMM : %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes number of rows of DRAMs on LRDIMM +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 131 (Bits 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 57 +/// +fapi2::ReturnCode decoder_v1_0::num_rows_of_drams(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< NUM_ROWS_OF_DRAMS >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + NUM_REGISTERS_USED.iv_byte, + l_field_bits, + "Failed bound check for number of rows of DRAMs on LRDIMM ") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Number of rows of DRAMs on LRDIMM : %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes heat spreader solution +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 132 (Bit 7) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 58 +/// +fapi2::ReturnCode decoder_v1_0::heat_spreader_solution(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< HEAT_SPREADER_SOLUTION >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + HEAT_SPREADER_SOLUTION.iv_byte, + l_field_bits, + "Failed bound check for heat spreader solution") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Heat spreader solution: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes number of continuation codes +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 133 (bit 6~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 58 +/// +fapi2::ReturnCode decoder_v1_0::num_continuation_codes(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< CONTINUATION_CODES >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 10; // JEP106AS spec + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + CONTINUATION_CODES.iv_byte, + l_field_bits, + "Failed bound check for number of continuation codes") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Number of continuation codes: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes manufacturer ID code +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 134 (bit 7~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 58 +/// +fapi2::ReturnCode decoder_v1_0::manufacturer_id_code(uint8_t& o_output) +{ + constexpr size_t BYTE_INDEX = 134; + uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(iv_target), + BYTE_INDEX, + l_raw_byte); + + // All bits used for encoding, no bounds to check + o_output = l_raw_byte; + + FAPI_INF("%s. Register revision number: %d", + mss::c_str(iv_target), + o_output); + + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes register revision number +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 135 (bit 7~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 58 +/// +fapi2::ReturnCode decoder_v1_0::register_rev_num(uint8_t& o_output) +{ + constexpr size_t BYTE_INDEX = 135; + uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(iv_target), + BYTE_INDEX, + l_raw_byte); + + // All bits used for encoding, no bounds to check + o_output = l_raw_byte; + + FAPI_INF("%s. Register revision number: %d", + mss::c_str(iv_target), + o_output); + + return fapi2::FAPI2_RC_SUCCESS; +} + +/// +/// @brief Decodes address mapping from register to dram +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 136 (bit 0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 59 +/// +fapi2::ReturnCode decoder_v1_0::register_to_dram_addr_mapping(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< ADDR_MAPPING >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + ADDR_MAPPING.iv_byte, + l_field_bits, + "Failed bound check for to register to dram addr mapping") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Address mapping from register to dram: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for CKE signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 60 +/// +fapi2::ReturnCode decoder_v1_0::cke_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< CKE_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + CKE_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for CKE") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CKE: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for ODT signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 60 +/// +fapi2::ReturnCode decoder_v1_0::odt_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< ODT_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + ODT_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for ODT") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for ODT: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for command/address (CA) signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 5~4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 60 +/// +fapi2::ReturnCode decoder_v1_0::ca_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< CA_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t INVALID_VAL = 4; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < INVALID_VAL, // extract sanity check + CA_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for CA") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CA: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for chip select (CS) signal +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (bit 6~7) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 60 +/// +fapi2::ReturnCode decoder_v1_0::cs_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< CS_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + CS_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for CS") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CS: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (B side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (bit 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 60 +/// +fapi2::ReturnCode decoder_v1_0::b_side_clk_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< B_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + B_SIDE_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (A side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (bit 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 60 +/// +fapi2::ReturnCode decoder_v1_0::a_side_clk_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< A_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + A_SIDE_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes data buffer revision number +/// @param[out] o_output revision number +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 139 (Bits 7~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 60 +/// +fapi2::ReturnCode decoder_v1_0::data_buffer_rev(uint8_t& o_output) +{ + // Extracting desired bits + constexpr size_t BYTE_INDEX = 139; + const uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(iv_target), + BYTE_INDEX, + l_raw_byte); + + // This checks JEDEC range is met + constexpr size_t UNDEFINED = 0xFF; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_raw_byte != UNDEFINED, + BYTE_INDEX, + l_raw_byte, + "Failed bounds check for data buffer revision number") ); + + // Update output only if check passes + o_output = l_raw_byte; + + FAPI_INF("%s. Data buffer rev: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes DRAM VrefDQ for Package Rank 0 +/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 140 (Bits 5~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 61 +/// +fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank0(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK0 >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // JESD79-4 specification + constexpr size_t RESERVED = 0b110011; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + VREF_DQ_RANK0.iv_byte, + l_field_bits, + "Failed bounds check for DRAM VrefDQ for Package Rank 0") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM VrefDQ for Package Rank 0: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM VrefDQ for Package Rank 1 +/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 141 (Bits 5~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 61 +/// +fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank1(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK1 >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // JESD79-4 specification + constexpr size_t RESERVED = 0b110011; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + VREF_DQ_RANK1.iv_byte, + l_field_bits, + "Failed bounds check for DRAM VrefDQ for Package Rank 1") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM VrefDQ for Package Rank 1: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM VrefDQ for Package Rank 2 +/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 142 (Bits 5~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 61 +/// +fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank2(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK2 >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // JESD79-4 specification + constexpr size_t RESERVED = 0b110011; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + VREF_DQ_RANK2.iv_byte, + l_field_bits, + "Failed bounds check for DRAM VrefDQ for Package Rank 2") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM VrefDQ for Package Rank 2: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM VrefDQ for Package Rank 3 +/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 143 (Bits 5~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 4 +/// @note Page 4.1.2.12.2 - 61 +/// +fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank3(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK3 >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // JESD79-4 specification + constexpr size_t RESERVED = 0b110011; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + VREF_DQ_RANK3.iv_byte, + l_field_bits, + "Failed bounds check for DRAM VrefDQ for Package Rank 3") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM VrefDQ for Package Rank 3: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes data buffer VrefDQ for DRAM interface +/// @param[out] o_output encoding of F5BC6x in DDR4DB01 spec +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 144 (Bits 5~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 61 +/// +fapi2::ReturnCode decoder_v1_0::data_buffer_vref_dq(uint8_t& o_output) +{ + constexpr size_t BYTE_INDEX = 144; + uint8_t l_raw_data = iv_spd_data[BYTE_INDEX]; + + // Trace in the front assists w/ debug + FAPI_INF("%s SPD data at Byte %d: 0x%llX.", + mss::c_str(iv_target), + BYTE_INDEX, + l_raw_data); + + // DDR4DB01 spec + constexpr size_t RESERVED = 0b00110011; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_raw_data < RESERVED, + BYTE_INDEX, + l_raw_data, + "Failed bounds check for data buffer VrefDQ for DRAM interface") ); + + // Update output only if check passes + o_output = l_raw_data; + + FAPI_INF("%s. Data buffer VrefDQ for DRAM interface: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM interface MDQ Drive Strenth +/// of the data buffer component for a particular dimm speed +/// @param[in] i_dimm_speed the dimm speed in MT/s +/// @param[out] o_output encoding of F5BC6x in +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 145 - 147 (Bits 6~4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 62 +/// +fapi2::ReturnCode decoder_v1_0::data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) +{ + uint8_t l_byte = 0; + uint8_t l_field_bits = 0; + + FAPI_TRY( mdq_helper(i_dimm_speed, l_byte) ); + + { + constexpr size_t START = 1; + constexpr size_t LEN = 3; + const field_t MDQ_DRIVE_STRENGTH(l_byte, START, LEN); + + l_field_bits = extract_spd_field( iv_target, MDQ_DRIVE_STRENGTH, iv_spd_data ); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Lets make sure we aren't being set to a reserved field + bool is_reserved_bit = false; + + switch(l_field_bits) + { + case 0b011: + case 0b100: + case 0b110: + case 0b111: + is_reserved_bit = true; + break; + + default: + is_reserved_bit = false; + break; + } + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 7; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + (l_field_bits <= MAX_VALID_VALUE) && + (is_reserved_bit != true), + l_byte, + l_field_bits, + "Failed bounds check for DRAM interface MDQ Drive Strenth") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM interface MDQ Drive Strenth: %d", + mss::c_str(iv_target), + o_output); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM interface MDQ read termination strength +/// of the data buffer component for a particular dimm speed +/// @param[in] i_dimm_speed the dimm speed in MT/s +/// @param[out] o_output encoding of F5BC6x in +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 145 - 147 (Bits 2~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 62 +/// +fapi2::ReturnCode decoder_v1_0::data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output) +{ + uint8_t l_byte = 0; + uint8_t l_field_bits = 0; + + FAPI_TRY( mdq_helper(i_dimm_speed, l_byte) ); + + { + constexpr size_t START = 1; + constexpr size_t LEN = 3; + const field_t DATA_BUFFER_MDQ_RTT(l_byte, START, LEN); + + l_field_bits = extract_spd_field( iv_target, DATA_BUFFER_MDQ_RTT, iv_spd_data ); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 7; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + l_byte, + l_field_bits, + "Failed bounds check for DRAM interface MDQ RTT:") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM interface MDQ RTT: %d", + mss::c_str(iv_target), + o_output); + } +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM drive strenth +/// for a particular dimm speed +/// @param[in] i_dimm_speed the dimm speed in MT/s +/// @param[out] o_output DRAM drive strength (encoding) +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 148 (Bits 5~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 63 +/// +fapi2::ReturnCode decoder_v1_0::dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) +{ + size_t l_start = 0; + FAPI_TRY( drive_strength_start_bit_finder(i_dimm_speed, l_start) ); + + { + constexpr size_t BYTE_INDEX = 148; + constexpr size_t LEN = 2; + const field_t DRAM_DRIVE_STRENGTH(BYTE_INDEX, l_start, LEN); + + uint8_t l_field_bits = extract_spd_field( iv_target, DRAM_DRIVE_STRENGTH, iv_spd_data ); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // SPD JEDEC specification + constexpr size_t RESERVED = 0b11; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, + BYTE_INDEX, + l_field_bits, + "Failed bounds check for DRAM VrefDQ for Package Rank 3") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM drive strenth: %d", + mss::c_str(iv_target), + o_output); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM ODT for RTT_NOM +/// for a particular dimm speed +/// @param[in] i_dimm_speed the dimm speed in MT/s +/// @param[out] o_output ODT termination strength (encoding) +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 149 - 151 (Bits 2~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - (64 - 65) +/// +fapi2::ReturnCode decoder_v1_0::dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output) +{ + size_t l_byte = 0; + FAPI_TRY( rtt_wr_and_nom_byte_finder(i_dimm_speed, l_byte) ); + + { + constexpr size_t START = 5; + constexpr size_t LEN = 3; + const field_t DRAM_RTT_NOM(l_byte, START, LEN); + + uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_NOM, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 7; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + l_byte, + l_field_bits, + "Failed bounds check for DRAM RTT_NOM") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM RTT_NOM: %d", + mss::c_str(iv_target), + o_output); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM ODT for RTT_WR +/// for a particular dimm speed +/// @param[in] i_dimm_speed the dimm speed in MT/s +/// @param[out] o_output ODT termination strength (encoding) +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 149 - 151 (Bits 5~3) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - (64 - 65) +/// +fapi2::ReturnCode decoder_v1_0::dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output) +{ + size_t l_byte = 0; + FAPI_TRY( rtt_wr_and_nom_byte_finder(i_dimm_speed, l_byte) ); + + { + constexpr size_t START = 2; + constexpr size_t LEN = 3; + const field_t DRAM_RTT_WR(l_byte, START, LEN); + + uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_WR, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // Lets make sure we aren't being set to a reserved field + bool is_reserved_bit = false; + + switch(l_field_bits) + { + case 0b101: + case 0b110: + case 0b111: + is_reserved_bit = true; + break; + + default: + is_reserved_bit = false; + break; + } + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 7; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + (l_field_bits <= MAX_VALID_VALUE) && + (is_reserved_bit != true), + l_byte, + l_field_bits, + "Failed bounds check for DRAM RTT_WR") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM_RTT_WR: %d", + mss::c_str(iv_target), + o_output); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1 +/// for a particular dimm speed +/// @param[in] i_dimm_speed the dimm speed in MT/s +/// @param[out] o_output ODT termination strength (encoding) +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 152 - 154 (Bits 2~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 65 +/// +fapi2::ReturnCode decoder_v1_0::dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output) +{ + size_t l_byte = 0; + FAPI_TRY( rtt_park_byte_finder(i_dimm_speed, l_byte) ); + + { + constexpr size_t START = 5; + constexpr size_t LEN = 3; + const field_t DRAM_RTT_PARK(l_byte, START, LEN); + + uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_PARK, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 7; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + l_byte, + l_field_bits, + "Failed bounds check for DRAM RTT_PARK (package ranks 0,1)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM RTT_PARK (package ranks 0,1): %d", + mss::c_str(iv_target), + o_output); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3 +/// for a particular dimm speed +/// @param[in] i_dimm_speed the dimm speed in MT/s +/// @param[out] o_output ODT termination strength (encoding) +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 152 - 154 (Bits 5~3) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 2 +/// @note Page 4.1.2.12.2 - 65 +/// +fapi2::ReturnCode decoder_v1_0::dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output) +{ + size_t l_byte = 0; + FAPI_TRY( rtt_park_byte_finder(i_dimm_speed, l_byte) ); + + { + constexpr size_t START = 2; + constexpr size_t LEN = 3; + const field_t DRAM_RTT_PARK(l_byte, START, LEN); + + uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_PARK, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VALUE = 7; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VALUE, + l_byte, + l_field_bits, + "Failed bounds check for DRAM RTT_PARK (package ranks 2,3)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. DRAM RTT_PARK (package ranks 2,3): %d", + mss::c_str(iv_target), + o_output); + } + +fapi_try_exit: + return fapi2::current_err; +} + +}// lrdimm +}//spd +}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_1.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_1.C index cdaee5940..dfe54bbe3 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_1.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_1.C @@ -32,3 +32,312 @@ // *HWP Team: Memory // *HWP Level: 2 // *HWP Consumed by: HB:FSP + +// std lib +#include <vector> + +// fapi2 +#include <fapi2.H> + +// mss lib +#include <lib/spd/lrdimm/lrdimm_decoder.H> +#include <lib/spd/common/spd_decoder.H> +#include <lib/utils/checker.H> +#include <lib/utils/c_str.H> +#include <lib/utils/find.H> + +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + +namespace mss +{ +namespace spd +{ +namespace lrdimm +{ + +/// +/// @brief Decodes register and data buffer types +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 131 (Bits 7~4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 63 +/// +fapi2::ReturnCode decoder_v1_1::register_and_buffer_type(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< REGISTER_TYPE >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t RESERVED = 2; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits < RESERVED, // extract sanity check + REGISTER_TYPE.iv_byte, + l_field_bits, + "Failed bounds check for Register and Data Buffer Types") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register and Data Buffer Types: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Decodes register output drive strength for CKE signal +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (Bits 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 65 +/// +fapi2::ReturnCode decoder_v1_1::cke_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< CKE_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + CKE_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for CKE") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CKE: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for ODT signal +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (Bits 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 65 +/// +fapi2::ReturnCode decoder_v1_1::odt_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< ODT_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + ODT_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for ODT") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for ODT: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for chip select (CS) signal +/// @param[out] o_output encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 137 (Bits 6~7) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 65 +/// +fapi2::ReturnCode decoder_v1_1::cs_signal_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< CS_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + CS_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for CS") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for CS: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (B side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (Bits 1~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 66 +/// +fapi2::ReturnCode decoder_v1_1::b_side_clk_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< B_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + B_SIDE_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y0,Y2)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for clock (A side) +/// @param[out] o_output drive strength encoding from SPD +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (Bits 3~2) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 66 +/// +fapi2::ReturnCode decoder_v1_1::a_side_clk_output_driver(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< A_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, + A_SIDE_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for clock (Y1,Y3)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE) +/// @param[out] o_output encoded drive strength +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (Bit 4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 66 +/// +fapi2::ReturnCode decoder_v1_1::bcom_bcke_bodt_drive_strength(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< BCOM_BODT_BCKE_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, + BCOM_BODT_BCKE_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for data buffer control (BCOM, BODT, BCKE)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for data buffer control (BCOM, BODT, BCKE): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes register output drive strength for data buffer control (BCK) +/// @param[out] o_output encoded drive strength +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (Bit 5) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 3 +/// @note Page 4.1.2.12.3 - 66 +/// +fapi2::ReturnCode decoder_v1_1::bck_output_drive_strength(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< BCK_DRIVE_STRENGTH >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 3; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, + BCK_DRIVE_STRENGTH.iv_byte, + l_field_bits, + "Failed bounds check for Register Output Driver for data buffer control (BCK)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Register Output Driver for data buffer control (BCK): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +}// lrdimm +}// spd +}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_2.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_2.C index 0682389dc..5bf7d02ed 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_2.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/lrdimm/lrdimm_decoder_v1_2.C @@ -32,3 +32,206 @@ // *HWP Team: Memory // *HWP Level: 2 // *HWP Consumed by: HB:FSP + +// std lib +#include <vector> + +// fapi2 +#include <fapi2.H> + +// mss lib +#include <lib/spd/lrdimm/lrdimm_decoder.H> +#include <lib/spd/common/spd_decoder.H> +#include <lib/utils/checker.H> +#include <lib/utils/c_str.H> +#include <lib/utils/find.H> + +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_DIMM; + +namespace mss +{ +namespace spd +{ +namespace lrdimm +{ + +/// +/// @brief Decodes RCD output slew rate control +/// @param[out] o_output encoded drive strength +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 138 (Bit 6) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 4 +/// @note Page 4.1.2.L-4 - 70 +/// +fapi2::ReturnCode decoder_v1_2::slew_rate_control(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< RCD_SLEW_CNTRL >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 0b1111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + RCD_SLEW_CNTRL.iv_byte, + l_field_bits, + "Failed bound check for RCD output slew rate control") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. RCD output slew rate control: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes VrefDQ range for DRAM interface range +/// @param[out] o_output spd encoding +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 155 (Bits 3~0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 4 +/// @note Page 4.1.2.L-4 - 76 +/// +fapi2::ReturnCode decoder_v1_2::dram_vref_dq_range(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< DRAM_VREF_DQ_RANGE >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 0b1111; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + DRAM_VREF_DQ_RANGE.iv_byte, + l_field_bits, + "Failed bound check for VrefDQ range for DRAM interface range ") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. VrefDQ range for DRAM interface range: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes data buffer VrefDQ range for DRAM interface range +/// @param[out] o_output spd encoding +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 155 (Bit 4) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 4 +/// @note Page 4.1.2.L-4 - 76 +/// +fapi2::ReturnCode decoder_v1_2::data_buffer_vref_dq_range(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_VREF_DQ >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + DATA_BUFFER_VREF_DQ.iv_byte, + l_field_bits, + "Failed bound check for data buffer VrefDQ range for DRAM interface range") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Data buffer VrefDQ range for DRAM interface range: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes data buffer gain adjustment +/// @param[out] o_output spd encoding +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 156 (Bit 0) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 4 +/// @note Page 4.1.2.L-4 - 77 +/// +fapi2::ReturnCode decoder_v1_2::data_buffer_gain_adjustment(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_GAIN_ADJUST >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + DATA_BUFFER_GAIN_ADJUST.iv_byte, + l_field_bits, + "Failed bound check for data buffer gain adjustment") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Data buffer gain adjustment: %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Decodes data buffer Decision Feedback Equalization (DFE) +/// @param[out] o_output spd encoding +/// @return FAPI2_RC_SUCCESS if okay +/// @note SPD Byte 156 (Bit 1) +/// @note Item JEDEC Standard No. 21-C +/// @note DDR4 SPD Document Release 4 +/// @note Page 4.1.2.L-4 - 77 +/// +fapi2::ReturnCode decoder_v1_2::data_buffer_dfe(uint8_t& o_output) +{ + // Extracting desired bits + uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_DFE >(iv_target, iv_spd_data); + FAPI_INF("Field Bits value: %d", l_field_bits); + + // This checks my extracting params returns a value within bound + constexpr size_t MAX_VALID_VAL = 1; + + FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target, + l_field_bits <= MAX_VALID_VAL, // extract sanity check + DATA_BUFFER_DFE.iv_byte, + l_field_bits, + "Failed bound check for data buffer Decision Feedback Equalization (DFE)") ); + + // Update output only if check passes + o_output = l_field_bits; + + FAPI_INF("%s. Data buffer Decision Feedback Equalization (DFE): %d", + mss::c_str(iv_target), + o_output); + +fapi_try_exit: + return fapi2::current_err; +} + +}// lrdimm +}// spd +}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C index b841879f2..0e2643e8a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/rdimm/rdimm_decoder_v1_0.C @@ -380,7 +380,7 @@ fapi2::ReturnCode rdimm_decoder_v1_0::manufacturer_id_code(uint8_t& o_output) o_output = l_raw_byte; - FAPI_INF("%s. Register revision number: %d", + FAPI_INF("%s. Manufacturer ID code: %d", mss::c_str(iv_target), o_output); |