Skip to content

Commit

Permalink
Add check for matching PMIC vendor and IDT revisions
Browse files Browse the repository at this point in the history
Change-Id: Id8cbf68b37e61f5f9001af74b41bec323a251b64
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/94695
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Dev-Ready: Mark Pizzutillo <mark.pizzutillo@ibm.com>
Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/94988
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 Apr 24, 2020
1 parent 58930a3 commit 09ee51c
Show file tree
Hide file tree
Showing 8 changed files with 386 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/import/chips/ocmb/common/include/pmic_regs.H
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2019 */
/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -111,7 +111,7 @@ struct pmicRegs<mss::pmic::product::JEDEC_COMPLIANT>
static constexpr uint8_t R38_PASSWORD_UPPER_BYTE_1 = 0x38;
static constexpr uint8_t R39_COMMAND_CODES = 0x39;
static constexpr uint8_t R3A = 0x3A;
static constexpr uint8_t R3B = 0x3B;
static constexpr uint8_t R3B_REVISION = 0x3B;
static constexpr uint8_t R3C_VENDOR_ID_BYTE_0 = 0x3C;
static constexpr uint8_t R3D_VENDOR_ID_BYTE_1 = 0x3D;

Expand Down
Expand Up @@ -1291,6 +1291,57 @@ 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_REVISION partial specialization
///
template< proc_type P>
struct attrEngineTraits<P, pmic::attr_eff_engine_fields, pmic::attr_eff_engine_fields::PMIC0_REVISION>
{
using attr_type = fapi2::ATTR_MEM_EFF_PMIC0_REVISION_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
using attr_type_to_set = attr_integral_type;
static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_PMIC0_REVISION_TargetType;
static constexpr pmic::ffdc_codes FFDC_CODE = pmic::SET_PMIC0_REVISION;

///
/// @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_revision(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_revision(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.revision_pmic0(o_setting);
}
};

//----------------------------------------
// PMIC 1
Expand Down Expand Up @@ -2628,6 +2679,58 @@ 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, PMIC1_REVISION partial specialization
///
template< proc_type P>
struct attrEngineTraits<P, pmic::attr_eff_engine_fields, pmic::attr_eff_engine_fields::PMIC1_REVISION>
{
using attr_type = fapi2::ATTR_MEM_EFF_PMIC1_REVISION_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
using attr_type_to_set = attr_integral_type;
static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_PMIC1_REVISION_TargetType;
static constexpr pmic::ffdc_codes FFDC_CODE = pmic::SET_PMIC1_REVISION;

///
/// @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_revision(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_revision(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.revision_pmic1(o_setting);
}
};

} // namespace mss

#endif
Expand Up @@ -68,6 +68,13 @@ typedef fapi2::ReturnCode (*pmic_attr_ptr_signed)(const fapi2::Target<fapi2::TAR

// Pointers below allow for run-time attribute getter selection by PMIC ID (0,1)

// PMIC0/1 Revision
static constexpr pmic_attr_ptr get_revision[] =
{
mss::attr::get_pmic0_revision,
mss::attr::get_pmic1_revision
};

// Voltage Setting
static constexpr pmic_attr_ptr get_swa_voltage_setting[] =
{
Expand Down Expand Up @@ -201,6 +208,7 @@ static constexpr pmic_attr_ptr get_sequence[] =
mss::attr::get_pmic0_sequence,
mss::attr::get_pmic1_sequence
};

// Sequence Delay
static constexpr pmic_attr_ptr get_swa_sequence_delay[] =
{
Expand Down
Expand Up @@ -166,8 +166,11 @@ enum class attr_eff_engine_fields
PMIC0_REDUNDANCY = 47,
PMIC1_REDUNDANCY = 48,

PMIC0_REVISION = 49,
PMIC1_REVISION = 50,

// Dispatcher set to last enum value
DISPATCHER = PMIC1_REDUNDANCY,
DISPATCHER = PMIC1_REVISION,
};

///
Expand Down Expand Up @@ -234,6 +237,9 @@ enum ffdc_codes

SET_PMIC0_REDUNDANCY = 0x1080,
SET_PMIC1_REDUNDANCY = 0x1081,

SET_PMIC0_REVISION = 0x1082,
SET_PMIC1_REVISION = 0x1083,
};

