summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorChristian Geddes <crgeddes@us.ibm.com>2019-10-16 10:10:34 -0500
committerWilliam G Hoffa <wghoffa@us.ibm.com>2019-11-01 15:41:41 -0500
commit632582f105da7a546708c4f9705761948d7688fa (patch)
treef76238e3071d6d7b39459b17eb83796aca6c95a1 /src/usr
parent3f41702fbfd6a5c4f4de9eabedf1d8acb801ae20 (diff)
downloadtalos-hostboot-632582f105da7a546708c4f9705761948d7688fa.tar.gz
talos-hostboot-632582f105da7a546708c4f9705761948d7688fa.zip
Allow dynmic i2c device addresses and set up PMIC targets to do this
Depending on which vendor made a given OCMB the i2c device address of the PMIC targets on the OCMB will be different. To account for this we have added a new DYNAMIC_DEVICE_ADDRESS attribute. This attribute is filled out on the PMIC target by looking at the SPD on parent OCMB chip. This means that we must do presence detection on the OCMB prior to the the PMIC targets. While doing i2c operations if a given target has the DYNAMIC_DEVICE_ADDRESS we will use that over the devAddr in the any complex i2c attribute for that target. Change-Id: I22a185a65c064a1514751dd5828547c57af98df1 RTC: 209714 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/85394 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com> Reviewed-by: Roland Veloz <rveloz@us.ibm.com> Reviewed-by: William G Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/fapiwrap/fapiWrap.C9
-rw-r--r--src/usr/fapiwrap/makefile1
-rw-r--r--src/usr/hwas/common/hwas.C69
-rw-r--r--src/usr/i2c/eeprom_utils.C12
-rw-r--r--src/usr/i2c/fapi_i2c_dd.C12
-rw-r--r--src/usr/i2c/i2cTargetPres.C115
-rwxr-xr-xsrc/usr/targeting/common/xmltohb/attribute_types_hb.xml15
-rw-r--r--src/usr/targeting/common/xmltohb/target_types_hb.xml8
8 files changed, 227 insertions, 14 deletions
diff --git a/src/usr/fapiwrap/fapiWrap.C b/src/usr/fapiwrap/fapiWrap.C
index dc52570e6..a65b7c233 100644
--- a/src/usr/fapiwrap/fapiWrap.C
+++ b/src/usr/fapiwrap/fapiWrap.C
@@ -27,7 +27,8 @@
#include <fapi2/plat_hwp_invoker.H> // FAPI_INVOKE_HWP
#include <trace/interface.H> // tracing includes
-#include <exp_getidec.H> // exp_getidec
+#include <exp_getidec.H> // exp_getidec
+#include <pmic_i2c_addr_get.H> // get_pmic_i2c_addr
trace_desc_t* g_trac_fapiwrap;
TRAC_INIT(&g_trac_fapiwrap, FAPIWRAP_COMP_NAME, 6*KILOBYTE, TRACE::BUFFER_SLOW);
@@ -55,4 +56,10 @@ namespace FAPIWRAP
return l_errl;
}
+
+ uint8_t get_pmic_dev_addr( const char* i_spd,
+ const uint8_t i_pmic_id)
+ {
+ return get_pmic_i2c_addr(i_spd, i_pmic_id);
+ }
} \ No newline at end of file
diff --git a/src/usr/fapiwrap/makefile b/src/usr/fapiwrap/makefile
index 61ccd9646..96d96e48b 100644
--- a/src/usr/fapiwrap/makefile
+++ b/src/usr/fapiwrap/makefile
@@ -38,6 +38,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/procedures/hwp/ffdc/
# HWP include directories :
EXTRAINCDIR += ${ROOTPATH}/src/import/chips/ocmb/explorer/procedures/hwp/memory/
+EXTRAINCDIR += ${ROOTPATH}/src/import/chips/ocmb/common/spd_access/
# HWP objects
OBJS += exp_getidec.o
diff --git a/src/usr/hwas/common/hwas.C b/src/usr/hwas/common/hwas.C
index 8498b12b7..9464e59c9 100644
--- a/src/usr/hwas/common/hwas.C
+++ b/src/usr/hwas/common/hwas.C
@@ -569,6 +569,59 @@ errlHndl_t discoverMuxTargetsAndEnable(const Target &i_sysTarget)
return l_err;
}
+/**
+ * @brief Do presence detect on only PMIC targets and enable HWAS state
+ *
+ * @param[in] i_sysTarget the top level target (CLASS_SYS)
+ * @return errlHndl_t return nullptr if no error,
+ * else return a handle to an error entry
+ *
+ */
+errlHndl_t discoverPmicTargetsAndEnable(const Target &i_sysTarget)
+{
+ HWAS_INF(ENTER_MRK"discoverPmicTargetsAndEnable");
+
+ errlHndl_t l_err{nullptr};
+
+ do
+ {
+ // Only get PMIC targets
+ const PredicateCTM l_pmicPred(CLASS_ASIC, TYPE_PMIC);
+ TARGETING::PredicatePostfixExpr l_asicPredExpr;
+ l_asicPredExpr.push(&l_pmicPred);
+ TargetHandleList l_pPmicCheckPres;
+ targetService().getAssociated( l_pPmicCheckPres, (&i_sysTarget),
+ TargetService::CHILD, TargetService::ALL, &l_asicPredExpr);
+
+ // Do the presence detect on only PMIC targets
+ // NOTE: this function will remove any non-functional targets
+ // from pPmicCheckPres
+ l_err = platPresenceDetect(l_pPmicCheckPres);
+
+ // If an issue with platPresenceDetect, then exit, returning
+ // error back to caller
+ if (nullptr != l_err)
+ {
+ break;
+ }
+
+ // Enable the HWAS State for the PMICs
+ const bool l_present(true);
+ const bool l_functional(true);
+ const uint32_t l_errlEid(0);
+ for (TargetHandle_t pTarget : l_pPmicCheckPres)
+ {
+ // set HWAS state to show PMIC is present and functional
+ enableHwasState(pTarget, l_present, l_functional, l_errlEid);
+ }
+ } while (0);
+
+ HWAS_INF(EXIT_MRK"discoverPmicTargetsAndEnable exit with %s",
+ (nullptr == l_err ? "no error" : "error"));
+
+ return l_err;
+}
+
errlHndl_t discoverTargets()
{
HWAS_DBG("discoverTargets entry");
@@ -643,11 +696,13 @@ errlHndl_t discoverTargets()
PredicateCTM predPmic(CLASS_ASIC, TYPE_PMIC);
// We can ignore chips of TYPE_I2C_MUX because they
// were already detected above in discoverMuxTargetsAndEnable
+ // Also we can ignore chips of type PMIC because they will be processed
+ // below.
PredicateCTM predMux(CLASS_CHIP, TYPE_I2C_MUX);
PredicatePostfixExpr checkExpr;
checkExpr.push(&predChip).push(&predDimm).Or().push(&predEnc).Or().
- push(&predMcs).Or().push(&predPmic).Or().
- push(&predMux).Not().And();
+ push(&predMcs).Or().push(&predMux).Not().And().
+ push(&predPmic).Not().And();
TargetHandleList pCheckPres;
targetService().getAssociated( pCheckPres, pSys,
@@ -865,6 +920,16 @@ errlHndl_t discoverTargets()
} // for pTarget_it
+ // After processing all other targets look at the pmics,
+ // we must wait because we need the SPD cached from the OCMBs
+ // which occurs when OCMBs go through presence detection above
+ errl = discoverPmicTargetsAndEnable(*pSys);
+
+ if (errl != NULL)
+ {
+ break; // break out of the do/while so that we can return
+ }
+
// Check for non-present Procs and if found, trigger
// DeconfigGard::_invokeDeconfigureAssocProc() to run by setting
// setXAOBusEndpointDeconfigured to true
diff --git a/src/usr/i2c/eeprom_utils.C b/src/usr/i2c/eeprom_utils.C
index 7935094a3..8333ebf49 100644
--- a/src/usr/i2c/eeprom_utils.C
+++ b/src/usr/i2c/eeprom_utils.C
@@ -87,6 +87,18 @@ bool eepromPresence ( TARGETING::Target * i_target )
break;
}
+ // If the target has dynamic device address attribute, then use that instead of the
+ // read-only address found in ATTR_EEPROM_XX_INFO attrs. We use the dynamic address
+ // attribute because ATTR_EEPROM_XX_INFO attrs are not writable and its difficult
+ // to override complex attributes.
+ if(i_target->tryGetAttr<TARGETING::ATTR_DYNAMIC_I2C_DEVICE_ADDRESS>(i2cInfo.devAddr))
+ {
+ TRACDCOMP(g_trac_eeprom,
+ "Using DYNAMIC_I2C_DEVICE_ADDRESS %.2x for HUID %.8x",
+ i2cInfo.devAddr,
+ TARGETING::get_huid(i_target));
+ }
+
//Check for the target at the I2C level
l_present = I2C::i2cPresence(i2cMasterTarget,
i2cInfo.port,
diff --git a/src/usr/i2c/fapi_i2c_dd.C b/src/usr/i2c/fapi_i2c_dd.C
index d800af376..46e0720a1 100644
--- a/src/usr/i2c/fapi_i2c_dd.C
+++ b/src/usr/i2c/fapi_i2c_dd.C
@@ -108,6 +108,18 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType,
break;
}
+ // If the target has dynamic device address attribute, then use that instead of the
+ // read-only address found in ATTR_FAPI_I2C_CONTROL_INFO. We use the dynamic address
+ // attribute because ATTR_FAPI_I2C_CONTROL_INFO is not writable and its difficult
+ // to override complex attributes.
+ if(i_target->tryGetAttr<TARGETING::ATTR_DYNAMIC_I2C_DEVICE_ADDRESS>(l_i2cInfo.devAddr))
+ {
+ TRACDCOMP(g_trac_i2c,
+ "Using DYNAMIC_I2C_DEVICE_ADDRESS %.2x for HUID %.8x",
+ l_i2cInfo.devAddr,
+ TARGETING::get_huid(i_target));
+ }
+
// grab target pointer to master
TARGETING::TargetService& ts = TARGETING::targetService();
TARGETING::Target * i2cm = ts.toTarget(l_i2cInfo.i2cMasterPath);
diff --git a/src/usr/i2c/i2cTargetPres.C b/src/usr/i2c/i2cTargetPres.C
index 13bfa88c1..2aba61de3 100644
--- a/src/usr/i2c/i2cTargetPres.C
+++ b/src/usr/i2c/i2cTargetPres.C
@@ -32,6 +32,8 @@
#include <initservice/initserviceif.H>
#include <errl/errlmanager.H>
#include "i2c_common.H"
+#include <vpd/spdenums.H>
+#include <fapiwrap/fapiWrapif.H>
extern trace_desc_t* g_trac_i2c;
@@ -181,6 +183,18 @@ errlHndl_t genericI2CTargetPresenceDetect(TARGETING::Target* i_target,
//* If we make it through all of the checks then we have verified master is present *
//***********************************************************************************
+ // If the target has dynamic device address attribute, then use that instead of the
+ // read-only address found in ATTR_FAPI_I2C_CONTROL_INFO. We use the dynamic address
+ // attribute because ATTR_FAPI_I2C_CONTROL_INFO is not writable and its difficult
+ // to override complex attributes.
+ if(i_target->tryGetAttr<TARGETING::ATTR_DYNAMIC_I2C_DEVICE_ADDRESS>(l_i2cInfo.devAddr))
+ {
+ TRACDCOMP(g_trac_i2c,
+ "Using DYNAMIC_I2C_DEVICE_ADDRESS %.2x for HUID %.8x",
+ l_i2cInfo.devAddr,
+ TARGETING::get_huid(i_target));
+ }
+
//Check for the target at the I2C level
l_target_present = I2C::i2cPresence(l_i2cMasterTarget,
l_i2cInfo.port,
@@ -231,10 +245,89 @@ errlHndl_t ocmbI2CPresencePerformOp(DeviceFW::OperationType i_opType,
}
/**
- * @brief Performs a presence detect operation on a Target that has the
+ * @brief Performs a presence detect operation on a PMIC Target
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ * @param[in] i_target Presence detect target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes, always 1)
+ * Output: Success = 1, Failure = 0
+ * @param[in] i_accessType DeviceFW::AccessType enum (userif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there are no arguments.
+ * @return errlHndl_t
+ */
+errlHndl_t pmicI2CPresencePerformOp(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+
+ errlHndl_t l_errl = nullptr;
+ bool l_pmicPresent = 0;
+ TARGETING::Target* l_parentOcmb = TARGETING::getImmediateParentByAffinity(i_target);
+
+ uint8_t l_spdBlob[SPD::DDIMM_DDR4_SPD_SIZE];
+ size_t l_spdSize = SPD::DDIMM_DDR4_SPD_SIZE;
+
+ do{
+
+ l_errl = deviceRead(l_parentOcmb,
+ l_spdBlob,
+ l_spdSize,
+ DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD_WITHOUT_EFD));
+
+ if(l_errl)
+ {
+ TRACFCOMP( g_trac_i2c, ERR_MRK"pmicI2CPresencePerformOp() "
+ "Error reading SPD associated with PMIC 0x%.08X, failed to determine presence",
+ TARGETING::get_huid(i_target));
+ break;
+ }
+
+ TARGETING::ATTR_REL_POS_type l_relPos = i_target->getAttr<TARGETING::ATTR_REL_POS>();
+
+ // PMICs will have a different device address depending on the vendor.
+ // Prior to doing present detection on a pmic we must first query the
+ // device address from the parent OCMB's SPD
+ uint8_t l_devAddr = FAPIWRAP::get_pmic_dev_addr(reinterpret_cast<char *>(l_spdBlob),
+ l_relPos);
+
+ assert(l_devAddr != 0,
+ "Found devAddr for PMIC 0x%.08x to be 0, this cannot be. Check SPD and REL_POS on target",
+ TARGETING::get_huid(i_target));
+
+ i_target->setAttr<TARGETING::ATTR_DYNAMIC_I2C_DEVICE_ADDRESS>(l_devAddr);
+
+ l_errl = genericI2CTargetPresenceDetect(i_target,
+ io_buflen,
+ l_pmicPresent);
+
+ if (l_errl)
+ {
+ TRACFCOMP( g_trac_i2c, ERR_MRK"pmicI2CPresencePerformOp() "
+ "Error detecting target 0x%.08X, io_buffer will not be set",
+ TARGETING::get_huid(i_target));
+ break;
+ }
+
+ // Copy variable describing if target is present or not to i/o buffer param
+ memcpy(io_buffer, &l_pmicPresent, sizeof(l_pmicPresent));
+ io_buflen = sizeof(l_pmicPresent);
+
+ }while(0);
+
+ return l_errl;
+}
+
+/**
+ * @brief Performs a presence detect operation on a Mux Target that has the
* ATTR_FAPI_I2C_CONTROL_INFO and can be detected via that device
*
- * Currently used to detect I2C_MUTEX targets
*
* @param[in] i_opType Operation type, see DeviceFW::OperationType
* in driverif.H
@@ -248,7 +341,7 @@ errlHndl_t ocmbI2CPresencePerformOp(DeviceFW::OperationType i_opType,
* In this function, there are no arguments.
* @return errlHndl_t
*/
-errlHndl_t basicI2CPresencePerformOp(DeviceFW::OperationType i_opType,
+errlHndl_t muxI2CPresencePerformOp(DeviceFW::OperationType i_opType,
TARGETING::Target* i_target,
void* io_buffer,
size_t& io_buflen,
@@ -256,13 +349,13 @@ errlHndl_t basicI2CPresencePerformOp(DeviceFW::OperationType i_opType,
va_list i_args)
{
bool l_muxPresent = 0;
- errlHndl_t l_returnedError = nullptr;
+ errlHndl_t l_errl = nullptr;
- l_returnedError = genericI2CTargetPresenceDetect(i_target,
- io_buflen,
- l_muxPresent);
+ l_errl = genericI2CTargetPresenceDetect(i_target,
+ io_buflen,
+ l_muxPresent);
- if (l_returnedError)
+ if (l_errl)
{
TRACFCOMP( g_trac_i2c, ERR_MRK"basicI2CTargetPresenceDetect() "
"Error detecting target 0x%.08X, io_buffer will not be set",
@@ -275,7 +368,7 @@ errlHndl_t basicI2CPresencePerformOp(DeviceFW::OperationType i_opType,
io_buflen = sizeof(l_muxPresent);
}
- return l_returnedError;
+ return l_errl;
}
// Register the ocmb presence detect function with the device framework
@@ -288,12 +381,12 @@ DEVICE_REGISTER_ROUTE(DeviceFW::READ,
DEVICE_REGISTER_ROUTE( DeviceFW::READ,
DeviceFW::PRESENT,
TARGETING::TYPE_I2C_MUX,
- basicI2CPresencePerformOp );
+ muxI2CPresencePerformOp );
// Register the pmic vrm presence detect function with the device framework
DEVICE_REGISTER_ROUTE( DeviceFW::READ,
DeviceFW::PRESENT,
TARGETING::TYPE_PMIC,
- basicI2CPresencePerformOp );
+ pmicI2CPresencePerformOp );
}
diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
index 4910ca681..3e651b498 100755
--- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
@@ -175,6 +175,21 @@
</attribute>
<attribute>
+ <id>DYNAMIC_I2C_DEVICE_ADDRESS</id>
+ <description>
+ This attribute is used when a given target could have different
+ i2c device addresses depending on which manufacture's device we
+ are using.
+ </description>
+ <simpleType>
+ <uint8_t/>
+ </simpleType>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+ </attribute>
+
+ <attribute>
<id>EARLY_TESTCASES_ISTEP</id>
<description>
Indicates which istep we should execute the CXX testcases after, if
diff --git a/src/usr/targeting/common/xmltohb/target_types_hb.xml b/src/usr/targeting/common/xmltohb/target_types_hb.xml
index 03ae7a01d..26cf81f6f 100644
--- a/src/usr/targeting/common/xmltohb/target_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/target_types_hb.xml
@@ -266,6 +266,14 @@
</targetTypeExtension>
<targetTypeExtension>
+ <id>pmic</id>
+ <attribute>
+ <id>DYNAMIC_I2C_DEVICE_ADDRESS</id>
+ <default>0</default>
+ </attribute>
+ </targetTypeExtension>
+
+ <targetTypeExtension>
<id>sys-sys-power9</id>
<attribute>
<id>ALLOW_ATTR_OVERRIDES_IN_SECURE_MODE</id>
OpenPOWER on IntegriCloud