diff options
9 files changed, 636 insertions, 29 deletions
diff --git a/src/import/chips/ocmb/common/include/pmic_regs_fld.H b/src/import/chips/ocmb/common/include/pmic_regs_fld.H index 2eb348df9..67b36b305 100644 --- a/src/import/chips/ocmb/common/include/pmic_regs_fld.H +++ b/src/import/chips/ocmb/common/include/pmic_regs_fld.H @@ -72,6 +72,8 @@ struct pmicFields<mss::pmic::product::JEDEC_COMPLIANT> static constexpr uint8_t VIN_BULK_INPUT_PWR_GOOD_STATUS = 0x07; static constexpr uint8_t DELAY_FLD_LENGTH = 3; + static constexpr uint8_t VOLTAGE_SETTING_START = 0; + static constexpr uint8_t VOLTAGE_SETTING_LENGTH = 7; }; #endif diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.C b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.C index b9fd7c640..b4b59e165 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.C +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.C @@ -22,3 +22,315 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file pmic_bias_utils.C +/// @brief Procedure definition to bias PMIC +/// +// *HWP HWP Owner: Mark Pizzutillo <mark.pizzutillo@ibm.com> +// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> +#include <lib/utils/pmic_bias_utils.H> +#include <lib/i2c/i2c_pmic.H> +#include <lib/utils/pmic_consts.H> +#include <lib/utils/pmic_common_utils.H> +#include <pmic_regs.H> +#include <generic/memory/lib/utils/c_str.H> +#include <generic/memory/lib/utils/mss_math.H> + +namespace mss +{ +namespace pmic +{ + +/// +/// @brief Set the voltage of a rail (post-rounding) +/// +/// @param[in] i_pmic_target PMIC target +/// @param[in] i_rail rail to set +/// @param[in] i_target_voltage voltage to set to +/// @param[in] i_range_selection range (0 or 1) of the rail +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode set_new_rail_voltage( + const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::rail i_rail, + const uint32_t i_target_voltage, + const uint8_t i_range_selection) +{ + using CONSTS = mss::pmic::consts<mss::pmic::product::JEDEC_COMPLIANT>; + using FIELDS = pmicFields<mss::pmic::product::JEDEC_COMPLIANT>; + + FAPI_ASSERT(i_range_selection < CONSTS::NUM_RANGES, + fapi2::PMIC_VOLTAGE_RANGE_SETTING_OUT_OF_RANGE() + .set_TARGET(i_pmic_target) + .set_RAIL(i_rail) + .set_RANGE_SETTING(i_range_selection), + "set_new_rail_voltage(): The voltage setting provided for PMIC %s on rail %u was out of range (Valid: 0,1). Given: %u", + mss::c_str(i_pmic_target), uint8_t(i_rail), i_range_selection); + + { + // Make sure voltage falls within range + static const uint32_t MIN_VOLT = mss::pmic::VOLT_RANGE_MINS[i_rail][i_range_selection]; + static const uint32_t MAX_VOLT = mss::pmic::VOLT_RANGE_MAXES[i_rail][i_range_selection]; + + FAPI_ASSERT((i_target_voltage >= MIN_VOLT) && (i_target_voltage <= MAX_VOLT), + fapi2::PMIC_BIAS_VOLTAGE_OUT_OF_RANGE() + .set_TARGET(i_pmic_target) + .set_VOLTAGE(i_target_voltage) + .set_MIN(MIN_VOLT) + .set_MAX(MAX_VOLT) + .set_RAIL(i_rail), + "set_new_rail_voltage(): After rounding the bias voltage, " + "the resulting voltage %lumV was out of range LOW: %lumV HIGH: %lumV for PMIC %s on rail %u", + i_target_voltage, MIN_VOLT, MAX_VOLT, mss::c_str(i_pmic_target), uint8_t(i_rail)); + { + // Convert to bit mapping and write back + const uint32_t l_offset_from_min = i_target_voltage - MIN_VOLT; + const uint8_t l_voltage_bitmap = l_offset_from_min / CONSTS::VOLT_STEP; + + // Shift and write back + fapi2::buffer<uint8_t> l_voltage_write_back; + + l_voltage_write_back.insertFromRight<FIELDS::VOLTAGE_SETTING_START, FIELDS::VOLTAGE_SETTING_LENGTH>(l_voltage_bitmap); + + FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, mss::pmic::VOLT_SETTING_ACTIVE_REGS[i_rail], l_voltage_write_back), + "set_voltage_percent: Error writing 0x%02hhX of PMIC %s", mss::pmic::VOLT_SETTING_ACTIVE_REGS[i_rail], + mss::c_str(i_pmic_target)); + } + } + + return fapi2::FAPI2_RC_SUCCESS; +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Round a target rail voltage to the nearest step of 5mV to create the voltage bitmap +/// +/// @param[in] i_target_voltage_unrounded unrounded voltage +/// @return float rounded voltage +/// +uint32_t round_rail_target_voltage(const uint32_t i_target_voltage_unrounded) +{ + using CONSTS = mss::pmic::consts<mss::pmic::product::JEDEC_COMPLIANT>; + + // Round to nearest unit by converting to a MV integer + const uint32_t l_target_multiple = CONSTS::VOLT_STEP; + + const uint32_t l_target_voltage = mss::round_to_nearest_multiple(i_target_voltage_unrounded, l_target_multiple); + + // Inform the user. This will be especially useful for debugging + FAPI_INF("Voltage rounded to %luV", l_target_voltage); + + return l_target_voltage; +} + +/// +/// @brief Checks if bias percentage is within the MAX_BIAS threshold +/// +/// @param[in] i_percent percentage to check +/// @param[in] i_force force change (would force evaluation to true) +/// @return true if in range, false if not +/// +bool bias_percent_within_threshold(const float i_percent, const bool i_force) +{ + return i_force || ((i_percent < mss::pmic::PERCENT_MAX_BIAS) && (i_percent > (-1) * mss::pmic::PERCENT_MAX_BIAS)); +} + +/// +/// @brief Get the current rail voltage of a JEDEC PMIC +/// +/// @param[in] i_pmic_target PMIC target +/// @param[in] i_rail rail to read from +/// @param[out] o_current_rail_voltage voltage calculated for rail +/// @param[out] o_range_selection range selection of that voltage +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error +/// @note not templated as the arguments may differ for other chips (if we ever use others) +/// +fapi2::ReturnCode get_current_rail_voltage(const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& + i_pmic_target, + const mss::pmic::rail i_rail, + uint32_t& o_current_rail_voltage, + uint8_t& o_range_selection) +{ + fapi2::buffer<uint8_t> l_voltage_setting_reg_contents; + fapi2::buffer<uint8_t> l_voltage_range_reg_contents; + + using REGS = pmicRegs<mss::pmic::product::JEDEC_COMPLIANT>; + using FIELDS = pmicFields<mss::pmic::product::JEDEC_COMPLIANT>; + using CONSTS = mss::pmic::consts<mss::pmic::product::JEDEC_COMPLIANT>; + + // Get voltage for rail + FAPI_TRY(mss::pmic::i2c::reg_read(i_pmic_target, mss::pmic::VOLT_SETTING_ACTIVE_REGS[i_rail], + l_voltage_setting_reg_contents), + "set_voltage_percent: Error reading 0x%02hhX of PMIC %s", mss::pmic::VOLT_SETTING_ACTIVE_REGS[i_rail], + mss::c_str(i_pmic_target)); + + // Get voltage range selections + FAPI_TRY(mss::pmic::i2c::reg_read_reverse_buffer(i_pmic_target, REGS::R2B, l_voltage_range_reg_contents), + "set_voltage_percent: Error reading 0x%02hhX of PMIC %s", REGS::R2B, mss::c_str(i_pmic_target)); + { + // Identify range + const uint8_t l_range_selection = l_voltage_range_reg_contents.getBit(mss::pmic::VOLT_RANGE_FLDS[i_rail]); + uint8_t l_voltage_setting = 0; + + l_voltage_setting_reg_contents.extractToRight<FIELDS::VOLTAGE_SETTING_START, FIELDS::VOLTAGE_SETTING_LENGTH> + (l_voltage_setting); + + // Get current voltage using: range_min + (step * setting) + o_current_rail_voltage = mss::pmic::VOLT_RANGE_MINS[i_rail][l_range_selection] + (CONSTS::VOLT_STEP * + l_voltage_setting); + o_range_selection = l_range_selection; + } + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set the voltage percent on the specified rail of a JEDEC-compliant PMIC +/// +/// @param[in] i_pmic_target PMIC to bias +/// @param[in] i_rail rail to bias +/// @param[in] i_percent percentage change +/// @param[in] i_force override 10% change limit +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode set_voltage_percent( + const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::rail i_rail, + const float i_percent, + const bool i_force) +{ + static constexpr float PERCENT_CONVERSION = 100; + + // Make sure less than 10% if not overriding or within threshold + FAPI_ASSERT(bias_percent_within_threshold(i_percent, i_force), + fapi2::PMIC_BIAS_VOLTAGE_PAST_THRESHOLD() + .set_TARGET(i_pmic_target) + .set_PERCENT(i_percent) + .set_RAIL(i_rail), + "set_voltage_percent(): Bias percentage %f%% provided to PMIC %s exceed the maximum of 10%%. Use -f to override", + i_percent, mss::c_str(i_pmic_target)); + { + uint32_t l_current_rail_voltage; + uint8_t l_range_selection; + + FAPI_TRY(mss::pmic::get_current_rail_voltage(i_pmic_target, i_rail, l_current_rail_voltage, l_range_selection), + "set_voltage_percent: Error getting current rail voltage for rail # %u of PMIC %s", i_rail, mss::c_str(i_pmic_target)); + { + // Obtain target voltage by percent offset + const uint32_t l_target_voltage_unrounded = l_current_rail_voltage * ((PERCENT_CONVERSION + i_percent) / + PERCENT_CONVERSION); + + const uint32_t l_target_voltage = mss::pmic::round_rail_target_voltage(l_target_voltage_unrounded); + + FAPI_TRY(set_new_rail_voltage(i_pmic_target, i_rail, l_target_voltage, l_range_selection), + "set_voltage_percent(): Error setting voltage on PMIC %s", mss::c_str(i_pmic_target)); + } + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set the voltage of a JEDEC_COMPLIANT pmic's rail +/// +/// @param[in] i_pmic_target PMIC to bias +/// @param[in] i_rail rail to bias +/// @param[in] i_value value to set to +/// @param[in] i_force override 10% change limit +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode set_voltage_value( + const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::rail i_rail, + const float i_value, + const bool i_force) +{ + static constexpr float V_TO_MV_CONVERSION = 1000; + static constexpr float PERCENT_CONVERSION = 100; + + const uint32_t l_value_mv = i_value * V_TO_MV_CONVERSION; + + uint32_t l_current_rail_voltage = 0; + uint8_t l_range_selection; + + // Get range selection and voltage + FAPI_TRY(mss::pmic::get_current_rail_voltage(i_pmic_target, i_rail, l_current_rail_voltage, l_range_selection), + "set_voltage_percent: Error getting current rail voltage for rail # %u of PMIC %s", i_rail, mss::c_str(i_pmic_target)); + { + // Calculate percent change + // Float to avoid integer division + const float l_percent_change = (((l_current_rail_voltage / static_cast<float>(l_value_mv)) - 1)) * PERCENT_CONVERSION; + + // Make sure less than 10% if not overriding or within threshold + FAPI_ASSERT(bias_percent_within_threshold(l_percent_change, i_force), + fapi2::PMIC_BIAS_VOLTAGE_PAST_THRESHOLD() + .set_TARGET(i_pmic_target) + .set_PERCENT(l_percent_change) + .set_RAIL(i_rail), + "set_voltage_value(): Bias percentage %f%% provided to PMIC %s exceed the maximum of 10%%. Use -f to override", + l_percent_change, mss::c_str(i_pmic_target)); + + { + const uint32_t l_target_voltage = mss::pmic::round_rail_target_voltage(l_value_mv); + + // Verify new valid voltage and write to PMIC + FAPI_TRY(set_new_rail_voltage(i_pmic_target, i_rail, l_target_voltage, l_range_selection), + "set_voltage_value(): Error setting voltage on PMIC %s", mss::c_str(i_pmic_target)); + } + } + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief bias procedure for JEDEC compliant chips +/// +/// @param[in] i_pmic_target - the pmic_target +/// @param[in] i_setting setting to change (swa_volt, swb_volt, etc.) +/// @param[in] i_amount amount to change by +/// @param[in] i_unit percentage or value +/// @param[in] i_force ignore 10% change limit +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// @note not templated by vendor. As long as the TI +/// +fapi2::ReturnCode bias_chip( + const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::setting i_setting, + const float i_amount, + const mss::pmic::unit i_unit, + const bool i_force) +{ + using CONSTS = mss::pmic::consts<mss::pmic::product::JEDEC_COMPLIANT>; + + if (i_unit == mss::pmic::unit::PERCENT) + { + FAPI_TRY(set_voltage_percent(i_pmic_target, + static_cast<mss::pmic::rail>(i_setting % CONSTS::NUMBER_OF_RAILS), + i_amount, i_force)); + } + else // value + { + FAPI_TRY(set_voltage_value(i_pmic_target, + static_cast<mss::pmic::rail>(i_setting % CONSTS::NUMBER_OF_RAILS), + i_amount, i_force)); + } + +fapi_try_exit: + return fapi2::current_err; +} + +} // pmic +} // mss diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.H b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.H index 58757e249..64fd9fdcf 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.H +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.H @@ -30,13 +30,18 @@ // *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 #ifndef __PMIC_BIAS_UTILS_H__ #define __PMIC_BIAS_UTILS_H__ #include <fapi2.H> +#include <lib/utils/pmic_consts.H> +#include <lib/utils/pmic_common_utils.H> +#include <pmic_regs.H> +#include <pmic_regs_fld.H> +#include <generic/memory/lib/utils/c_str.H> namespace mss { @@ -49,12 +54,16 @@ namespace pmic enum setting { // We order these by rail in groups of 4 so they match with the rail enums, - // so the rail can be derived from just a % 4 when we have more settings to change + // so the rail can be derived from just a % 4 when we have more settings to change (see current) SWA_VOLT = 0, SWB_VOLT = 1, SWC_VOLT = 2, SWD_VOLT = 3, - NO_SETTING = 4, + // SWA_CURRENT = 4, + // SWB_CURRENT = 5, + // .. + // .. + NO_SETTING = 8, }; /// @@ -67,7 +76,108 @@ enum unit PERCENT = 2, }; -}// pmic -}// mss +// Max bias % change that the procedure will allow without override flag +static constexpr float PERCENT_MAX_BIAS = 10.0; + +//-------- JEDEC SPECIFIC HELPER FUNCS ---------// + +/// +/// @brief Set the voltage of a rail (post-rounding) +/// +/// @param[in] i_pmic_target PMIC target +/// @param[in] i_rail rail to set +/// @param[in] i_target_voltage voltage to set to +/// @param[in] i_range_selection range (0 or 1) of the rail +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode set_new_rail_voltage( + const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::rail i_rail, + const uint32_t i_target_voltage, + const uint8_t i_range_selection); + +/// +/// @brief round a target rail voltage to the nearest step of 5mV to create the voltage bitmap +/// +/// @param[in] l_target_voltage_unrounded unrounded voltage +/// @return uint32_t rounded voltage +/// +uint32_t round_rail_target_voltage(const uint32_t l_target_voltage_unrounded); + +/// +/// @brief Checks if bias percentage is within the MAX_BIAS threshold +/// +/// @param[in] i_percent percentage to check +/// @param[in] i_force force change (would force evaluation to true) +/// @return true if in range, false if not +/// +bool bias_percent_within_threshold(const float i_percent, const bool i_force); + +/// +/// @brief Get the current rail voltage of a JEDEC PMIC +/// +/// @param[in] i_pmic_target PMIC target +/// @param[in] i_rail rail to read from +/// @param[out] o_current_rail_voltage voltage calculated for rail +/// @param[out] o_range_selection range selection of that voltage +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error +/// @note not templated as the arguments may differ for other chips (if we ever use others) +/// +fapi2::ReturnCode get_current_rail_voltage(const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& + i_pmic_target, + const mss::pmic::rail i_rail, + uint32_t& o_current_rail_voltage, + uint8_t& o_range_selection); + +//-------------- HELPER FUNCTIONS --------------// + +/// +/// @brief Set the voltage percent on the specified rail of a PMIC device +/// +/// @param[in] i_pmic_target PMIC target +/// @param[in] i_rail rail to bias +/// @param[in] i_percent percentage change +/// @param[in] i_force override 10% change limit +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode set_voltage_percent(const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::rail i_rail, + const float i_percent, + const bool i_force); + +/// +/// @brief Set the voltage of a rail by a value +/// +/// @param[in] i_pmic_target PMIC to bias +/// @param[in] i_rail rail to bias +/// @param[in] i_value value to set to +/// @param[in] i_force override 10% change limit +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode set_voltage_value(const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::rail i_rail, + const float i_value, + const bool i_force); + +//------------------- BIAS FUNCTIONS -----------------// + +/// +/// @brief Bias a chip with the given settings +/// +/// @param[in] i_pmic_target - the pmic_target +/// @param[in] i_setting setting to change (swa_volt, swb_volt, etc.) +/// @param[in] i_amount amount to change by +/// @param[in] i_unit percentage or value +/// @param[in] i_force ignore 10% change limit +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success +/// +fapi2::ReturnCode bias_chip(const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target, + const mss::pmic::setting i_setting, + const float i_amount, + const mss::pmic::unit i_unit, + const bool i_force); + +} // pmic +} // mss #endif diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_common_utils.H b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_common_utils.H index 78cf87f6e..6516140c7 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_common_utils.H +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_common_utils.H @@ -63,6 +63,14 @@ using FIELDS = pmicFields<mss::pmic::product::JEDEC_COMPLIANT>; using CONSTS = mss::pmic::consts<mss::pmic::product::JEDEC_COMPLIANT>;; // Arrays to easily index common parameters by rail +static constexpr uint8_t const VOLT_SETTING_ACTIVE_REGS[] = +{ + REGS::R21_SWA_VOLTAGE_SETTING, + REGS::R23_SWB_VOLTAGE_SETTING, + REGS::R25_SWC_VOLTAGE_SETTING, + REGS::R27_SWD_VOLTAGE_SETTING +}; + static constexpr uint8_t const VOLT_SETTING_REGS[] = { REGS::R21_SWA_VOLTAGE_SETTING, @@ -79,7 +87,7 @@ static constexpr uint8_t const VOLT_RANGE_FLDS[] = FIELDS::SWD_VOLTAGE_RANGE }; -static constexpr float const VOLT_RANGE_MINS[][CONSTS::NUM_RANGES] = +static constexpr uint32_t const VOLT_RANGE_MINS[][CONSTS::NUM_RANGES] = { {CONSTS::SWABC_VOLT_RANGE0_MIN, CONSTS::SWABC_VOLT_RANGE1_MIN}, {CONSTS::SWABC_VOLT_RANGE0_MIN, CONSTS::SWABC_VOLT_RANGE1_MIN}, @@ -87,7 +95,7 @@ static constexpr float const VOLT_RANGE_MINS[][CONSTS::NUM_RANGES] = {CONSTS::SWD_VOLT_RANGE0_MIN, CONSTS::SWD_VOLT_RANGE1_MIN} }; -static constexpr float const VOLT_RANGE_MAXES[][CONSTS::NUM_RANGES] = +static constexpr uint32_t const VOLT_RANGE_MAXES[][CONSTS::NUM_RANGES] = { {CONSTS::SWABC_VOLT_RANGE0_MAX, CONSTS::SWABC_VOLT_RANGE1_MAX}, {CONSTS::SWABC_VOLT_RANGE0_MAX, CONSTS::SWABC_VOLT_RANGE1_MAX}, diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_consts.H b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_consts.H index 3d5a45b5c..addf8ca6b 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_consts.H +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_consts.H @@ -289,18 +289,18 @@ struct consts<mss::pmic::product::JEDEC_COMPLIANT> static constexpr uint8_t MAX_DELAY_BITMAP = 0b00000111; static constexpr uint8_t CONVERT_RANGE1_TO_RANGE0 = 40; - static constexpr float SWABC_VOLT_RANGE0_MIN = 0.8; - static constexpr float SWABC_VOLT_RANGE0_MAX = 1.435; - static constexpr float SWABC_VOLT_RANGE1_MIN = 0.6; - static constexpr float SWABC_VOLT_RANGE1_MAX = 1.235; - - static constexpr float SWD_VOLT_RANGE0_MIN = 1.5; - static constexpr float SWD_VOLT_RANGE0_MAX = 2.135; - static constexpr float SWD_VOLT_RANGE1_MIN = 2.2; - static constexpr float SWD_VOLT_RANGE1_MAX = 2.835; - - // the overarching JEDEC spec says 5. Sticking with 5 until we hear otherwise. - static constexpr float VOLT_STEP = 0.005; // 5 mV + // Values below are in millivolts (mV) + static constexpr uint32_t SWABC_VOLT_RANGE0_MIN = 800; + static constexpr uint32_t SWABC_VOLT_RANGE0_MAX = 1435; + static constexpr uint32_t SWABC_VOLT_RANGE1_MIN = 600; + static constexpr uint32_t SWABC_VOLT_RANGE1_MAX = 1235; + + static constexpr uint32_t SWD_VOLT_RANGE0_MIN = 1500; + static constexpr uint32_t SWD_VOLT_RANGE0_MAX = 2135; + static constexpr uint32_t SWD_VOLT_RANGE1_MIN = 2200; + static constexpr uint32_t SWD_VOLT_RANGE1_MAX = 2835; + + static constexpr uint32_t VOLT_STEP = 5; }; /// diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.C b/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.C index a8da82dcd..c0b65f3ba 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.C +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.C @@ -30,11 +30,20 @@ // *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 <lib/utils/pmic_bias_utils.H> +#include <lib/utils/pmic_common_utils.H> +#include <pmic_bias.H> +#include <generic/memory/lib/utils/find.H> +#include <lib/i2c/i2c_pmic.H> +#include <pmic_regs.H> +#include <pmic_regs_fld.H> +#include <lib/utils/pmic_bias_utils.H> +#include <lib/utils/pmic_consts.H> +#include <generic/memory/lib/utils/c_str.H> extern "C" { @@ -42,6 +51,7 @@ extern "C" /// @brief Bias procedure for PMIC devices /// /// @param[in] i_ocmb_target explorer target + /// @param[in] i_id the PMIC to change (PMIC0,PMIC1) /// @param[in] i_setting setting to change (swa_volt, swb_volt, etc.) /// @param[in] i_amount amount to change by /// @param[in] i_unit percentage or value @@ -49,12 +59,54 @@ extern "C" /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success /// fapi2::ReturnCode pmic_bias(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_ocmb_target, + const mss::pmic::id i_id, const mss::pmic::setting i_setting, const float i_amount, const mss::pmic::unit i_unit, const bool i_force) { - // TK - L1 implementation, function not filled in yet + // Check that our inputs are valid + FAPI_ASSERT(i_id != mss::pmic::id::UNKNOWN_ID, + fapi2::PMIC_NO_PMIC_SPECIFIED() + .set_TARGET(i_ocmb_target) + .set_PMIC_ID(uint8_t(i_id)), + "pmic_bias(): PMIC ID %u was unknown for bias procedure call on OCMB %s", + uint8_t(i_id), i_ocmb_target); + + FAPI_ASSERT(i_setting != mss::pmic::setting::NO_SETTING, + fapi2::PMIC_NO_SETTING_SPECIFIED() + .set_TARGET(i_ocmb_target) + .set_SETTING_ID(uint8_t(i_setting)), + "pmic_bias(): PMIC setting ID %u was unknown for bias procedure call on OCMB %s", + uint8_t(i_setting), i_ocmb_target); + + FAPI_ASSERT(i_unit != mss::pmic::unit::NO_UNIT, + fapi2::PMIC_NO_UNIT_SPECIFIED() + .set_TARGET(i_ocmb_target) + .set_UNIT_ID(uint8_t(i_unit)), + "pmic_bias(): Biasing unit ID %u was unknown for bias procedure call on OCMB %s", + uint8_t(i_unit), i_ocmb_target); + + for (const auto& l_pmic : mss::find_targets<fapi2::TARGET_TYPE_PMIC>(i_ocmb_target)) + { + // If matching ID (pmic0, pmic1), then we will bias it + if ((mss::index(l_pmic) % mss::pmic::consts<mss::pmic::product::JEDEC_COMPLIANT>::NUM_UNIQUE_PMICS) == i_id) + { + // Poll to make sure PBULK reports good, then we can be sure we can write/read registers + 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)); + + FAPI_INF("Performing BIAS on PMIC %s", mss::c_str(l_pmic)); + + // Now call the bias function + FAPI_TRY(mss::pmic::bias_chip(l_pmic, i_setting, i_amount, i_unit, i_force), + "Error biasing PMIC %s", mss::c_str(l_pmic)); + } + } + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: + return fapi2::current_err; } -} +} // extern C diff --git a/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.H b/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.H index 924ada60e..75a2465b3 100644 --- a/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.H +++ b/src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.H @@ -37,9 +37,11 @@ #define __PMIC_BIAS_H__ #include <fapi2.H> -#include <lib/pmic/pmic_bias_utils.H> +#include <lib/utils/pmic_bias_utils.H> +#include <lib/utils/pmic_consts.H> typedef fapi2::ReturnCode (*pmic_bias_FP_t) (const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&, + const mss::pmic::id i_id, const mss::pmic::setting, const float, const mss::pmic::unit, @@ -51,16 +53,19 @@ extern "C" /// @brief Bias procedure for PMIC devices /// /// @param[in] i_ocmb_target explorer target + /// @param[in] i_id the PMIC to change (PMIC0,PMIC1) /// @param[in] i_setting setting to change (swa_volt, swb_volt, etc.) /// @param[in] i_amount amount to change by /// @param[in] i_unit percentage or value /// @param[in] i_force ignore 10% change limit /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success /// - fapi2::ReturnCode exp_pmic_bias(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_ocmb_target, - const mss::pmic::setting i_setting = mss::pmic::setting::NO_SETTING, - const float i_amount = 0, - const mss::pmic::unit i_unit = mss::pmic::unit::NO_UNIT, - const bool i_force = false); + fapi2::ReturnCode pmic_bias(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_ocmb_target, + const mss::pmic::id i_id = mss::pmic::id::PMIC0, + const mss::pmic::setting i_setting = mss::pmic::setting::NO_SETTING, + const float i_amount = 0, + const mss::pmic::unit i_unit = mss::pmic::unit::NO_UNIT, + const bool i_force = false); } + #endif diff --git a/src/import/chips/ocmb/common/procedures/xml/error_info/pmic_errors.xml b/src/import/chips/ocmb/common/procedures/xml/error_info/pmic_errors.xml index 6c2437728..843a92812 100644 --- a/src/import/chips/ocmb/common/procedures/xml/error_info/pmic_errors.xml +++ b/src/import/chips/ocmb/common/procedures/xml/error_info/pmic_errors.xml @@ -64,7 +64,7 @@ <hwpError> <rc>RC_PMIC_VOLTAGE_OUT_OF_RANGE</rc> <description> - The voltage from the SPD and offset combination was out of range for the PMIC. + The voltage from the SPD and offset combination or bias operation was out of range for the PMIC. </description> <ffdc>TARGET</ffdc> <ffdc>VOLTAGE_BITMAP</ffdc> @@ -98,6 +98,24 @@ </hwpError> <hwpError> + <rc>RC_PMIC_VOLTAGE_RANGE_SETTING_OUT_OF_RANGE</rc> + <description> + The PMIC voltage setting range was too large (Valid: 0,1) + </description> + <ffdc>TARGET</ffdc> + <ffdc>RAIL</ffdc> + <ffdc>RANGE_SETTING</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> <rc>RC_PMIC_DELAY_OUT_OF_RANGE</rc> <description> The sequence delay specified by the SPD was out of range for the PMIC (max bitmap: 0b111) @@ -116,6 +134,24 @@ </hwpError> <hwpError> + <rc>RC_PMIC_BIAS_VOLTAGE_PAST_THRESHOLD</rc> + <description> + The bias voltage provided exceeded the 10%% change limit. Use -f argument to override. + </description> + <ffdc>TARGET</ffdc> + <ffdc>RAIL</ffdc> + <ffdc>PERCENT</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> <rc>RC_PMIC_DIMM_SPD_4U</rc> <description> The module_height attribute SPD of this DIMM was read as 4U. @@ -132,4 +168,75 @@ </callout> </hwpError> + <hwpError> + <rc>RC_PMIC_BIAS_VOLTAGE_OUT_OF_RANGE</rc> + <description> + The target voltage supplied to the BIAS operation was out of range for the PMIC. + </description> + <ffdc>TARGET</ffdc> + <ffdc>VOLTAGE</ffdc> + <ffdc>MIN</ffdc> + <ffdc>MAX</ffdc> + <ffdc>RAIL</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PMIC_NO_PMIC_SPECIFIED</rc> + <description> + The PMIC ENUM ID provided to the procedure was unknown + </description> + <ffdc>TARGET</ffdc> + <ffdc>PMIC_ID</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PMIC_NO_SETTING_SPECIFIED</rc> + <description> + The PMIC SETTING ENUM provided to the procedure was unknown + </description> + <ffdc>TARGET</ffdc> + <ffdc>SETTING_ID</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + </hwpError> + + <hwpError> + <rc>RC_PMIC_NO_UNIT_SPECIFIED</rc> + <description> + The PMIC UNIT ENUM provided to the procedure was unknown + </description> + <ffdc>TARGET</ffdc> + <ffdc>UNIT_ID</ffdc> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <callout> + <target>TARGET</target> + <priority>HIGH</priority> + </callout> + </hwpError> + </hwpErrors> diff --git a/src/import/generic/memory/lib/utils/mss_math.H b/src/import/generic/memory/lib/utils/mss_math.H index 65fc0f898..b3ff26fde 100644 --- a/src/import/generic/memory/lib/utils/mss_math.H +++ b/src/import/generic/memory/lib/utils/mss_math.H @@ -107,6 +107,17 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Round value to a multiple of another number +/// +/// @param[in] i_value value to round +/// @param[in] i_multiple multiple to round to +/// @return uint64_t rounded value +/// +inline uint32_t round_to_nearest_multiple(const uint32_t i_value, const uint32_t i_multiple) +{ + return ((i_value + i_multiple / 2) / i_multiple) * i_multiple; +} /// /// @brief Determines if the double has decimal digits and adds 1 and rounds if true |