summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/fapiwrap/fapiWrapif.H12
-rw-r--r--src/include/usr/i2c/eeprom_const.H6
-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
10 files changed, 242 insertions, 17 deletions
diff --git a/src/include/usr/fapiwrap/fapiWrapif.H b/src/include/usr/fapiwrap/fapiWrapif.H
index f37aea26b..e3a50f3b7 100644
--- a/src/include/usr/fapiwrap/fapiWrapif.H
+++ b/src/include/usr/fapiwrap/fapiWrapif.H
@@ -55,6 +55,18 @@ namespace FAPIWRAP
errlHndl_t explorer_getidec( TARGETING::Target * i_ocmbChip,
uint16_t& o_chipId,
uint8_t& o_ec);
+
+ /**
+ * @brief This function wraps around the FAPI2 HWP "get_pmic_i2c_addr" which
+ * takes in a DDIMM's DDR4 SPD data and a PMIC's position relative to
+ * its parent OCMB's chip and returns the device address of that pmic
+ * @param[in] i_spd - Binary blob containing addresses a given OCMB's PMICs
+ * @param[in] i_pmic_id - PMIC's position relative to parent OCMB
+ * @return uint8_t 0 if invalid pmic_id is passed, PMIC's devAddress otherwise
+ */
+ uint8_t get_pmic_dev_addr( const char* i_spd,
+ const uint8_t i_pmic_id);
+
}
#endif \ No newline at end of file
diff --git a/src/include/usr/i2c/eeprom_const.H b/src/include/usr/i2c/eeprom_const.H
index 055aa2172..275388450 100644
--- a/src/include/usr/i2c/eeprom_const.H
+++ b/src/include/usr/i2c/eeprom_const.H
@@ -170,9 +170,9 @@ struct eecacheSectionHeader
*/
struct eeprom_addr_t
{
- uint64_t port;
- uint64_t engine;
- uint64_t devAddr;
+ uint8_t port;
+ uint8_t engine;
+ uint8_t devAddr;
int64_t eepromRole;
uint64_t offset;
eeprom_addr_size_t addrSize;
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