summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/import/chips/ocmb/common/include/pmic_regs_fld.H2
-rw-r--r--src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.C312
-rw-r--r--src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_bias_utils.H120
-rw-r--r--src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_common_utils.H12
-rw-r--r--src/import/chips/ocmb/common/procedures/hwp/pmic/lib/utils/pmic_consts.H24
-rw-r--r--src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.C58
-rw-r--r--src/import/chips/ocmb/common/procedures/hwp/pmic/pmic_bias.H17
-rw-r--r--src/import/chips/ocmb/common/procedures/xml/error_info/pmic_errors.xml109
-rw-r--r--src/import/generic/memory/lib/utils/mss_math.H11
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
OpenPOWER on IntegriCloud