diff options
author | Louis Stermole <stermole@us.ibm.com> | 2016-08-04 12:43:48 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2016-08-22 11:47:44 -0400 |
commit | 67717a4f64e8cb1728fe2d2d8890394d575d02c2 (patch) | |
tree | 26f96d8b2550a8a52ed9b020d1707b79eca20a62 /src/import/chips/p9/procedures/hwp | |
parent | 48f839b9b7e30d1d96807e25cb71a35877eb1184 (diff) | |
download | talos-hostboot-67717a4f64e8cb1728fe2d2d8890394d575d02c2.tar.gz talos-hostboot-67717a4f64e8cb1728fe2d2d8890394d575d02c2.zip |
Adding initialization of PHY RD_VREF according to ATTR_MSS_VPD_MT_VREF_MC_RD
Change-Id: Ie25cff42202834185c796237de2b5dfd387b3c24
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/27997
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Brian R. Silver <bsilver@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com>
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28116
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp')
4 files changed, 166 insertions, 1 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C index 2173fd184..dcddc4313 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C @@ -664,6 +664,9 @@ fapi2::ReturnCode phy_scominit(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target FAPI_TRY( mss::dp16::reset_write_clock_enable(p, l_pairs) ); FAPI_TRY( mss::dp16::reset_read_clock_enable(p, l_pairs) ); + // Reset Read VREF according to ATTR_MSS_VPD_MT_VREF_MC_RD value + FAPI_TRY( mss::dp16::reset_rd_vref(p) ); + // Write Control reset FAPI_TRY( mss::wc::reset(p) ); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C index c725f5615..c7198d00c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C @@ -210,6 +210,74 @@ const std::vector< std::pair<uint64_t, uint64_t> > dp16Traits<TARGET_TYPE_MCA>:: { MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_4, MCA_DDRPHY_DP16_CTLE_CTL_BYTE1_P0_4 }, }; +// Definition of the DP16 RD_VREF Control registers +// DP16 RD_VREF Control registers all come in pairs - one per 8 bits +// 5 DP16 per MCA gives us 10 Registers. +const std::vector< std::pair<uint64_t, uint64_t> > dp16Traits<TARGET_TYPE_MCA>::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 }, +}; + +/// +/// @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<T> +/// @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<T> > +fapi2::ReturnCode rd_vref_bitfield_helper( const fapi2::Target<T>& 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_TARGET(i_target), + "Target %s VPD_MT_VREF_MC_RD percentage out of bounds (%d - %d): %d", + c_str(i_target), + TT::MAX_RD_VREF, + TT::MIN_RD_VREF, + 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 { @@ -841,5 +909,49 @@ 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<TARGET_TYPE_MCA>& i_target ) +{ + typedef dp16Traits<TARGET_TYPE_MCA> TT; + + std::vector< std::pair<fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > > l_data; + uint64_t l_vref_bitfield = 0; + uint8_t is_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( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<TARGET_TYPE_SYSTEM>(), is_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 (!is_sim) + { + // Do a read/modify/write + FAPI_TRY( mss::scom_suckah(i_target, TT::RD_VREF_CNTRL_REG, l_data) ); + + for (auto& l_regpair : l_data) + { + // Write the same value for all the DQ and DQS nibbles + l_regpair.first.insertFromRight<TT::RD_VREF_BYTE0_NIB0, TT::RD_VREF_BYTE0_NIB0_LEN>(l_vref_bitfield); + l_regpair.first.insertFromRight<TT::RD_VREF_BYTE0_NIB1, TT::RD_VREF_BYTE0_NIB1_LEN>(l_vref_bitfield); + l_regpair.second.insertFromRight<TT::RD_VREF_BYTE1_NIB2, TT::RD_VREF_BYTE1_NIB2_LEN>(l_vref_bitfield); + l_regpair.second.insertFromRight<TT::RD_VREF_BYTE1_NIB3, TT::RD_VREF_BYTE1_NIB3_LEN>(l_vref_bitfield); + } + + FAPI_INF("blasting VREF settings from VPD to dp16 RD_VREF byte0 and byte1"); + + FAPI_TRY( mss::scom_blastah(i_target, TT::RD_VREF_CNTRL_REG, l_data) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + } // close namespace dp16 } // close namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H index 33a9f3c4c..b2c7b98c6 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H @@ -123,6 +123,15 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA> // any of this for some time. static constexpr uint64_t DLL_PER_DP16 = 2; + // Maximum and minimum RD_VREF percentage of VDD. We only test against max and min because + // there are so many allowable values. + static constexpr uint64_t MAX_RD_VREF = fapi2::ENUM_ATTR_MSS_VPD_MT_VREF_MC_RD_VDD91875; + static constexpr uint64_t MIN_RD_VREF = fapi2::ENUM_ATTR_MSS_VPD_MT_VREF_MC_RD_VDD31208; + + // Constants used for converting RD_VREF percentage to DAC settings, normalized to integers + static constexpr uint64_t RD_VREF_DVDD = 12; + static constexpr uint64_t RD_VREF_DAC_STEP = 6500; + // Vectors of DP16 registers. The pair represents the two DLL in per DP16 static const std::vector< std::pair<uint64_t, uint64_t> > DLL_CNFG_REG; static const std::vector< std::pair<uint64_t, uint64_t> > DLL_DAC_LOWER_REG; @@ -137,6 +146,7 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA> static const std::vector< std::pair<uint64_t, uint64_t> > AC_BOOST_CNTRL_REG; static const std::vector< std::pair<uint64_t, uint64_t> > CTLE_CNTRL_REG; + static const std::vector< std::pair<uint64_t, uint64_t> > RD_VREF_CNTRL_REG; static const std::vector< uint64_t > DATA_BIT_DIR1; enum @@ -161,9 +171,32 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA> CTLE_ODD_CAP_LEN = MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_0_01_NIB_1_3_DQSEL_CAP_LEN, CTLE_ODD_RES = MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_0_01_NIB_1_3_DQSEL_RES, CTLE_ODD_RES_LEN = MCA_DDRPHY_DP16_CTLE_CTL_BYTE0_P0_0_01_NIB_1_3_DQSEL_RES_LEN, + + RD_VREF_BYTE0_NIB0 = MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_0_01_NIB0, + RD_VREF_BYTE0_NIB0_LEN = MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_0_01_NIB0_LEN, + RD_VREF_BYTE0_NIB1 = MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_0_01_NIB1, + RD_VREF_BYTE0_NIB1_LEN = MCA_DDRPHY_DP16_RD_VREF_BYTE0_DAC_P0_0_01_NIB1_LEN, + RD_VREF_BYTE1_NIB2 = MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_0_01_NIB2, + RD_VREF_BYTE1_NIB2_LEN = MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_0_01_NIB2_LEN, + RD_VREF_BYTE1_NIB3 = MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_0_01_NIB3, + RD_VREF_BYTE1_NIB3_LEN = MCA_DDRPHY_DP16_RD_VREF_BYTE1_DAC_P0_0_01_NIB3_LEN, }; }; +/// +/// @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<T> +/// @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<T> > +fapi2::ReturnCode rd_vref_bitfield_helper( const fapi2::Target<T>& i_target, + const uint32_t i_vref, + uint64_t& o_bitfield ); + namespace dp16 { @@ -528,6 +561,16 @@ template< fapi2::TargetType T, typename TT = dp16Traits<T> > fapi2::ReturnCode reset_dll_vreg_config1( const fapi2::Target<T>& i_target ); /// +/// @brief Configure Read VREF Registers +/// @tparam T the fapi2::TargetType +/// @tparam TT the target traits +/// @param[in] i_target a fapi2 target +/// @return FAPI2_RC_SUCCESs iff ok +/// +template< fapi2::TargetType T, typename TT = dp16Traits<T> > +fapi2::ReturnCode reset_rd_vref( const fapi2::Target<T>& i_target ); + +/// /// Specializations /// @@ -598,6 +641,13 @@ fapi2::ReturnCode reset_io_tx_config0( const fapi2::Target<fapi2::TARGET_TYPE_MC /// fapi2::ReturnCode reset_dll_vreg_config1( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target ); +/// +/// @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<fapi2::TARGET_TYPE_MCA>& i_target ); + } // close namespace dp16 } // close namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/fake_vpd.C b/src/import/chips/p9/procedures/hwp/memory/lib/utils/fake_vpd.C index dea9d53b3..5c9982d38 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/fake_vpd.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/fake_vpd.C @@ -57,7 +57,7 @@ static constexpr uint8_t raw_mt[raw_mt_size] = 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x16, 0x16, 0x00, 0x01, - 0x31, 0xaa, 0x00, 0x01, 0x31, 0xaa, 0x80, 0x23, 0x80, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0xfd, 0x00, 0x01, 0x31, 0xfd, 0x80, 0x23, 0x80, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; |