Skip to content

Commit

Permalink
Add support for new pmic sequencing SPD fields
Browse files Browse the repository at this point in the history
Change-Id: I8847090585161375fbb2c0ef853cffed80a67cc3
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/82961
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/83375
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R Geddes <crgeddes@us.ibm.com>
  • Loading branch information
markypizz authored and crgeddes committed Sep 27, 2019
1 parent 04d5973 commit 48abe5e
Show file tree
Hide file tree
Showing 14 changed files with 480 additions and 240 deletions.
Expand Up @@ -2379,6 +2379,108 @@ struct attrEngineTraits<P, pmic::attr_eff_engine_fields, pmic::attr_eff_engine_f
}
};

//
/// @brief Traits for attr_engine
/// @class attrEngineTraits
/// @tparam P processor type
/// @note P, pmic::attr_eff_engine_fields, PMIC0_SEQUENCE partial specialization
///
template< proc_type P>
struct attrEngineTraits<P, pmic::attr_eff_engine_fields, pmic::attr_eff_engine_fields::PMIC0_SEQUENCE>
{
using attr_type = fapi2::ATTR_MEM_EFF_PMIC0_SEQUENCE_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_PMIC0_SEQUENCE_TargetType;
static constexpr pmic::ffdc_codes FFDC_CODE = pmic::SET_PMIC0_SEQUENCE;

///
/// @brief attribute getter
/// @param[in] i_target the fapi2 target
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& o_setting)
{
return attr::get_pmic0_sequence(i_target, o_setting);
}

///
/// @brief attribute setter
/// @param[in] i_target the fapi2 target
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& i_setting)
{
return attr::set_pmic0_sequence(i_target, i_setting);
}

///
/// @brief Computes setting for attribute
/// @param[in] i_spd_data EFD data
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
attr_integral_type& o_setting)
{
return i_spd_data.sequence_pmic0(o_setting);
}
};

//
/// @brief Traits for attr_engine
/// @class attrEngineTraits
/// @tparam P processor type
/// @note P, pmic::attr_eff_engine_fields, PMIC1_SEQUENCE partial specialization
///
template< proc_type P>
struct attrEngineTraits<P, pmic::attr_eff_engine_fields, pmic::attr_eff_engine_fields::PMIC1_SEQUENCE>
{
using attr_type = fapi2::ATTR_MEM_EFF_PMIC1_SEQUENCE_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_PMIC1_SEQUENCE_TargetType;
static constexpr pmic::ffdc_codes FFDC_CODE = pmic::SET_PMIC1_SEQUENCE;

///
/// @brief attribute getter
/// @param[in] i_target the fapi2 target
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& o_setting)
{
return attr::get_pmic1_sequence(i_target, o_setting);
}

///
/// @brief attribute setter
/// @param[in] i_target the fapi2 target
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& i_setting)
{
return attr::set_pmic1_sequence(i_target, i_setting);
}

///
/// @brief Computes setting for attribute
/// @param[in] i_spd_data EFD data
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
attr_integral_type& o_setting)
{
return i_spd_data.sequence_pmic1(o_setting);
}
};

}//mss

#endif
Expand Up @@ -156,9 +156,11 @@ enum class attr_eff_engine_fields

PMIC0_MFG_ID = 43,
PMIC1_MFG_ID = 44,
PMIC0_SEQUENCE = 45,
PMIC1_SEQUENCE = 46,

// Dispatcher set to last enum value
DISPATCHER = PMIC1_MFG_ID,
DISPATCHER = PMIC1_SEQUENCE,
};

///
Expand Down Expand Up @@ -220,7 +222,8 @@ enum ffdc_codes
SET_PMIC0_MFG_ID = 0x107C,
SET_PMIC1_MFG_ID = 0x107D,

SET_DRAM_MODULE_HEIGHT = 0x107E,
SET_PMIC0_SEQUENCE = 0x107E,
SET_PMIC1_SEQUENCE = 0x107F,
};

///
Expand Down Expand Up @@ -292,41 +295,6 @@ struct consts<mss::pmic::product::JEDEC_COMPLIANT>
static constexpr uint32_t VOLT_STEP = 5;
};

///
/// @brief PMIC traits that change depending on DIMM module height
///
/// @tparam H module_height enum
///
template<mss::pmic::module_height H>
struct pmic_traits;

///
/// @brief pmic traits for 1U dimms
///
template <>
struct pmic_traits<mss::pmic::module_height::HEIGHT_1U>
{
static constexpr uint8_t PMICS_PER_DIMM = 2;
};

///
/// @brief pmic traits for 2U dimms
///
template <>
struct pmic_traits<mss::pmic::module_height::HEIGHT_2U>
{
static constexpr uint8_t PMICS_PER_DIMM = 2;
};

///
/// @brief pmic traits for 4U dimms
///
template <>
struct pmic_traits<mss::pmic::module_height::HEIGHT_4U>
{
static constexpr uint8_t PMICS_PER_DIMM = 4;
};

namespace i2c
{

Expand Down
Expand Up @@ -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

0 comments on commit 48abe5e

Please sign in to comment.