diff --git a/src/include/usr/hdat/hdat.H b/src/include/usr/hdat/hdat.H index 3f151609e70..98c9b813dba 100755 --- a/src/include/usr/hdat/hdat.H +++ b/src/include/usr/hdat/hdat.H @@ -93,6 +93,17 @@ struct hdatHDIFDataArray_t // (<= hdatAllocSize) } __attribute__ ((packed)); +/** @brief Type definition for a versioned data array header. Used when internal + * data is an array and the array data must be versioned + */ +struct hdatHDIFVersionedDataArray_t +{ + uint32_t hdatOffset; // 0x0000 Offset to array from this structure + uint32_t hdatArrayCnt; // 0x0004 Number of array entries + uint32_t hdatAllocSize; // 0x0008 Size of allocated space for array entry + uint32_t hdatActSize; // 0x000C Actual size of an array entry + uint32_t hdatVersion; // 0x0010 Version of the array instance format +} __attribute__ ((packed)); /** @brief Type definition for the 5-tuples that the SPIRA uses to address other * data structures. diff --git a/src/include/usr/i2c/i2cif.H b/src/include/usr/i2c/i2cif.H index 9c498d7bc4d..c0bee8be237 100644 --- a/src/include/usr/i2c/i2cif.H +++ b/src/include/usr/i2c/i2cif.H @@ -230,13 +230,15 @@ struct DeviceInfo_t uint8_t slavePort; //< I2C Slave Port. 0xFF if N/A uint16_t busFreqKhz; //< Bus speed in KHz uint8_t devicePurpose; //< Slave device purpose (from enum) + TARGETING::ATTR_ORDINAL_ID_type assocNode; //< Upstream node's ordinal ID + TARGETING::ATTR_POSITION_type assocProc; //< Upstream proc's position }; /** * Retrieve some information about I2C devices that the Host * needs to know about. * - * @param[in] i_i2cMaster I2C master to query, pass in NULL + * @param[in] i_i2cMaster I2C master to query, pass in nullptr * to get a system-wide list * @param[out] o_deviceInfo list of I2C device structures * diff --git a/src/usr/hdat/hdatmsarea.C b/src/usr/hdat/hdatmsarea.C index 14736b12632..ceb469828ec 100755 --- a/src/usr/hdat/hdatmsarea.C +++ b/src/usr/hdat/hdatmsarea.C @@ -385,12 +385,14 @@ void HdatMsArea::setMsaI2cInfo( std::vector &i_I2cDevEntries ) { HDAT_ENTER(); - iv_msaI2cHdr.hdatOffset = 0x0010; // this is just header of 4 words. arrays start at 0x0010 + // this is just header of 5 words. arrays start at 0x0014 + iv_msaI2cHdr.hdatOffset = sizeof(iv_msaI2cHdr); iv_msaI2cHdr.hdatArrayCnt = i_I2cDevEntries.size(); iv_msaI2cHdr.hdatAllocSize = sizeof(hdatI2cData_t); iv_msaI2cHdr.hdatActSize = sizeof(hdatI2cData_t); + iv_msaI2cHdr.hdatVersion = HOST_I2C_DEV_INFO_VERSION::V2; iv_msaHostI2cCnt = i_I2cDevEntries.size(); - iv_msaHostI2cSize = sizeof(hdatHDIFDataArray_t) + + iv_msaHostI2cSize = sizeof(iv_msaI2cHdr) + (sizeof(hdatI2cData_t) * iv_msaHostI2cCnt); HDAT_INF("iv_msaHostI2cCnt=%d, iv_msaHostI2cSize=%d", iv_msaHostI2cCnt, iv_msaHostI2cSize); @@ -585,7 +587,7 @@ uint32_t HdatMsArea::getMsAreaSize() l_size += (iv_maxEcCnt * sizeof(hdatMsAreaEcLvl_t)); - l_size += sizeof(hdatHDIFDataArray_t); + l_size += sizeof(iv_msaI2cHdr); l_size += (sizeof(hdatI2cData_t) * iv_msaHostI2cCnt); @@ -650,12 +652,12 @@ void HdatMsArea::commit(UtilMem &i_data) i_data.write(iv_ecLvl,iv_maxEcCnt * sizeof(hdatMsAreaEcLvl_t)); - i_data.write(&iv_msaI2cHdr, sizeof(hdatHDIFDataArray_t)); + i_data.write(&iv_msaI2cHdr, sizeof(iv_msaI2cHdr)); if (NULL != iv_msaI2cDataPtr) { i_data.write(iv_msaI2cDataPtr, - (iv_msaHostI2cSize - sizeof(hdatHDIFDataArray_t))); + (iv_msaHostI2cSize - sizeof(iv_msaI2cHdr))); } this->endCommit(i_data); diff --git a/src/usr/hdat/hdatmsarea.H b/src/usr/hdat/hdatmsarea.H index ccd238fa3da..850adc0c23c 100755 --- a/src/usr/hdat/hdatmsarea.H +++ b/src/usr/hdat/hdatmsarea.H @@ -597,27 +597,27 @@ private: * @li iv_ramPtrs - ptr to storage which contains one of more ptrs * to RAM objects */ - uint32_t iv_kwdSize; - uint32_t iv_maxAddrRngCnt; - uint32_t iv_maxEcCnt; - uint32_t iv_msaHostI2cCnt; - uint32_t iv_msaHostI2cSize; - uint32_t iv_maxRamCnt; - uint32_t iv_actRamCnt; - uint32_t iv_maxRamObjSize; - char *iv_kwd; - bool iv_ramPadReq; - hdatFruId_t iv_fru; - hdatMsAreaId_t iv_msId; - hdatMsAreaSize_t iv_msSize; - hdatHDIFDataArray_t iv_addrRngArrayHdr; - hdatMsAreaAddrRange_t *iv_addrRange; - hdatMsAreaAffinity_t iv_aff; - hdatHDIFDataArray_t iv_ecArrayHdr; - hdatMsAreaEcLvl_t *iv_ecLvl; - hdatHDIFDataArray_t iv_msaI2cHdr; - uint8_t *iv_msaI2cDataPtr; - HdatRam **iv_ramPtrs; + uint32_t iv_kwdSize; + uint32_t iv_maxAddrRngCnt; + uint32_t iv_maxEcCnt; + uint32_t iv_msaHostI2cCnt; + uint32_t iv_msaHostI2cSize; + uint32_t iv_maxRamCnt; + uint32_t iv_actRamCnt; + uint32_t iv_maxRamObjSize; + char *iv_kwd; + bool iv_ramPadReq; + hdatFruId_t iv_fru; + hdatMsAreaId_t iv_msId; + hdatMsAreaSize_t iv_msSize; + hdatHDIFDataArray_t iv_addrRngArrayHdr; + hdatMsAreaAddrRange_t *iv_addrRange; + hdatMsAreaAffinity_t iv_aff; + hdatHDIFDataArray_t iv_ecArrayHdr; + hdatMsAreaEcLvl_t *iv_ecLvl; + hdatHDIFVersionedDataArray_t iv_msaI2cHdr; + uint8_t *iv_msaI2cDataPtr; + HdatRam **iv_ramPtrs; /** Class (static) Data diff --git a/src/usr/hdat/hdatpcrd.C b/src/usr/hdat/hdatpcrd.C index cd5b75ac15a..1ecda256b42 100644 --- a/src/usr/hdat/hdatpcrd.C +++ b/src/usr/hdat/hdatpcrd.C @@ -143,7 +143,8 @@ HdatPcrd::HdatPcrd(errlHndl_t &o_errlHndl, const hdatMsAddr_t &i_msAddr) // Allocate the CHIP INFO section also iv_numPcrdEntries = HDAT_NUM_P7_PCRD_ENTRIES; iv_spPcrdEntrySize = sizeof(hdatSpPcrd_t) + HDAT_FULL_MVPD_SIZE + - sizeof(hdatHDIFDataArray_t) + (sizeof(hdatI2cData_t) * HDAT_PCRD_MAX_I2C_DEV); + sizeof(hdatHDIFVersionedDataArray_t) + ((sizeof(hdatI2cData_t) + * HDAT_PCRD_MAX_I2C_DEV)); // Allocate space for each CHIP -- will use max amount to start uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo; @@ -446,9 +447,8 @@ errlHndl_t HdatPcrd::hdatLoadPcrd(uint32_t &o_size, uint32_t &o_count) // Setting Host I2C device entry data uint32_t l_pcrdHI2cTotalSize = 0; - hdatHDIFDataArray_t *l_hostI2cFullPcrdHdrPtr = NULL; - l_hostI2cFullPcrdHdrPtr = - reinterpret_cast + hdatHDIFVersionedDataArray_t *l_hostI2cFullPcrdHdrPtr = + reinterpret_cast (l_FullMvpdAddr+l_FullMvpdSize); // Need to get i2c Master data correctly @@ -456,25 +456,29 @@ errlHndl_t HdatPcrd::hdatLoadPcrd(uint32_t &o_size, uint32_t &o_count) hdatGetI2cDeviceInfo(l_pProcTarget, l_i2cDevEntries); - l_pcrdHI2cTotalSize = sizeof(hdatHDIFDataArray_t) + + l_pcrdHI2cTotalSize = sizeof(*l_hostI2cFullPcrdHdrPtr) + (sizeof(hdatI2cData_t) * l_i2cDevEntries.size()); HDAT_INF("pcrdHI2cNumEntries=0x%x, l_pcrdHI2cTotalSize=0x%x", l_i2cDevEntries.size(), l_pcrdHI2cTotalSize); - l_hostI2cFullPcrdHdrPtr->hdatOffset = 0x0010; // All array entries start right after header which is of 4 word size + // All array entries start right after header which is of 5 word + // size + l_hostI2cFullPcrdHdrPtr->hdatOffset = + sizeof(*l_hostI2cFullPcrdHdrPtr); l_hostI2cFullPcrdHdrPtr->hdatArrayCnt = l_i2cDevEntries.size(); l_hostI2cFullPcrdHdrPtr->hdatAllocSize = sizeof(hdatI2cData_t); l_hostI2cFullPcrdHdrPtr->hdatActSize = sizeof(hdatI2cData_t); + l_hostI2cFullPcrdHdrPtr->hdatVersion = + HOST_I2C_DEV_INFO_VERSION::V2; - hdatI2cData_t *l_hostI2cFullPcrdDataPtr = NULL; - l_hostI2cFullPcrdDataPtr = + hdatI2cData_t *l_hostI2cFullPcrdDataPtr = reinterpret_cast - (reinterpret_cast(l_hostI2cFullPcrdHdrPtr) - +sizeof(hdatHDIFDataArray_t)); + (reinterpret_cast(l_hostI2cFullPcrdHdrPtr) + +sizeof(*l_hostI2cFullPcrdHdrPtr)); if ( l_i2cDevEntries.size() != 0 ) { @@ -489,15 +493,15 @@ errlHndl_t HdatPcrd::hdatLoadPcrd(uint32_t &o_size, uint32_t &o_count) } this->iv_spPcrd->hdatPcrdIntData[HDAT_PCRD_DA_HOST_I2C]. hdatOffset = this->iv_spPcrd->hdatPcrdIntData - [HDAT_PCRD_DA_CHIP_VPD].hdatOffset + + [HDAT_PCRD_DA_CHIP_VPD].hdatOffset + this->iv_spPcrd->hdatPcrdIntData[HDAT_PCRD_DA_CHIP_VPD]. hdatSize; this->iv_spPcrd->hdatPcrdIntData [HDAT_PCRD_DA_HOST_I2C].hdatSize = l_pcrdHI2cTotalSize; this->iv_spPcrd->hdatHdr.hdatSize += - sizeof(hdatHDIFDataArray_t) + (sizeof(hdatI2cData_t) * HDAT_PCRD_MAX_I2C_DEV); + sizeof(*l_hostI2cFullPcrdHdrPtr) + (sizeof(hdatI2cData_t) + * HDAT_PCRD_MAX_I2C_DEV); - uint8_t* l_temp = reinterpret_cast (l_hostI2cFullPcrdHdrPtr); @@ -509,7 +513,8 @@ errlHndl_t HdatPcrd::hdatLoadPcrd(uint32_t &o_size, uint32_t &o_count) this->iv_spPcrd->hdatPcrdIntData[HDAT_PCRD_DA_PNOR].hdatOffset = this->iv_spPcrd->hdatPcrdIntData[HDAT_PCRD_DA_HOST_I2C].hdatOffset + - sizeof(hdatHDIFDataArray_t) + (sizeof(hdatI2cData_t) * HDAT_PCRD_MAX_I2C_DEV); + sizeof(hdatHDIFVersionedDataArray_t) + (sizeof(hdatI2cData_t) + * HDAT_PCRD_MAX_I2C_DEV); if(l_pProcTarget == l_pMasterProc) { diff --git a/src/usr/hdat/hdatutil.C b/src/usr/hdat/hdatutil.C index 3e8ef607eb7..0e2ba360596 100644 --- a/src/usr/hdat/hdatutil.C +++ b/src/usr/hdat/hdatutil.C @@ -1664,6 +1664,26 @@ errlHndl_t hdatGetFullEepromVpd(TARGETING::Target * i_target, return(err); } +//****************************************************************************** +// byNodeProcAffinty (std::sort comparison function) +//****************************************************************************** + +bool byNodeProcAffinity( + const DeviceInfo_t& i_lhs, + const DeviceInfo_t& i_rhs) +{ + bool lhsLogicallyBeforeRhs = (i_lhs.assocNode < i_rhs.assocNode); + if(i_lhs.assocNode == i_rhs.assocNode) + { + lhsLogicallyBeforeRhs = (i_lhs.assocProc < i_rhs.assocProc); + if(i_lhs.assocProc == i_rhs.assocProc) + { + lhsLogicallyBeforeRhs = (i_lhs.masterChip < i_rhs.masterChip); + } + } + return lhsLogicallyBeforeRhs; +} + /******************************************************************************* * hdatGetI2cDeviceInfo * @@ -1674,46 +1694,123 @@ errlHndl_t hdatGetFullEepromVpd(TARGETING::Target * i_target, * @post None * * @param[in] i_pTarget - * The i2c master target handle + * The i2c master target handle, or nullptr for all i2c masters * @param[out] o_i2cDevEntries * The host i2c dev entries * * @return void * *******************************************************************************/ -void hdatGetI2cDeviceInfo(TARGETING::Target* i_pTarget, - std::vector&o_i2cDevEntries) +void hdatGetI2cDeviceInfo( + TARGETING::Target* i_pTarget, + std::vector& o_i2cDevEntries) { HDAT_ENTER(); - std::vector o_deviceInfo; - getDeviceInfo( i_pTarget, o_deviceInfo); - uint32_t l_I2cLinkId = 0; - if(!o_deviceInfo.size()) + std::vector deviceInfo; + getDeviceInfo(nullptr,deviceInfo); + + if(deviceInfo.empty()) { - HDAT_INF(" No i2c connections found for i2c master : 0x08X", - i_pTarget->getAttr()); + HDAT_INF("No I2C connections found for I2C master with HUID of 0x%08X", + TARGETING::get_huid(i_pTarget)); } - else + else // At least one device, and index [0] is valid { - for ( auto &l_i2cDevEle : o_deviceInfo ) + // Order by node ordinal ID, processor position, I2C master target + // pointer + std::sort(deviceInfo.begin(), deviceInfo.end(), + byNodeProcAffinity); + + union LinkId { + struct + { + uint8_t node; ///< Ordinal ID of node + uint8_t proc; ///< Processor position + uint16_t instance; ///< Link instance (unique across a given + ///< processor and its downstream + ///< membufs) + }; + uint32_t val; ///< Allow access to the raw value + } linkId = { { + .node=static_cast(deviceInfo[0].assocNode), + .proc=static_cast(deviceInfo[0].assocProc), + .instance=0 } + }; + + for (const auto& i2cDevice : deviceInfo) + { + if( (i2cDevice.assocNode != linkId.node) + || (i2cDevice.assocProc != linkId.proc)) + { + linkId.node=i2cDevice.assocNode; + linkId.proc=i2cDevice.assocProc; + linkId.instance=0; + } + hdatI2cData_t l_hostI2cObj; memset(&l_hostI2cObj, 0x00, sizeof(hdatI2cData_t)); - l_hostI2cObj.hdatI2cEngine = l_i2cDevEle.engine; - l_hostI2cObj.hdatI2cMasterPort = l_i2cDevEle.masterPort; - l_hostI2cObj.hdatI2cBusSpeed = l_i2cDevEle.busFreqKhz; - l_hostI2cObj.hdatI2cSlaveDevType = l_i2cDevEle.deviceType; - l_hostI2cObj.hdatI2cSlaveDevAddr = l_i2cDevEle.addr; - l_hostI2cObj.hdatI2cSlavePort = l_i2cDevEle.slavePort; - l_hostI2cObj.hdatI2cSlaveDevPurp = l_i2cDevEle.devicePurpose; - l_hostI2cObj.hdatI2cLinkId = l_I2cLinkId++; + l_hostI2cObj.hdatI2cEngine = i2cDevice.engine; + l_hostI2cObj.hdatI2cMasterPort = i2cDevice.masterPort; + l_hostI2cObj.hdatI2cBusSpeed = i2cDevice.busFreqKhz; + l_hostI2cObj.hdatI2cSlaveDevType = i2cDevice.deviceType; + l_hostI2cObj.hdatI2cSlaveDevAddr = i2cDevice.addr; + l_hostI2cObj.hdatI2cSlavePort = i2cDevice.slavePort; + l_hostI2cObj.hdatI2cSlaveDevPurp = i2cDevice.devicePurpose; + l_hostI2cObj.hdatI2cLinkId = linkId.val; + + // @TODO RTC 176759 Populate SLCA and I2C label + l_hostI2cObj.hdatI2cSlcaIndex = 0; + memset(&l_hostI2cObj.hdatI2cLabel,0x00, + sizeof(l_hostI2cObj.hdatI2cLabel)); + + // Don't include the device if the slave address is + // invalid + if(l_hostI2cObj.hdatI2cSlaveDevAddr == UINT8_MAX) + { + continue; + } - o_i2cDevEntries.push_back(l_hostI2cObj); + assert(linkId.instance <= UINT16_MAX,"Illegal link ID instance " + "detected"); + ++linkId.instance; + + if( (i_pTarget == nullptr) + || (i_pTarget == i2cDevice.masterChip)) + { + o_i2cDevEntries.push_back(l_hostI2cObj); + } } } + for(auto const& i2cDevice : o_i2cDevEntries) + { + HDAT_DBG("Unique I2C device attached to HUID=0x%08X: " + "engine=0x%02X, " + "port=0x%02X, " + "speed=0x%04X, " + "slave type=0x%02X, " + "slave address=0x%02X, " + "slave port=0x%02X, " + "slave purpose=0x%08X, " + "link ID=0x%08X, " + "SLCA index=0x%04X, " + "slave label=\"%s\"", + TARGETING::get_huid(i_pTarget), + i2cDevice.hdatI2cEngine, + i2cDevice.hdatI2cMasterPort, + i2cDevice.hdatI2cBusSpeed, + i2cDevice.hdatI2cSlaveDevType, + i2cDevice.hdatI2cSlaveDevAddr, + i2cDevice.hdatI2cSlavePort, + i2cDevice.hdatI2cSlaveDevPurp, + i2cDevice.hdatI2cLinkId, + i2cDevice.hdatI2cSlcaIndex, + i2cDevice.hdatI2cLabel); + } + HDAT_EXIT(); } diff --git a/src/usr/hdat/hdatutil.H b/src/usr/hdat/hdatutil.H index bb29db91638..1e730aebaaa 100755 --- a/src/usr/hdat/hdatutil.H +++ b/src/usr/hdat/hdatutil.H @@ -101,6 +101,10 @@ namespace HDAT extern trace_desc_t* g_trac_hdat; +enum HOST_I2C_DEV_INFO_VERSION : uint32_t +{ + V2 = 0x00000002, +}; /** @brief Defines the Host I2C device info */ @@ -115,6 +119,8 @@ struct hdatI2cData_t uint8_t hdatReserved1; uint32_t hdatI2cSlaveDevPurp; uint32_t hdatI2cLinkId; + uint16_t hdatI2cSlcaIndex; + char hdatI2cLabel[64]; }__attribute__ ((packed)); diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C index 682fd899299..6dad98be0b7 100755 --- a/src/usr/i2c/i2c.C +++ b/src/usr/i2c/i2c.C @@ -3781,7 +3781,7 @@ void getMasterInfo( const TARGETING::Target* i_chip, //can be computed by adding an offset of 0x1000 each time info.scomAddr = 0x000A0000 + engine*P9_ENGINE_SCOM_OFFSET; info.engine = engine; - info.freq = i2cGetNestFreq()*1000*1000; //convert MHz->Hz + info.freq = i2cGetNestFreq()*FREQ_CONVERSION::HZ_PER_MHZ; // PIB_CLK = NEST_FREQ /4 // Local Bus = PIB_CLK / 4 info.freq = info.freq/16; //convert nest to local bus @@ -3792,8 +3792,51 @@ void getMasterInfo( const TARGETING::Target* i_chip, } } +//****************************************************************************** +// areI2cDevicesLogicallyEqual (std::unique equality comparison) +//****************************************************************************** + +bool areI2cDevicesLogicallyEqual( + const DeviceInfo_t& i_lhs, + const DeviceInfo_t& i_rhs) +{ + return (i_lhs.masterChip == i_rhs.masterChip) + && (i_lhs.engine == i_rhs.engine) + && (i_lhs.masterPort == i_rhs.masterPort) + && (i_lhs.addr == i_rhs.addr) + && (i_lhs.slavePort == i_rhs.slavePort); +} + +//****************************************************************************** +// byI2cDeviceOrder (std::sort comparison function) +//****************************************************************************** + +bool byI2cDeviceOrder( + const DeviceInfo_t& i_lhs, + const DeviceInfo_t& i_rhs) +{ + bool lhsLogicallyBeforeRhs = (i_lhs.masterChip < i_rhs.masterChip); + if(i_lhs.masterChip == i_rhs.masterChip) + { + lhsLogicallyBeforeRhs = (i_lhs.engine < i_rhs.engine); + if(i_lhs.engine == i_rhs.engine) + { + lhsLogicallyBeforeRhs = (i_lhs.masterPort < i_rhs.masterPort); + if(i_lhs.masterPort == i_rhs.masterPort) + { + lhsLogicallyBeforeRhs = (i_lhs.addr < i_rhs.addr); + if(i_lhs.addr == i_rhs.addr) + { + lhsLogicallyBeforeRhs = (i_lhs.slavePort < i_rhs.slavePort); + } + } + } + } + return lhsLogicallyBeforeRhs; +} + /** - * Retrieve some information about all I2C devices that the Host + * Retrieve some information about I2C devices that the Host * needs to know about */ void getDeviceInfo( TARGETING::Target* i_i2cMaster, @@ -3801,197 +3844,319 @@ void getDeviceInfo( TARGETING::Target* i_i2cMaster, { TRACFCOMP(g_trac_i2c,"getDeviceInfo>>"); - //Get list of all I2C Masters - std::list l_i2cInfo; - I2C::getMasterInfo( i_i2cMaster, l_i2cInfo ); - - //Find all the EEPROMs connected via i2c - std::list l_eepromInfo; - EEPROM::getEEPROMs( l_eepromInfo ); - - //Find all TPMs -#ifdef CONFIG_TPMDD - TPMDD::tpm_info_t tpmInfo; - errlHndl_t l_err = NULL; - TARGETING::TargetHandleList tpmList; - TRUSTEDBOOT::getTPMs(tpmList); -#endif + TARGETING::TargetHandleList chipTargets; + if(i_i2cMaster == nullptr) + { + // If no target specified, use every proc / membuf chip + TARGETING::Target* pSys = nullptr; + TARGETING::targetService().getTopLevelTarget(pSys); + assert(pSys != nullptr,"System target was nullptr"); + + TARGETING::PredicateCTM procChip( + TARGETING::CLASS_CHIP,TARGETING::TYPE_PROC); + TARGETING::PredicateCTM membufChip( + TARGETING::CLASS_CHIP,TARGETING::TYPE_MEMBUF); + + TARGETING::PredicatePostfixExpr procOrMembuf; + procOrMembuf.push(&procChip).push(&membufChip).Or(); + + TARGETING::targetService().getAssociated( + chipTargets, + pSys, + TARGETING::TargetService::CHILD, + TARGETING::TargetService::ALL, + &procOrMembuf); + } + else + { + // Otherwise, use the input target + chipTargets.push_back(i_i2cMaster); + } - for( std::list::iterator i2cm = l_i2cInfo.begin(); - i2cm != l_i2cInfo.end(); - ++i2cm ) + for(auto pChipTarget : chipTargets) { - TRACDCOMP(g_trac_i2c,"i2c loop - eng=%.8X", TARGETING::get_huid(i_i2cMaster)); - /* I2C Busses */ - std::list::iterator l_eep = l_eepromInfo.begin(); - while( l_eep != l_eepromInfo.end() ) + // If target is a processor, find its upstream node; if a membuf, find + // both the upstream processor and node + TARGETING::Target* pProc = nullptr; + if(pChipTarget->getAttr() == TARGETING::TYPE_PROC) { - TRACDCOMP(g_trac_i2c,"eeprom loop - eng=%.8X, port=%.8X", TARGETING::get_huid(l_eep->i2cMaster), l_eep->engine ); - DeviceInfo_t l_currentDI; - - //ignore the devices that aren't on the current target - if( l_eep->i2cMaster != i_i2cMaster ) - { - TRACDCOMP(g_trac_i2c,"skipping unmatched i2cmaster"); - l_eep = l_eepromInfo.erase(l_eep); - continue; - } - - //skip the devices that are on a different engine - else if( l_eep->engine != i2cm->engine) - { - TRACDCOMP(g_trac_i2c,"skipping umatched engine"); - ++l_eep; - continue; - } - - l_currentDI.masterChip = l_eep->i2cMaster; - l_currentDI.engine = l_eep->engine; - l_currentDI.masterPort = l_eep->port; - l_currentDI.addr = l_eep->devAddr; - l_currentDI.slavePort = 0xFF; - l_currentDI.busFreqKhz = (l_eep->busFreq) / 1000; - l_currentDI.deviceType = TARGETING::HDAT_I2C_DEVICE_TYPE_SEEPROM; - switch(l_eep->device) - { - case EEPROM::VPD_PRIMARY: - case EEPROM::VPD_BACKUP: - l_currentDI.devicePurpose = - TARGETING::HDAT_I2C_DEVICE_PURPOSE_MODULE_VPD; - break; - case EEPROM::SBE_PRIMARY: - case EEPROM::SBE_BACKUP: - l_currentDI.devicePurpose = - TARGETING::HDAT_I2C_DEVICE_PURPOSE_SBE_SEEPROM; - break; - case EEPROM::LAST_CHIP_TYPE: - break; - } - - TRACDCOMP(g_trac_i2c,"Adding addr=%X", l_eep->devAddr); - o_deviceInfo.push_back(l_currentDI); - l_eep = l_eepromInfo.erase(l_eep); - } //end of eeprom iter - -#ifdef CONFIG_TPMDD - for(auto pTpm : tpmList) + pProc = pChipTarget; + } + else { - DeviceInfo_t l_currentDI; - TPMDD::tpm_locality_t locality = TPMDD::TPM_LOCALITY_0; - - // Lookup i2c info for the TPM - l_err = TPMDD::tpmReadAttributes(pTpm, - tpmInfo, locality); - if( NULL != l_err ) - { - // Unable to get info, so we skip - delete l_err; - continue; - } - // ignore the devices that aren't on the current target - if( tpmInfo.i2cTarget != i_i2cMaster ) + TARGETING::TargetHandleList affinityParentTargets; + TARGETING::getParentAffinityTargets ( + affinityParentTargets, + pChipTarget, + TARGETING::CLASS_CHIP, + TARGETING::TYPE_PROC, + false); + // Chip like TPM might not have upstream processor + if(affinityParentTargets.empty()) { continue; } - // skip the devices that are on a different engine - else if( tpmInfo.engine != i2cm->engine ) + assert(affinityParentTargets.size() == 1, + "Exactly one affinity parent expected, not %d", + affinityParentTargets.size()); + pProc = affinityParentTargets[0]; + } + auto assocProc = pProc->getAttr(); + assert(assocProc <= UINT8_MAX,"Proc position exceeded max for uint8_t"); + + TARGETING::TargetHandleList affinityParentTargets; + TARGETING::getParentAffinityTargets ( + affinityParentTargets, + pProc, + TARGETING::CLASS_ENC, + TARGETING::TYPE_NODE, + false); + assert(affinityParentTargets.size() == 1, + "Exactly one affinity parent expected, not %d", + affinityParentTargets.size()); + TARGETING::Target* pNode = affinityParentTargets[0]; + auto assocNode = pNode->getAttr(); + assert(assocNode <= UINT8_MAX,"Node position exceeded max for uint8_t"); + + //Get list of all I2C Masters + std::list l_i2cInfo; + I2C::getMasterInfo( pChipTarget, l_i2cInfo ); + + //Find all the EEPROMs connected via i2c + std::list l_eepromInfo; + EEPROM::getEEPROMs( l_eepromInfo ); + + //Find all TPMs + #ifdef CONFIG_TPMDD + TPMDD::tpm_info_t tpmInfo; + errlHndl_t l_err = NULL; + TARGETING::TargetHandleList tpmList; + TRUSTEDBOOT::getTPMs(tpmList); + #endif + + for(auto const& i2cm : l_i2cInfo) + { + TRACDCOMP(g_trac_i2c,"i2c loop - eng=%.8X", TARGETING::get_huid(pChipTarget)); + /* I2C Busses */ + std::list::iterator l_eep = + l_eepromInfo.begin(); + while( l_eep != l_eepromInfo.end() ) { - continue; - } - - l_currentDI.masterChip = tpmInfo.i2cTarget; - l_currentDI.engine = tpmInfo.engine; - l_currentDI.masterPort = tpmInfo.port; - l_currentDI.addr = tpmInfo.devAddr; - l_currentDI.slavePort = 0xFF; - l_currentDI.busFreqKhz = (tpmInfo.busFreq) / 1000; - l_currentDI.deviceType = - TARGETING::HDAT_I2C_DEVICE_TYPE_NUVOTON_TPM; - l_currentDI.devicePurpose = TARGETING::HDAT_I2C_DEVICE_PURPOSE_TPM; - - o_deviceInfo.push_back(l_currentDI); + TRACDCOMP(g_trac_i2c,"eeprom loop - eng=%.8X, port=%.8X", TARGETING::get_huid(l_eep->i2cMaster), l_eep->engine ); + DeviceInfo_t l_currentDI; - } //end of tpm iter -#endif + //ignore the devices that aren't on the current target + if( l_eep->i2cMaster != pChipTarget ) + { + TRACDCOMP(g_trac_i2c,"skipping unmatched i2cmaster"); + l_eep = l_eepromInfo.erase(l_eep); + continue; + } - } //end of i2cm + //skip the devices that are on a different engine + else if( l_eep->engine != i2cm.engine) + { + TRACDCOMP(g_trac_i2c,"skipping umatched engine"); + ++l_eep; + continue; + } -// @TODO RTC 173541: Re-enable -// #if CONFIG_INCLUDE_XML_OPENPOWER -#if 0 - TARGETING::Target * sys = NULL; - TARGETING::targetService().getTopLevelTarget(sys); + l_currentDI.assocNode = assocNode; + l_currentDI.assocProc = assocProc; + l_currentDI.masterChip = l_eep->i2cMaster; + l_currentDI.engine = l_eep->engine; + l_currentDI.masterPort = l_eep->port; + l_currentDI.addr = l_eep->devAddr; + l_currentDI.slavePort = 0xFF; + l_currentDI.busFreqKhz = (l_eep->busFreq) + / FREQ_CONVERSION::HZ_PER_KHZ; + l_currentDI.deviceType = + TARGETING::HDAT_I2C_DEVICE_TYPE_SEEPROM; + switch(l_eep->device) + { + case EEPROM::VPD_PRIMARY: + case EEPROM::VPD_BACKUP: + l_currentDI.devicePurpose = + TARGETING::HDAT_I2C_DEVICE_PURPOSE_MODULE_VPD; + //TODO RTC:165485 this isn't currently right. we'll need + //to add the changes in the enum and possibly the other + //struct/attribute. + break; + case EEPROM::SBE_PRIMARY: + case EEPROM::SBE_BACKUP: + l_currentDI.devicePurpose = + TARGETING::HDAT_I2C_DEVICE_PURPOSE_SBE_SEEPROM; + break; + case EEPROM::LAST_CHIP_TYPE: + break; + } - //need to get all targets here, and pull it out. - TARGETING::TargetHandleList pChildList; + TRACDCOMP(g_trac_i2c,"Adding addr=%X", l_eep->devAddr); + o_deviceInfo.push_back(l_currentDI); + l_eep = l_eepromInfo.erase(l_eep); + } //end of eeprom iter - TARGETING::targetService().getAssociated(pChildList, sys, - TARGETING::TargetService::CHILD, - TARGETING::TargetService::ALL); - pChildList.push_back(sys); + #ifdef CONFIG_TPMDD + for(auto pTpm : tpmList) + { + DeviceInfo_t l_currentDI; + TPMDD::tpm_locality_t locality = TPMDD::TPM_LOCALITY_0; - for(TARGETING::TargetHandleList::const_iterator childItr = - pChildList.begin(); - childItr != pChildList.end(); ++childItr) - { - TARGETING::ATTR_HDAT_I2C_ENGINE_type l_i2cEngine; - (*childItr)->tryGetAttr(l_i2cEngine); + // Lookup i2c info for the TPM + l_err = TPMDD::tpmReadAttributes(pTpm, + tpmInfo, locality); + if( NULL != l_err ) + { + // Unable to get info, so we skip + delete l_err; + continue; + } + // ignore the devices that aren't on the current target + if( tpmInfo.i2cTarget != pChipTarget ) + { + continue; + } + // skip the devices that are on a different engine + else if( tpmInfo.engine != i2cm.engine ) + { + continue; + } - if(l_i2cEngine[0] == 0) + l_currentDI.assocNode = assocNode; + l_currentDI.assocProc = assocProc; + l_currentDI.masterChip = tpmInfo.i2cTarget; + l_currentDI.engine = tpmInfo.engine; + l_currentDI.masterPort = tpmInfo.port; + l_currentDI.addr = tpmInfo.devAddr; + l_currentDI.slavePort = 0xFF; + l_currentDI.busFreqKhz = (tpmInfo.busFreq) + / FREQ_CONVERSION::HZ_PER_KHZ; + l_currentDI.deviceType = + TARGETING::HDAT_I2C_DEVICE_TYPE_NUVOTON_TPM; + l_currentDI.devicePurpose = + TARGETING::HDAT_I2C_DEVICE_PURPOSE_TPM; + + o_deviceInfo.push_back(l_currentDI); + + } //end of tpm iter + #endif + + } //end of i2cm + +#if CONFIG_INCLUDE_XML_OPENPOWER + + TARGETING::ATTR_HDAT_I2C_ELEMENTS_type l_arrayLength = 0; + auto present = pChipTarget->tryGetAttr< + TARGETING::ATTR_HDAT_I2C_ELEMENTS>(l_arrayLength); + if(!present || l_arrayLength == 0) { + // The arrays are non-existent or empty continue; } - TARGETING::ATTR_HDAT_I2C_MASTER_PORT_type l_i2cMasterPort; - (*childItr)->tryGetAttr( - l_i2cMasterPort); + // Assume all required attributes are present from this point + TARGETING::ATTR_HDAT_I2C_ENGINE_type l_i2cEngine = {0}; + present = pChipTarget->tryGetAttr( + l_i2cEngine); + assert(present,"Target 0x%08X does not have ATTR_HDAT_I2C_ENGINE " + "attribute",TARGETING::get_huid(pChipTarget)); + + TARGETING::ATTR_HDAT_I2C_MASTER_PORT_type l_i2cMasterPort = {0}; + present = pChipTarget->tryGetAttr< + TARGETING::ATTR_HDAT_I2C_MASTER_PORT>(l_i2cMasterPort); + assert(present,"Target 0x%08X does not have ATTR_HDAT_I2C_MASTER_PORT " + "attribute",TARGETING::get_huid(pChipTarget)); + TARGETING::ATTR_HDAT_I2C_DEVICE_TYPE_type l_i2cDevType; - (*childItr)->tryGetAttr( - l_i2cDevType); - TARGETING::ATTR_HDAT_I2C_ADDR_type l_i2cAddr; - (*childItr)->tryGetAttr(l_i2cAddr); - TARGETING::ATTR_HDAT_I2C_SLAVE_PORT_type l_i2cSlavePort; - (*childItr)->tryGetAttr( - l_i2cSlavePort); - TARGETING::ATTR_HDAT_I2C_BUS_FREQ_type l_i2cBusFreq; - (*childItr)->tryGetAttr( - l_i2cBusFreq); + memset(&l_i2cDevType,TARGETING::HDAT_I2C_DEVICE_TYPE_UNKNOWN, + sizeof(l_i2cDevType)); + present = pChipTarget->tryGetAttr< + TARGETING::ATTR_HDAT_I2C_DEVICE_TYPE>(l_i2cDevType); + assert(present,"Target 0x%08X does not have ATTR_HDAT_I2C_DEVICE_TYPE " + "attribute",TARGETING::get_huid(pChipTarget)); + + TARGETING::ATTR_HDAT_I2C_ADDR_type l_i2cAddr = {0}; + present = pChipTarget->tryGetAttr( + l_i2cAddr); + assert(present,"Target 0x%08X does not have ATTR_HDAT_I2C_ADDR " + "attribute",TARGETING::get_huid(pChipTarget)); + + TARGETING::ATTR_HDAT_I2C_SLAVE_PORT_type l_i2cSlavePort = {0}; + present = pChipTarget->tryGetAttr< + TARGETING::ATTR_HDAT_I2C_SLAVE_PORT>(l_i2cSlavePort); + assert(present,"Target 0x%08X does not have ATTR_HDAT_I2C_SLAVE_PORT " + "attribute",TARGETING::get_huid(pChipTarget)); + + TARGETING::ATTR_HDAT_I2C_BUS_FREQ_type l_i2cBusFreq = {0}; + present = pChipTarget->tryGetAttr( + l_i2cBusFreq); + assert(present,"Target 0x%08X does not have ATTR_HDAT_I2C_BUS_FREQ " + "attribute",TARGETING::get_huid(pChipTarget)); + TARGETING::ATTR_HDAT_I2C_DEVICE_PURPOSE_type l_i2cDevPurpose; - (*childItr)->tryGetAttr( - l_i2cDevPurpose); + memset(&l_i2cDevPurpose,TARGETING::HDAT_I2C_DEVICE_PURPOSE_UNKNOWN, + sizeof(l_i2cDevPurpose)); + present = pChipTarget->tryGetAttr< + TARGETING::ATTR_HDAT_I2C_DEVICE_PURPOSE>(l_i2cDevPurpose); + assert(present,"Target 0x%08X does not have " + "ATTR_HDAT_I2C_DEVICE_PURPOSE attribute", + TARGETING::get_huid(pChipTarget)); + + for(TARGETING::ATTR_HDAT_I2C_ELEMENTS_type l_idx=0; + l_idx < l_arrayLength; + ++l_idx) + { + if( ( pChipTarget->getAttr() + == TARGETING::TYPE_PROC) + && (l_i2cEngine[l_idx] == 0)) + { + // We never expose proc engine 0 devices to host, since they are + // owned by SBE + continue; + } - uint8_t l_arrayLength = - (*childItr)->getAttr(); + if(l_i2cAddr[l_idx] == UINT8_MAX) + { + continue; + } - if(l_arrayLength == 0) - { - //The arrays are empty - continue; - } - for(uint8_t l_idx=0; - l_idx < l_arrayLength; - l_idx++) - { - DeviceInfo_t l_currentDevice; - l_currentDevice.masterChip = (*childItr); + DeviceInfo_t l_currentDevice = {nullptr}; + l_currentDevice.assocNode = assocNode; + l_currentDevice.assocProc = assocProc; + l_currentDevice.masterChip = pChipTarget; l_currentDevice.engine = l_i2cEngine[l_idx]; l_currentDevice.masterPort = l_i2cMasterPort[l_idx]; l_currentDevice.addr = l_i2cAddr[l_idx]; l_currentDevice.slavePort = l_i2cSlavePort[l_idx]; - l_currentDevice.busFreqKhz = l_i2cBusFreq[l_idx] / 1000; + l_currentDevice.busFreqKhz = l_i2cBusFreq[l_idx] + / FREQ_CONVERSION::HZ_PER_KHZ; l_currentDevice.deviceType = l_i2cDevType[l_idx]; l_currentDevice.devicePurpose = l_i2cDevPurpose[l_idx]; o_deviceInfo.push_back(l_currentDevice); } - } #endif + } //end of per chip loop + + // Order I2C devices by chip, engine, port, address, slave port + std::sort(o_deviceInfo.begin(), o_deviceInfo.end(), + byI2cDeviceOrder); + + // Move logical duplicates to end + std::vector::iterator + pInvalidEntries = std::unique( + o_deviceInfo.begin(), + o_deviceInfo.end(), + areI2cDevicesLogicallyEqual); + + // Erase the duplicates + o_deviceInfo.erase(pInvalidEntries,o_deviceInfo.end()); + TRACFCOMP(g_trac_i2c,"<1000; + my $VERSION = "1.0.0"; my $force = 0; @@ -1695,7 +1697,7 @@ sub processI2C if ($targetObj->isBusAttributeDefined( $i2c->{SOURCE},$i2c->{BUS_NUM},"I2C_SPEED")) { - $speed = $targetObj->getBusAttribute( + $speed = HZ_PER_KHZ * $targetObj->getBusAttribute( $i2c->{SOURCE},$i2c->{BUS_NUM},"I2C_SPEED"); } diff --git a/src/usr/targeting/common/xmltohb/attribute_types_openpower.xml b/src/usr/targeting/common/xmltohb/attribute_types_openpower.xml index a7a476588d2..545157ef383 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types_openpower.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types_openpower.xml @@ -246,7 +246,7 @@ into a struct in i2c.C - + 32 non-volatile