diff options
Diffstat (limited to 'src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_enable_utils.C')
-rw-r--r-- | src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_enable_utils.C | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_enable_utils.C b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_enable_utils.C index 65bf83b5a..ec85b7da4 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_enable_utils.C +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_enable_utils.C @@ -380,5 +380,143 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Order PMICs by sequence defined in the SPD +/// +/// @param[in] i_dimm DIMM target to pull SPD fields from +/// @param[in] i_dimm_index index of the DIMM target +/// @param[in] i_pmics_per_dimm number of PMICs per dimm +/// @param[in,out] io_pmics vector of PMICs that will be re-ordered in place +/// @return fapi2::ReturnCode +/// +fapi2::ReturnCode order_pmics_by_sequence( + const fapi2::Target<fapi2::TARGET_TYPE_DIMM> i_dimm, + const uint8_t i_dimm_index, + const uint8_t i_pmics_per_dimm, + std::vector<fapi2::Target<fapi2::TARGET_TYPE_PMIC>>& io_pmics) +{ + const auto l_begin_offset = i_dimm_index * i_pmics_per_dimm; + const auto l_iterator_begin = io_pmics.begin() + l_begin_offset; + const auto l_iterator_end = l_iterator_begin + i_pmics_per_dimm; + + fapi2::ReturnCode l_rc_0_out = fapi2::FAPI2_RC_SUCCESS; + fapi2::ReturnCode l_rc_1_out = fapi2::FAPI2_RC_SUCCESS; + + std::sort(l_iterator_begin, l_iterator_end, [&l_rc_0_out, &l_rc_1_out, i_dimm] ( + const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& l_first_pmic, + const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& l_second_pmic) -> bool + { + // Here we should only be dealing with PMICs of the same DIMM. So we can just check the first one which dimm we're on + uint8_t l_sequence_pmic_0 = 0; + uint8_t l_sequence_pmic_1 = 0; + + // Need to pull out the RC's manually. Goto's in lambdas apparently don't play nicely + fapi2::ReturnCode l_rc_0 = mss::pmic::get_sequence[mss::index(l_first_pmic)](i_dimm, l_sequence_pmic_0); + fapi2::ReturnCode l_rc_1 = mss::pmic::get_sequence[mss::index(l_second_pmic)](i_dimm, l_sequence_pmic_1); + + // Hold on to an error if we see one + if (l_rc_0 != fapi2::FAPI2_RC_SUCCESS) + { + l_rc_0_out = l_rc_0; + } + if (l_rc_1 != fapi2::FAPI2_RC_SUCCESS) + { + l_rc_1_out = l_rc_1; + } + + return l_sequence_pmic_0 < l_sequence_pmic_1; + }); + + FAPI_TRY(l_rc_0_out, "Error getting sequencing attributes for PMICs associated with DIMM 0 target %s", + mss::c_str(i_dimm)); + FAPI_TRY(l_rc_1_out, "Error getting sequencing attributes for PMICs associated with DIMM 1 target %s", + mss::c_str(i_dimm)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Enable pmics using manual mode (direct VR enable, no SPD fields) +/// @param[in] i_pmics vector of PMICs to enable +/// +fapi2::ReturnCode enable_manual(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_PMIC>> i_pmics) +{ + using CONSTS = mss::pmic::consts<mss::pmic::product::JEDEC_COMPLIANT>; + using REGS = pmicRegs<mss::pmic::product::JEDEC_COMPLIANT>; + using FIELDS = pmicFields<mss::pmic::product::JEDEC_COMPLIANT>; + + for (const auto& l_pmic : i_pmics) + { + fapi2::buffer<uint8_t> l_programmable_mode; + l_programmable_mode.writeBit<FIELDS::R2F_SECURE_MODE>(CONSTS::PROGRAMMABLE_MODE); + + FAPI_INF("Enabling PMIC %s with default settings", mss::c_str(l_pmic)); + + // Make sure power is applied and we can read the PMIC + FAPI_TRY(mss::pmic::poll_for_pbulk_good(l_pmic), + "pmic_enable: poll for pbulk good either failed, or returned not good status on PMIC %s", + mss::c_str(l_pmic)); + + // Enable programmable mode + FAPI_TRY(mss::pmic::i2c::reg_write_reverse_buffer(l_pmic, REGS::R2F, l_programmable_mode)); + + // Start VR Enable + FAPI_TRY(mss::pmic::start_vr_enable(l_pmic), + "Error starting VR_ENABLE on PMIC %s", mss::c_str(l_pmic)); + } + +fapi_try_exit: + return fapi2::current_err; +} +/// +/// @brief Function to enable 1U and 2U pmics +/// +/// @param[in] i_pmic_target - the pmic target +/// @param[in] i_dimm_target - the dimm target that the PMIC resides on +/// @param[in] i_vendor_id - the vendor ID of the PMIC to bias +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS if successful +/// +fapi2::ReturnCode enable_chip_1U_2U(const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const fapi2::Target<fapi2::TargetType::TARGET_TYPE_DIMM>& i_dimm_target, + const uint16_t i_vendor_id) +{ + FAPI_INF("Setting PMIC %s settings from SPD", mss::c_str(i_pmic_target)); + + // Make sure it is TI or IDT + FAPI_ASSERT((i_vendor_id == mss::pmic::vendor::IDT || + i_vendor_id == mss::pmic::vendor::TI), + fapi2::PMIC_CHIP_NOT_RECOGNIZED() + .set_TARGET(i_pmic_target) + .set_VENDOR_ID(i_vendor_id), + "Unknown PMIC: %s with vendor ID 0x%04hhX", + mss::c_str(i_pmic_target), + uint8_t(i_vendor_id) ); + + if (i_vendor_id == mss::pmic::vendor::IDT) + { + FAPI_TRY(mss::pmic::bias_with_spd_settings<mss::pmic::vendor::IDT>(i_pmic_target, i_dimm_target), + "enable_chip<IDT, 1U/2U>: Error biasing PMIC %s with SPD settings", + mss::c_str(i_pmic_target)); + } + else // assert done in pmic_enable.C that vendor is IDT or TI + { + FAPI_TRY(mss::pmic::bias_with_spd_settings<mss::pmic::vendor::TI>(i_pmic_target, i_dimm_target), + "enable_chip<TI, 1U/2U>: Error biasing PMIC %s with SPD settings", + mss::c_str(i_pmic_target)); + } + + // Start VR Enable + FAPI_TRY(mss::pmic::start_vr_enable(i_pmic_target), + "Error starting VR_ENABLE on PMIC %s", mss::c_str(i_pmic_target)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; } + +} // pmic } // mss |