Skip to content

Commit

Permalink
p9_sbe_lpc_init: Fix LPC bus LRESET for DD2
Browse files Browse the repository at this point in the history
Change the order of operations so that first the LPC Master is reset,
then the bus reset is driven with a proper delay. Previously the bus reset
duration depended on the code path taken (DD1 vs. DD2) and was likely too
short on DD2.

Also extract the various parts of the sequence into individual functions to
improve readability.

Change-Id: I55cd750735ae21131c57c185ffc8a4fa1392b2dc
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/44416
Reviewed-by: Dean Sanner <dsanner@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Reviewed-by: Joseph J. McGill <jmcgill@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/71479
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
  • Loading branch information
fenkes-ibm authored and crgeddes committed Feb 12, 2019
1 parent 40451ee commit 05f19a4
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 64 deletions.
174 changes: 110 additions & 64 deletions src/import/chips/p9/procedures/hwp/perv/p9_sbe_lpc_init.C
Original file line number Diff line number Diff line change
Expand Up @@ -44,65 +44,13 @@
#include "p9_misc_scom_addresses.H"
#include "p9_misc_scom_addresses_fld.H"

fapi2::ReturnCode p9_sbe_lpc_init(const
fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip)
static fapi2::ReturnCode reset_lpc_master(
const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip)
{
const uint64_t C_LPC_TIMEOUT_ADDR = 0x00400000C001202C;
const uint64_t C_LPC_TIMEOUT_DATA = 0x00000000FE000000;
const uint64_t C_OPB_TIMEOUT_ADDR = 0x00400000C0010040;
const uint64_t C_OPB_TIMEOUT_DATA = 0x00000000FFFFFFFE;
fapi2::buffer<uint64_t> l_data64;
uint8_t l_use_gpio = 0;
uint8_t l_is_fsp = 0;
FAPI_DBG("p9_sbe_lpc_init: Entering ...");

FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_LPC_RESET_GPIO, i_target_chip, l_use_gpio),
"Error getting the use_gpio_attr");

FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SP_MODE, i_target_chip, l_is_fsp), "Error getting ATTR_IS_SP_MODE");

//For DD2 and beyond we want to use the lpc reset that will reset the external LPC Bus attached devices -- this is what was broken in DD1
if (l_use_gpio == 0)
{
//Write to the LPCM OPB Master Control Register (address x'C001 0008')
fapi2::buffer<uint64_t> l_lpcm_opb_master_control_register_data(0);
l_lpcm_opb_master_control_register_data.setBit<PU_LPC_CMD_REG_RNW>().insertFromRight<PU_LPC_CMD_REG_ADR, PU_LPC_CMD_REG_ADR_LEN>
(LPCM_OPB_MASTER_CONTROL_REG).insertFromRight<PU_LPC_CMD_REG_SIZE, PU_LPC_CMD_REG_SIZE_LEN>(0x4);
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_lpcm_opb_master_control_register_data),
"Erro writing the LPC_CMD_REG to get the current reset value");
FAPI_TRY(fapi2::getScom(i_target_chip, PU_LPC_DATA_REG, l_data64), "Error getting the reset value");
//Set register bit 23 lpc_lreset_oe to b'1'
l_data64.setBit<LPC_LRESET_OE>();
l_lpcm_opb_master_control_register_data.clearBit<PU_LPC_CMD_REG_RNW>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_lpcm_opb_master_control_register_data),
"Error writing to the LPC_CMD_REG to set lpc_lreset_oe");
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_DATA_REG, l_data64), "Error setting lpc_lreset_oe");
//Set register bit 22 lpc_reset_out to b'1'
l_data64.setBit<LPC_LRESET_OUT>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_lpcm_opb_master_control_register_data),
"Error writing to the LPC_CMD_REG to set the lpc_reset_out");
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_DATA_REG, l_data64), "Error setting lpc_reset_out");
//Clear register bits 22 and 23 to b'00'
l_data64.clearBit<LPC_LRESET_OE>().clearBit<LPC_LRESET_OUT>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_lpcm_opb_master_control_register_data),
"Error writing to the LPC_CMD_REG to clear lpc_lreset_oe and lpc_reset_out");
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_DATA_REG, l_data64), "Error clearing lpc_lreset_oe and lpc_reset_out");
}

