Skip to content

Commit

Permalink
Support new i2c device link ID format
Browse files Browse the repository at this point in the history
Change-Id: Ie79caad8ec9fe0be5421185360c5ea9b2d5dee3d
RTC: 173541
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42681
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: NAGENDRA K. GURRAM <nagendra.g@in.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
  • Loading branch information
Nick Bofferding authored and crgeddes committed Jul 14, 2017
1 parent 34514fe commit 3fbd50a
Show file tree
Hide file tree
Showing 13 changed files with 529 additions and 225 deletions.
11 changes: 11 additions & 0 deletions src/include/usr/hdat/hdat.H
Expand Up @@ -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.
Expand Down
4 changes: 3 additions & 1 deletion src/include/usr/i2c/i2cif.H
Expand Up @@ -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
*
Expand Down
12 changes: 7 additions & 5 deletions src/usr/hdat/hdatmsarea.C
Expand Up @@ -385,12 +385,14 @@ void HdatMsArea::setMsaI2cInfo(
std::vector<hdatI2cData_t> &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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
42 changes: 21 additions & 21 deletions src/usr/hdat/hdatmsarea.H
Expand Up @@ -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
Expand Down
33 changes: 19 additions & 14 deletions src/usr/hdat/hdatpcrd.C
Expand Up @@ -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;
Expand Down Expand Up @@ -446,35 +447,38 @@ 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<hdatHDIFDataArray_t *>
hdatHDIFVersionedDataArray_t *l_hostI2cFullPcrdHdrPtr =
reinterpret_cast<hdatHDIFVersionedDataArray_t *>
(l_FullMvpdAddr+l_FullMvpdSize);

// Need to get i2c Master data correctly
std::vector<hdatI2cData_t> l_i2cDevEntries;

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<hdatI2cData_t *>
(reinterpret_cast<uint8_t *>(l_hostI2cFullPcrdHdrPtr)
+sizeof(hdatHDIFDataArray_t));
(reinterpret_cast<uint8_t *>(l_hostI2cFullPcrdHdrPtr)
+sizeof(*l_hostI2cFullPcrdHdrPtr));

if ( l_i2cDevEntries.size() != 0 )
{
Expand All @@ -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<uint8_t *>
(l_hostI2cFullPcrdHdrPtr);

Expand All @@ -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)
{
Expand Down
137 changes: 117 additions & 20 deletions src/usr/hdat/hdatutil.C
Expand Up @@ -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
*
Expand All @@ -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<hdatI2cData_t>&o_i2cDevEntries)
void hdatGetI2cDeviceInfo(
TARGETING::Target* i_pTarget,
std::vector<hdatI2cData_t>& o_i2cDevEntries)
{
HDAT_ENTER();
std::vector<DeviceInfo_t> o_deviceInfo;
getDeviceInfo( i_pTarget, o_deviceInfo);
uint32_t l_I2cLinkId = 0;

if(!o_deviceInfo.size())
std::vector<DeviceInfo_t> deviceInfo;
getDeviceInfo(nullptr,deviceInfo);

if(deviceInfo.empty())
{
HDAT_INF(" No i2c connections found for i2c master : 0x08X",
i_pTarget->getAttr<ATTR_HUID>());
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<uint8_t>(deviceInfo[0].assocNode),
.proc=static_cast<uint8_t>(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();
}

Expand Down

0 comments on commit 3fbd50a

Please sign in to comment.