From e3f7d637814b291cf2f95297ba18f947b45f6dc9 Mon Sep 17 00:00:00 2001 From: Brian Silver Date: Fri, 20 Jan 2017 09:53:24 -0600 Subject: Map from Centaur canonical rank numbering to Nimbus Reassigned rank pairs to be DIMM0 ranks first ZCAL config ODT values from VPD Change-Id: If24e74e9e878c24125540e324cad40a7218c59ff Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35162 Dev-Ready: Louis Stermole Reviewed-by: Brian R. Silver Tested-by: Jenkins Server Tested-by: Hostboot CI Reviewed-by: STEPHEN GLANCY Reviewed-by: JACOB L. HARVEY Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35164 Tested-by: FSP CI Jenkins Tested-by: Jenkins OP Build CI Reviewed-by: Christian R. Geddes --- .../p9/procedures/hwp/memory/lib/phy/ddr_phy.C | 180 ++++++++++++--------- 1 file changed, 105 insertions(+), 75 deletions(-) (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C') 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 e58ab08ef..f2ee912bf 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 @@ -960,17 +960,26 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target& /// /// @brief Setup odt_wr/rd_config -/// @param[in] i_target the MCA target associated with this cal setup +/// @param[in] i_target the MCA target +/// @param[in] i_dimm_count the number of DIMM presently on the target +/// @param[in] i_odt_rd the RD ODT values from VPD +/// @param[in] i_odt_wr the WR ODT values from VPD /// @return FAPI2_RC_SUCCESS iff setup was successful /// template<> -fapi2::ReturnCode reset_odt_config( const fapi2::Target& i_target ) +fapi2::ReturnCode reset_odt_config_helper( + const fapi2::Target& i_target, + const uint64_t i_dimm_count, + const uint8_t i_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM], + const uint8_t i_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]) { - uint8_t l_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]; - uint8_t l_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]; + // The fields in the ODT VPD are 8 bits wide, but we only use the left-most 2 bits + // of each nibble. The encoding for each rank in the VPD is + // [Dimm0 ODT0][Dimm0 ODT1][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A] - FAPI_TRY( mss::vpd_mt_odt_rd(i_target, &(l_odt_rd[0][0])) ); - FAPI_TRY( mss::vpd_mt_odt_wr(i_target, &(l_odt_wr[0][0])) ); + constexpr uint64_t BIT_FIELD0_START = 0; + constexpr uint64_t BIT_FIELD1_START = 4; + constexpr uint64_t BIT_FIELD_LENGTH = 2; // Nimbus PHY is more or less hard-wired for 2 DIMM/port 4R/DIMM // So there's not much point in looping over DIMM or ranks. @@ -983,56 +992,57 @@ fapi2::ReturnCode reset_odt_config( const fapi2::Target& // 48:55, ATTR_VPD_ODT_RD[0][0][0]; # when Read of Rank0 // 56:63, ATTR_VPD_ODT_RD[0][0][1]; # when Read of Rank1 fapi2::buffer l_data; + uint8_t l_vpd_0 = 0; + uint8_t l_vpd_1 = 0; - l_data.insertFromRight(l_odt_rd[0][0]); - l_data.insertFromRight(l_odt_rd[0][1]); + // Extract the 2 DIMM0 bits we need from the VPD. + fapi2::buffer(i_odt_rd[0][0]).extract(l_vpd_0); + fapi2::buffer(i_odt_rd[0][1]).extract(l_vpd_1); + // Extract the 2 DIMM1 bits we need from the VPD. + fapi2::buffer(i_odt_rd[0][0]).extract(l_vpd_0); + fapi2::buffer(i_odt_rd[0][1]).extract(l_vpd_1); + + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", i_odt_rd[0][0], l_vpd_0); + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", i_odt_rd[0][1], l_vpd_1); + + l_data.insert(l_vpd_0); + l_data.insert(l_vpd_1); FAPI_INF("odt_rd_config0: 0x%016llx", uint64_t(l_data)); FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_RD_CONFIG0_P0, l_data) ); } + // Remember Centaur-canonical rank numbering is different from Nimbus numbering. Here, + // we need to lay the canonically defined VPD into the proper subfield based on DIMM config. { - // DPHY01_DDRPHY_SEQ_ODT_RD_CONFIG1_P0 - // 48:55, ATTR_VPD_ODT_RD[0][0][2]; # when Read of Rank2 - // 56:63, ATTR_VPD_ODT_RD[0][0][3]; # when Read of Rank3 - fapi2::buffer l_data; + // "dual drop" which means what is in the VPD as ranks 4/5 go in to 2/3 + fapi2::buffer l_values2 = (i_dimm_count == MAX_DIMM_PER_PORT) ? i_odt_rd[1][0] : i_odt_rd[0][2]; + fapi2::buffer l_values3 = (i_dimm_count == MAX_DIMM_PER_PORT) ? i_odt_rd[1][1] : i_odt_rd[0][3]; - l_data.insertFromRight(l_odt_rd[0][2]); - l_data.insertFromRight(l_odt_rd[0][3]); - FAPI_INF("odt_rd_config1: 0x%016llx", uint64_t(l_data)); - FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_RD_CONFIG1_P0, l_data) ); - } + uint8_t l_vpd_2 = 0; + uint8_t l_vpd_3 = 0; + + // Extract the 2 DIMM0 bits we need from the VPD. + l_values2.extract(l_vpd_2); + l_values3.extract(l_vpd_3); + // Extract the 2 DIMM1 bits we need from the VPD. + l_values2.extract(l_vpd_2); + l_values3.extract(l_vpd_3); + + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", l_values2, l_vpd_2); + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", l_values3, l_vpd_3); - { // DPHY01_DDRPHY_SEQ_ODT_RD_CONFIG2_P0 // 48:55, ATTR_VPD_ODT_RD[0][1][0]; # when Read of Rank4 // 56:63, ATTR_VPD_ODT_RD[0][1][1]; # when Read of Rank5 fapi2::buffer l_data; - l_data.insertFromRight(l_odt_rd[1][0]); - l_data.insertFromRight(l_odt_rd[1][1]); - FAPI_INF("odt_rd_config2: 0x%016llx", uint64_t(l_data)); - FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_RD_CONFIG2_P0, l_data) ); + l_data.insert(l_vpd_2); + l_data.insert(l_vpd_3); + FAPI_INF("odt_rd_config1: 0x%016llx", uint64_t(l_data)); + FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_RD_CONFIG1_P0, l_data) ); } - { - // DPHY01_DDRPHY_SEQ_ODT_RD_CONFIG3_P0 - // 48:55, ATTR_VPD_ODT_RD[0][1][2]; # when Read of Rank6 - // 56:63, ATTR_VPD_ODT_RD[0][1][3]; # when Read of Rank7 - fapi2::buffer l_data; - - l_data.insertFromRight(l_odt_rd[1][2]); - l_data.insertFromRight(l_odt_rd[1][3]); - FAPI_INF("odt_rd_config3: 0x%016llx", uint64_t(l_data)); - FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_RD_CONFIG3_P0, l_data) ); - } + // TODO RTC:167929 Can ODT VPD processing be shared between RD and WR? // // ODT Write @@ -1042,56 +1052,76 @@ fapi2::ReturnCode reset_odt_config( const fapi2::Target& // 48:55, ATTR_VPD_ODT_WR[0][0][0]; # when Read of Rank0 // 56:63, ATTR_VPD_ODT_WR[0][0][1]; # when Read of Rank1 fapi2::buffer l_data; + uint8_t l_vpd_0 = 0; + uint8_t l_vpd_1 = 0; + + // Extract the 2 DIMM0 bits we need from the VPD. + fapi2::buffer(i_odt_wr[0][0]).extract(l_vpd_0); + fapi2::buffer(i_odt_wr[0][1]).extract(l_vpd_1); + // Extract the 2 DIMM1 bits we need from the VPD. + fapi2::buffer(i_odt_wr[0][0]).extract(l_vpd_0); + fapi2::buffer(i_odt_wr[0][1]).extract(l_vpd_1); + + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", i_odt_wr[0][0], l_vpd_0); + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", i_odt_wr[0][1], l_vpd_1); - l_data.insertFromRight(l_odt_wr[0][0]); - l_data.insertFromRight(l_odt_wr[0][1]); + l_data.insert(l_vpd_0); + l_data.insert(l_vpd_1); FAPI_INF("odt_wr_config0: 0x%016llx", uint64_t(l_data)); FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_WR_CONFIG0_P0, l_data) ); } { - // DPHY01_DDRPHY_SEQ_ODT_WR_CONFIG1_P0 - // 48:55, ATTR_VPD_ODT_WR[0][0][2]; # when Read of Rank2 - // 56:63, ATTR_VPD_ODT_WR[0][0][3]; # when Read of Rank3 - fapi2::buffer l_data; + // "dual drop" which means what is in the VPD as ranks 4/5 go in to 2/3 + fapi2::buffer l_values2 = (i_dimm_count == MAX_DIMM_PER_PORT) ? i_odt_wr[1][0] : i_odt_wr[0][2]; + fapi2::buffer l_values3 = (i_dimm_count == MAX_DIMM_PER_PORT) ? i_odt_wr[1][1] : i_odt_wr[0][3]; - l_data.insertFromRight(l_odt_wr[0][2]); - l_data.insertFromRight(l_odt_wr[0][3]); - FAPI_INF("odt_wr_config1: 0x%016llx", uint64_t(l_data)); - FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_WR_CONFIG1_P0, l_data) ); - } + uint8_t l_vpd_2 = 0; + uint8_t l_vpd_3 = 0; + + // Extract the 2 DIMM0 bits we need from the VPD. + l_values2.extract(l_vpd_2); + l_values3.extract(l_vpd_3); + // Extract the 2 DIMM1 bits we need from the VPD. + l_values2.extract(l_vpd_2); + l_values3.extract(l_vpd_3); + + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", l_values2, l_vpd_2); + FAPI_DBG("vpd: 0x%02x extract: 0x%02x", l_values3, l_vpd_3); - { // DPHY01_DDRPHY_SEQ_ODT_WR_CONFIG2_P0 // 48:55, ATTR_VPD_ODT_WR[0][1][0]; # when Read of Rank4 // 56:63, ATTR_VPD_ODT_WR[0][1][1]; # when Read of Rank5 fapi2::buffer l_data; - l_data.insertFromRight(l_odt_wr[1][0]); - l_data.insertFromRight(l_odt_wr[1][1]); - FAPI_INF("odt_wr_config2: 0x%016llx", uint64_t(l_data)); - FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_WR_CONFIG2_P0, l_data) ); + l_data.insert(l_vpd_2); + l_data.insert(l_vpd_3); + FAPI_INF("odt_wr_config1: 0x%016llx", uint64_t(l_data)); + FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_WR_CONFIG1_P0, l_data) ); } - { - // DPHY01_DDRPHY_SEQ_ODT_WR_CONFIG3_P0 - // 48:55, ATTR_VPD_ODT_WR[0][1][2]; # when Read of Rank6 - // 56:63, ATTR_VPD_ODT_WR[0][1][3]; # when Read of Rank7 - fapi2::buffer l_data; +fapi_try_exit: + return fapi2::current_err; +} - l_data.insertFromRight(l_odt_wr[1][2]); - l_data.insertFromRight(l_odt_wr[1][3]); - FAPI_INF("odt_wr_config3: 0x%016llx", uint64_t(l_data)); - FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_SEQ_ODT_WR_CONFIG3_P0, l_data) ); - } +/// +/// @brief Setup odt_wr/rd_config, reads attributes +/// @param[in] i_target the MCA target associated with this cal setup +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +template<> +fapi2::ReturnCode reset_odt_config( const fapi2::Target& i_target ) +{ + uint8_t l_odt_rd[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]; + uint8_t l_odt_wr[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM]; + + uint64_t l_dimm_count = count_dimm(i_target); + + FAPI_TRY( mss::vpd_mt_odt_rd(i_target, &(l_odt_rd[0][0])) ); + FAPI_TRY( mss::vpd_mt_odt_wr(i_target, &(l_odt_wr[0][0])) ); + + return reset_odt_config_helper( + i_target, l_dimm_count, l_odt_rd, l_odt_wr); fapi_try_exit: return fapi2::current_err; -- cgit v1.2.1