summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/i2c/eepromif.H35
-rw-r--r--src/include/usr/i2c/i2cif.H30
-rw-r--r--src/usr/devtree/bld_devtree.C296
-rw-r--r--src/usr/devtree/devtree.C17
-rwxr-xr-xsrc/usr/i2c/eepromdd.C148
-rwxr-xr-xsrc/usr/i2c/i2c.C26
-rwxr-xr-xsrc/usr/i2c/test/eepromddtest.H19
-rwxr-xr-xsrc/usr/i2c/test/i2ctest.H25
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
OpenPOWER on IntegriCloud