diff options
Diffstat (limited to 'src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_enable.C')
-rw-r--r-- | src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_enable.C | 101 |
1 files changed, 97 insertions, 4 deletions
diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_enable.C b/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_enable.C index c1403be9d..a10f772b6 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_enable.C +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_enable.C @@ -30,17 +30,23 @@ // *HWP HWP Owner: Mark Pizzutillo <mark.pizzutillo@ibm.com> // *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com> // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB #include <fapi2.H> #include <pmic_enable.H> +#include <generic/memory/lib/utils/find.H> +#include <lib/utils/pmic_common_utils.H> #include <lib/utils/pmic_enable_utils.H> +#include <lib/utils/pmic_consts.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> +#include <generic/memory/lib/utils/c_str.H> +#include <mss_generic_attribute_getters.H> extern "C" { /// - /// @brief enable function for pmic module + /// @brief Enable function for pmic module. Calls appropriate enable func with matching DIMM target /// @param[in] i_target ocmb target /// @param[in] i_mode enable mode operation /// @return FAPI2_RC_SUCCESS iff ok @@ -48,7 +54,94 @@ extern "C" fapi2::ReturnCode pmic_enable(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_ocmb_target, const mss::pmic::enable_mode i_mode) { - // TK - L1 implementation, function not filled in yet + auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_ocmb_target); + auto l_pmics = mss::find_targets<fapi2::TARGET_TYPE_PMIC>(i_ocmb_target); + + // Sort by index (low to high) since find_targets may not return the correct order + std::sort(l_dimms.begin(), l_dimms.end(), + [] (const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& l_first_dimm, + const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& l_second_dimm) -> bool + { + return mss::index(l_first_dimm) < mss::index(l_second_dimm); + }); + + std::sort(l_pmics.begin(), l_pmics.end(), + [] (const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& l_first_pmic, + const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& l_second_pmic) -> bool + { + return mss::index(l_first_pmic) < mss::index(l_second_pmic); + }); + + // Start at PMIC0. If there was ever a weird case where there is a 4U dimm + // on the same OCMB as a 2U dimm (is this possible?), + // we would have 6 total PMICs. So, we need to keep + // track of where we left off for the last pmic we enabled + uint8_t l_pmic_index = 0; + + // Not asserting vectors non-empty because there could be OCMBs without DIMMs on them + for (const auto& l_dimm : l_dimms) + { + // Get module height for DIMM to determine the number of PMICs we should be using + uint8_t l_module_height = 0; + FAPI_TRY(mss::attr::get_dram_module_height(l_dimm, l_module_height)); + + if (l_module_height == mss::pmic::module_height::HEIGHT_1U || + l_module_height == mss::pmic::module_height::HEIGHT_2U) + { + // 1U and 2U are the same sequence, use 1U traits + using PMIC_TRAITS = mss::pmic::pmic_traits<mss::pmic::module_height::HEIGHT_1U>; + + uint16_t l_vendor_id = 0; + + // PMIC0 and PMIC1 of each DIMM + for (uint8_t l_current_pmic = 0; l_current_pmic < PMIC_TRAITS::PMICS_PER_DIMM; ++l_current_pmic) + { + const auto l_current_pmic_target = l_pmics[l_pmic_index + l_current_pmic]; + // Get vendor ID + FAPI_TRY(mss::pmic::get_mfg_id[l_current_pmic](l_dimm, l_vendor_id)); + + // Poll to make sure PBULK reports good, then we can enable the chip and write/read registers + FAPI_TRY(mss::pmic::poll_for_pbulk_good(l_current_pmic_target), + "pmic_enable: poll for pbulk good either failed, or returned not good status on PMIC %s", + mss::c_str(l_current_pmic_target)); + + // Call the enable procedure + FAPI_TRY((mss::pmic::enable_chip + <mss::pmic::module_height::HEIGHT_1U> + (l_current_pmic_target, l_dimm, l_vendor_id, i_mode)), + "pmic_enable: Error enabling PMIC %s", mss::c_str(l_current_pmic_target)); + + } + + // Increment by the number of PMICs that were enabled and move on to the next dimm + l_pmic_index += PMIC_TRAITS::PMICS_PER_DIMM; + } + else // 4U DIMM: + { + // Asserting out here as if we see a 4U at this point we shouldn't be able to proceed + // Ugly assert false, but we need the above else later so we will use this for now + FAPI_ASSERT(false, + fapi2::PMIC_DIMM_SPD_4U() + .set_TARGET(l_dimm), + "DIMM %s module height attribute identified as 4U. Not supported yet.", + mss::c_str(l_dimm)); + + // The enable algorithm will be: + // Load SPD for PMIC0 and PMIC1 + // Broadcast enable both together + + // Load SPD for PMIC2 and PMIC3 (which should be the same data as for PMIC0 and PMIC1) + // Broadcast and enable both together + + // using PMIC_TRAITS = mss::pmic::pmic_traits<mss::pmic::module_height::HEIGHT_4U>; + // l_pmic_index += PMIC_TRAITS::PMICS_PER_DIMM; + } + } + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; } -} + +} // extern C |