/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ /* You may obtain a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ /* implied. See the License for the specific language governing */ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ /// /// @file dp16.C /// @brief Static data and subroutines to control the DP16 logic blocks /// // *HWP HWP Owner: Jacob L Harvey // *HWP HWP Backup: Andre Marin // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: FSP:HB #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_DIMM; using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_SYSTEM; namespace mss { // Definition of the DP16 DLL Config registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< uint64_t > dp16Traits::DLL_CNFG_REG = { MCA_DDRPHY_DP16_DLL_CONFIG1_P0_0, MCA_DDRPHY_DP16_DLL_CONFIG1_P0_1, MCA_DDRPHY_DP16_DLL_CONFIG1_P0_2, MCA_DDRPHY_DP16_DLL_CONFIG1_P0_3, MCA_DDRPHY_DP16_DLL_CONFIG1_P0_4, }; // Definition of the DP16 DLL Control registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Control Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_CNTRL_REG = { { MCA_DDRPHY_DP16_DLL_CNTL0_P0_0, MCA_DDRPHY_DP16_DLL_CNTL1_P0_0 }, { MCA_DDRPHY_DP16_DLL_CNTL0_P0_1, MCA_DDRPHY_DP16_DLL_CNTL1_P0_1 }, { MCA_DDRPHY_DP16_DLL_CNTL0_P0_2, MCA_DDRPHY_DP16_DLL_CNTL1_P0_2 }, { MCA_DDRPHY_DP16_DLL_CNTL0_P0_3, MCA_DDRPHY_DP16_DLL_CNTL1_P0_3 }, { MCA_DDRPHY_DP16_DLL_CNTL0_P0_4, MCA_DDRPHY_DP16_DLL_CNTL1_P0_4 }, }; // Definition of the DP16 DLL DAC Lower registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_DAC_LOWER_REG = { { MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_0, MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_0 }, { MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_1, MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_1 }, { MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_2, MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_2 }, { MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_3, MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_3 }, { MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_4, MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_4 }, }; // Definition of the DP16 DLL DAC Upper registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_DAC_UPPER_REG = { { MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_0, MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_0 }, { MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_1, MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_1 }, { MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_2, MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_2 }, { MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_3, MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_3 }, { MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_4, MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_4 }, }; // Definition of the DP16 DLL Slave Lower registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_SLAVE_LOWER_REG = { { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER0_P0_0, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER1_P0_0 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER0_P0_1, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER1_P0_1 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER0_P0_2, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER1_P0_2 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER0_P0_3, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER1_P0_3 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER0_P0_4, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_LOWER1_P0_4 }, }; // Definition of the DP16 DLL Slave Upper registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_SLAVE_UPPER_REG = { { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER0_P0_0, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER1_P0_0 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER0_P0_1, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER1_P0_1 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER0_P0_2, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER1_P0_2 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER0_P0_3, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER1_P0_3 }, { MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER0_P0_4, MCA_DDRPHY_DP16_DLL_SLAVE_VREG_UPPER1_P0_4 }, }; // Definition of the DP16 DLL SW Control registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_SW_CNTRL_REG = { { MCA_DDRPHY_DP16_DLL_SW_CONTROL0_P0_0, MCA_DDRPHY_DP16_DLL_SW_CONTROL1_P0_0 }, { MCA_DDRPHY_DP16_DLL_SW_CONTROL0_P0_1, MCA_DDRPHY_DP16_DLL_SW_CONTROL1_P0_1 }, { MCA_DDRPHY_DP16_DLL_SW_CONTROL0_P0_2, MCA_DDRPHY_DP16_DLL_SW_CONTROL1_P0_2 }, { MCA_DDRPHY_DP16_DLL_SW_CONTROL0_P0_3, MCA_DDRPHY_DP16_DLL_SW_CONTROL1_P0_3 }, { MCA_DDRPHY_DP16_DLL_SW_CONTROL0_P0_4, MCA_DDRPHY_DP16_DLL_SW_CONTROL1_P0_4 }, }; // Definition of the DP16 DLL VREG Coarse registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_VREG_COARSE_REG = { { MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0, MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_0 }, { MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_1, MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_1 }, { MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_2, MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_2 }, { MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_3, MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_3 }, { MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_4, MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_4 }, }; // Definition of the DP16 DLL VREG Control registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_VREG_CNTRL_REG = { { MCA_DDRPHY_DP16_DLL_VREG_CONTROL0_P0_0, MCA_DDRPHY_DP16_DLL_VREG_CONTROL1_P0_0 }, { MCA_DDRPHY_DP16_DLL_VREG_CONTROL0_P0_1, MCA_DDRPHY_DP16_DLL_VREG_CONTROL1_P0_1 }, { MCA_DDRPHY_DP16_DLL_VREG_CONTROL0_P0_2, MCA_DDRPHY_DP16_DLL_VREG_CONTROL1_P0_2 }, { MCA_DDRPHY_DP16_DLL_VREG_CONTROL0_P0_3, MCA_DDRPHY_DP16_DLL_VREG_CONTROL1_P0_3 }, { MCA_DDRPHY_DP16_DLL_VREG_CONTROL0_P0_4, MCA_DDRPHY_DP16_DLL_VREG_CONTROL1_P0_4 }, }; // Definition of the DP16 DLL Extra registers // DP16 DLL registers all come in pairs - DLL per 8 bits // 5 DLL per MCA gives us 10 DLL Config Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::DLL_EXTRA_REG = { { MCA_DDRPHY_DP16_DLL_EXTRA0_P0_0, MCA_DDRPHY_DP16_DLL_EXTRA1_P0_0 }, { MCA_DDRPHY_DP16_DLL_EXTRA0_P0_1, MCA_DDRPHY_DP16_DLL_EXTRA1_P0_1 }, { MCA_DDRPHY_DP16_DLL_EXTRA0_P0_2, MCA_DDRPHY_DP16_DLL_EXTRA1_P0_2 }, { MCA_DDRPHY_DP16_DLL_EXTRA0_P0_3, MCA_DDRPHY_DP16_DLL_EXTRA1_P0_3 }, { MCA_DDRPHY_DP16_DLL_EXTRA0_P0_4, MCA_DDRPHY_DP16_DLL_EXTRA1_P0_4 }, }; // Definition of the DP16 Data Bit Dir1 registers // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< uint64_t > dp16Traits::DATA_BIT_DIR1_REG { MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_0, MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_1, MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_2, MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_3, MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_4, }; // Definition of the DP16 AC Boost Control registers // DP16 AC Boost registers all come in pairs - one per 8 bits // 5 DP16 per MCA gives us 10 Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::AC_BOOST_CNTRL_REG = { { MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE0_P0_0, MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE1_P0_0 }, { MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE0_P0_1, MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE1_P0_1 }, { MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE0_P0_2, MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE1_P0_2 }, { MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE0_P0_3, MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE1_P0_3 }, { MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE0_P0_4, MCA_DDRPHY_DP16_ACBOOST_CTL_BYTE1_P0_4 }, }; // Definition of the DP16 CTLE Control registers // DP16 CTLE Control registers all come in pairs - one per 8 bits // 5 DP16 per MCA gives us 10 Registers. // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< std::pair > dp16Traits::CTLE_CNTRL_REG = { { MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_0, MCA_DDRPHY_DP16_CTLE_CTL_BYTE1_P0_0 }, { MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_1, MCA_DDRPHY_DP16_CTLE_CTL_BYTE1_P0_1 }, { MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_2, MCA_DDRPHY_DP16_CTLE_CTL_BYTE1_P0_2 }, { MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_3, MCA_DDRPHY_DP16_CTLE_CTL_BYTE1_P0_3 }, { MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_4, MCA_DDRPHY_DP16_CTLE_CTL_BYTE1_P0_4 }, }; // Definition of the IO TX FET slice registers // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< uint64_t > dp16Traits::IO_TX_FET_SLICE_REG { MCA_DDRPHY_DP16_IO_TX_FET_SLICE_P0_0, MCA_DDRPHY_DP16_IO_TX_FET_SLICE_P0_1, MCA_DDRPHY_DP16_IO_TX_FET_SLICE_P0_2, MCA_DDRPHY_DP16_IO_TX_FET_SLICE_P0_3, MCA_DDRPHY_DP16_IO_TX_FET_SLICE_P0_4, }; // Definition of the IO TX PFET slice registers // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< uint64_t > dp16Traits::IO_TX_PFET_TERM_REG { MCA_DDRPHY_DP16_IO_TX_PFET_TERM_P0_0, MCA_DDRPHY_DP16_IO_TX_PFET_TERM_P0_1, MCA_DDRPHY_DP16_IO_TX_PFET_TERM_P0_2, MCA_DDRPHY_DP16_IO_TX_PFET_TERM_P0_3, MCA_DDRPHY_DP16_IO_TX_PFET_TERM_P0_4, }; // Receiver configuration for the DP16. const std::vector< uint64_t > dp16Traits::DP16_RX_REGS { { MCA_DDRPHY_DP16_RX_PEAK_AMP_P0_0, MCA_DDRPHY_DP16_RX_PEAK_AMP_P0_1, MCA_DDRPHY_DP16_RX_PEAK_AMP_P0_2, MCA_DDRPHY_DP16_RX_PEAK_AMP_P0_3, MCA_DDRPHY_DP16_RX_PEAK_AMP_P0_4, }, }; // Definition of the DD1 DP16 RD_VREF Control registers // Note: For DD2 if we use the DD2_PERBIT_RDVREF_DISABLE, then these registers are still valid // DP16 RD_VREF Control registers all come in pairs - one per 8 bits // 5 DP16 per MCA gives us 10 Registers. const std::vector< uint64_t > dp16Traits::DD1_RD_VREF_CNTRL_REG = { { MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_0, MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_0 , MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_1, MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_1 , MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_2, MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_2 , MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_3, MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_3 , MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_4, MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_4 }, }; // Definition of the DD2 DP16 RD_VREF Control registers // Note: DO NOT use this for DD1 as it will lead to a runtime scom access error // DD2 DP16 RD_VREF Control registers all come in one register per pair of bits // One register per two bits DP16 per MCA gives us 36 Registers. // TK update the below constants with the DD2 register fixes const std::vector< uint64_t > dp16Traits::DD2_RD_VREF_CNTRL_REG = { { // DP0 MCA_DDRPHY_DP16_RD_VREF_DAC_0_P0_0, MCA_DDRPHY_DP16_RD_VREF_DAC_1_P0_0, MCA_DDRPHY_DP16_RD_VREF_DAC_2_P0_0, MCA_DDRPHY_DP16_RD_VREF_DAC_3_P0_0, MCA_DDRPHY_DP16_RD_VREF_DAC_4_P0_0, MCA_DDRPHY_DP16_RD_VREF_DAC_5_P0_0, MCA_DDRPHY_DP16_RD_VREF_DAC_6_P0_0, MCA_DDRPHY_DP16_RD_VREF_DAC_7_P0_0, // DP1 MCA_DDRPHY_DP16_RD_VREF_DAC_0_P0_1, MCA_DDRPHY_DP16_RD_VREF_DAC_1_P0_1, MCA_DDRPHY_DP16_RD_VREF_DAC_2_P0_1, MCA_DDRPHY_DP16_RD_VREF_DAC_3_P0_1, MCA_DDRPHY_DP16_RD_VREF_DAC_4_P0_1, MCA_DDRPHY_DP16_RD_VREF_DAC_5_P0_1, MCA_DDRPHY_DP16_RD_VREF_DAC_6_P0_1, MCA_DDRPHY_DP16_RD_VREF_DAC_7_P0_1, // DP2 MCA_DDRPHY_DP16_RD_VREF_DAC_0_P0_2, MCA_DDRPHY_DP16_RD_VREF_DAC_1_P0_2, MCA_DDRPHY_DP16_RD_VREF_DAC_2_P0_2, MCA_DDRPHY_DP16_RD_VREF_DAC_3_P0_2, MCA_DDRPHY_DP16_RD_VREF_DAC_4_P0_2, MCA_DDRPHY_DP16_RD_VREF_DAC_5_P0_2, MCA_DDRPHY_DP16_RD_VREF_DAC_6_P0_2, MCA_DDRPHY_DP16_RD_VREF_DAC_7_P0_2, // DP3 MCA_DDRPHY_DP16_RD_VREF_DAC_0_P0_3, MCA_DDRPHY_DP16_RD_VREF_DAC_1_P0_3, MCA_DDRPHY_DP16_RD_VREF_DAC_2_P0_3, MCA_DDRPHY_DP16_RD_VREF_DAC_3_P0_3, MCA_DDRPHY_DP16_RD_VREF_DAC_4_P0_3, MCA_DDRPHY_DP16_RD_VREF_DAC_5_P0_3, MCA_DDRPHY_DP16_RD_VREF_DAC_6_P0_3, MCA_DDRPHY_DP16_RD_VREF_DAC_7_P0_3, // DP4 - we only have 8 bits here, so 4 registers MCA_DDRPHY_DP16_RD_VREF_DAC_0_P0_4, MCA_DDRPHY_DP16_RD_VREF_DAC_1_P0_4, MCA_DDRPHY_DP16_RD_VREF_DAC_2_P0_4, MCA_DDRPHY_DP16_RD_VREF_DAC_3_P0_4, }, }; // Definition of the DP16 DRIFT_LIMITS registers const std::vector< uint64_t > dp16Traits::DRIFT_LIMITS_REG = { MCA_DDRPHY_DP16_DRIFT_LIMITS_P0_0, MCA_DDRPHY_DP16_DRIFT_LIMITS_P0_1, MCA_DDRPHY_DP16_DRIFT_LIMITS_P0_2, MCA_DDRPHY_DP16_DRIFT_LIMITS_P0_3, MCA_DDRPHY_DP16_DRIFT_LIMITS_P0_4, }; // Definition of the DP16 RD_VREF Calibration enable registers const std::vector< uint64_t > dp16Traits::RD_VREF_CAL_ENABLE_REG = { MCA_DDRPHY_DP16_RD_VREF_CAL_EN_P0_0, MCA_DDRPHY_DP16_RD_VREF_CAL_EN_P0_1, MCA_DDRPHY_DP16_RD_VREF_CAL_EN_P0_2, MCA_DDRPHY_DP16_RD_VREF_CAL_EN_P0_3, MCA_DDRPHY_DP16_RD_VREF_CAL_EN_P0_4, }; // Definition of the DP16 RD_VREF Calibration enable registers const std::vector< uint64_t > dp16Traits::RD_VREF_CAL_ERROR_REG = { MCA_DDRPHY_DP16_RD_VREF_CAL_ERROR_P0_0, MCA_DDRPHY_DP16_RD_VREF_CAL_ERROR_P0_1, MCA_DDRPHY_DP16_RD_VREF_CAL_ERROR_P0_2, MCA_DDRPHY_DP16_RD_VREF_CAL_ERROR_P0_3, MCA_DDRPHY_DP16_RD_VREF_CAL_ERROR_P0_4, }; // Definition of the DP16 Phase Rotator Static Offset registers // All-caps (as opposed to the others) as it's really in the dp16Traits class which is all caps ) const std::vector< uint64_t > dp16Traits::PR_STATIC_OFFSET_REG { MCA_DDRPHY_DP16_WRCLK_PR_P0_0, MCA_DDRPHY_DP16_WRCLK_PR_P0_1, MCA_DDRPHY_DP16_WRCLK_PR_P0_2, MCA_DDRPHY_DP16_WRCLK_PR_P0_3, MCA_DDRPHY_DP16_WRCLK_PR_P0_4, }; ////////////////////////////////////// // Defines all WR VREF registers // ////////////////////////////////////// // Definition of the WR VREF config0 register const std::vector< uint64_t > dp16Traits::WR_VREF_CONFIG0_REG = { MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_0, MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_1, MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_2, MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_3, MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_4, }; // Definition of the WR VREF config1 register const std::vector< uint64_t > dp16Traits::WR_VREF_CONFIG1_REG = { MCA_DDRPHY_DP16_WR_VREF_CONFIG1_P0_0, MCA_DDRPHY_DP16_WR_VREF_CONFIG1_P0_1, MCA_DDRPHY_DP16_WR_VREF_CONFIG1_P0_2, MCA_DDRPHY_DP16_WR_VREF_CONFIG1_P0_3, MCA_DDRPHY_DP16_WR_VREF_CONFIG1_P0_4, }; // Definition of the WR VREF status0 register const std::vector< uint64_t > dp16Traits::WR_VREF_STATUS0_REG = { MCA_DDRPHY_DP16_WR_VREF_STATUS0_P0_0, MCA_DDRPHY_DP16_WR_VREF_STATUS0_P0_1, MCA_DDRPHY_DP16_WR_VREF_STATUS0_P0_2, MCA_DDRPHY_DP16_WR_VREF_STATUS0_P0_3, MCA_DDRPHY_DP16_WR_VREF_STATUS0_P0_4, }; // Definition of the WR VREF status1 register const std::vector< uint64_t > dp16Traits::WR_VREF_STATUS1_REG = { MCA_DDRPHY_DP16_WR_VREF_STATUS1_P0_0, MCA_DDRPHY_DP16_WR_VREF_STATUS1_P0_1, MCA_DDRPHY_DP16_WR_VREF_STATUS1_P0_2, MCA_DDRPHY_DP16_WR_VREF_STATUS1_P0_3, MCA_DDRPHY_DP16_WR_VREF_STATUS1_P0_4, }; // Definition of the error mask registers element is DP16 number, first is mask 0 second is mask 1 const std::vector< std::pair > dp16Traits::WR_VREF_ERROR_MASK_REG = { { MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK0_P0_0, MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK1_P0_0 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK0_P0_1, MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK1_P0_1 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK0_P0_2, MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK1_P0_2 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK0_P0_3, MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK1_P0_3 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK0_P0_4, MCA_DDRPHY_DP16_WR_VREF_ERROR_MASK1_P0_4 }, }; // Definition of the error registers element is DP16 number, first is error 0 second is error 1 const std::vector< std::pair > dp16Traits::WR_VREF_ERROR_REG = { { MCA_DDRPHY_DP16_WR_VREF_ERROR0_P0_0, MCA_DDRPHY_DP16_WR_VREF_ERROR1_P0_0 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR0_P0_1, MCA_DDRPHY_DP16_WR_VREF_ERROR1_P0_1 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR0_P0_2, MCA_DDRPHY_DP16_WR_VREF_ERROR1_P0_2 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR0_P0_3, MCA_DDRPHY_DP16_WR_VREF_ERROR1_P0_3 }, { MCA_DDRPHY_DP16_WR_VREF_ERROR0_P0_4, MCA_DDRPHY_DP16_WR_VREF_ERROR1_P0_4 }, }; // Definition of the VREF value registers for RP0 element is DP16 number, first is value 0 second is value 1 const std::vector< std::pair > dp16Traits::WR_VREF_VALUE_RP0_REG = { { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR0_P0_0 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR0_P0_1 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR0_P0_2 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR0_P0_3 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR0_P0_4 }, }; // Definition of the VREF value registers for RP1 element is DP16 number, first is value 0 second is value 1 const std::vector< std::pair > dp16Traits::WR_VREF_VALUE_RP1_REG = { { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR1_P0_0 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR1_P0_1 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR1_P0_2 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR1_P0_3 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR1_P0_4 }, }; // Definition of the VREF value registers for RP2 element is DP16 number, first is value 0 second is value 1 const std::vector< std::pair > dp16Traits::WR_VREF_VALUE_RP2_REG = { { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR2_P0_0 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR2_P0_1 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR2_P0_2 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR2_P0_3 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR2_P0_4 }, }; // Definition of the VREF value registers for RP3 element is DP16 number, first is value 0 second is value 1 const std::vector< std::pair > dp16Traits::WR_VREF_VALUE_RP3_REG = { { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR3_P0_0 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR3_P0_1 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR3_P0_2 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR3_P0_3 }, { MCA_DDRPHY_DP16_WR_VREF_VALUE0_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_WR_VREF_VALUE1_RANK_PAIR3_P0_4 }, }; // Definition of the windage value registers per MCA. These are per rank pair, per DP16 and there are 2. const std::vector dp16Traits::READ_DELAY_OFFSET_REG = { MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET0_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY_OFFSET1_RANK_PAIR3_P0_4, }; // Definition of the DISABLE registers, per dp per rank pair const std::vector< std::vector> > dp16Traits::BIT_DISABLE_REG = { { { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP0_P0_0, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP0_P0_0 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP0_P0_1, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP0_P0_1 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP0_P0_2, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP0_P0_2 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP0_P0_3, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP0_P0_3 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP0_P0_4, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP0_P0_4 }, }, { { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP1_P0_0, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP1_P0_0 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP1_P0_1, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP1_P0_1 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP1_P0_2, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP1_P0_2 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP1_P0_3, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP1_P0_3 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP1_P0_4, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP1_P0_4 }, }, { { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP2_P0_0, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP2_P0_0 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP2_P0_1, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP2_P0_1 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP2_P0_2, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP2_P0_2 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP2_P0_3, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP2_P0_3 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP2_P0_4, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP2_P0_4 }, }, { { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP3_P0_0, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP3_P0_0 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP3_P0_1, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP3_P0_1 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP3_P0_2, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP3_P0_2 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP3_P0_3, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP3_P0_3 }, { MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP3_P0_4, MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP3_P0_4 }, }, }; // we need these declarations here in order for the linker to see the definitions constexpr const uint64_t dp16Traits::GATE_DELAY_BIT_POS[]; constexpr const uint64_t dp16Traits::BLUE_WATERFALL_BIT_POS[]; const std::vector< uint64_t > dp16Traits::DATA_BIT_ENABLE0_REG = { MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_0, MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_1, MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_2, MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_3, MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_4, }; const std::vector< uint64_t > dp16Traits::DATA_BIT_ENABLE1_REG = { MCA_0_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_0, MCA_0_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_1, MCA_0_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_2, MCA_0_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_3, MCA_0_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_4, }; const std::vector< uint64_t > dp16Traits::RD_DIA_CONFIG5_REG = { MCA_DDRPHY_DP16_RD_DIA_CONFIG5_P0_0, MCA_DDRPHY_DP16_RD_DIA_CONFIG5_P0_1, MCA_DDRPHY_DP16_RD_DIA_CONFIG5_P0_2, MCA_DDRPHY_DP16_RD_DIA_CONFIG5_P0_3, MCA_DDRPHY_DP16_RD_DIA_CONFIG5_P0_4, }; const std::vector< uint64_t > dp16Traits::RD_LVL_STATUS0_REG = { MCA_DDRPHY_DP16_RD_LVL_STATUS0_P0_0, MCA_DDRPHY_DP16_RD_LVL_STATUS0_P0_1, MCA_DDRPHY_DP16_RD_LVL_STATUS0_P0_2, MCA_DDRPHY_DP16_RD_LVL_STATUS0_P0_3, MCA_DDRPHY_DP16_RD_LVL_STATUS0_P0_4, }; const std::vector< uint64_t > dp16Traits::RD_LVL_STATUS2_REG = { MCA_DDRPHY_DP16_RD_LVL_STATUS2_P0_0, MCA_DDRPHY_DP16_RD_LVL_STATUS2_P0_1, MCA_DDRPHY_DP16_RD_LVL_STATUS2_P0_2, MCA_DDRPHY_DP16_RD_LVL_STATUS2_P0_3, MCA_DDRPHY_DP16_RD_LVL_STATUS2_P0_4, }; const std::vector< uint64_t > dp16Traits::RD_STATUS0_REG = { MCA_DDRPHY_DP16_RD_STATUS0_P0_0, MCA_DDRPHY_DP16_RD_STATUS0_P0_1, MCA_DDRPHY_DP16_RD_STATUS0_P0_2, MCA_DDRPHY_DP16_RD_STATUS0_P0_3, MCA_DDRPHY_DP16_RD_STATUS0_P0_4, }; const std::vector< uint64_t > dp16Traits::WR_ERROR0_REG = { MCA_DDRPHY_DP16_WR_ERROR0_P0_0, MCA_DDRPHY_DP16_WR_ERROR0_P0_1, MCA_DDRPHY_DP16_WR_ERROR0_P0_2, MCA_DDRPHY_DP16_WR_ERROR0_P0_3, MCA_DDRPHY_DP16_WR_ERROR0_P0_4, }; const std::vector< uint64_t > dp16Traits::DATA_BIT_ENABLE1 = { MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_0, MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_1, MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_2, MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_3, MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_4, }; // Definition of the READ_DELAY registers, per rank pair const std::vector< std::vector > dp16Traits::READ_DELAY_REG = { { MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_4, }, { MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_4, }, { MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_4, }, { MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_4, }, }; // Definition of the READ_EYE_SIZE registers, per rank pair const std::vector< std::vector > dp16Traits::READ_EYE_SIZE_REG = { { MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR0_P0_4, }, { MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR1_P0_4, }, { MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR2_P0_4, }, { MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_READ_EYE_SIZE0_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE1_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE2_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE3_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE4_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE5_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE6_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE7_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE8_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE9_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE10_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_READ_EYE_SIZE11_RANK_PAIR3_P0_4, }, }; // Definition of the RDCLK delay registers, per rank pair const std::vector< std::vector > dp16Traits::RDCLK_REG = { { MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_4, }, { MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_4, }, { MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_4, }, { MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_4, }, }; const std::vector< std::vector > dp16Traits::WR_DQ_DELAY_REG = { // RP0 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_4, }, // RP1 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_4, }, // RP2 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_4, }, // RP3 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_4, }, }; const std::vector> dp16Traits::WR_DELAY_REG { // RP0 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_16_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_18_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_20_RP0_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_22_RP0_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_16_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_18_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_20_RP0_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_22_RP0_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_16_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_18_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_20_RP0_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_22_RP0_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_16_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_18_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_20_RP0_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_22_RP0_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_8_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_9_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_10_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_11_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_12_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_13_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_14_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_15_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_16_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_18_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_20_RP0_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_22_RP0_REG_P0_4, }, // RP1 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_16_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_18_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_20_RP1_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_22_RP1_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_16_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_18_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_20_RP1_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_22_RP1_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_16_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_18_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_20_RP1_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_22_RP1_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_16_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_18_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_20_RP1_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_22_RP1_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_8_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_9_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_10_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_11_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_12_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_13_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_14_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_15_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_16_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_18_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_20_RP1_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_22_RP1_REG_P0_4, }, // RP2 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_16_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_18_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_20_RP2_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_22_RP2_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_16_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_18_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_20_RP2_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_22_RP2_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_16_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_18_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_20_RP2_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_22_RP2_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_16_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_18_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_20_RP2_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_22_RP2_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_8_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_9_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_10_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_11_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_12_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_13_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_14_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_15_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_16_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_18_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_20_RP2_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_22_RP2_REG_P0_4, }, // RP3 { // DP0 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_16_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_18_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_20_RP3_REG_P0_0, MCA_DP16_WR_DELAY_VALUE_22_RP3_REG_P0_0, // DP1 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_16_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_18_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_20_RP3_REG_P0_1, MCA_DP16_WR_DELAY_VALUE_22_RP3_REG_P0_1, // DP2 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_16_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_18_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_20_RP3_REG_P0_2, MCA_DP16_WR_DELAY_VALUE_22_RP3_REG_P0_2, // DP3 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_16_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_18_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_20_RP3_REG_P0_3, MCA_DP16_WR_DELAY_VALUE_22_RP3_REG_P0_3, // DP4 MCA_DP16_WR_DELAY_VALUE_0_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_1_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_2_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_3_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_4_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_5_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_6_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_7_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_8_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_9_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_10_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_11_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_12_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_13_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_14_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_15_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_16_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_18_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_20_RP3_REG_P0_4, MCA_DP16_WR_DELAY_VALUE_22_RP3_REG_P0_4, }, }; /// /// @brief Given a RD_VREF value, create a PHY 'standard' bit field for that percentage. /// @tparam T fapi2 Target Type - derived /// @tparam TT traits type defaults to dp16Traits /// @param[in] i_target the fapi2 target of the port /// @param[in] i_vref the value from the mss_vpd_mt_vref_mc_rd attribute for your target /// @param[out] o_bitfield value of DAC bitfield for given VREF setting /// @return FAPI2_RC_SUCCESS iff ok /// template< fapi2::TargetType T, typename TT = dp16Traits > fapi2::ReturnCode rd_vref_bitfield_helper( const fapi2::Target& i_target, const uint32_t i_vref, uint64_t& o_bitfield ) { FAPI_INF("rd_vref_bitfield_helper for target %s seeing vref percentage: %d", c_str(i_target), i_vref); // Zero is a special "no-op" value, which we can get if the VPD attributes aren't // set up. This can happen for an MCA with no functional DIMM present. if (i_vref == 0) { o_bitfield = 0; return fapi2::FAPI2_RC_SUCCESS; } else if ( (i_vref > TT::MAX_RD_VREF) || (i_vref < TT::MIN_RD_VREF) ) { // Set up some constexprs to work around linker error when pushing traits values into ffdc constexpr uint64_t l_max = TT::MAX_RD_VREF; constexpr uint64_t l_min = TT::MIN_RD_VREF; FAPI_ASSERT( false, fapi2::MSS_INVALID_VPD_MT_VREF_MC_RD() .set_VALUE(i_vref) .set_VREF_MAX(l_max) .set_VREF_MIN(l_min) .set_MCS_TARGET(mss::find_target(i_target)), "Target %s VPD_MT_VREF_MC_RD percentage out of bounds (%d - %d): %d", c_str(i_target), l_max, l_min, i_vref ); } else { // Per R. King, VREF equation is: // Vref = 1.1025 for DAC < 15 // Vref = 1.2 - .0065 * DAC for DAC >= 15 // where DAC is simply the 7-bit field value // note values multiplied by 10 to make everything an integer o_bitfield = TT::RD_VREF_DVDD * (100000 - i_vref) / TT::RD_VREF_DAC_STEP; return fapi2::FAPI2_RC_SUCCESS; } fapi_try_exit: return fapi2::current_err; } namespace dp16 { typedef std::pair< uint64_t, uint64_t > register_data_pair; typedef std::vector< register_data_pair > register_data_vector; // Why the tables you ask? Because these bits need to be controlled // depending on phy, packaging, board swizzling and it's just eaiser // to see the bits like this than in a more compact algorithmic arrangement. // Systems without Spare Bytes (or with deconfigured spares) static const register_data_vector data_bit_enable_no_spare[] = { // DHPY01 { {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_0, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_1, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_2, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_3, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_4, 0xFF00}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_0, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_1, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_2, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_3, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_4, 0x0}, }, }; // Rank Pair will be added to the register address before writing static const register_data_vector wrclk_enable_no_spare_x4[] = { { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0x8400}, } }; static const register_data_vector wrclk_enable_no_spare_x8[] = { // Port 0 settings { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0x0C00}, }, // Port 1 settings { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0xC0C0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0x0C00}, }, // Port 2 settings { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0xC300}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0xC0C0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0x0C00}, }, // Port 3 settings { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0xC300}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0xC000}, }, // Port 4 settings // This is flipped w/the settings from the rosetta stone // due to the port 4 & 6 view from the PHY { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0xC000}, }, // Port 5 settings // This is flipped w/the settings from the rosetta stone // due to the port 5 & 7 view from the PHY { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0xC300}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0xC000}, }, // Port 6 settings // This is flipped w/the settings from the rosetta stone // due to the port 4 & 6 view from the PHY { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0xC0C0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0x0C00}, }, // Port 7 settings // This is flipped w/the settings from the rosetta stone // due to the port 5 & 7 view from the PHY { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x0F00}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0xC000}, }, }; // Some compile constants to define expected sizes constexpr size_t CLK_ENABLE_X4_SIZE = 1; constexpr size_t CLK_ENABLE_X8_SIZE = 8; // Rank Pair will be added to the register address before writing static const register_data_vector rdclk_enable_no_spare_x4[] = { { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0x8400}, }, }; static const register_data_vector rdclk_enable_no_spare_x8[] = { // Port 0 settings { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0x0C00}, }, // Port 1 settings { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0xC0C0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0x0C00}, }, // Port 2 settings { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0xC300}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0xC0C0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0x0C00}, }, // Port 3 settings { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0xC300}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0xC000}, }, // Port 4 settings // This is flipped w/the settings from the rosetta stone // due to the port 4 & 6 view from the PHY { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0xC000}, }, // Port 5 settings // This is flipped w/the settings from the rosetta stone // due to the port 5 & 7 view from the PHY { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0xC300}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0xC000}, }, // Port 6 settings // This is flipped w/the settings from the rosetta stone // due to the port 4 & 6 view from the PHY { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0xC0C0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0x0C00}, }, // Port 7 settings // This is flipped w/the settings from the rosetta stone // due to the port 5 & 7 view from the PHY { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0x0CC0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0xC0C0}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x0F00}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0xC300}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0xC000}, }, }; // Systems With Spare Bytes Enabled static const register_data_vector data_bit_enable_spare[] = { // DHPY01 { {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_0, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_1, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_2, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_3, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE0_P0_4, 0xFFFF}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_0, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_1, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_2, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_3, 0x0}, {MCA_DDRPHY_DP16_DATA_BIT_ENABLE1_P0_4, 0x0}, }, }; static const register_data_vector wrclk_enable_spare_x4[] = { { {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_0, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_1, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_2, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_3, 0x8640}, {MCA_DDRPHY_DP16_WRCLK_EN_RP0_P0_4, 0x8640}, }, }; static const register_data_vector rdclk_enable_spare_x4[] = { { {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_0, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_1, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_2, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_3, 0x8640}, {MCA_DDRPHY_DP16_READ_CLOCK_RANK_PAIR0_P0_4, 0x8640}, }, }; /// /// @brief Save settings for a given rank pair /// @return FAPI2_RC_SUCCES iff ok /// template<> fapi2::ReturnCode rd_ctr_settings::save() { typedef mss::dp16Traits TT; // Read each register and save in private variables FAPI_TRY( mss::scom_suckah(iv_target, TT::READ_DELAY_REG[iv_rp], iv_read_delay) ); FAPI_TRY( mss::scom_suckah(iv_target, TT::RDCLK_REG[iv_rp], iv_rdclk_delay) ); FAPI_TRY( mss::scom_suckah(iv_target, TT::BIT_DISABLE_REG[iv_rp], iv_dq_disable) ); FAPI_TRY( mss::scom_suckah(iv_target, TT::READ_EYE_SIZE_REG[iv_rp], iv_read_eye_size) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Restore settings for a given rank pair /// @return FAPI2_RC_SUCCES iff ok /// template<> fapi2::ReturnCode rd_ctr_settings::restore() const { typedef mss::dp16Traits TT; std::vector> l_post_training_settings; std::vector, fapi2::buffer > > l_post_training_disables; // Log values before restoring them FAPI_TRY( mss::scom_suckah(iv_target, TT::READ_DELAY_REG[iv_rp], l_post_training_settings) ); if( l_post_training_settings.size() != iv_read_delay.size() ) { // Asserting out instead of collecting FFDC since this is a // programming bug that shouldn't occur. FAPI_ERR("Number of READ_DELAY registers != number of stored registers: %d != %d", l_post_training_settings.size(), iv_read_delay.size()); fapi2::Assert(false); } // TK Should these messages be written in FFDC so we can see them in FW? for (uint64_t l_idx = 0; l_idx < l_post_training_settings.size(); ++l_idx) { FAPI_INF("%s restoring value of READ_DELAY scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::READ_DELAY_REG[iv_rp][l_idx], l_post_training_settings[l_idx], iv_read_delay[l_idx]); } FAPI_TRY( mss::scom_suckah(iv_target, TT::RDCLK_REG[iv_rp], l_post_training_settings) ); if( l_post_training_settings.size() != iv_rdclk_delay.size() ) { // Asserting out instead of collecting FFDC since this is a // programming bug that shouldn't occur. FAPI_ERR("Number of RDCLK registers != number of stored registers: %d != %d", l_post_training_settings.size(), iv_rdclk_delay.size()); fapi2::Assert(false); } for (uint64_t l_idx = 0; l_idx < l_post_training_settings.size(); ++l_idx) { FAPI_INF("%s restoring value of RDCLK scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::RDCLK_REG[iv_rp][l_idx], l_post_training_settings[l_idx], iv_rdclk_delay[l_idx]); } FAPI_TRY( mss::scom_suckah(iv_target, TT::BIT_DISABLE_REG[iv_rp], l_post_training_disables) ); if( l_post_training_disables.size() != iv_dq_disable.size() ) { // Asserting out instead of collecting FFDC since this is a // programming bug that shouldn't occur. FAPI_ERR("Number of BIT_DISABLE registers != number of stored registers: %d != %d", l_post_training_disables.size(), iv_dq_disable.size()); fapi2::Assert(false); } for (uint64_t l_idx = 0; l_idx < l_post_training_disables.size(); ++l_idx) { FAPI_INF("%s restoring value of DATA_DISABLE scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::BIT_DISABLE_REG[iv_rp][l_idx].first, l_post_training_disables[l_idx].first, iv_dq_disable[l_idx].first); FAPI_INF("%s restoring value of DATA_DISABLE scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::BIT_DISABLE_REG[iv_rp][l_idx].second, l_post_training_disables[l_idx].second, iv_dq_disable[l_idx].second); } FAPI_TRY( mss::scom_suckah(iv_target, TT::READ_EYE_SIZE_REG[iv_rp], l_post_training_settings) ); if( l_post_training_settings.size() != iv_read_eye_size.size() ) { // Asserting out instead of collecting FFDC since this is a // programming bug that shouldn't occur. FAPI_ERR("Number of READ_EYE_SIZE registers != number of stored registers: %d != %d", l_post_training_settings.size(), iv_read_eye_size.size()); fapi2::Assert(false); } for (uint64_t l_idx = 0; l_idx < l_post_training_settings.size(); ++l_idx) { FAPI_INF("%s restoring value of READ_EYE_SIZE scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::READ_EYE_SIZE_REG[iv_rp][l_idx], l_post_training_settings[l_idx], iv_read_eye_size[l_idx]); } // Write each register back from private variables FAPI_TRY( mss::scom_blastah(iv_target, TT::READ_DELAY_REG[iv_rp], iv_read_delay) ); FAPI_TRY( mss::scom_blastah(iv_target, TT::RDCLK_REG[iv_rp], iv_rdclk_delay) ); FAPI_TRY( mss::scom_blastah(iv_target, TT::BIT_DISABLE_REG[iv_rp], iv_dq_disable) ); FAPI_TRY( mss::scom_blastah(iv_target, TT::READ_EYE_SIZE_REG[iv_rp], iv_read_eye_size) ); // Run the record_bad_bits function to restore the BAD_DQ_BITMAP attribute using the pre-training disable bits FAPI_TRY( mss::dp16::record_bad_bits(iv_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Save settings for a given rank pair /// @return FAPI2_RC_SUCCES iff ok /// template<> fapi2::ReturnCode wr_ctr_settings::save() { typedef mss::dp16Traits TT; // Read each register and save in private variables FAPI_TRY( mss::scom_suckah(iv_target, TT::WR_DELAY_REG[iv_rp], iv_write_delay) ); FAPI_TRY( mss::scom_suckah(iv_target, TT::BIT_DISABLE_REG[iv_rp], iv_dq_disable) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Restore settings for a given rank pair /// @return FAPI2_RC_SUCCES iff ok /// template<> fapi2::ReturnCode wr_ctr_settings::restore() const { typedef mss::dp16Traits TT; std::vector> l_post_training_settings; std::vector, fapi2::buffer > > l_post_training_disables; // Log values before restoring them FAPI_TRY( mss::scom_suckah(iv_target, TT::WR_DELAY_REG[iv_rp], l_post_training_settings) ); if( l_post_training_settings.size() != iv_write_delay.size() ) { // Asserting out instead of collecting FFDC since this is a // programming bug that shouldn't occur. FAPI_ERR("Number of WRITE_DELAY registers != number of stored registers: %d != %d", l_post_training_settings.size(), iv_write_delay.size()); fapi2::Assert(false); } // TK Should these messages be written in FFDC so we can see them in FW? for (uint64_t l_idx = 0; l_idx < l_post_training_settings.size(); ++l_idx) { FAPI_INF("%s restoring value of WRITE_DELAY scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::WR_DELAY_REG[iv_rp][l_idx], l_post_training_settings[l_idx], iv_write_delay[l_idx]); } FAPI_TRY( mss::scom_suckah(iv_target, TT::BIT_DISABLE_REG[iv_rp], l_post_training_disables) ); if( l_post_training_disables.size() != iv_dq_disable.size() ) { // Asserting out instead of collecting FFDC since this is a // programming bug that shouldn't occur. FAPI_ERR("Number of BIT_DISABLE registers != number of stored registers: %d != %d", l_post_training_disables.size(), iv_dq_disable.size()); fapi2::Assert(false); } for (uint64_t l_idx = 0; l_idx < l_post_training_disables.size(); ++l_idx) { FAPI_INF("%s restoring value of DATA_DISABLE scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::BIT_DISABLE_REG[iv_rp][l_idx].first, l_post_training_disables[l_idx].first, iv_dq_disable[l_idx].first); FAPI_INF("%s restoring value of DATA_DISABLE scom 0x%016llx from 0x%016llx to 0x%016llx", mss::c_str(iv_target), TT::BIT_DISABLE_REG[iv_rp][l_idx].second, l_post_training_disables[l_idx].second, iv_dq_disable[l_idx].second); } // Write each register back from private variables FAPI_TRY( mss::scom_blastah(iv_target, TT::WR_DELAY_REG[iv_rp], iv_write_delay) ); FAPI_TRY( mss::scom_blastah(iv_target, TT::BIT_DISABLE_REG[iv_rp], iv_dq_disable) ); // Run the record_bad_bits function to restore the BAD_DQ_BITMAP attribute using the pre-training disable bits FAPI_TRY( mss::dp16::record_bad_bits(iv_target) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset the data bit enable registers /// @param[in] i_target a port target /// @return FAPI2_RC_SUCCES iff ok /// fapi2::ReturnCode reset_data_bit_enable( const fapi2::Target& i_target ) { // Determine if we're running with spares or not. Once we know that, we can find the right vector to iterate over. // Note: Is this ATTR_EFF_DIMM_SPARE? Because that's per DIMM, but this is a port-level statement, right? BRS // Assume Nimbus for now - no spares ever. BRS bool l_using_spares = false; // Since this code is the MCA specialization, we know we never deal with DPHY23 - Nimbus PHY are // 4 copies of the same PHY. So we can use the DPHY01 data for all position. auto l_reg_data = l_using_spares ? data_bit_enable_spare[0] : data_bit_enable_no_spare[0]; FAPI_DBG("reg/data vector %d", l_reg_data.size()); for (const auto& rdp : l_reg_data) { // This is probably important enough to be seen all the time, not just debug FAPI_INF( "Setting up DATA_BIT_ENABLE 0x%llx (0x%llx) %s", rdp.first, rdp.second, mss::c_str(i_target) ); FAPI_TRY( mss::putScom(i_target, rdp.first, rdp.second) ); } fapi_try_exit: return fapi2::current_err; } /// /// @brief Helper function to select rdclk/wrclk enable settings /// @tparam N size of x4 register_data_vectors /// @tparam M size of x8 register_data_vectors /// @param[in] i_target a port target /// @param[in] i_clk_enable_data_x4 array of register_data_vectors /// @param[in] i_clk_enable_data_x8 array of register_data_vectors /// @param[out] o_reg_data rdclk settings /// @return FAPI2_RC_SUCCES iff ok /// template < size_t N, size_t M > static fapi2::ReturnCode clock_enable_helper( const fapi2::Target& i_target, const register_data_vector (&i_clk_enable_data_x4)[N], const register_data_vector (&i_clk_enable_data_x8)[M], register_data_vector& o_reg_data ) { // Compile-time checks to assure we don't seg fault static_assert( (N == CLK_ENABLE_X4_SIZE) && (M == CLK_ENABLE_X8_SIZE), "Expected register_data_vector size for x4 is 1," " register_data_vector size for x8 is 8"); // Retrieving DRAM width accessor to determine our device width // to set appropriate settings for x8 and x4 cases uint8_t l_dram_width[mss::MAX_DIMM_PER_PORT] = {}; FAPI_TRY( mss::eff_dram_width(i_target, &l_dram_width[0]) ); // I am iterating over functional DIMMs to skip empty DIMM slots // I'm looking for the 1st instance of whether to use x4 or x8 settings // This should be fine since 2 DIMMs w/the same width use the same settings // and DIMM mixing isn't allowed and would error out due to our plug_rules // before getting here in eff_config for( const auto& d : mss::find_targets(i_target) ) { const auto l_sdram_width = l_dram_width[mss::index(d)]; switch(l_sdram_width) { case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8: // Settings for x8 mappings were created for all 8 ports and DP instances // under a proc since they vary. So are indexing with mss::pos versus mss::index o_reg_data = i_clk_enable_data_x8[mss::pos(i_target)]; return fapi2::FAPI2_RC_SUCCESS; break; case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4: // Settings for x4 mapping are the same for all 8 ports and DP instances // so we only use one setting, only the first index is defined o_reg_data = i_clk_enable_data_x4[0]; return fapi2::FAPI2_RC_SUCCESS; break; default: FAPI_ASSERT( false, fapi2::MSS_INVALID_DRAM_WIDTH(). set_DRAM_WIDTH(l_sdram_width). set_DIMM_TARGET(d), "Received in valid DRAM width: x%d for %s. " "Expected x8 or x4 configuration.", l_sdram_width, mss::c_str(d) ); break; }// switch }// dimm fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset the read clock enable registers /// @param[in] i_target /// @param[in] i_rank_pairs /// @return FAPI2_RC_SUCCES iff ok /// fapi2::ReturnCode reset_read_clock_enable( const fapi2::Target& i_target, const std::vector< uint64_t >& i_rank_pairs ) { register_data_vector l_reg_data; FAPI_TRY( clock_enable_helper(i_target, rdclk_enable_no_spare_x4, rdclk_enable_no_spare_x8, l_reg_data), "Failed clock_enable_helper() on %s", mss::c_str(i_target) ); for (const auto& rp : i_rank_pairs) { for (const auto& rdp : l_reg_data) { // Grab the register and add the rank pair in constexpr size_t RP_ADDR_START = 22; constexpr size_t RP_ADDR_LEN = 2; fapi2::buffer l_address(rdp.first); l_address.insertFromRight(rp); fapi2::buffer l_data; constexpr size_t QUAD_LEN = 16; l_data.insertFromRight(rdp.second); FAPI_INF( "Setting up RDCLK RP%d 0x%llx (0x%llx) %s", rp, l_address, l_data, mss::c_str(i_target) ); FAPI_TRY( mss::putScom(i_target, l_address, l_data) ); } } fapi_try_exit: return fapi2::current_err; } /// /// @brief Resets the write clock enable registers /// @param[in] i_target /// @param[in] i_rank_pairs /// @return FAPI2_RC_SUCCESs iff ok /// fapi2::ReturnCode reset_write_clock_enable( const fapi2::Target& i_target, const std::vector< uint64_t >& i_rank_pairs ) { register_data_vector l_reg_data; FAPI_TRY( clock_enable_helper(i_target, wrclk_enable_no_spare_x4, wrclk_enable_no_spare_x8, l_reg_data), "Failed clock_enable_helper() on %s", mss::c_str(i_target) ); for (const auto& rp : i_rank_pairs) { for (const auto& rdp : l_reg_data) { // Grab the register and add the rank pair in constexpr size_t RP_ADDR_START = 22; constexpr size_t RP_ADDR_LEN = 2; fapi2::buffer l_address(rdp.first); l_address.insertFromRight(rp); fapi2::buffer l_data; constexpr size_t QUAD_LEN = 16; l_data.insertFromRight(rdp.second); FAPI_INF( "Setting up WRCLK RP%d 0x%llx (0x%llx) %s", rp, l_address, l_data, mss::c_str(i_target) ); FAPI_TRY( mss::putScom(i_target, l_address, l_data) ); } } fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset the training delay configuration /// @param[in] i_target the port target /// @param[in] i_rank_pairs vector of rank pairs /// @return FAPI2_RC_SUCCES iff ok /// fapi2::ReturnCode reset_delay_values( const fapi2::Target& i_target, const std::vector< uint64_t >& i_rank_pairs ) { std::vector l_addrs( { MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_0, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_1, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_2, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_3, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_4, } ); fapi2::buffer l_data; #if 0 // Don't reset the write level values before calibration, per S. Wyatt // Reset the write level values FAPI_INF( "Resetting write level values %s", mss::c_str(i_target) ); FAPI_TRY( mss::wc::read_config2(i_target, l_data) ); mss::wc::set_reset_wr_delay_wl(l_data); FAPI_TRY( mss::wc::write_config2(i_target, l_data) ); #endif for (const auto& rp : i_rank_pairs) { for (const auto& a : l_addrs) { // Add the rank pair into the register to get the actual address fapi2::buffer l_address(a); l_address.insertFromRight<22, 2>(rp); FAPI_DBG( "Resetting DP16 gate delay 0x%llx %s", l_address, mss::c_str(i_target) ); FAPI_TRY( mss::putScom(i_target, l_address, 0) ); } } fapi_try_exit: return fapi2::current_err; } /// /// @brief Configure the DP16 sysclk /// @param[in] i_target a MCBIST target /// @return FAPI2_RC_SUCCESs iff ok /// fapi2::ReturnCode reset_sysclk( const fapi2::Target& i_target ) { static const std::vector< std::pair > l_addrs( { {MCA_DDRPHY_DP16_SYSCLK_PR0_P0_0, MCA_DDRPHY_DP16_SYSCLK_PR1_P0_0}, {MCA_DDRPHY_DP16_SYSCLK_PR0_P0_1, MCA_DDRPHY_DP16_SYSCLK_PR1_P0_1}, {MCA_DDRPHY_DP16_SYSCLK_PR0_P0_2, MCA_DDRPHY_DP16_SYSCLK_PR1_P0_2}, {MCA_DDRPHY_DP16_SYSCLK_PR0_P0_3, MCA_DDRPHY_DP16_SYSCLK_PR1_P0_3}, {MCA_DDRPHY_DP16_SYSCLK_PR0_P0_4, MCA_DDRPHY_DP16_SYSCLK_PR1_P0_4}, } ); fapi2::buffer l_data; uint8_t l_sim = 0; FAPI_TRY( mss::is_simulation( l_sim) ); l_data.setBit(); if (l_sim) { l_data.setBit(); } // Need to run on the magic port too for (const auto& p : mss::find_targets_with_magic(i_target)) { FAPI_DBG("set dp16_sysclk for %s", mss::c_str(p)); for (const auto& a : l_addrs) { FAPI_TRY( mss::putScom(p, a.first, l_data) ); FAPI_TRY( mss::putScom(p, a.second, l_data) ); } } fapi_try_exit: return fapi2::current_err; } /// /// @brief Configure the DP16 io_tx config0 registers /// @param[in] i_target a MCBIST target /// @return FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode reset_io_tx_config0( const fapi2::Target& i_target ) { static const std::vector l_addrs( { MCA_DDRPHY_DP16_IO_TX_CONFIG0_P0_0, MCA_DDRPHY_DP16_IO_TX_CONFIG0_P0_1, MCA_DDRPHY_DP16_IO_TX_CONFIG0_P0_2, MCA_DDRPHY_DP16_IO_TX_CONFIG0_P0_3, MCA_DDRPHY_DP16_IO_TX_CONFIG0_P0_4, } ); fapi2::buffer l_data; uint64_t l_freq_bitfield; // Right now freq is per MCBIST. uint64_t l_freq; FAPI_TRY( mss::freq(i_target, l_freq) ); l_freq_bitfield = freq_bitfield_helper(l_freq); l_data.insertFromRight(l_freq_bitfield); FAPI_INF("blasting 0x%016lx to dp16 io_tx", l_data); FAPI_TRY( mss::scom_blastah(i_target.getChildren(), l_addrs, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Configure ADR DLL/VREG Config 1 /// @param[in] i_target a MCBIST target /// @return FAPI2_RC_SUCCESs iff ok /// fapi2::ReturnCode reset_dll_vreg_config1( const fapi2::Target& i_target ) { static const std::vector l_addrs( { MCA_DDRPHY_ADR_DLL_VREG_CONFIG_1_P0_ADR32S0, MCA_DDRPHY_ADR_DLL_VREG_CONFIG_1_P0_ADR32S1, } ); fapi2::buffer l_data; uint64_t l_freq_bitfield; // Right now freq is per MCBIST. uint64_t l_freq; FAPI_TRY( mss::freq(i_target, l_freq) ); l_freq_bitfield = freq_bitfield_helper(l_freq); l_data.insertFromRight(l_freq_bitfield); FAPI_INF("blasting 0x%016lx to dp16 DLL/VREG config 1", l_data); FAPI_TRY( mss::scom_blastah(i_target.getChildren(), l_addrs, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset AC_BOOST_CNTL MCA specialization - for all DP16 in the target /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_ac_boost_cntl( const fapi2::Target& i_target ) { typedef dp16Traits TT; // Get the attributes which contain the information from the VPD fapi2::buffer l_rd_up; fapi2::buffer l_wr_down; fapi2::buffer l_wr_up; // Keep track of the bit postion we start at, so we can slide thru the attributes // as we iterate over the registers uint64_t l_start_bit = 0; constexpr uint64_t BIT_FIELD_LEN = 3; constexpr uint64_t BIT_POSITION_DELTA = BIT_FIELD_LEN * 2; // A little DP block indicator useful for tracing uint64_t l_which_dp16 = 0; FAPI_TRY( mss::vpd_mt_mc_dq_acboost_rd_up(i_target, l_rd_up) ); FAPI_TRY( mss::vpd_mt_mc_dq_acboost_wr_down(i_target, l_wr_down) ); FAPI_TRY( mss::vpd_mt_mc_dq_acboost_wr_up(i_target, l_wr_up) ); FAPI_INF("seeing acboost attributes wr_down: 0x%08lx wr_up: 0x%08lx, rd_up: 0x%08lx", l_wr_down, l_wr_up, l_rd_up); // For all of the AC Boost attributes, they're laid out in the uint32_t as such: // (dear OpenPOWER: remember in IBM-speak, bit 0 is the left-most bit because no // good reason) // Bit 0-2 = DP16 Block 0 (DQ Bits 0-7) // Bit 3-5 = DP16 Block 0 (DQ Bits 8-15) // Bit 6-8 = DP16 Block 1 (DQ Bits 0-7) // Bit 9-11 = DP16 Block 1 (DQ Bits 8-15) // Bit 12-14 = DP16 Block 2 (DQ Bits 0-7) // Bit 15-17 = DP16 Block 2 (DQ Bits 8-15) // Bit 18-20 = DP16 Block 3 (DQ Bits 0-7) // Bit 21-23 = DP16 Block 3 (DQ Bits 8-15) // Bit 24-26 = DP16 Block 4 (DQ Bits 0-7) // Bit 27-29 = DP16 Block 4 (DQ Bits 8-15) // For all the AC_BOOST registers on this MCA, shuffle in the bits and write // the registers. for (const auto& r : TT::AC_BOOST_CNTRL_REG) { fapi2::buffer l_boost_0; fapi2::buffer l_boost_1; // Read FAPI_TRY( mss::getScom(i_target, r.first, l_boost_0) ); FAPI_TRY( mss::getScom(i_target, r.second, l_boost_1) ); // Modify { // Yeah, we could do this once, however we need to flush them to 0 every time so this is the same fapi2::buffer l_scratch_0; fapi2::buffer l_scratch_1; FAPI_TRY(l_wr_down.extractToRight(l_scratch_0, l_start_bit, BIT_FIELD_LEN), "unable to extract ac boost wr down 0"); l_boost_0.insertFromRight(l_scratch_0); FAPI_TRY(l_wr_down.extractToRight(l_scratch_1, l_start_bit + BIT_FIELD_LEN, BIT_FIELD_LEN), "unable to extract ac boost wr down 1"); l_boost_1.insertFromRight(l_scratch_1); FAPI_INF("ac boost wr down for %s dp16 %d: 0x%08lx, 0x%08lx (0x%016lx, 0x%016lx)", mss::c_str(i_target), l_which_dp16, l_scratch_0, l_scratch_1, l_boost_0, l_boost_1); } { fapi2::buffer l_scratch_0; fapi2::buffer l_scratch_1; FAPI_TRY(l_wr_up.extractToRight(l_scratch_0, l_start_bit, BIT_FIELD_LEN), "unable to extract ac boost wr up 0"); l_boost_0.insertFromRight(l_scratch_0); FAPI_TRY(l_wr_up.extractToRight(l_scratch_1, l_start_bit + BIT_FIELD_LEN, BIT_FIELD_LEN), "unable to extract ac boost wr up 1"); l_boost_1.insertFromRight(l_scratch_1); FAPI_INF("ac boost wr up for %s dp16 %d: 0x%08lx, 0x%08lx (0x%016lx, 0x%016lx)", mss::c_str(i_target), l_which_dp16, l_scratch_0, l_scratch_1, l_boost_0, l_boost_1); } { fapi2::buffer l_scratch_0; fapi2::buffer l_scratch_1; FAPI_TRY(l_rd_up.extractToRight(l_scratch_0, l_start_bit, BIT_FIELD_LEN), "unable to extract ac boost rd up 0"); l_boost_0.insertFromRight(l_scratch_0); FAPI_TRY(l_rd_up.extractToRight(l_scratch_1, l_start_bit + BIT_FIELD_LEN, BIT_FIELD_LEN), "unable to extract ac boost rd up 1"); l_boost_1.insertFromRight(l_scratch_1); FAPI_INF("ac boost rd down for %s dp16 %d: 0x%08lx, 0x%08lx (0x%016lx, 0x%016lx)", mss::c_str(i_target), l_which_dp16, l_scratch_0, l_scratch_1, l_boost_0, l_boost_1); } // Write FAPI_TRY( mss::putScom(i_target, r.first, l_boost_0) ); FAPI_TRY( mss::putScom(i_target, r.second, l_boost_1) ); // Slide over in the attributes, bump the dp16 trace counter, and do it again l_start_bit += BIT_POSITION_DELTA; ++l_which_dp16; } fapi_try_exit: return fapi2::current_err; } /// /// @brief Helper to write and trace ctle cap and res /// @tparam S the start of the insertion /// @tparam L the length of the insertion /// @param[in] l_ctle_cap the value of the CAP attribute /// @param[in] l_start_bit the bit in the attribute to start at /// @param[in,out] the ctle buffer to write /// @return FAPI2_RC_SUCCESS iff OK /// template< uint64_t S, uint64_t L > fapi2::ReturnCode ctle_helper( const fapi2::buffer i_ctle_cap, const uint64_t l_start_bit, fapi2::buffer& io_ctle) { fapi2::buffer l_scratch; FAPI_DBG("ctle start: %d len: %d, insert start: %d len: %d", l_start_bit, L, S, L); FAPI_TRY(i_ctle_cap.extractToRight(l_scratch, l_start_bit, L), "unable to extract ctle cap"); io_ctle.insertFromRight(l_scratch); fapi_try_exit: return fapi2::current_err; }; /// /// @brief Set RX_CONFIG0_P0_DP16_0_READ_CENTERING_MODE - for all DP16 in the target /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode setup_custom_read_centering_mode( const fapi2::Target& i_target ) { typedef dp16Traits TT; constexpr uint8_t CUSTOM_READ_CENTERING = 0b11; std::vector< fapi2::buffer< uint64_t > > l_data; const auto& DP16_RX_REGS = TT::DP16_RX_REGS; FAPI_TRY( mss::scom_suckah(i_target, DP16_RX_REGS, l_data) ); for (auto& l_reg_data : l_data) { l_reg_data.insertFromRight(CUSTOM_READ_CENTERING); FAPI_INF("%s setting custom read centering mode 0x%016lx", mss::c_str(i_target), l_reg_data); } FAPI_TRY( mss::scom_blastah(i_target, DP16_RX_REGS, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset CTLE_CNTL MCA specialization - for all DP16 in the target /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok template<> fapi2::ReturnCode reset_ctle_cntl( const fapi2::Target& i_target ) { typedef dp16Traits TT; // Get the attributes which contain the information from the VPD fapi2::buffer l_ctle_cap; fapi2::buffer l_ctle_res; // The length of the bit fields allows us to slide along the attribute uint64_t l_cap_start_bit = 0; uint64_t l_res_start_bit = 0; constexpr uint64_t CAP_BIT_FIELD_LEN = 2; constexpr uint64_t RES_BIT_FIELD_LEN = 3; // A little DP block indicator useful for tracing uint64_t l_which_dp16 = 0; FAPI_TRY( mss::vpd_mt_mc_dq_ctle_cap(i_target, l_ctle_cap) ); FAPI_TRY( mss::vpd_mt_mc_dq_ctle_res(i_target, l_ctle_res) ); FAPI_INF("%s seeing ctle attributes cap: 0x%016lx res: 0x%016lx", mss::c_str(i_target), l_ctle_cap, l_ctle_res); // For the capacitance CTLE attributes, they're laid out in the uint64_t as such. The resitance // attributes are the same, but 3 bits long. Notice that DP Block X Nibble 0 is DQ0:3, // Nibble 1 is DQ4:7, Nibble 2 is DQ8:11 and 3 is DQ12:15. // (dear OpenPOWER: remember in IBM-speak, bit 0 is the left-most bit because no // good reason) // Bit 0-1 = DP16 Block 0 Nibble 0 Bit 16-17 = DP16 Block 2 Nibble 0 Bit 32-33 = DP16 Block 4 Nibble 0 // Bit 2-3 = DP16 Block 0 Nibble 1 Bit 18-19 = DP16 Block 2 Nibble 1 Bit 34-35 = DP16 Block 4 Nibble 1 // Bit 4-5 = DP16 Block 0 Nibble 2 Bit 20-21 = DP16 Block 2 Nibble 2 Bit 36-37 = DP16 Block 4 Nibble 2 // Bit 6-7 = DP16 Block 0 Nibble 3 Bit 22-23 = DP16 Block 2 Nibble 3 Bit 38-39 = DP16 Block 4 Nibble 3 // Bit 8-9 = DP16 Block 1 Nibble 0 Bit 24-25 = DP16 Block 3 Nibble 0 // Bit 10-11 = DP16 Block 1 Nibble 1 Bit 26-27 = DP16 Block 3 Nibble 1 // Bit 12-13 = DP16 Block 1 Nibble 2 Bit 28-29 = DP16 Block 3 Nibble 2 // Bit 14-15 = DP16 Block 1 Nibble 3 Bit 30-31 = DP16 Block 3 Nibble 3 // For all the CTLE registers on this MCA, walk the attributes and stick the values in the right places // in the registers for (const auto& r : TT::CTLE_CNTRL_REG) { fapi2::buffer l_ctle_0; fapi2::buffer l_ctle_1; // Read FAPI_TRY( mss::getScom(i_target, r.first, l_ctle_0) ); FAPI_TRY( mss::getScom(i_target, r.second, l_ctle_1) ); // Modify // I didn't make an inner loop here as the nibbles even, odd, etc. end up just different enough to make // keeping track of the cap/res starts, buffers, a mess. This, while a bit unrolled, is far esier to undertand. // Byte 0 { // DP16 Block 0 Nibble 0 { fapi2::buffer l_scratch_0; fapi2::buffer l_scratch_1; FAPI_TRY((ctle_helper(l_ctle_cap, l_cap_start_bit, l_ctle_0))); FAPI_TRY((ctle_helper(l_ctle_res, l_res_start_bit, l_ctle_0))); FAPI_INF("ctle nibble %d for %s dp16 %d: 0x%016lx, 0x%016lx", 0, mss::c_str(i_target), l_which_dp16, l_ctle_0, l_ctle_1); } // DP16 Block 0 Nibble 1 { fapi2::buffer l_scratch_0; fapi2::buffer l_scratch_1; l_cap_start_bit += CAP_BIT_FIELD_LEN; l_res_start_bit += RES_BIT_FIELD_LEN; FAPI_TRY((ctle_helper(l_ctle_cap, l_cap_start_bit, l_ctle_0))); FAPI_TRY((ctle_helper(l_ctle_res, l_res_start_bit, l_ctle_0))); FAPI_INF("ctle nibble %d for %s dp16 %d: 0x%016lx, 0x%016lx", 1, mss::c_str(i_target), l_which_dp16, l_ctle_0, l_ctle_1); } // DP16 Block 0 Nibble 2 { fapi2::buffer l_scratch_0; fapi2::buffer l_scratch_1; l_cap_start_bit += CAP_BIT_FIELD_LEN; l_res_start_bit += RES_BIT_FIELD_LEN; FAPI_TRY((ctle_helper(l_ctle_cap, l_cap_start_bit, l_ctle_1))); FAPI_TRY((ctle_helper(l_ctle_res, l_res_start_bit, l_ctle_1))); FAPI_INF("ctle nibble %d for %s dp16 %d: 0x%016lx, 0x%016lx", 2, mss::c_str(i_target), l_which_dp16, l_ctle_0, l_ctle_1); } // DP16 Block 0 Nibble 3 { fapi2::buffer l_scratch_0; fapi2::buffer l_scratch_1; l_cap_start_bit += CAP_BIT_FIELD_LEN; l_res_start_bit += RES_BIT_FIELD_LEN; FAPI_TRY((ctle_helper(l_ctle_cap, l_cap_start_bit, l_ctle_1))); FAPI_TRY((ctle_helper(l_ctle_res, l_res_start_bit, l_ctle_1))); FAPI_INF("ctle nibble %d for %s dp16 %d: 0x%016lx, 0x%016lx", 3, mss::c_str(i_target), l_which_dp16, l_ctle_0, l_ctle_1); } } // Write FAPI_TRY( mss::putScom(i_target, r.first, l_ctle_0) ); FAPI_TRY( mss::putScom(i_target, r.second, l_ctle_1) ); // Jump over the 3rd nibble so the start bits are correct at the top of the loop l_cap_start_bit += CAP_BIT_FIELD_LEN; l_res_start_bit += RES_BIT_FIELD_LEN; ++l_which_dp16; } fapi_try_exit: return fapi2::current_err; } /// /// @brief Configure Read VREF Registers /// @param[in] i_target a MCA target /// @return FAPI2_RC_SUCCESs iff ok /// fapi2::ReturnCode reset_rd_vref( const fapi2::Target& i_target ) { typedef dp16Traits TT; std::vector< fapi2::buffer< uint64_t > > l_data; uint64_t l_vref_bitfield = 0; uint8_t l_sim = 0; uint32_t l_vref = 0; FAPI_TRY( mss::vpd_mt_vref_mc_rd(i_target, l_vref) ); FAPI_TRY( rd_vref_bitfield_helper(i_target, l_vref, l_vref_bitfield) ); FAPI_TRY( mss::is_simulation( l_sim) ); // Leave the values as-is if we're on VBU or Awan, since we know that works. Use the real value for unit test and HW if (!l_sim) { // Setup the rd vref from VPD { // Do a read/modify/write const auto& RD_VREF_CNTRL_REG = mss::chip_ec_nimbus_lt_2_0(i_target) ? TT::DD1_RD_VREF_CNTRL_REG : TT::DD2_RD_VREF_CNTRL_REG; FAPI_TRY( mss::scom_suckah(i_target, RD_VREF_CNTRL_REG, l_data) ); for (auto& l_reg_data : l_data) { // Write the same value for all the DQ and DQS nibbles l_reg_data.insertFromRight(l_vref_bitfield); l_reg_data.insertFromRight(l_vref_bitfield); } FAPI_INF("%s blasting VREF settings from VPD to dp16 RD_VREF registers", mss::c_str(i_target)); FAPI_TRY( mss::scom_blastah(i_target, RD_VREF_CNTRL_REG, l_data) ); } // Turn on the rd vref calibration. We leverage an attribute to control this. { uint16_t l_vref_cal_enable = 0; FAPI_TRY( mss::rdvref_cal_enable(i_target, l_vref_cal_enable) ); FAPI_TRY( mss::scom_blastah(i_target, TT::RD_VREF_CAL_ENABLE_REG, l_vref_cal_enable) ); } } fapi_try_exit: return fapi2::current_err; } /// /// @brief sets the register value for DQ/DQS driver impedance from the VPD value - TARGET_TYPE_MCA specialization /// @param[in] i_target the port in question /// @param[out] o_reg_value value to push into the registers /// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff no error /// template<> fapi2::ReturnCode get_dq_dqs_drv_imp_field_value( const fapi2::Target& i_target, fapi2::buffer* o_reg_value ) { //traits definition typedef dp16Traits TT; //disable is Hi-Z state, no slices enabled constexpr uint8_t REG_VALUE_DISABLE = 0x00; //left justifies values as that's the lower order bit for IBM //these registers enable 240 Ohm slices in parallel //the impedance becomes 240/N - N being the number of slices enabled //thus 34 Ohms is all seven slices enabled. constexpr uint8_t REG_VALUE_240OHM = 0b01000000; constexpr uint8_t REG_VALUE_120OHM = 0b01100000; constexpr uint8_t REG_VALUE_80OHM = 0b01110000; constexpr uint8_t REG_VALUE_60OHM = 0b01111000; constexpr uint8_t REG_VALUE_48OHM = 0b01111100; constexpr uint8_t REG_VALUE_40OHM = 0b01111110; constexpr uint8_t REG_VALUE_34OHM = 0b01111111; fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; uint8_t l_vpd_value[TT::DP_COUNT] = {}; //goes the attr get FAPI_TRY(vpd_mt_mc_drv_imp_dq_dqs(i_target, l_vpd_value)); //loops through all of the DP's for(uint8_t dp = 0; dp < TT::DP_COUNT; ++dp) { switch(l_vpd_value[dp]) { case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_DISABLE: o_reg_value[dp] = REG_VALUE_DISABLE; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_OHM240: o_reg_value[dp] = REG_VALUE_240OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_OHM120: o_reg_value[dp] = REG_VALUE_120OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_OHM80: o_reg_value[dp] = REG_VALUE_80OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_OHM60: o_reg_value[dp] = REG_VALUE_60OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_OHM48: o_reg_value[dp] = REG_VALUE_48OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_OHM40: o_reg_value[dp] = REG_VALUE_40OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS_OHM34: o_reg_value[dp] = REG_VALUE_34OHM; break; //all non-enum values are errors, set current error and exit default: FAPI_ASSERT(false, fapi2::MSS_INVALID_VPD_VALUE_MC_DRV_IMP_DQ_DQS() .set_VALUE(l_vpd_value[dp]) .set_DP(dp) .set_MCS_TARGET(mss::find_target(i_target)), "%s DQ_DQS %s impedance value is not valid: %u for DP[%u]", c_str(i_target), "driver", l_vpd_value[dp], dp); break; } //successfully got the value, print an info statement for debug FAPI_INF("%s DQ/DQS %s impedance for DP[%u] VPD: %u register value 0x%02x", c_str(i_target), "DRV", dp, l_vpd_value[dp], o_reg_value[dp]); } fapi_try_exit: return fapi2::current_err; } /// /// @brief sets up the DQ/DQS driver impedances - TARGET_TYPE_MCA specialization /// @param[in] i_target the port in question /// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff no error /// template<> fapi2::ReturnCode reset_dq_dqs_drv_imp( const fapi2::Target& i_target ) { //traits definition typedef dp16Traits TT; constexpr uint64_t NFET_LOC = TT::IO_TX_FET_SLICE_EN_N_WR; constexpr uint64_t NFET_LEN = TT::IO_TX_FET_SLICE_EN_N_WR_LEN; constexpr uint64_t PFET_LOC = TT::IO_TX_FET_SLICE_EN_P_WR; constexpr uint64_t PFET_LEN = TT::IO_TX_FET_SLICE_EN_P_WR_LEN; fapi2::buffer l_field_value[TT::DP_COUNT]; //gets the field value FAPI_TRY(get_dq_dqs_drv_imp_field_value(i_target, l_field_value)); //loops through all DP's and sets the register values for(uint8_t dp = 0; dp < TT::DP_COUNT ; ++dp) { //sets up the scom value const auto l_scom_value = fapi2::buffer() .insertFromRight(l_field_value[dp]) .insertFromRight(l_field_value[dp]); //blasts those scoms FAPI_TRY(mss::putScom( i_target, TT::IO_TX_FET_SLICE_REG[dp], l_scom_value )); } fapi_try_exit: return fapi2::current_err; } /// /// @brief sets the register value for DQ/DQS receiver impedance from the VPD value - MCA specialization /// @param[in] i_target the port in question /// @param[out] o_reg_value value to push into the registers /// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff no error /// template<> fapi2::ReturnCode get_dq_dqs_rcv_imp_field_value( const fapi2::Target& i_target, fapi2::buffer* o_reg_value ) { //traits definition typedef dp16Traits TT; //disable is Hi-Z state, no slices enabled constexpr uint8_t REG_VALUE_DISABLE = 0x00; //left justifies values as that's the lower order bit for IBM //these registers enable 240 Ohm slices in parallel //the impedance becomes 240/N - N being the number of slices enabled //thus 34 Ohms is all seven slices enabled. constexpr uint8_t REG_VALUE_240OHM = 0b01000000; constexpr uint8_t REG_VALUE_120OHM = 0b01100000; constexpr uint8_t REG_VALUE_80OHM = 0b01110000; constexpr uint8_t REG_VALUE_60OHM = 0b01111000; constexpr uint8_t REG_VALUE_48OHM = 0b01111100; constexpr uint8_t REG_VALUE_40OHM = 0b01111110; constexpr uint8_t REG_VALUE_34OHM = 0b01111111; fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; uint8_t l_vpd_value[TT::DP_COUNT] = {}; //goes the attr get FAPI_TRY(vpd_mt_mc_rcv_imp_dq_dqs(i_target, l_vpd_value)); //loops through and checks each value for the DP for(uint8_t dp = 0; dp < TT::DP_COUNT; ++dp) { switch(l_vpd_value[dp]) { case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_DISABLE: o_reg_value[dp] = REG_VALUE_DISABLE; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_OHM240: o_reg_value[dp] = REG_VALUE_240OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_OHM120: o_reg_value[dp] = REG_VALUE_120OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_OHM80: o_reg_value[dp] = REG_VALUE_80OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_OHM60: o_reg_value[dp] = REG_VALUE_60OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_OHM48: o_reg_value[dp] = REG_VALUE_48OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_OHM40: o_reg_value[dp] = REG_VALUE_40OHM; break; case fapi2::ENUM_ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS_OHM34: o_reg_value[dp] = REG_VALUE_34OHM; break; //all non-enum values are errors, set current error and exit default: FAPI_ASSERT(false, fapi2::MSS_INVALID_VPD_VALUE_MC_RCV_IMP_DQ_DQS() .set_VALUE(l_vpd_value[dp]) .set_DP(dp) .set_MCS_TARGET(mss::find_target(i_target)), "%s DQ_DQS %s impedance value is not valid: %u for DP[%u]", c_str(i_target), "receiver", l_vpd_value[dp], dp); break; } //successfully got the value, print an info statement for debug FAPI_INF("%s DQ/DQS %s impedance for DP[%u] VPD: %u register value 0x%02x", c_str(i_target), "RCV", dp, l_vpd_value[dp], o_reg_value[dp]); } fapi_try_exit: return fapi2::current_err; } /// /// @brief sets up the DQ/DQS receiver impedances - MCA specialization /// @param[in] i_target the port in question /// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff no error /// template<> fapi2::ReturnCode reset_dq_dqs_rcv_imp( const fapi2::Target& i_target ) { //traits definition typedef dp16Traits TT; constexpr uint64_t LOC = TT::IO_TX_PFET_TERM_EN_P_WR; constexpr uint64_t LEN = TT::IO_TX_PFET_TERM_EN_P_WR_LEN; fapi2::buffer l_field_value[TT::DP_COUNT]; //gets the field value FAPI_TRY(get_dq_dqs_rcv_imp_field_value(i_target, l_field_value)); //loops through all DP's and sets the register values for(uint8_t dp = 0; dp < TT::DP_COUNT ; ++dp) { //sets up the scom value const auto l_scom_value = fapi2::buffer().insertFromRight(l_field_value[dp]); //blasts those scoms FAPI_TRY(mss::putScom( i_target, TT::IO_TX_PFET_TERM_REG[dp], l_scom_value )); } fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset blue waterfall range in DRIFT_LIMITS register /// @tparam T fapi2 Target Type - derived /// @tparam TT traits type defaults to dp16Traits /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_drift_limits( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; uint8_t l_sim = 0; fapi2::buffer l_data; uint64_t l_freq = 0; blue_waterfall_range l_value = blue_waterfall_range::ONE_TO_FOUR; const auto l_mcbist = mss::find_target(i_target); FAPI_TRY( mss::is_simulation( l_sim) ); if (mss::chip_ec_nimbus_lt_2_0(i_target)) { // This regfield doesn't exist on DD1, so nothing to do here FAPI_INF("%s Skipping initialization of RDCLK extended range, since we're on DD1", c_str(i_target)); return fapi2::FAPI2_RC_SUCCESS; } // Get the frequency attribute FAPI_TRY(mss::freq(l_mcbist, l_freq)); // Set the blue waterfall range according to the frequency value as follows: // for 2133, 1866 set ext range to 1-4 // for 2400, 2666 set ext range to 2-5 l_value = ((l_freq == fapi2::ENUM_ATTR_MSS_FREQ_MT2666) || (l_freq == fapi2::ENUM_ATTR_MSS_FREQ_MT2400)) ? blue_waterfall_range::TWO_TO_FIVE : blue_waterfall_range::ONE_TO_FOUR; // So if the red waterfall workaround was/ is going to run, we have to change the blue waterfall range // This is freq independent mss::workarounds::dp16::update_blue_waterfall_extend_range( i_target, l_value); //From John Bialas : the value is good for hardware, but not so much in sim, in sim they should be 0s - bgass - 10/6/2017 l_value = (l_sim == 1) ? blue_waterfall_range::ZERO_TO_THREE : l_value; FAPI_INF("%s Initializing RDCLK extended range to 0x%01x", c_str(i_target), l_value); // Loops through all DP's and sets the register values for(uint8_t dp = 0; dp < TT::DP_COUNT; ++dp) { FAPI_TRY(read_drift_limits(i_target, dp, l_data), "Failed to read PHY DRIFT_LIMITS register on DP%d", dp); set_blue_waterfall_range(i_target, l_data, l_value); FAPI_TRY(write_drift_limits(i_target, dp, l_data), "Failed to write PHY DRIFT_LIMITS register on DP%d", dp); } fapi_try_exit: return fapi2::current_err; } //////////////////////////////////////////////////// // reset procedures for all the WR VREF registers // //////////////////////////////////////////////////// /// /// @brief Reset wr vref config0 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_config0( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; // Builds up the base register value by field for clarity, using characterized values that lead to the best results fapi2::buffer l_config0_data; l_config0_data.setBit() // Smallest available step size - algorithm adds 1 so this is a 1 not a 0 .insertFromRight(0b000) // Big step size of 2 - algorithm adds 1 so the register setting is a 1 .insertFromRight(0b0001) // For intermediary bits, skip all 7, aka only run one bit on each DRAM for intermediary bits .insertFromRight(0b000) // Run for the maximum number of VREFs looking for an increase .insertFromRight(0b111); // Whether the 2D VREF is enabled or not varies by the calibration attribute fapi2::buffer l_cal_steps_enabled; FAPI_TRY( mss::cal_step_enable(i_target, l_cal_steps_enabled) ); // Adds the information to the buffer l_config0_data.writeBit(!l_cal_steps_enabled.getBit()); // Blast out the scoms FAPI_TRY( mss::scom_blastah(i_target, TT::WR_VREF_CONFIG0_REG, l_config0_data) ); // Return success return fapi2::FAPI2_RC_SUCCESS; // Handle errors fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset wr vref config1 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_config1( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; //constants to make the compiler happy constexpr uint64_t RANGE_CROSSOVER = 0b0011000; constexpr uint64_t SINGLE_RANGE_MAX = 0b0110010; // builds up the base register value fapi2::buffer l_config1_data; // default to algorithm to use range 1 l_config1_data.clearBit() // JEDEC standard value for Range 2 to 1 crossover .insertFromRight(RANGE_CROSSOVER) // JEDEC standard value for a single range max .insertFromRight(SINGLE_RANGE_MAX); // blast out the scoms return mss::scom_blastah(i_target, TT::WR_VREF_CONFIG1_REG, l_config1_data) ; } /// /// @brief Reset wr vref status0 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_status0( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; // reset to all 0's return mss::scom_blastah(i_target, TT::WR_VREF_STATUS0_REG, 0x0000 ) ; } /// /// @brief Reset wr vref status1 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_status1( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; // reset to all 0's return mss::scom_blastah(i_target, TT::WR_VREF_STATUS1_REG, 0x0000 ) ; } /// /// @brief Reset wr vref error_mask - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_error_mask( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; // set all errors to be informational - masked off // TK update this post characterization // Note: the 0xffff includes the workaround for HW375535 - Error register latching return mss::scom_blastah(i_target, TT::WR_VREF_ERROR_MASK_REG, 0xFFFF ) ; } /// /// @brief Reset wr vref error - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_error( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; // clears all errors return mss::scom_blastah(i_target, TT::WR_VREF_ERROR_REG, 0x0000 ) ; } /// /// @brief Resets the WR VREF values by rank pair for given registers /// @tparam uint64_t RP the rankpair to reset /// @param[in] i_target the fapi2 target of the port /// @param[in] i_rp_registers registers to reset /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template< uint64_t RP > fapi2::ReturnCode reset_wr_vref_value_by_rp( const fapi2::Target& i_target, const std::vector< std::pair >& i_rp_registers ) { // traits definition typedef dp16Traits TT; // declares constants for the VREF train attributes - UT will fail if the ATTR changes // Value start location and length constexpr uint8_t VREF_VALUE_LOC = 2; constexpr uint8_t VREF_VALUE_LEN = TT::WR_VREF_VALUE_VALUE_DRAM_EVEN_LEN; // VREF range start location - it's only one bit constexpr uint8_t VREF_RANGE_LOC = 7; // declares variables uint64_t l_dimm = 0; uint64_t l_rank = 0; std::vector< uint64_t > l_prp; uint8_t l_vref_value[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; uint8_t l_vref_range[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; fapi2::buffer l_vref_reg_data; // sets up the rank pair information FAPI_TRY(mss::rank::primary_ranks(i_target, l_prp)); // if this rank is declared, set up it's values // if not use the defaults of dimm = 0, rank = 0 - doesn't matter as this rank won't be calibrated if(l_prp.size() > RP) { l_dimm = l_prp[RP] / MAX_RANK_PER_DIMM; l_rank = l_prp[RP] % MAX_RANK_PER_DIMM; } FAPI_INF("%s %s RP %d found! using DIMM%d and Rank%d", mss::c_str(i_target), ((l_prp.size() <= RP) ? "no" : ""), RP, 0, 0); // gets the VREF information FAPI_TRY( mss::eff_vref_dq_train_value(i_target, &l_vref_value[0][0])); FAPI_TRY( mss::eff_vref_dq_train_range(i_target, &l_vref_range[0][0])); //sets up the data { uint64_t l_value = 0; const fapi2::buffer l_vref_val_buf = l_vref_value[l_dimm][l_rank]; l_vref_val_buf.extractToRight(l_value); const fapi2::buffer l_vref_range_buf = l_vref_range[l_dimm][l_rank]; const auto l_range = l_vref_range_buf.getBit(); l_vref_reg_data.writeBit(l_range) .writeBit(l_range) .insertFromRight(l_value) .insertFromRight(l_value); } //blasts out the scoms FAPI_INF("%s RP %d getting reset to values 0x%04lx", mss::c_str(i_target), RP, l_vref_value); FAPI_TRY(mss::scom_blastah(i_target, i_rp_registers, l_vref_reg_data )); // return success return fapi2::FAPI2_RC_SUCCESS; // handle errorss fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset wr vref value rank pair 0 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_value_rp0( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; return reset_wr_vref_value_by_rp<0>(i_target, TT::WR_VREF_VALUE_RP0_REG); } /// /// @brief Reset wr vref value rank pair 1 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_value_rp1( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; return reset_wr_vref_value_by_rp<1>(i_target, TT::WR_VREF_VALUE_RP1_REG); } /// /// @brief Reset wr vref value rank pair 2 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_value_rp2( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; return reset_wr_vref_value_by_rp<2>(i_target, TT::WR_VREF_VALUE_RP2_REG); } /// /// @brief Reset wr vref value rank pair3 - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_value_rp3( const fapi2::Target& i_target ) { // traits definition typedef dp16Traits TT; return reset_wr_vref_value_by_rp<3>(i_target, TT::WR_VREF_VALUE_RP3_REG); } /// /// @brief Resets all WR VREF registers - specialization for MCA /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_wr_vref_registers( const fapi2::Target& i_target ) { // resets all of the below registers FAPI_TRY( reset_wr_vref_config0(i_target)); FAPI_TRY( reset_wr_vref_config1(i_target)); FAPI_TRY( reset_wr_vref_status0(i_target)); FAPI_TRY( reset_wr_vref_status1(i_target)); FAPI_TRY( reset_wr_vref_error_mask(i_target)); FAPI_TRY( reset_wr_vref_error(i_target)); FAPI_TRY( reset_wr_vref_value_rp0(i_target)); FAPI_TRY( reset_wr_vref_value_rp1(i_target)); FAPI_TRY( reset_wr_vref_value_rp2(i_target)); FAPI_TRY( reset_wr_vref_value_rp3(i_target)); // return success return fapi2::FAPI2_RC_SUCCESS; // handle errors fapi_try_exit: return fapi2::current_err; } /// /// @brief Resets all read delay offset registers /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// template<> fapi2::ReturnCode reset_read_delay_offset_registers( const fapi2::Target& i_target ) { typedef dp16Traits TT; // Represents the number phase rotator ticks per clock constexpr int64_t TICKS_PER_CLK = 128; // We grab the information from the VPD and blast it in to all the registers. Note the // VPD is picoseconds but the register wants phase rotator ticks - so we convert. Likewise, the VPD // is per port so we can easily cram the data in to the port using the blastah. fapi2::buffer l_data; int64_t l_phase_rot_ticks = 0; int16_t l_windage = 0; int64_t l_tck_in_ps = 0; uint64_t l_freq = 0; FAPI_TRY( mss::vpd_mt_windage_rd_ctr(i_target, l_windage), "Failed vpd_mt_windage_rd_ctr accessor for %s", mss::c_str(i_target) ); FAPI_TRY( mss::freq(mss::find_target(i_target), l_freq), "Failed freq accessor for %s", mss::c_str(i_target) ); FAPI_TRY( mss::freq_to_ps(l_freq, l_tck_in_ps), "Failled to convert freq_to_ps for %s", mss::c_str(i_target) ); // Static cast to be explicit that calculation should produce a floating point result l_phase_rot_ticks = mss::round_half_away_from_zero( (l_windage * TICKS_PER_CLK) / static_cast(l_tck_in_ps) ); l_data .insertFromRight(l_phase_rot_ticks) .insertFromRight(l_phase_rot_ticks); FAPI_INF( "vpd_mt_windage_rd_ctr = %d, ticks = %d for %s", l_windage, l_phase_rot_ticks, mss::c_str(i_target) ); FAPI_TRY( mss::scom_blastah(i_target, TT::READ_DELAY_OFFSET_REG, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Process disable bits and setup controller as necessary /// @param[in] i_target the fapi2 target of the port /// @param[in] i_dimm the fapi2 target of the failed DIMM /// @param[in] i_rp the rank pairs to check as a bit-map /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired /// fapi2::ReturnCode process_bad_bits( const fapi2::Target& i_target, const fapi2::Target& i_dimm, const uint64_t i_rp ) { typedef dp16Traits TT; // In a x4 configuration, all bits in the disable registers are used. // Named like a local variable so it matches the x8 vector constexpr uint8_t l_x4_mask = 0b11111111; // Vector of DQS maps different for x8. // Inner vector is bit-map representing valid DQS in the Disable 1 register. Nimbus // has no spares so we never check the lower DQS for DP4 std::vector< std::vector > l_x8_dqs = { // Port 0 // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b00110011, 0b11000011, 0b00110011, 0b00111100, 0b00110000 }, // Port 1 // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b11000011, 0b00111100, 0b00110011, 0b11001100, 0b00110000 }, // Port 2 // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b11001100, 0b11000011, 0b11000011, 0b00111100, 0b00110000 }, // Port 3 // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b00111100, 0b00111100, 0b11001100, 0b11001100, 0b11000000 }, // Port 4 (possibly port 6) // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b00110011, 0b00110011, 0b11001100, 0b11000011, 0b00110000 }, // Port 5 (possibly port 7) // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b11001100, 0b11000011, 0b00111100, 0b11110000, 0b11000000 }, // Port 6 (possibly port 4) // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b00110011, 0b11000011, 0b00111100, 0b00111100, 0b11000000 }, // Port 7 (possibly port 5) // DP 16,17 18,19 20,21 22,23 // 0 Y Y // 1 Y Y // 2 Y Y // 3 Y Y // 4 Y X X (no spares) // DP0 DP1 DP2 DP3 DP4 { 0b11001100, 0b00110011, 0b00110011, 0b11001100, 0b11000000 }, }; // The field in the disable bit register address which specifies which rp the register is for. constexpr uint64_t RP_OFFSET = 60; // The DQS bits (disable 1) are left aligned in a 16 bit register and we have a // right aligned mask so this is the number of bits to shift right to right align // disable 1. constexpr uint64_t DQS_SHIFT = 8; // If we have this number of bad bits, there's no way we can use this rank pair // Note, if we have 5 bad bits we might have one nibble and one bit ... constexpr uint64_t MIN_BAD_BITS = 6; constexpr uint64_t MIN_BAD_X4_DQS = 3; constexpr uint64_t MIN_BAD_X8_DQS = 1; // We can handle 1 bad nibble + 1 bad bit. If we see 2 bad bits but no bad nibbles // that's basically the same as one of the bad bits can be considered a bad nibble. // This is a sly way to handle two bad bits ... hence the name constexpr uint64_t MAX_BAD_NIBBLES = 1; constexpr uint64_t MAX_BAD_BITS = 1; constexpr uint64_t SLY_BAD_BITS = 2; uint64_t l_which_port = mss::pos(i_target); fapi2::buffer l_rpb(i_rp); std::vector< std::pair, fapi2::buffer > > l_read; while (l_rpb != 0) { // We increment l_which_dp as soon as we enter the loop below uint64_t l_which_dp = ~0; // A map of the indexes of the bad nibbles. We do bad nibble checking in two phases; // the DQS and the DQ. Since bad bits in the DQ/DQS of the nibble are the same nibble, // we use a map to consolodate the findings. In the end all we care about is whether there // is more than one entry in this map. std::map l_bad_nibbles; uint64_t l_bad_bits = 0; // Find the first bit set in the rank pairs - this will tell us which rank pair has a fail const auto l_fbs = mss::first_bit_set(uint64_t(l_rpb)) - RP_OFFSET; FAPI_INF("checking bad bits for RP%d", l_fbs); FAPI_TRY( mss::scom_suckah(i_target, TT::BIT_DISABLE_REG[l_fbs], l_read) ); // Loop over the read information for the DP for (auto& v : l_read) { uint8_t l_width = 0; uint8_t l_dqs_mask = 0; uint64_t l_dq_bad_bit_count = 0; uint64_t l_dqs_bad_bit_count = 0; l_which_dp += 1; const uint64_t l_which_nibble = l_which_dp * BITS_PER_NIBBLE; FAPI_INF("read disable0 0x%016lx disable1 0x%016lx", v.first, v.second); // // Before we mess around, check for a simple pass // if ((v.first == 0) && (v.second == 0)) { FAPI_INF("port %d DP%d all bits good", l_which_port, l_which_dp); continue; } // // Check for a simple fail. In all cases if we see 6 or more bits set in the // disable 0, we have a dead nibble + more than one bit. We don't need to worry about // disable bits because this port will be deconfigured all together. // l_dq_bad_bit_count = mss::bit_count(uint64_t(v.first)); FAPI_INF("bad DQ count for port %d DP%d %d", l_which_port, l_which_dp, l_dq_bad_bit_count); FAPI_ASSERT(l_dq_bad_bit_count < MIN_BAD_BITS, fapi2::MSS_DISABLED_BITS() .set_MCA_TARGET(i_target) .set_DIMM_TARGET(i_dimm), "%s port %d DP%d too many bad DQ bits 0x%016lx", mss::c_str(i_dimm), l_which_port, l_which_dp, v.first); // // Find the DQS mask for this DP. // FAPI_TRY( mss::eff_dram_width(i_dimm, l_width) ); l_dqs_mask = (l_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? l_x8_dqs[l_which_port][l_which_dp] : l_x4_mask; FAPI_INF("DQS mask for port %d DP%d 0x%x (0x%016lx)", l_which_port, l_which_dp, l_dqs_mask, v.second); // // Check for a simple DQS fail. For x4 if we have 3 DQS bad, we're cooked (that's // at least 2 nibbles.) For x8 of we have 1 DQS bad we're cooked (that's at least 1 byte // or at least 2 nibbles.) // if (v.second != 0) { l_dqs_bad_bit_count = mss::bit_count((v.second >> DQS_SHIFT) & l_dqs_mask); FAPI_INF("bad DQS count for port %d DP%d %d", l_which_port, l_which_dp, l_dqs_bad_bit_count); FAPI_ASSERT(l_dqs_bad_bit_count < ((l_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? MIN_BAD_X8_DQS : MIN_BAD_X4_DQS), fapi2::MSS_DISABLED_BITS().set_MCA_TARGET(i_target).set_DIMM_TARGET(i_dimm), "%s port %d DP%d too many bad DQS bits 0x%016lx", mss::c_str(i_dimm), l_which_port, l_which_dp, v.second); // So there's no way to get here if we have a x8 config. Either we had no bad DQS, in which case // we didn't come down here at all, or we have at least one bad DQS. And for x8 that means we have // at least one bad byte and that's 2 nibbles so we're cooked. The only thing we need to check // here is x4 DQS. We know that we have fewer than 3 bad DQS. If both DQS are on the same nibble // that's just one bad nibble. If the DQS are a P/N of different nibbles then we're cooked. // Loop over the read information for each nibble. Need index to do the shift. // Don't get fancy and try to incorporate the DQ checking in here too. Notice that // this DQS checking is only valid for x4 - x8 was taken care of with the bit_count check. for (size_t n = 0; n < NIBBLES_PER_DP; ++n) { // DQS disable are in disable 1 which is a left-aligned 16 bit register. // We shift it over to mask off the nibble we're checking const uint16_t l_dqs_nibble_mask = 0b1100000000000000 >> (n * BITS_PER_DQS); FAPI_INF("%s port %d DP%d nibble %d (%d) mask: 0x%x dqs: 0x%x", mss::c_str(i_dimm), l_which_port, l_which_dp, n, n + l_which_nibble, l_dqs_nibble_mask, v.second); if ((l_dqs_nibble_mask & v.second) != 0) { FAPI_INF("dqs check indicating %d as a bad nibble", n); l_bad_nibbles[n + l_which_nibble] = 1; } } // Check to see if the DQ nibble processing found more than one bad nibble. If it did, // we're done. FAPI_ASSERT(l_bad_nibbles.size() <= MAX_BAD_NIBBLES, fapi2::MSS_DISABLED_BITS().set_MCA_TARGET(i_target).set_DIMM_TARGET(i_dimm), "%s port %d DP%d too many bad nibbles %d", mss::c_str(i_dimm), l_which_port, l_which_nibble, l_bad_nibbles.size()); } // // Ok, if we made it this far we don't have anything in the DQS alone which tells us we have an // uncorrectable situation. We can check the DQ nibbles and see what they have to say. We can do // x8 and x4 nibbles all the same ... // if (v.first != 0 ) { for (size_t n = 0; n < NIBBLES_PER_DP; ++n) { // DQ nibbles are in disable 0 which is a 16 bit register. // We shift it over to mask off the nibble we're checking const uint16_t l_dq_nibble_mask = 0b1111000000000000 >> (n * BITS_PER_NIBBLE); // DQ are a little different. We need to see how many bits are in the nibble. // If we have > 2 bad bits, we kill this nibble. If we only have one bad bit // we add this bit to the total of bad singleton bits. const uint64_t l_bit_count = mss::bit_count(l_dq_nibble_mask & v.first); FAPI_INF("%s port %d DP%d nibble %d (%d) mask: 0x%x dq: 0x%x c: %d", mss::c_str(i_dimm), l_which_port, l_which_dp, n, n + l_which_nibble, l_dq_nibble_mask, v.first, l_bit_count); // If we don't have any set bits, we're good to go. If we have more than the max bad bits, // then we have a bad nibble. Otherwise we must have one bad bit in the nibble. It counts // as a bad bit but doesn't kill the nibble (yet.) if (l_bit_count != 0) { if (l_bit_count > MAX_BAD_BITS) { FAPI_INF("dq check indicating %d (%d) as a bad nibble", n, n + l_which_nibble); l_bad_nibbles[n + l_which_nibble] = 1; } else { FAPI_INF("dq check indicating nibble %d (%d) has a bad bit", n, n + l_which_nibble); l_bad_bits += l_bit_count; } } } } } // // Ok, so now we know how many bad bits we have and how many bad nibbles. If we have more than // one bad nibble, we're cooked. If we have one bad nibble and one bad bit, we're ok. Also, if // we have no bad nibbles and two bad bits (a sly bad nibble) we are ok - one of those bad bits // counts as a bad nibble. // FAPI_ASSERT(l_bad_nibbles.size() <= MAX_BAD_NIBBLES, fapi2::MSS_DISABLED_BITS().set_MCA_TARGET(i_target).set_DIMM_TARGET(i_dimm), "%s port %d DP%d too many bad nibbles %d", mss::c_str(i_dimm), l_which_port, l_which_dp, l_bad_nibbles.size()); // If we have one bad nibble, assert that we have one or fewer bad bits if (l_bad_nibbles.size() == MAX_BAD_NIBBLES) { FAPI_ASSERT(l_bad_bits <= MAX_BAD_BITS, fapi2::MSS_DISABLED_BITS().set_MCA_TARGET(i_target).set_DIMM_TARGET(i_dimm), "%s port %d DP%d bad nibbles %d + %d bad bits", mss::c_str(i_dimm), l_which_port, l_which_dp, l_bad_nibbles.size(), l_bad_bits); } // If we have no bad nibbles, assert we have 2 or fewer bad bits. This is a sly bad nibble // scenario; one of the bits is represents a bad nibble if (l_bad_nibbles.size() == 0) { FAPI_ASSERT(l_bad_bits <= SLY_BAD_BITS, fapi2::MSS_DISABLED_BITS().set_MCA_TARGET(i_target).set_DIMM_TARGET(i_dimm), "%s port %d DP%d %d bad bits", mss::c_str(i_dimm), l_which_port, l_which_dp, l_bad_bits); } // We're all done. Clear the bit l_rpb.clearBit(l_fbs + RP_OFFSET); } fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset the bad-bits masks for a port /// @note Read the bad bits from the f/w attributes and stuff them in the /// appropriate registers. /// @param[in] i_target the fapi2 target of the port /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff no errors /// fapi2::ReturnCode reset_bad_bits( const fapi2::Target& i_target ) { for( const auto& d : mss::find_targets(i_target) ) { uint8_t l_bad_dq[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] = {}; FAPI_TRY( mss::bad_dq_bitmap(d, &(l_bad_dq[0][0])), "%s failed bad_dq_bitmap", mss::c_str(d) ); FAPI_TRY( reset_bad_bits_helper(d, l_bad_dq), "%s failed reset_bad_bits_helper", mss::c_str(d) ); } fapi_try_exit: return fapi2::current_err; } /// /// @brief Configures the DQS_DISABLE register based upon the bad DQ information for x4 DRAM /// @param[in] i_target - the DIMM target on which to operate /// @param[in] i_dq_disable - the DQ disable information /// @param[in] i_reg - the DQS disable bit register to update /// fapi2::ReturnCode reset_dqs_disable(const fapi2::Target& i_target, const fapi2::buffer& i_dq_disable, const uint64_t i_reg) { // Declaring the mappings from bad DQ to bad DQS constexpr uint64_t BAD_DQ = MCA_DDRPHY_DP16_DATA_BIT_DISABLE0_RP0_P0_0_01_DISABLE_15; constexpr uint64_t BAD_DQ_LEN = BITS_PER_NIBBLE; constexpr uint64_t BAD_DQS = MCA_DDRPHY_DP16_DATA_BIT_DISABLE1_RP0_P0_0_01_DISABLE_16_23; constexpr uint64_t BAD_DQS_LEN = 2; // An entire nibble is bad if all of it's bits are set, so 0xf constexpr uint64_t ALL_BAD = 0xf; // Declares variables fapi2::buffer l_dqs_disable; const auto& l_mca = mss::find_target(i_target); // Checks if this DIMM is a x8 DIMM first, if so, skip it as a chip kill here is beyond our corrective capabilities uint8_t l_width = 0; FAPI_TRY(mss::eff_dram_width(i_target, l_width)); // Skip if the DIMIM is a x8 if(l_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) { FAPI_INF("%s is a x8 DIMM, clearing DQS register 0x%016lx", mss::c_str(i_target), i_reg); return mss::putScom(l_mca, i_reg, l_dqs_disable); } // Due to plug rules check, we should be a x4 now, so let's reset some DQS bits for(uint64_t l_nibble = 0; l_nibble < NIBBLES_PER_DP; ++l_nibble) { // If we have a whole nibble bad, set the bad DQS bits const auto DQ_START = BAD_DQ + (l_nibble * BAD_DQ_LEN); const auto DQS_START = BAD_DQS + (l_nibble * BAD_DQS_LEN); uint64_t l_nibble_disable = 0; FAPI_TRY(i_dq_disable.extractToRight(l_nibble_disable, DQ_START, BAD_DQ_LEN)); if(l_nibble_disable == ALL_BAD) { FAPI_INF("%s found that nibble %lu was all bad on DQS reg 0x%016llx", mss::c_str(i_target), l_nibble, i_reg); FAPI_TRY(l_dqs_disable.setBit(DQS_START, BAD_DQS_LEN)); } } // Sets up the DQS register FAPI_INF("%s setting DQS disable register 0x%016llx to 0x%016llx", mss::c_str(i_target), i_reg, l_dqs_disable); FAPI_TRY(mss::putScom(l_mca, i_reg, l_dqs_disable), "%s failed to set 0x%016llx", mss::c_str(l_mca), i_reg); fapi_try_exit: return fapi2::current_err; } /// /// @brief Reset the bad-bits masks for a port - helper for ease of testing /// @note Read the bad bits from the f/w attributes and stuff them in the /// appropriate registers. /// @param[in] i_target the fapi2 target of the DIMM /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff no errors on the scoms /// fapi2::ReturnCode reset_bad_bits_helper( const fapi2::Target& i_target, const uint8_t (&i_bad_dq)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) { typedef dp16Traits TT; std::vector l_ranks; // Loop over the ranks, makes things simpler than looping over the DIMM (surprisingly) FAPI_TRY( rank::ranks(i_target, l_ranks), "%s failed ranks::ranks", mss::c_str(i_target) ); for (const auto& r : l_ranks) { uint64_t l_rp = 0; const uint64_t l_dimm_index = rank::get_dimm_from_rank(r); FAPI_TRY( mss::rank::get_pair_from_rank(mss::find_target(i_target), r, l_rp), "%s failed get_pair_from_rank rank:%u", mss::c_str(i_target), r ); FAPI_INF("%s processing bad bits for DIMM%d rank %d (%d) rp %d", mss::c_str(i_target), l_dimm_index, mss::index(r), r, l_rp); // We loop over the disable registers for this rank pair, and shift the bits from the attribute // array in to the disable registers { // This is the set of registers for this rank pair. It is indexed by DP. We know the bad bits // [0] and [1] are the 16 bits for DP0, [2],[3] are the 16 for DP1, etc. const auto& l_addrs = TT::BIT_DISABLE_REG[l_rp]; // This is the section of the attribute we need to use. The result is an array of 10 bytes. const uint8_t* l_bad_bits = &(i_bad_dq[mss::index(r)][0]); // Where in the array we are, incremented by two for every DP size_t l_byte_index = 0; for (const auto& a : l_addrs) { const uint64_t l_register_value = (l_bad_bits[l_byte_index] << 8) | l_bad_bits[l_byte_index + 1]; FAPI_INF("%s writing 0x%016lX value 0x%016lX from 0x02%X, 0x%02X", mss::c_str(i_target), a.first, l_register_value, l_bad_bits[l_byte_index], l_bad_bits[l_byte_index + 1]); FAPI_TRY( mss::putScom(mss::find_target(i_target), a.first, l_register_value), "%s failed mss::putScom rank:%u scom: 0x%016lx", mss::c_str(i_target), r, a.first ); FAPI_TRY(reset_dqs_disable(i_target, l_register_value, a.second), "%s failed reset_dqs_disable rank:%u scom: 0x%016lx", mss::c_str(i_target), r, a.first ); l_byte_index += 2; } } } fapi_try_exit: return fapi2::current_err; } /// /// @brief Write disable bits - helper for testing /// @note This is different than a register write as it writes attributes which /// cause firmware to act on the disabled bits. /// @param[in] i_target the fapi2 target of the port /// @param[out] o_bad_dq an array of [BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] containing the attribute information /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired /// fapi2::ReturnCode record_bad_bits_helper( const fapi2::Target& i_target, uint8_t (&o_bad_dq)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] ) { typedef dp16Traits TT; std::vector l_ranks; // Loop over the ranks, makes things simpler than looping over the DIMM (surprisingly) FAPI_TRY( rank::ranks(i_target, l_ranks) ); for (const auto& r : l_ranks) { uint64_t l_rp = 0; uint64_t l_dimm_index = rank::get_dimm_from_rank(r); FAPI_TRY( mss::rank::get_pair_from_rank(mss::find_target(i_target), r, l_rp) ); FAPI_INF("%s recording bad bits for DIMM%d rank %d (%d) rp %d", mss::c_str(i_target), l_dimm_index, mss::index(r), r, l_rp); FAPI_ASSERT( l_rp < MAX_RANK_PAIRS, fapi2::MSS_INVALID_RANK_PAIR() .set_RANK_PAIR(l_rp) .set_FUNCTION(RECORD_BAD_BITS_HELPER) .set_MCA_TARGET(mss::find_target(i_target)), "%s Invalid rank pair (%d) in record_bad_bits_helper", mss::c_str(i_target), l_rp); // We loop over the disable registers for this rank pair, and shift the bits from the attribute // array in to the disable registers { // Grab a pointer to our argument simply to make the code a little easier to read uint8_t* l_bad_bits = &(o_bad_dq[mss::index(r)][0]); // The values we'll pull from the registers in the scom suckah below. We only read the registers for // our current rank pair. std::vector< std::pair< fapi2::buffer, fapi2::buffer > > l_register_value; FAPI_TRY( mss::scom_suckah(mss::find_target(i_target), TT::BIT_DISABLE_REG[l_rp], l_register_value) ); // Where in the array we are, incremented by two for every DP size_t l_byte_index = 0; for (const auto& v : l_register_value) { // Grab the left and right bytes from the bad bits register and stick them in the // nth and nth + 1 bytes of the array l_bad_bits[l_byte_index] = (v.first & 0xFF00) >> 8; l_bad_bits[l_byte_index + 1] = v.first & 0x00FF; FAPI_DBG("%s Recording ATTR_BAD_DQ_BITMAP value 0x%0lX to 0x%X, 0x%X from 0x%016lx", mss::c_str(i_target), v.first, l_bad_bits[l_byte_index], l_bad_bits[l_byte_index + 1], v.first); l_byte_index += 2; } } } fapi_try_exit: return fapi2::current_err; } /// /// @brief Process read vref calibration errors /// @param[in] i_target the fapi2 target of the DIMM /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired /// fapi2::ReturnCode process_rdvref_cal_errors( const fapi2::Target& i_target ) { typedef dp16Traits TT; const auto& l_mca = mss::find_target(i_target); // We want the index as we want to grab the register for the error log too. size_t l_index = 0; std::vector> l_data; // Boolean to keep track of if a fail was calibration related, or scom related bool l_cal_fail = false; // Suck all the cal error bits out ... FAPI_TRY( mss::scom_suckah(l_mca, TT::RD_VREF_CAL_ERROR_REG, l_data) ); FAPI_INF("%s Processing RD_VREF_CAL_ERROR", mss::c_str(i_target)); // From here on out, the FIR's are all cal fails l_cal_fail = true; for (const auto& v : l_data) { // They should all be 0's. If they're not, we have a problem. FAPI_ASSERT(v == 0, fapi2::MSS_FAILED_RDVREF_CAL() .set_MCA_TARGET(l_mca) .set_DIMM_TARGET(i_target) .set_REGISTER(TT::RD_VREF_CAL_ERROR_REG[l_index]) .set_VALUE(v), "DP16 failed read vref calibration on %s. register 0x%016lx value 0x%016lx", mss::c_str(l_mca), TT::RD_VREF_CAL_ERROR_REG[l_index], v); ++l_index; } FAPI_INF("%s RD_VREF_CAL_ERROR complete", mss::c_str(i_target)); return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: // If the FIR's are cal fails, then check to see if FIRs or PLL fails were the cause return mss::check::fir_or_pll_fail( l_mca, fapi2::current_err, l_cal_fail); } /// /// @brief Process write vref calibration errors /// @param[in] i_target the fapi2 target of the DIMM /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired /// fapi2::ReturnCode process_wrvref_cal_errors( const fapi2::Target& i_target ) { typedef dp16Traits TT; const auto& l_mca = mss::find_target(i_target); // All PHY registers are 16 bits and start at bit 48 bits 0-47 are filler constexpr uint64_t DATA_START = 48; constexpr uint64_t DATA_LEN = 16; // We want the index as we want to grab the register for the error log too. uint64_t l_index = 0; std::vector, fapi2::buffer>> l_data; std::vector, fapi2::buffer>> l_mask; // Boolean to keep track of if a fail was calibration related, or scom related bool l_cal_fail = false; // Suck all the cal error bits out ... FAPI_TRY( mss::scom_suckah(l_mca, TT::WR_VREF_ERROR_REG, l_data) ); FAPI_TRY( mss::scom_suckah(l_mca, TT::WR_VREF_ERROR_MASK_REG, l_mask) ); // From here on out, the FIR's are all cal fails l_cal_fail = true; // Loop through both data and mask { // Note: ideally these would be cbegin/cend, but HB doesn't support constant iterators for vectors auto l_data_it = l_data.begin(); auto l_mask_it = l_mask.begin(); for(; (l_data_it < l_data.end()) && (l_mask_it < l_mask.end()); ++l_mask_it, ++l_data_it, ++l_index) { // Not sure if there's value add to a function to do these, but it's 2x repetition, so not bad to maintain // WR VREF can either escalate "error" bits as errors or informational, based upon a mask FAPI_INF("%s DP[%lu] WR VREF[%d] ERROR 0x%016lx MASK 0x%016lx", mss::c_str(i_target), l_index, 0, l_data_it->first, l_mask_it->first); FAPI_INF("%s DP[%lu] WR VREF[%d] ERROR 0x%016lx MASK 0x%016lx", mss::c_str(i_target), l_index, 1, l_data_it->second, l_mask_it->second); // Inverts as a 1 bit indicates an informational error. we only want to log true errors fapi2::buffer l_mask_compare = l_mask_it->first; l_mask_compare.flipBit(); // Now does bitwise anding to determine what's an actual error w/ the masking // The ffdc will collect all of the registers, so if we fail out on the first register // We'll know if we failed other ones via the register dump FAPI_ASSERT(0 == (l_mask_compare & l_data_it->first), fapi2::MSS_FAILED_WRVREF_CAL() .set_MCA_TARGET(l_mca) .set_DIMM_TARGET(i_target) .set_REGISTER(TT::WR_VREF_ERROR_REG[l_index].first) .set_VALUE(l_data_it->first) .set_MASK(l_mask_it->first), "DP16 failed write vref calibration on %s. register 0x%016lx value 0x%016lx mask 0x%016lx", mss::c_str(i_target), TT::WR_VREF_ERROR_REG[l_index].first, l_data_it->first, l_mask_it->first); l_mask_compare = l_mask_it->second; l_mask_compare.flipBit(); FAPI_ASSERT(0 == (l_mask_compare & l_data_it->second), fapi2::MSS_FAILED_WRVREF_CAL() .set_MCA_TARGET(l_mca) .set_DIMM_TARGET(i_target) .set_REGISTER(TT::WR_VREF_ERROR_REG[l_index].second) .set_VALUE(l_data_it->second) .set_MASK(l_mask_it->second), "DP16 failed write vref calibration on %s. register 0x%016lx value 0x%016lx mask 0x%016lx", mss::c_str(i_target), TT::WR_VREF_ERROR_REG[l_index].second, l_data_it->second, l_mask_it->second); } } FAPI_INF("%s WRVREF_CAL_ERROR complete", mss::c_str(i_target)); return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: // If the FIR's are cal fails, then check to see if FIR's were the cause return mss::check::fir_or_pll_fail( l_mca, fapi2::current_err, l_cal_fail); } /// /// @brief Write FORCE_FIFO_CAPTURE to all DP16 instances /// Force DQ capture in Read FIFO to support DDR4 LRDIMM calibration /// @param[in] i_target the fapi2 target of the port /// @param[in] i_state mss::states::ON or mss::states::OFF /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// template<> fapi2::ReturnCode write_force_dq_capture( const fapi2::Target& i_target, const mss::states i_state) { typedef dp16Traits TT; fapi2::buffer l_data; // read the data from one of the RD_DIA_CONFIG5 registers // because the value should be the same for other registers FAPI_TRY(mss::getScom(i_target, MCA_DDRPHY_DP16_RD_DIA_CONFIG5_P0_0, l_data)); l_data.writeBit(i_state); FAPI_TRY( mss::scom_blastah(i_target, TT::RD_DIA_CONFIG5_REG, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Writes DATA_BIT_ENABLE0 to all DP16 instances /// @param[in] i_target the fapi2 target of the port /// @param[in] i_state mss::states::ON or mss::states::OFF /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// template< > fapi2::ReturnCode write_data_bit_enable0( const fapi2::Target& i_target, const mss::states i_state) { typedef dp16Traits TT; // '1'b indicates the DP16 bit is enabled, and is used for sending or receiving // data to or from the memory device. // '0'b indicates the DP16 bit is not used to send or receive data fapi2::buffer l_data; l_data.writeBit(i_state); FAPI_TRY( mss::scom_blastah(i_target, TT::DATA_BIT_ENABLE0_REG, l_data) ); fapi_try_exit: return fapi2::current_err; } /// /// @brief Write DFT_FORCE_OUTPUTS to all DP16 instances /// @param[in] i_target the fapi2 target of the port /// @param[in] i_state mss::states::ON or mss::states::OFF /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// template< > fapi2::ReturnCode write_dft_force_outputs( const fapi2::Target< fapi2::TARGET_TYPE_MCA >& i_target, const mss::states i_state) { typedef dp16Traits TT; // The 24 outputs of the DP16 are forced to a low-impedance state the corresponding DATA_BIT_ENABLE bit is '1'b // and forced to a high-impedence state when the corresponding DATA_BIT_ENABLE bit is '0'b // When a DP16 output is forced to a low-z state, the value driven out, '1'b or '0'b , is determined // by the corresponding DATA_BIT_DIR bit value. // The 24 outputs of the DP16 are not forced when set with '0'b fapi2::buffer l_data; l_data.writeBit(i_state); FAPI_TRY( mss::scom_blastah(i_target, TT::DATA_BIT_ENABLE1_REG, l_data) ); fapi_try_exit: return fapi2::current_err; } namespace wr_vref { /// /// @brief Gets the WR VREF range based upon the composite range /// @param[in] i_value the composite range value /// @return l_range the JEDEC WR VREF range /// uint8_t get_range(const uint64_t i_value) { // According to JEDEC range 1 uses a 0 and range 2 uses a 1 constexpr uint64_t RANGE1 = 0x00; constexpr uint64_t RANGE2 = 0x01; const uint8_t l_range = ((i_value >= WR_VREF_CROSSOVER_RANGE) ? RANGE1 : RANGE2); return l_range; } /// /// @brief Gets the WR VREF value based upon the composite range /// @param[in] i_value the composite range value /// @return l_range the JEDEC WR VREF value /// uint8_t get_value(const uint64_t i_value) { // Subtract out the crossover range if need be // Remember, the JEDEC range overlaps for a number of VREFs // The crossover range is used to offset the start of the JEDEC range that is higher than the other const uint8_t l_value = ((i_value >= WR_VREF_CROSSOVER_RANGE) ? (i_value - WR_VREF_CROSSOVER_RANGE) : (i_value)); return l_value; } /// /// @brief Gets the WR VREF value based upon the inputted values /// @param[in] i_range the JEDEC range to use /// @param[in] i_value the JEDED value to use /// @return l_range the JEDEC WR VREF value /// uint64_t compute_composite_value(const uint64_t i_range, const uint64_t i_value) { // Add in the crossover range if need be // Remember, the JEDEC range overlaps for a number of VREFs // The crossover range is used to offset the start of the JEDEC range that is higher than the other constexpr uint64_t USE_CROSSOVER_RANGE = 0; return i_value + ((i_range == USE_CROSSOVER_RANGE) ? WR_VREF_CROSSOVER_RANGE : 0); } /// /// @brief Offsets the WR VREF train and range values based upon the offset attribute /// @param[in] i_target the fapi2 target of the port /// @param[in,out] io_train_range - train range value to update /// @param[in,out] io_train_value - train range value to update /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// fapi2::ReturnCode offset_values( const fapi2::Target& i_target, uint8_t& io_train_range, uint8_t& io_train_value ) { const auto& l_mcs = mss::find_target(i_target); // Computing the composite range simplifies the logic for offsetting a WR VREF range and value int64_t l_composite = compute_composite_value(io_train_range, io_train_value); int8_t l_offset = 0; FAPI_TRY( mss::wr_vref_offset(mss::find_target(i_target), l_offset) ); l_composite += l_offset; // Check that the value is in range FAPI_ASSERT( (l_composite >= 0) && (l_composite <= WR_VREF_MAX_COMPOSITE_RANGE), fapi2::MSS_OFFSET_WR_VREF_OUT_OF_RANGE() .set_TARGET(i_target) .set_MCS_TARGET(l_mcs) .set_MAX(WR_VREF_MAX_COMPOSITE_RANGE) .set_OFFSET(l_offset) .set_COMPOSITE(l_composite), "%s Offset composite range is out of bounds (%d - %d): %d offset is: %d", mss::c_str(i_target), 0, WR_VREF_MAX_COMPOSITE_RANGE, l_composite, l_offset ); io_train_range = get_range(l_composite); io_train_value = get_value(l_composite); fapi_try_exit: return fapi2::current_err; } /// /// @brief Checks that the rank pair and DRAM are in bounds /// @param[in] i_target - the MCA target on which to operate /// @param[in] i_rp - the rank pair on which to operate /// @param[in] i_dram - the DRAM that needs to have the workaround applied to it /// @param[in] i_function - the calling function to callout in FFDC /// fapi2::ReturnCode check_rp_and_dram( const fapi2::Target& i_target, const uint64_t i_rp, const uint64_t i_dram, const ffdc_function_codes i_function ) { fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; // Checks inputs uint8_t l_width[MAX_DIMM_PER_PORT] = {}; FAPI_TRY( mss::eff_dram_width(i_target, l_width) ); // Checks for DRAM in bounds { const uint64_t MAX_NUM_DRAM = l_width[0] == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8 ? MAX_DRAMS_X8 : MAX_DRAMS_X4; FAPI_ASSERT(i_dram < MAX_NUM_DRAM, fapi2::MSS_INVALID_INDEX_PASSED() .set_INDEX(i_dram) .set_FUNCTION(i_function), "%s Invalid DRAM index passed to check_for_dram_disabled (%d)", mss::c_str(i_target), i_dram); } // Checks for i_rp in bounds FAPI_ASSERT(i_rp < MAX_RANK_PAIRS, fapi2::MSS_INVALID_RANK(). set_PORT_TARGET(i_target). set_RANK(i_rp). set_FUNCTION(i_function), "%s rank pair is out of bounds %lu", mss::c_str(i_target), i_rp); fapi_try_exit: return fapi2::current_err; } /// /// @brief Determine the dp and reg number to the give DRAM /// @param[in] i_target - the fapi2 target type MCA /// @param[in] i_dram - the DRAM /// @param[out] o_dp - the dp number for the given DRAM /// @param[out] o_reg_num - the register number for the given DRAM /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// fapi2::ReturnCode dram_to_dp_reg(const fapi2::Target& i_target, const uint64_t i_dram, uint64_t& o_dp, uint64_t& o_reg_num) { uint8_t l_widths[mss::PORTS_PER_MCS] = {0}; typedef dp16Traits TT; FAPI_TRY( mss::eff_dram_width(i_target, l_widths) ); // Calculate the address // The assumption here is that the i_dram is within bound. Therefore, the calculated dp and reg_num should also be within bound. { const auto l_dram_per_dp = (l_widths[0] == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? BYTES_PER_DP : NIBBLES_PER_DP; o_dp = i_dram / l_dram_per_dp; o_reg_num = (i_dram % l_dram_per_dp) / TT::NUM_DRAM_PER_REG; } fapi_try_exit: return fapi2::current_err; } /// /// @brief Gets the write vref register /// @param[in] i_target - the fapi2 target type MCA /// @param[in] i_rp - rank pair, to make sure the dram and rp are within bounds /// @param[in] i_dram - the DRAM /// @param[out] o_reg - the dp16 wr_vref register for the rank pair and dram /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// fapi2::ReturnCode get_wr_vref_rp_reg(const fapi2::Target& i_target, const uint64_t i_rp, const uint64_t i_dram, uint64_t& o_reg) { uint64_t l_dp = 0; uint64_t l_reg_num = 0; // TODO: RTC187141 Clean up WR_VREF register traits typedef dp16Traits TT; const std::vector >> REGS = { TT::WR_VREF_VALUE_RP0_REG, TT::WR_VREF_VALUE_RP1_REG, TT::WR_VREF_VALUE_RP2_REG, TT::WR_VREF_VALUE_RP3_REG, }; // Make sure the rank pair and dram are within bounds FAPI_TRY( check_rp_and_dram(i_target, i_rp, i_dram, ffdc_function_codes::DRAM_TO_RP_REG)); // If the dram is within bound, compute the vector address FAPI_TRY(dram_to_dp_reg(i_target, i_dram, l_dp, l_reg_num)); o_reg = (l_reg_num == 0) ? REGS[i_rp][l_dp].first : REGS[i_rp][l_dp].second; fapi_try_exit: return fapi2::current_err; } /// /// @brief Gets the write vref registers by rank pair /// @param[in] i_rp - rank pair, to make sure the dram and rp are within bounds /// @param[out] o_regs - the dp16 wr_vref registers for the rank pair /// fapi2::ReturnCode get_wr_vref_regs_by_rp(const uint64_t i_rp, std::vector>& o_reg) { typedef dp16Traits TT; switch (i_rp) { case 0: o_reg = TT::WR_VREF_VALUE_RP0_REG; break; case 1: o_reg = TT::WR_VREF_VALUE_RP1_REG; break; case 2: o_reg = TT::WR_VREF_VALUE_RP2_REG; break; case 3: o_reg = TT::WR_VREF_VALUE_RP3_REG; break; default: FAPI_ASSERT( false, fapi2::MSS_RP_OUT_OF_RANGE() .set_RP(i_rp), "RP out of range %d", i_rp); break; } fapi_try_exit: return fapi2::current_err; } } // close namespace wr_vref } // close namespace dp16 /// /// @brief A generic bad bits setter - Nimbus specialization /// @param[in] i_target the fapi2 target oon which training was conducted /// @param[in] i_array the bad bits to set /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired /// template <> fapi2::ReturnCode set_bad_dq_bitmap(const fapi2::Target& i_target, uint8_t (&i_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) { return FAPI_ATTR_SET(fapi2::ATTR_BAD_DQ_BITMAP, i_target, i_array); } } // close namespace mss