diff options
-rw-r--r-- | src/include/usr/i2c/eepromif.H | 35 | ||||
-rw-r--r-- | src/include/usr/i2c/i2cif.H | 30 | ||||
-rw-r--r-- | src/usr/devtree/bld_devtree.C | 296 | ||||
-rw-r--r-- | src/usr/devtree/devtree.C | 17 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 148 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.C | 26 | ||||
-rwxr-xr-x | src/usr/i2c/test/eepromddtest.H | 19 | ||||
-rwxr-xr-x | src/usr/i2c/test/i2ctest.H | 25 |
8 files changed, 584 insertions, 12 deletions
diff --git a/src/include/usr/i2c/eepromif.H b/src/include/usr/i2c/eepromif.H index 7300ead04..d4d847777 100644 --- a/src/include/usr/i2c/eepromif.H +++ b/src/include/usr/i2c/eepromif.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,6 +25,8 @@ #ifndef __EEPROMIF_H #define __EEPROMIF_H +#include <list> + namespace EEPROM { @@ -38,7 +40,8 @@ typedef enum VPD_BACKUP = 1, SBE_PRIMARY = 2, SBE_BACKUP = 3, - LAST_CHIP_TYPE + LAST_CHIP_TYPE, + FIRST_CHIP_TYPE = VPD_PRIMARY } eeprom_chip_types_t; /** @@ -51,6 +54,34 @@ typedef enum */ bool eepromPresence ( TARGETING::Target * i_target ); +/** + * @brief Define a set of information about all EEPROMs in the + * system (primarily used to populate the devtree) + */ +struct EepromInfo_t +{ + TARGETING::Target* i2cMaster; //< I2C Master chip + uint64_t engine; //< I2C engine (relative to master chip) + uint64_t port; //< I2C port (relative to engine) + uint64_t busFreq; //< Bus speed in Hz + uint64_t devAddr; //< I2C device address (relative to port) + uint64_t sizeKB; //< Size in KB + uint64_t addrBytes; //< Number of bytes required for addressing + eeprom_chip_types_t device; //< Identifies role of eeprom + TARGETING::Target* assocTarg; //< Target associated with this device +}; + +/** + * @brief Return a set of information related to every unique + * EEPROM in the system + * + * @param[out] o_info - list of EEPROM Information + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log. + */ +void getEEPROMs( std::list<EepromInfo_t>& o_info ); + }; // end namespace EEPROM diff --git a/src/include/usr/i2c/i2cif.H b/src/include/usr/i2c/i2cif.H index 7d678cb87..c219fca29 100644 --- a/src/include/usr/i2c/i2cif.H +++ b/src/include/usr/i2c/i2cif.H @@ -25,6 +25,11 @@ #ifndef __I2CIF_H #define __I2CIF_H +// Handy macros to check i2c ranges +// Pass in an instance of a TARGETING::ATTR_I2C_BUS_SPEED_ARRAY_type +#define I2C_BUS_MAX_ENGINE(var) (sizeof(var)/sizeof(var[0])) +#define I2C_BUS_MAX_PORT(var) (sizeof(var[0])/sizeof(var[0][0])) + namespace I2C { @@ -146,6 +151,31 @@ enum i2cSetAccessModeType void i2cSetAccessMode( i2cSetAccessModeType i_setModeType ); + +/** + * @brief Define a set of information about the I2C masters + * (primarily used to populate the devtree) + */ +struct MasterInfo_t +{ + uint64_t scomAddr; //< Base scom address for control regs + uint8_t engine; //< Engine number + uint32_t freq; //< Clock frequency of master in Hz +}; + +/** + * @brief Return a set of information related to each I2C master on + * the given target chip + * + * @param[in] i_chip - I2C Master chip (proc or membuf) + * @param[out] o_info - list of I2C Information + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log. + */ +void getMasterInfo( const TARGETING::Target* i_chip, + std::list<MasterInfo_t>& o_info ); + }; // end namespace I2C #endif // end __I2CIF_H diff --git a/src/usr/devtree/bld_devtree.C b/src/usr/devtree/bld_devtree.C index 07ec2536c..f1b0fb0da 100644 --- a/src/usr/devtree/bld_devtree.C +++ b/src/usr/devtree/bld_devtree.C @@ -46,6 +46,8 @@ #include <config.h> #include <devicefw/userif.H> #include <vpd/cvpdenums.H> +#include <i2c/i2cif.H> +#include <i2c/eepromif.H> trace_desc_t *g_trac_devtree = NULL; @@ -87,6 +89,7 @@ enum BuildConstants +//@todo-RTC:123043 -- Should use the functions in RT_TARG uint32_t getProcChipId(const TARGETING::Target * i_pProc) { uint32_t l_fabId = i_pProc->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>(); @@ -94,6 +97,30 @@ uint32_t getProcChipId(const TARGETING::Target * i_pProc) return ( (l_fabId << CHIPID_NODE_SHIFT) + l_procPos); } +//@todo-RTC:123043 -- Should use the functions in RT_TARG +uint32_t getMembChipId(const TARGETING::Target * i_pMemb) +{ + PredicateCTM l_mcs(CLASS_UNIT,TYPE_MCS, MODEL_NA); + TargetHandleList mcs_list; + targetService().getAssociated(mcs_list, + i_pMemb, + TargetService::PARENT_BY_AFFINITY, + TargetService::ALL, + &l_mcs); + + if( mcs_list.size() != 1 ) + { + //should never happen + return 0; + } + Target* l_parentMCS = *(mcs_list.begin()); + uint32_t l_procId = getProcChipId(getParentChip(l_parentMCS)); + uint32_t l_membId = CEN_ID_TAG | (l_procId << CEN_ID_SHIFT); + l_membId |= l_parentMCS->getAttr<ATTR_CHIP_UNIT>(); + return l_membId; +} + + uint64_t getHomerPhysAddr(const TARGETING::Target * i_pProc) { //If running Sapphire need to place this at the top of memory @@ -116,6 +143,263 @@ uint64_t getHomerPhysAddr(const TARGETING::Target * i_pProc) return targHomer; } +void add_i2c_info( const TARGETING::Target* i_targ, + devTree* i_dt, + dtOffset_t i_node ) +{ + TRACFCOMP(g_trac_devtree,"add_i2c_info(%X)",TARGETING::get_huid(i_targ)); + + //get list of all I2C Masters + std::list<I2C::MasterInfo_t> l_i2cInfo; + I2C::getMasterInfo( i_targ, l_i2cInfo ); + + //find all of the EEPROMs connected via i2c + std::list<EEPROM::EepromInfo_t> l_eepromInfo; + EEPROM::getEEPROMs( l_eepromInfo ); + + //add any other i2c devices here as needed, e.g. TPM, etc + + //figure out what kind of chip we're talking about + TARGETING::TYPE l_master_type = i_targ->getAttr<TARGETING::ATTR_TYPE>(); + const char* l_masterName = "ibm,unknown"; + const char* l_chipname = "xx"; + uint32_t l_chipid = 0x0; + if( l_master_type == TARGETING::TYPE_PROC ) + { + l_masterName = "ibm,power8-i2cm"; + l_chipid = getProcChipId(i_targ); + l_chipname = "p8"; + } + else if( l_master_type == TARGETING::TYPE_MEMBUF ) + { + l_masterName = "ibm,centaur-i2cm"; + l_chipid = getMembChipId(i_targ); + l_chipname = "cen"; + } + + //compatible devices to make Opal/Linux happy + static const struct + { + const char* name; + size_t byteSize; + size_t addrBytes; + } atmel_ids[] = { + { "atmel,24c128", 16*KILOBYTE, 2 }, + { "atmel,24c256", 32*KILOBYTE, 2 }, + { "atmel,24c02", 256, 1 }, + + //Currently our minimum is 1KB, even for the 256 byte SPD + { "atmel,24c02", 1*KILOBYTE, 1 }, + }; + + /* + Devtree hierarchy is like so + i2cm@12345 { + i2c-bus@0 { + eeprom@12 { + } + } + i2c-bus@1 { + eeprom@12 { + } + eeprom@34 { + } + } + } + */ + for( std::list<I2C::MasterInfo_t>::iterator i2cm = l_i2cInfo.begin(); + i2cm != l_i2cInfo.end(); + ++i2cm ) + { + /* + i2cm@a0020 { + reg = <0xa0020 0x20>; << scom address space + chip-engine# = <0x1>; << i2c engine + compatible = "ibm,power8-i2cm"; << what Opal wants + clock-frequency = <0x2faf080>; << local bus in Hz + #address-cells = <0x1>; + phandle = <0x10000062>; << auto-filled + #size-cells = <0x0>; + linux,phandle = <0x10000062>; << Opal fills in + } + */ + dtOffset_t l_i2cNode = i_dt->addNode(i_node, + "i2cm", i2cm->scomAddr); + uint32_t l_i2cProp[2] = { + static_cast<uint32_t>(i2cm->scomAddr), + 0x20 }; //0x20 is number of scom regs per engine + i_dt->addPropertyCells32(l_i2cNode, "reg", l_i2cProp, 2); + i_dt->addPropertyCell32(l_i2cNode, "chip-engine#", i2cm->engine); + const char* l_i2cCompatStrs[] = {l_masterName, NULL}; + i_dt->addPropertyStrings(l_i2cNode, "compatible", l_i2cCompatStrs); + i_dt->addPropertyCell32(l_i2cNode, "clock-frequency", + i2cm->freq / 4); //Opal wants it pre-divided + i_dt->addPropertyCell32(l_i2cNode, "#address-cells", 1); + i_dt->addPropertyCell32(l_i2cNode, "#size-cells", 0); + + + /*I2C busses*/ + std::list<EEPROM::EepromInfo_t>::iterator eep = l_eepromInfo.begin(); + while( eep != l_eepromInfo.end() ) + { + // ignore the devices that aren't on the current target + if( eep->i2cMaster != i_targ ) + { + eep = l_eepromInfo.erase(eep); + continue; + } + // skip the devices that are on a different engine + else if( eep->engine != i2cm->engine ) + { + ++eep; + continue; + } + + /* + i2c-bus@0 { + reg = <0x0>; + bus-frequency = <0x61a80>; + compatible = "ibm,power8-i2c-port", << Opal fills in + "ibm,opal-i2c"; << Opal fills in + ibm,opal-id = <0x1>; << Opal fills in + ibm,port-name = "p8_00000000_e1p0"; << chip_chipid_eng_port + #address-cells = <0x1>; + phandle = <0x10000063>; << auto-filled + #size-cells = <0x0>; + linux,phandle = <0x10000063>; + } + */ + dtOffset_t l_busNode = i_dt->addNode( l_i2cNode, + "i2c-bus", eep->port ); + i_dt->addPropertyCell32(l_busNode, "reg", 0); + i_dt->addPropertyCell32(l_busNode, "bus-frequency", eep->busFreq); + i_dt->addPropertyCell32(l_busNode, "#address-cells", 1); + i_dt->addPropertyCell32(l_busNode, "#size-cells", 0); + char portname[20]; + sprintf( portname, "%s_%.8X_e%dp%d", + l_chipname, + l_chipid, + eep->engine, + eep->port ); + i_dt->addPropertyString(l_busNode, + "ibm,port-name", + portname); + + // find any other devices on the same port so we can add them + // all at once + EEPROM::EepromInfo_t cur_eep = *eep; + std::list<EEPROM::EepromInfo_t>::iterator eep2 = eep; + while( eep2 != l_eepromInfo.end() ) + { + // skip the devices for other busses + if( !((cur_eep.i2cMaster == eep2->i2cMaster) + && (cur_eep.engine == eep2->engine) + && (cur_eep.port == eep2->port)) ) + { + ++eep2; + continue; + } + + /* + eeprom@50 { + reg = <0x50>; << right-justified 7-bit addr + label = "system-vpd"; << arbitrary name + compatible = "atmel,24c64"; << use table above + status = "ok"; << Opal fills in + phandle = <0x10000065>; << auto-filled + linux,phandle = <0x10000065>; << Opal fills in + } + */ + dtOffset_t l_eepNode = i_dt->addNode( l_busNode, + "eeprom", + eep2->devAddr >> 1 ); + i_dt->addPropertyCell32(l_eepNode, "reg", eep2->devAddr >> 1); + char l_label[30]; + TARGETING::TYPE l_type = TARGETING::TYPE_NA; + l_type = eep2->assocTarg->getAttr<TARGETING::ATTR_TYPE>(); + if( (l_type == TARGETING::TYPE_SYS) + || (l_type == TARGETING::TYPE_NODE) ) + { + sprintf( l_label, "system-vpd" ); + } + else if( l_type == TARGETING::TYPE_PROC ) + { + const char* l_type = "vpd"; + switch( eep2->device ) + { + case(EEPROM::VPD_PRIMARY): + l_type = "proc-vpd"; + break; + case(EEPROM::VPD_BACKUP): + l_type = "proc-vpd-backup"; + break; + case(EEPROM::SBE_PRIMARY): + l_type = "sbe0"; + break; + case(EEPROM::SBE_BACKUP): + l_type = "sbe1"; + break; + default: + break; + } + sprintf( l_label, "%s-%d", + l_type, + eep2->assocTarg + ->getAttr<TARGETING::ATTR_POSITION>() ); + } + else if( l_type == TARGETING::TYPE_MEMBUF ) + { + sprintf( l_label, "memb-vpd-%d", + eep2->assocTarg + ->getAttr<TARGETING::ATTR_POSITION>() ); + } + else if( l_type == TARGETING::TYPE_DIMM ) + { + sprintf( l_label, "dimm-spd-%d", + eep2->assocTarg + ->getAttr<TARGETING::ATTR_POSITION>() ); + } + else + { + sprintf( l_label, "unknown" ); + } + i_dt->addPropertyString(l_eepNode, "label", l_label); + + // fill in atmel compatible + const char* l_compat = "unknown"; + bool l_foundit = false; + for( size_t a = 0; + a < (sizeof(atmel_ids)/sizeof(atmel_ids[0])); + a++ ) + { + if( (atmel_ids[a].byteSize == (KILOBYTE*eep2->sizeKB)) + || (atmel_ids[a].addrBytes == eep2->addrBytes) ) + { + l_compat = atmel_ids[a].name; + l_foundit = true; + break; + } + } + if( !l_foundit ) + { + TRACFCOMP( g_trac_devtree, "Could not find matching eeprom device for %s : size=%d,addr=%d", l_label, eep2->sizeKB, eep2->addrBytes ); + } + i_dt->addPropertyString(l_eepNode, "compatible", l_compat); + + // need to increment the outer loop if we're going to + // remove the element it points to + if( eep == eep2 ) + { + ++eep; + } + // now remove the device we added so we don't add it again + eep2 = l_eepromInfo.erase(eep2); + } + } + } + +} + void bld_xscom_node(devTree * i_dt, dtOffset_t & i_parentNode, const TARGETING::Target * i_pProc, uint32_t i_chipid) @@ -239,6 +523,10 @@ void bld_xscom_node(devTree * i_dt, dtOffset_t & i_parentNode, reinterpret_cast<uint32_t*>(l_laneEq[l_phb]), (sizeof(l_laneEq[l_phb])/sizeof(uint32_t))); } + + /*I2C Masters*/ + add_i2c_info( i_pProc, i_dt, xscomNode ); + } uint32_t bld_l3_node(devTree * i_dt, dtOffset_t & i_parentNode, @@ -927,6 +1215,8 @@ errlHndl_t bld_fdt_mem(devTree * i_dt, bool i_smallTree) l_ibscomBase); uint64_t propertyCells[2] = {l_ibscomBase,THIRTYTWO_GB}; i_dt->addPropertyCells64(membNode, "reg", propertyCells, 2); + i_dt->addPropertyCell32(membNode, "#address-cells", 1); + i_dt->addPropertyCell32(membNode, "#size-cells", 1); uint32_t l_ec = l_pMemB->getAttr<ATTR_EC>(); char cenVerStr[32]; @@ -946,8 +1236,7 @@ errlHndl_t bld_fdt_mem(devTree * i_dt, bool i_smallTree) i_dt->addPropertyCell32(membNode, "ibm,fsi-master-chip-id", l_procId); - uint32_t l_cenId = CEN_ID_TAG | (l_procId << CEN_ID_SHIFT); - l_cenId |= parentMCS->getAttr<ATTR_CHIP_UNIT>(); + uint32_t l_cenId = getMembChipId(l_pMemB); i_dt->addPropertyCell32(membNode, "ibm,chip-id",l_cenId); //Add the CMFSI (which CMFSI 0 or 1) and port @@ -957,6 +1246,9 @@ errlHndl_t bld_fdt_mem(devTree * i_dt, bool i_smallTree) {linkinfo.mPort,linkinfo.link}; i_dt->addPropertyCells32(membNode, "ibm,fsi-master-port", cmfsiCells, 2); + + //Add any I2C devices hanging off this chip + add_i2c_info( l_pMemB, i_dt, membNode ); } diff --git a/src/usr/devtree/devtree.C b/src/usr/devtree/devtree.C index c514f7970..6bdeff33a 100644 --- a/src/usr/devtree/devtree.C +++ b/src/usr/devtree/devtree.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -31,6 +31,11 @@ extern trace_desc_t *g_trac_devtree; +#define DEBUGOUT(msg...) +#define DEBUGOUTB(data,len,msg...) +//#define DEBUGOUT(msg...) TRACFCOMP(g_trac_devtree,msg) +//#define DEBUGOUTB(data,len,msg...) DEBUGOUT(msg);TRACFBIN(g_trac_devtree,"",data,len); + namespace DEVTREE { @@ -223,6 +228,7 @@ dtOffset_t devTree::findNode(const char* nodePath) dtOffset_t devTree::addNode(dtOffset_t parentNodeOffset, const char* nodeName) { + DEBUGOUT("DT> addNode:%s",nodeName); uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset); int skipWords = getNodeTagAndNameWords(parentNodeOffset); @@ -288,12 +294,14 @@ void devTree::addProperty(dtOffset_t parentNodeOffset, const char* propertyName) *curWord++ = DT_PROP; *curWord++ = 0; *curWord++ = addString(propertyName); + DEBUGOUT("DT> addProperty:%s",propertyName); } void devTree::addPropertyString(dtOffset_t parentNodeOffset, const char* propertyName, const char* propertyData) { + DEBUGOUT("DT> addPropertyString:%s=%s",propertyName,propertyData); uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset); int skipWords = getNodeTagAndNameWords(parentNodeOffset); @@ -329,6 +337,7 @@ void devTree::addPropertyBytes(dtOffset_t parentNodeOffset, const uint8_t* propertyData, uint32_t numBytes) { + DEBUGOUTB(propertyData,numBytes,"DT> addPropertyBytes:%s=",propertyName); uint32_t* curWord = getStructSectionAtOffset(parentNodeOffset); int skipWords = getNodeTagAndNameWords(parentNodeOffset); @@ -385,6 +394,7 @@ void devTree::addPropertyStrings(dtOffset_t parentNodeOffset, *curWord++ = DT_PROP; *curWord++ = newPropertyDataLength ; *curWord++ = addString(propertyName); + DEBUGOUT("DT> addPropertyStrings:%s",propertyName); for(int i = 0; i < newPropertyDataWords; ++i) { @@ -394,6 +404,7 @@ void devTree::addPropertyStrings(dtOffset_t parentNodeOffset, char* target = (char*)curWord; for(int stringIndex = 0; stringIndex < numStrings; stringIndex++) { + DEBUGOUT("DT> %s",propertyData[stringIndex]); size_t curStringLen = strlen(propertyData[stringIndex]); memcpy(target, propertyData[stringIndex], curStringLen); target += curStringLen + 1; @@ -432,9 +443,11 @@ void devTree::addPropertyCells32(dtOffset_t parentNodeOffset, *curWord++ = DT_PROP; *curWord++ = newPropertyDataLength; *curWord++ = addString(propertyName); + DEBUGOUT("DT> addPropertyCells32:%s",propertyName); for(uint32_t i = 0; i < numCells; ++i) { + DEBUGOUT("DT> %.8X",cells[i]); *curWord++ = cells[i]; } } @@ -455,9 +468,11 @@ void devTree::addPropertyCells64(dtOffset_t parentNodeOffset, *curWord++ = DT_PROP; *curWord++ = newPropertyDataLength; *curWord++ = addString(propertyName); + DEBUGOUT("DT> addPropertyCells32:%s",propertyName); for(uint32_t i = 0; i < numCells; ++i) { + DEBUGOUT("DT> %.16X",cells[i]); *curWord++ = cells[i] >> 32; *curWord++ = cells[i]; } diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index 10717af6a..317065c75 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -1264,4 +1264,150 @@ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target, return err; } // end eepromGetI2CMasterTarget + +/** + * @brief Return a set of information related to every unique + * EEPROM in the system + */ +void getEEPROMs( std::list<EepromInfo_t>& o_info ) +{ + TRACDCOMP(g_trac_eeprom,">>getEEPROMs()"); + + // loop through every present target + TARGETING::PredicateHwas isPresent; + isPresent.reset().poweredOn(true).present(true); + TARGETING::PredicatePostfixExpr goodFilter; + goodFilter.push(&isPresent); + // apply the filter through all targets. + TARGETING::TargetRangeFilter targ_itr( + TARGETING::targetService().begin(), + TARGETING::targetService().end(), + &goodFilter ); + for( ; targ_itr; ++targ_itr ) + { + TRACDCOMP(g_trac_eeprom,"Targ %.8X",TARGETING::get_huid(*targ_itr)); + + // try all defined types of EEPROMs + for( eeprom_chip_types_t eep_type = FIRST_CHIP_TYPE; + eep_type < LAST_CHIP_TYPE; + eep_type = static_cast<eeprom_chip_types_t>(eep_type+1) ) + { + bool found_eep = false; + TARGETING::EepromVpdPrimaryInfo eepromData; + + switch( eep_type ) + { + case VPD_PRIMARY: + if( targ_itr-> + tryGetAttr<TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO> + ( eepromData ) ) + + { + found_eep = true; + } + break; + + case VPD_BACKUP: + if( targ_itr-> + tryGetAttr<TARGETING::ATTR_EEPROM_VPD_BACKUP_INFO> + ( reinterpret_cast< + TARGETING::ATTR_EEPROM_VPD_BACKUP_INFO_type&> + ( eepromData) ) ) + { + found_eep = true; + } + break; + + case SBE_PRIMARY: + if( targ_itr-> + tryGetAttr<TARGETING::ATTR_EEPROM_SBE_PRIMARY_INFO> + ( reinterpret_cast< + TARGETING::ATTR_EEPROM_SBE_PRIMARY_INFO_type&> + ( eepromData) ) ) + { + found_eep = true; + } + break; + + case SBE_BACKUP: + if( targ_itr-> + tryGetAttr<TARGETING::ATTR_EEPROM_SBE_BACKUP_INFO> + ( reinterpret_cast< + TARGETING::ATTR_EEPROM_SBE_BACKUP_INFO_type&> + ( eepromData) ) ) + { + found_eep = true; + } + break; + + case LAST_CHIP_TYPE: + //only included to catch additional types later on + found_eep = false; + break; + } + if( found_eep ) + { + // check that the path exists + bool exists = false; + TARGETING::targetService().exists( eepromData.i2cMasterPath, + exists ); + if( !exists ) + { + continue; + } + + // Since it exists, convert to a target + TARGETING::Target* i2cm = TARGETING::targetService() + .toTarget( eepromData.i2cMasterPath ); + if( NULL == i2cm ) + { + //not sure how this could happen, but just skip it + continue; + } + + // ignore anything with junk data + TARGETING::Target * sys = NULL; + TARGETING::targetService().getTopLevelTarget( sys ); + if( i2cm == sys ) + { + continue; + } + + // copy all the data out + EepromInfo_t eep_info; + eep_info.i2cMaster = i2cm; + eep_info.engine = eepromData.engine; + eep_info.port = eepromData.port; + eep_info.devAddr = eepromData.devAddr; + eep_info.device = eep_type; + eep_info.assocTarg = *targ_itr; + eep_info.sizeKB = eepromData.maxMemorySizeKB; + eep_info.addrBytes = eepromData.byteAddrOffset; + //one more lookup for the speed + TARGETING::ATTR_I2C_BUS_SPEED_ARRAY_type speeds; + if( i2cm->tryGetAttr<TARGETING::ATTR_I2C_BUS_SPEED_ARRAY> + (speeds) ) + { + if( (eep_info.engine > I2C_BUS_MAX_ENGINE(speeds)) + || (eep_info.port > I2C_BUS_MAX_PORT(speeds)) ) + { + continue; + } + eep_info.busFreq = speeds[eep_info.engine][eep_info.port]; + eep_info.busFreq *= 1000; //convert KHz->Hz + } + else + { + continue; + } + + // stick it into the output list + o_info.push_back(eep_info); + TRACDCOMP(g_trac_eeprom,"--Adding i2cm=%.8X, type=%d, eng=%d, port=%d", TARGETING::get_huid(i2cm),eep_type,eepromData.engine,eepromData.port); + } + } + } + TRACDCOMP(g_trac_eeprom,"<<getEEPROMs()"); +} + } // end namespace EEPROM diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C index 5b1af57ef..35de15ca3 100755 --- a/src/usr/i2c/i2c.C +++ b/src/usr/i2c/i2c.C @@ -78,9 +78,9 @@ TRAC_INIT( & g_trac_i2cr, "I2CR", KILOBYTE ); #define CENTAUR_MASTER_ENGINES 1 // Number of Engines in a Centaur // Derived from ATTR_I2C_BUS_SPEED_ARRAY[engine][port] attribute -const TARGETING::ATTR_I2C_BUS_SPEED_ARRAY_type var = {{NULL}}; -#define I2C_BUS_ATTR_MAX_ENGINE sizeof(var)/sizeof(var[0]) -#define I2C_BUS_ATTR_MAX_PORT sizeof(var[0])/sizeof(var[0][0]) +const TARGETING::ATTR_I2C_BUS_SPEED_ARRAY_type g_var = {{NULL}}; +#define I2C_BUS_ATTR_MAX_ENGINE I2C_BUS_MAX_ENGINE(g_var) +#define I2C_BUS_ATTR_MAX_PORT I2C_BUS_MAX_PORT(g_var) // ---------------------------------------------- @@ -2984,5 +2984,25 @@ errlHndl_t i2cRegisterOp ( DeviceFW::OperationType i_opType, return err; } +/** + * @brief Return a set of information related to each I2C master on + * the given target chip + */ +void getMasterInfo( const TARGETING::Target* i_chip, + std::list<MasterInfo_t>& o_info ) +{ + TRACDCOMP(g_trac_i2c,"getMasterInfo(%.8X)",TARGETING::get_huid(i_chip)); + for( uint32_t engine = 0; + engine < I2C_BUS_ATTR_MAX_ENGINE; + engine++ ) + { + MasterInfo_t info; + info.scomAddr = 0x000A0000 + engine*0x20; + info.engine = engine; + info.freq = i2cGetNestFreq()*1000*1000; //convert MHz->Hz + + o_info.push_back(info); + } +} } // end namespace I2C diff --git a/src/usr/i2c/test/eepromddtest.H b/src/usr/i2c/test/eepromddtest.H index c26ccaf82..cdd6c4b20 100755 --- a/src/usr/i2c/test/eepromddtest.H +++ b/src/usr/i2c/test/eepromddtest.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -649,7 +651,20 @@ class EEPROMTest: public CxxTest::TestSuite fails, num_ops ); } - + /** + * @brief Verify we retrieve all of the EEPROMs we can think of + */ + void test_getEEPROMs( void ) + { + std::list<EEPROM::EepromInfo_t> info; + getEEPROMs( info ); + for( std::list<EEPROM::EepromInfo_t>::iterator eep = info.begin(); + eep != info.end(); + ++eep ) + { + TRACFCOMP( g_trac_eeprom, "Found EEPROM: Master=%.8X, Eng=%d, Port=%d, Freq=%d, Addr=%.2X, Dev=%d, Targ=%.8X", TARGETING::get_huid(eep->i2cMaster), eep->engine, eep->port, eep->busFreq, eep->devAddr, eep->device, eep->assocTarg ); + } + } }; diff --git a/src/usr/i2c/test/i2ctest.H b/src/usr/i2c/test/i2ctest.H index 95a5d231e..77470033e 100755 --- a/src/usr/i2c/test/i2ctest.H +++ b/src/usr/i2c/test/i2ctest.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,6 +40,7 @@ #include <i2c/i2cif.H> #include <targeting/common/predicates/predicates.H> #include <targeting/common/attributes.H> +#include <targeting/common/utilFilter.H> #include "../i2c.H" extern trace_desc_t* g_trac_i2c; @@ -1007,6 +1008,28 @@ class I2CTest: public CxxTest::TestSuite } + /** + * @brief Verify we retrieve all of the EEPROMs we can think of + */ + void test_getMasterInfo( void ) + { + std::list<I2C::MasterInfo_t> info; + TARGETING::TargetHandleList allchips; + TARGETING::getAllChips( allchips, TARGETING::TYPE_NA ); + for( TARGETING::TargetHandleList::iterator tgt = allchips.begin(); + tgt != allchips.end(); + ++tgt ) + { + getMasterInfo( *tgt, info ); + for( std::list<I2C::MasterInfo_t>::iterator i2cm = info.begin(); + i2cm != info.end(); + ++i2cm ) + { + TRACFCOMP( g_trac_i2c, "Found I2C Master: Master=%.8X :: Scom=%.8X, Eng=%d, Freq=%d", TARGETING::get_huid(*tgt), i2cm->scomAddr, i2cm->engine, i2cm->freq ); + } + } + } + }; #endif |