///
Expand Down
Expand Up @@ -559,6 +559,149 @@ fapi2::ReturnCode check_for_valid_module_height(const fapi2::Target<fapi2::TARGE
fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Check that the vendor ID register and attribute match
///
/// @param[in] i_ocmb_target OCMB target
/// @param[in] i_pmic_target PMIC target to check
/// @return fapi2::ReturnCode
///
fapi2::ReturnCode check_matching_vendors(
const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_ocmb_target,
const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& i_pmic_target)
{
using REGS = pmicRegs<mss::pmic::product::JEDEC_COMPLIANT>;

const uint8_t l_pmic_id = mss::index(i_pmic_target);

uint16_t l_vendor_attr = 0;
fapi2::buffer<uint8_t> l_vendor_reg0;
fapi2::buffer<uint8_t> l_vendor_reg1;

// Get attribute
FAPI_TRY(mss::attr::get_mfg_id[l_pmic_id](i_ocmb_target, l_vendor_attr));

// Now check the register
FAPI_TRY(mss::pmic::i2c::reg_read(i_pmic_target, REGS::R3C_VENDOR_ID_BYTE_0, l_vendor_reg0));
FAPI_TRY(mss::pmic::i2c::reg_read(i_pmic_target, REGS::R3D_VENDOR_ID_BYTE_1, l_vendor_reg1));

FAPI_TRY(mss::pmic::check_matching_vendors_helper(
i_pmic_target,
l_vendor_attr,
l_vendor_reg0(),
l_vendor_reg1()));

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Unit testable helper function: Check matching vendor ID between attr and reg values
///
/// @param[in] i_pmic_target PMIC target for FFDC
/// @param[in] i_vendor_attr vendor attribute value
/// @param[in] i_vendor_reg_lo vendor register low byte
/// @param[in] i_vendor_reg_hi vendor register high byte
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff no error
///
fapi2::ReturnCode check_matching_vendors_helper(
const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& i_pmic_target,
const uint16_t i_vendor_attr,
const uint8_t i_vendor_reg_lo,
const uint8_t i_vendor_reg_hi)
{
static constexpr uint8_t HI_BYTE_START = 0;
static constexpr uint8_t HI_BYTE_LEN = 8;

fapi2::buffer<uint16_t> l_vendor_reg(i_vendor_reg_lo);
l_vendor_reg.insert<HI_BYTE_START, HI_BYTE_LEN>(i_vendor_reg_hi);

FAPI_ASSERT(l_vendor_reg == i_vendor_attr,
fapi2::PMIC_MISMATCHING_VENDOR_IDS()
.set_VENDOR_ATTR(i_vendor_attr)
.set_VENDOR_REG(l_vendor_reg)
.set_PMIC_TARGET(i_pmic_target),
"Mismatching vendor IDs for %s. ATTR: 0x%04X REG: 0x%04X",
mss::c_str(i_pmic_target),
i_vendor_attr,
l_vendor_reg());

return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Check that the IDT revision # register and attribute match
///
/// @param[in] i_ocmb_target OCMB target
/// @param[in] i_pmic_target PMIC target to check
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff no error
///
fapi2::ReturnCode check_valid_idt_revisions(
const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_ocmb_target,
const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& i_pmic_target)
{
using REGS = pmicRegs<mss::pmic::product::JEDEC_COMPLIANT>;

uint8_t l_pmic_id = mss::index(i_pmic_target);
uint8_t l_rev = 0;
fapi2::buffer<uint8_t> l_rev_reg;

// Get attribute
FAPI_TRY(mss::attr::get_revision[l_pmic_id](i_ocmb_target, l_rev));

// Now check the register
FAPI_TRY(mss::pmic::i2c::reg_read(i_pmic_target, REGS::R3B_REVISION, l_rev_reg));

FAPI_TRY(mss::pmic::check_valid_idt_revisions_helper(i_pmic_target, l_rev, l_rev_reg()));

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Unit testable helper function: Check that the IDT revision # register and attribute match
///
/// @param[in] i_pmic_target PMIC target (for FFDC)
/// @param[in] i_rev_attr revision value from attribute
/// @param[in] i_rev_reg revision value from register
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff no error
///
fapi2::ReturnCode check_valid_idt_revisions_helper(
const fapi2::Target<fapi2::TARGET_TYPE_PMIC>& i_pmic_target,
const uint8_t i_rev_attr,
const uint8_t i_rev_reg)
{
// At the moment, we only care that if we have C1 revision in either the SPD, or
// in the revision register, that the other matches. That way we use new C1 settings
// on C1 PMICs only, and vice-versa.
constexpr uint8_t IDT_C1_REV = 0x21;

// If neither are IDT_C1, return
if (i_rev_attr != IDT_C1_REV && i_rev_reg != IDT_C1_REV)
{
return fapi2::FAPI2_RC_SUCCESS;
}

FAPI_ASSERT(i_rev_attr == i_rev_reg,
fapi2::PMIC_MISMATCHING_REVISIONS()
.set_REVISION_ATTR(i_rev_attr)
.set_REVISION_REG(i_rev_reg)
.set_PMIC_TARGET(i_pmic_target),
"Mismatching revisions for %s. ATTR: 0x%02X REG: 0x%02X",
mss::c_str(i_pmic_target),
i_rev_attr,
i_rev_reg);

return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Enable PMIC for SPD mode
///
Expand Down Expand Up @@ -588,6 +731,15 @@ fapi2::ReturnCode pmic_enable_SPD(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CH
"pmic_enable: poll for pbulk good either failed, or returned not good status on PMIC %s",
mss::c_str(l_pmic));

// Check that the PMIC vendor ID register matches the attribute
// (and therefore has the correct settings)
FAPI_TRY(mss::pmic::check_matching_vendors(i_ocmb_target, l_pmic));

if (l_vendor_id == mss::pmic::vendor::IDT)
{
FAPI_TRY(mss::pmic::check_valid_idt_revisions(i_ocmb_target, l_pmic));
}

// Call the enable procedure
FAPI_TRY((mss::pmic::enable_chip_1U_2U(l_pmic, i_ocmb_target, l_vendor_id)),
"pmic_enable: Error enabling PMIC %s", mss::c_str(l_pmic));
Expand Down

0 comments on commit 09ee51c

Please sign in to comment.