diff options
Diffstat (limited to 'src/usr/i2c/i2cTargetPres.C')
-rw-r--r-- | src/usr/i2c/i2cTargetPres.C | 127 |
1 files changed, 111 insertions, 16 deletions
diff --git a/src/usr/i2c/i2cTargetPres.C b/src/usr/i2c/i2cTargetPres.C index c3809f099..c7c9421a3 100644 --- a/src/usr/i2c/i2cTargetPres.C +++ b/src/usr/i2c/i2cTargetPres.C @@ -32,7 +32,7 @@ #include <initservice/initserviceif.H> #include <errl/errlmanager.H> #include "i2c_common.H" - +#include <fapiwrap/fapiWrapif.H> extern trace_desc_t* g_trac_i2c; @@ -182,6 +182,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, @@ -223,10 +235,6 @@ errlHndl_t ocmbI2CPresencePerformOp(DeviceFW::OperationType i_opType, { errlHndl_t l_invalidateErrl = nullptr; - // @TODO RTC 208696: Gemini vs Explorer Presence Detection via SPD - // This function will be updated to differentiate between Explorer and - // Gemini OCMB chips. For now, presense of an OCMB chip is inferred by - // the presense of the eeprom. bool l_ocmbPresent = EEPROM::eepromPresence(i_target); memcpy(io_buffer, &l_ocmbPresent, sizeof(l_ocmbPresent)); @@ -236,10 +244,97 @@ 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; + uint8_t l_devAddr; + TARGETING::Target* l_parentOcmb = TARGETING::getImmediateParentByAffinity(i_target); + auto l_parentHwasState = l_parentOcmb->getAttr<TARGETING::ATTR_HWAS_STATE>(); + + do{ + + if(! l_parentHwasState.present) + { + // If the parent chip is not present, then neither is the pmic + // so just break out and return not present + 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 + l_errl = FAPIWRAP::get_pmic_dev_addr(l_parentOcmb, + l_relPos, + l_devAddr); + if (l_errl) + { + TRACFCOMP( g_trac_i2c, ERR_MRK"pmicI2CPresencePerformOp() " + "Error attempting to read pmic device address on OCMB 0x%.08X", + TARGETING::get_huid(l_parentOcmb)); + break; + } + + 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)); + + if(l_devAddr == FAPIWRAP::NO_PMIC_DEV_ADDR) + { + // There is no pmic device address for this rel position on this ocmb so + // break and return not present. + break; + } + + 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 @@ -253,7 +348,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, @@ -261,13 +356,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", @@ -280,7 +375,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 @@ -293,12 +388,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 ); } |