if ((l_use_gpio != 0) && (l_is_fsp == fapi2::ENUM_ATTR_IS_SP_MODE_FSP))
{
//LPC Reset active
l_data64.flush<1>().clearBit<0>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_GPIO_OUTPUT_SCOM2, l_data64));

//Set GPI0 output enable
FAPI_TRY(fapi2::getScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));
l_data64.setBit<PU_GPIO_OUTPUT_EN_DO_EN_0>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));
}

//Do the functional reset that resets the internal registers
//Settting registers to do an LPC functional reset
//Setting registers to do an LPC functional reset
l_data64.flush<0>().setBit<CPLT_CONF1_TC_LP_RESET>();
FAPI_TRY(fapi2::putScom(i_target_chip, PERV_N3_CPLT_CONF1_OR, l_data64));

Expand All @@ -122,18 +70,116 @@ fapi2::ReturnCode p9_sbe_lpc_init(const
l_data64.flush<0>().setBit<CPLT_CONF1_TC_LP_RESET>();
FAPI_TRY(fapi2::putScom(i_target_chip, PERV_N3_CPLT_CONF1_CLEAR, l_data64));

if ((l_use_gpio != 0) && (l_is_fsp == fapi2::ENUM_ATTR_IS_SP_MODE_FSP))
return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
}

static fapi2::ReturnCode reset_lpc_bus_via_master(
const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip)
{
fapi2::buffer<uint64_t> l_data64;
fapi2::buffer<uint64_t> l_lpcm_opb_master_control_register_data(0);

//Write to the LPCM OPB Master Control Register (address x'C001 0008')
l_lpcm_opb_master_control_register_data.setBit<PU_LPC_CMD_REG_RNW>().insertFromRight<PU_LPC_CMD_REG_ADR, PU_LPC_CMD_REG_ADR_LEN>
(LPCM_OPB_MASTER_CONTROL_REG).insertFromRight<PU_LPC_CMD_REG_SIZE, PU_LPC_CMD_REG_SIZE_LEN>(0x4);
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_lpcm_opb_master_control_register_data),
"Erro writing the LPC_CMD_REG to get the current reset value");
FAPI_TRY(fapi2::getScom(i_target_chip, PU_LPC_DATA_REG, l_data64), "Error getting the reset value");

//Set register bit 23 lpc_lreset_oe to b'1' and set lpc_lreset_out to b'0' to drive a low reset
l_data64.setBit<LPC_LRESET_OE>().clearBit<LPC_LRESET_OUT>();
l_lpcm_opb_master_control_register_data.clearBit<PU_LPC_CMD_REG_RNW>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_lpcm_opb_master_control_register_data),
"Error writing to the LPC_CMD_REG to set lpc_lreset_oe");
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_DATA_REG, l_data64), "Error setting lpc_lreset_oe");

//Give the bus some time to reset
fapi2::delay(LPC_LRESET_DELAY_NS, LPC_LRESET_DELAY_NS);

//Clear bit 23 lpc_lreset_oe to stop driving the low reset
l_data64.clearBit<LPC_LRESET_OE>();
l_lpcm_opb_master_control_register_data.clearBit<PU_LPC_CMD_REG_RNW>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_lpcm_opb_master_control_register_data),
"Error writing to the LPC_CMD_REG to clear lpc_lreset_oe");
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_DATA_REG, l_data64), "Error clearing lpc_lreset_oe");

return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
}

