Skip to content

Commit

Permalink
Fix issue in pmic_enable where VR_ENABLE did not kick off
Browse files Browse the repository at this point in the history
Also fixing a small issue/oversight. The PMIC requires enabled startup sequences
to "enable" the rails of previous sequences.

Change-Id: Id8a5baf54f7aef0c7e6aa97539fc78196c011dbf
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/81828
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Dev-Ready: Steven B Janssen <janssens@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Devon A Baughen <devon.baughen1@ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/81860
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 Aug 13, 2019
1 parent 08db2d6 commit 24762ab
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 7 deletions.
Expand Up @@ -179,7 +179,6 @@ fapi_try_exit:
/// @param[in] i_dimm_target dimm target of PMIC
/// @param[in] i_id PMIC0 or PMIC1
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff no error
/// @note TK - this function may greatly change. It relies on SPD fields that may not be correct.
///
fapi2::ReturnCode bias_with_spd_startup_seq(
const fapi2::Target<fapi2::TargetType::TARGET_TYPE_PMIC>& i_pmic_target,
Expand All @@ -203,6 +202,15 @@ fapi2::ReturnCode bias_with_spd_startup_seq(
mss::pmic::get_swd_sequence_delay
};

static const std::vector<uint8_t> SEQUENCE_REGS =
{
0, // 0 would imply no sequence config (won't occur due to assert in bias_with_spd_startup_seq)
REGS::R40_POWER_ON_SEQUENCE_CONFIG_1,
REGS::R41_POWER_ON_SEQUENCE_CONFIG_2,
REGS::R42_POWER_ON_SEQUENCE_CONFIG_3,
REGS::R43_POWER_ON_SEQUENCE_CONFIG_4
};

// Arrays to store the attribute data
uint8_t l_sequence_orders[CONSTS::NUMBER_OF_RAILS];
uint8_t l_sequence_delays[CONSTS::NUMBER_OF_RAILS];
Expand All @@ -229,26 +237,48 @@ fapi2::ReturnCode bias_with_spd_startup_seq(

{
fapi2::buffer<uint8_t> l_power_on_sequence_config;
uint8_t l_highest_sequence = 0;

// Zero out sequence registers first
FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, REGS::R40_POWER_ON_SEQUENCE_CONFIG_1, l_power_on_sequence_config));
FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, REGS::R41_POWER_ON_SEQUENCE_CONFIG_2, l_power_on_sequence_config));
FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, REGS::R42_POWER_ON_SEQUENCE_CONFIG_3, l_power_on_sequence_config));
FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, REGS::R43_POWER_ON_SEQUENCE_CONFIG_4, l_power_on_sequence_config));

// Set the registers appropriately.
// We do manual reversing here (see above) so that we can also place in the delays as they're supposed to be
// Set the registers appropriately. We kind of need to do this greedy algorithm here since
// the SPD has fields of sequence per rail, the PMIC wants rails per sequence.
// 1. For each rail, set that bit in the corresponding sequence, and enable that sequence
// 2. Set that rail bit for each of the following sequences
// 3. Record the highest sequence used throughout the run
// 4. Clear out registers of sequences higher than the highest used (clear the set rail bits)
// We do this because for each rail, we may not know what the highest sequence will be yet.
// It makes the most sense to assume all sequences, then clear those that aren't used.
for (uint8_t l_rail_index = mss::pmic::rail::SWA; l_rail_index <= mss::pmic::rail::SWD; ++l_rail_index)
{
if (l_sequence_orders[l_rail_index] != 0) // If 0, it will not be sequenced
static constexpr uint8_t NO_SEQUENCE = 0;
const uint8_t l_rail_sequence = l_sequence_orders[l_rail_index];

if (l_rail_sequence != NO_SEQUENCE) // If 0, it will not be sequenced
{
// Update the new highest working sequence
l_highest_sequence = std::max(l_rail_sequence, l_highest_sequence);
// Set the register contents appropriately
FAPI_TRY(mss::pmic::set_startup_seq_register(i_pmic_target, l_rail_index,
l_sequence_orders[l_rail_index], l_sequence_delays[l_rail_index]));
l_rail_sequence, l_sequence_delays[l_rail_index]));
}

// else, zero, do nothing.
}

// Now erase the registers that are higher than our highest sequence (in order to satisfy note 2
// for registers R40 - R43):
// - 2. If bit [7] = ‘0’, bits [6:3] must be programmed as ‘0000’. If bit [7] = ‘1’,
// - at least one of the bits [6:3] must be programmed as ‘1’.
for (++l_highest_sequence; l_highest_sequence < SEQUENCE_REGS.size(); ++l_highest_sequence)
{
fapi2::buffer<uint8_t> l_clear;
FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, SEQUENCE_REGS[l_highest_sequence], l_power_on_sequence_config));
}
}

fapi_try_exit:
Expand Down Expand Up @@ -326,10 +356,24 @@ fapi2::ReturnCode set_startup_seq_register(
l_power_on_sequence_config.clearBit<DELAY_START, FIELDS::DELAY_FLD_LENGTH>();
l_power_on_sequence_config = l_power_on_sequence_config + i_delay;

l_power_on_sequence_config.setBit(SEQUENCE_BITS[i_rail]);
l_power_on_sequence_config.setBit(SEQUENCE_ENABLE_REVERSED);
FAPI_TRY(l_power_on_sequence_config.setBit(SEQUENCE_BITS[i_rail]));
FAPI_TRY(l_power_on_sequence_config.setBit(SEQUENCE_ENABLE_REVERSED));

FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, SEQUENCE_REGS[i_round], l_power_on_sequence_config));

// The startup sequence registers after the provided one must set the bits of the rail we just enabled in
// the current sequence. So here, we iterate through the remaining sequences and set those bits.
// since we don't know the information about all the rails within this one function (others may be
// set in later calls to this function) we will set these for each sequence register now, and then
// clear them out later when we know exactly which sequences will be enabled and which ones won't
for (uint8_t l_round_modify = i_round; l_round_modify < SEQUENCE_REGS.size(); ++l_round_modify)
{
l_power_on_sequence_config.flush<0>();
FAPI_TRY(mss::pmic::i2c::reg_read(i_pmic_target, SEQUENCE_REGS[l_round_modify], l_power_on_sequence_config));
FAPI_TRY(l_power_on_sequence_config.setBit(SEQUENCE_BITS[i_rail]));
FAPI_TRY(mss::pmic::i2c::reg_write(i_pmic_target, SEQUENCE_REGS[l_round_modify], l_power_on_sequence_config));
}

return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
Expand Down
Expand Up @@ -780,6 +780,10 @@ inline fapi2::ReturnCode enable_chip<mss::pmic::module_height::HEIGHT_1U>(
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:
Expand Down
Expand Up @@ -57,6 +57,13 @@ extern "C"
auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_ocmb_target);
auto l_pmics = mss::find_targets<fapi2::TARGET_TYPE_PMIC>(i_ocmb_target);

// Check that we have PMICs (we wouldn't on gemini, for example)
if (l_pmics.empty())
{
FAPI_INF("No PMICs to enable on %s, exiting.", mss::c_str(i_ocmb_target));
return fapi2::FAPI2_RC_SUCCESS;
}

// Sort by index (low to high) since find_targets may not return the correct order
std::sort(l_dimms.begin(), l_dimms.end(),
[] (const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& l_first_dimm,
Expand Down

0 comments on commit 24762ab

Please sign in to comment.