static fapi2::ReturnCode reset_lpc_bus_via_gpio(
const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip)
{
fapi2::buffer<uint64_t> l_data64;

//LPC Reset active
l_data64.flush<1>().clearBit<0>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_GPIO_OUTPUT_SCOM2, l_data64));

//Set GPI0 output enable
FAPI_TRY(fapi2::getScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));
l_data64.setBit<PU_GPIO_OUTPUT_EN_DO_EN_0>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));

//Give the bus some time to reset
fapi2::delay(LPC_LRESET_DELAY_NS, LPC_LRESET_DELAY_NS);

//Unset GPIO output enable
FAPI_TRY(fapi2::getScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));
l_data64.clearBit<PU_GPIO_OUTPUT_EN_DO_EN_0>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));

return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
}


fapi2::ReturnCode p9_sbe_lpc_init(
const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip)
{
const uint64_t C_LPC_TIMEOUT_ADDR = 0x00400000C001202C;
const uint64_t C_LPC_TIMEOUT_DATA = 0x00000000FE000000;
const uint64_t C_OPB_TIMEOUT_ADDR = 0x00400000C0010040;
const uint64_t C_OPB_TIMEOUT_DATA = 0x00000000FFFFFFFE;
fapi2::buffer<uint64_t> l_data64;
uint8_t l_use_gpio = 0;
uint8_t l_is_fsp = 0;
FAPI_DBG("p9_sbe_lpc_init: Entering ...");

FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_LPC_RESET_GPIO, i_target_chip, l_use_gpio),
"Error getting the use_gpio_attr");

FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SP_MODE, i_target_chip, l_is_fsp), "Error getting ATTR_IS_SP_MODE");

//------------------------------------------------------------------------------------------
//--- STEP 1: Functional reset of LPC Master
//------------------------------------------------------------------------------------------
FAPI_TRY(reset_lpc_master(i_target_chip));

//------------------------------------------------------------------------------------------
//--- STEP 2: Issue an LPC bus reset
//------------------------------------------------------------------------------------------
//For DD2 and beyond we want to use the lpc reset that will reset the external LPC Bus attached devices -- this is what was broken in DD1
if (l_use_gpio == 0)
{
FAPI_TRY(reset_lpc_bus_via_master(i_target_chip));
}
else if (l_is_fsp == fapi2::ENUM_ATTR_IS_SP_MODE_FSP)
{
//LPC Reset Disabled
l_data64.flush<0>().setBit<0>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_GPIO_OUTPUT_SCOM1, l_data64));

//Unset GPIO output enable
FAPI_TRY(fapi2::getScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));
l_data64.clearBit<PU_GPIO_OUTPUT_EN_DO_EN_0>();
FAPI_TRY(fapi2::putScom(i_target_chip, PU_GPIO_OUTPUT_EN, l_data64));
FAPI_TRY(reset_lpc_bus_via_gpio(i_target_chip));
}

//------------------------------------------------------------------------------------------
//--- STEP 3: Program settings in LPC Master and FPGA
//------------------------------------------------------------------------------------------

//Set up the LPC timeout settings
l_data64 = C_LPC_TIMEOUT_ADDR;
FAPI_TRY(fapi2::putScom(i_target_chip, PU_LPC_CMD_REG, l_data64), "Error tring to set LPC timeout address");
Expand Down
1 change: 1 addition & 0 deletions src/import/chips/p9/procedures/hwp/perv/p9_sbe_lpc_init.H
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ extern "C"
{
const uint64_t LPC_LRESET_OE = 23;
const uint64_t LPC_LRESET_OUT = 22;
const uint32_t LPC_LRESET_DELAY_NS = 200000;
const uint64_t LPCM_OPB_MASTER_CONTROL_REG = 0xC0010008;
const uint32_t CPLT_CONF1_TC_LP_RESET = 12;
fapi2::ReturnCode p9_sbe_lpc_init(const
Expand Down

0 comments on commit 05f19a4

Please sign in to comment.