summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/i2c')
-rwxr-xr-xsrc/usr/i2c/eepromdd.C401
-rwxr-xr-xsrc/usr/i2c/eepromdd.H66
-rwxr-xr-xsrc/usr/i2c/i2c.C163
-rwxr-xr-xsrc/usr/i2c/test/eepromddtest.H192
-rwxr-xr-xsrc/usr/i2c/test/i2ctest.H191
5 files changed, 755 insertions, 258 deletions
diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C
index c4a785c30..b5ba280e5 100755
--- a/src/usr/i2c/eepromdd.C
+++ b/src/usr/i2c/eepromdd.C
@@ -5,7 +5,7 @@
/* */
/* IBM CONFIDENTIAL */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2012 */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
/* */
/* p1 */
/* */
@@ -42,7 +42,9 @@
#include <devicefw/driverif.H>
#include <i2c/eepromddreasoncodes.H>
+#include <i2c/eepromif.H>
#include "eepromdd.H"
+
// ----------------------------------------------
// Globals
// ----------------------------------------------
@@ -60,6 +62,7 @@ TRAC_INIT( & g_trac_eepromr, "EEPROMR", KILOBYTE );
// Easy macro replace for unit testing
//#define TRACUCOMP(args...) TRACFCOMP(args)
#define TRACUCOMP(args...)
+
// ----------------------------------------------
// Defines
// ----------------------------------------------
@@ -102,12 +105,17 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType,
eeprom_addr_t i2cInfo;
i2cInfo.deviceType = LAST_DEVICE_TYPE;
- i2cInfo.addr = va_arg( i_args, uint64_t );
i2cInfo.chip = va_arg( i_args, uint64_t );
+ i2cInfo.offset = va_arg( i_args, uint64_t );
TRACDCOMP( g_trac_eeprom,
ENTER_MRK"eepromPerformOp()" );
+ TRACUCOMP (g_trac_eeprom, ENTER_MRK"eepromPerformOp(): "
+ "i_opType=%d, chip=%d, offset=%d, len=%d",
+ (uint64_t) i_opType, i2cInfo.chip, i2cInfo.offset, io_buflen);
+
+
do
{
// Read Attributes needed to complete the operation
@@ -122,6 +130,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType,
// Check to see if we need to find a new target for
// the I2C Master
err = eepromGetI2CMasterTarget( i_target,
+ i2cInfo,
theTarget );
if( err )
@@ -157,7 +166,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType,
else
{
TRACFCOMP( g_trac_eeprom,
- ERR_MRK"Invalid EEPROM Operation!" );
+ ERR_MRK"eepromPerformOp(): Invalid EEPROM Operation!");
/*@
* @errortype
@@ -205,8 +214,8 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target,
do
{
TRACSCOMP( g_trac_eepromr,
- "EEPROM READ START : Chip: %02d : Addr %.2X : Len %d",
- i_i2cInfo.chip, i_i2cInfo.addr, i_buflen );
+ "EEPROM READ START : Chip: %02d : Offset %.2X : Len %d",
+ i_i2cInfo.chip, i_i2cInfo.offset, i_buflen );
err = eepromPrepareAddress( &byteAddr,
byteAddrSize,
@@ -250,6 +259,9 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target,
if( err )
{
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromRead(): I2C Read failed on %d/%d/0x%x",
+ i_i2cInfo.port, i_i2cInfo.engine, i_i2cInfo.devAddr );
break;
}
@@ -257,8 +269,10 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target,
unlock = false;
TRACSCOMP( g_trac_eepromr,
- "EEPROM READ END : Chip: %02d : Addr %.2X : Len %d : %016llx",
- i_i2cInfo.chip, i_i2cInfo.addr, i_buflen, *((uint64_t*)o_buffer) );
+ "EEPROM READ END : Chip: %02d : Offset %.2X : Len %d : %016llx",
+ i_i2cInfo.chip, i_i2cInfo.offset, i_buflen,
+ *((uint64_t*)o_buffer) );
+
} while( 0 );
// Catch it if we break out early.
@@ -286,7 +300,9 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target,
uint8_t byteAddr[MAX_BYTE_ADDR];
size_t byteAddrSize = 0;
uint8_t * newBuffer = NULL;
- bool needFree = true;
+ bool needFree = false;
+ bool unlock = false;
+ eeprom_addr_t l_i2cInfo = i_i2cInfo;
TRACDCOMP( g_trac_eeprom,
ENTER_MRK"eepromWrite()" );
@@ -294,8 +310,9 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target,
do
{
TRACSCOMP( g_trac_eepromr,
- "EEPROM WRITE START : Chip: %02d : Addr %.2X : Len %d : %016llx",
- i_i2cInfo.chip, i_i2cInfo.addr, io_buflen, *((uint64_t*)io_buffer) );
+ "EEPROM WRITE START : Chip: %02d : Offset %.2X : Len %d : %016llx",
+ i_i2cInfo.chip, i_i2cInfo.offset, io_buflen,
+ *((uint64_t*)io_buffer) );
err = eepromPrepareAddress( &byteAddr,
byteAddrSize,
@@ -306,44 +323,122 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target,
break;
}
- size_t newBufLen = byteAddrSize + io_buflen;
+
+ // EEPROM devices have write page boundaries, so when necessary
+ // need to split up command into multiple write operations
+
+ // Setup a max-size buffer of byteAddrSize + writePageSize
+ size_t newBufLen = byteAddrSize + i_i2cInfo.writePageSize;
newBuffer = static_cast<uint8_t*>(malloc( newBufLen ));
needFree = true;
- // If we have an address to add to the buffer, do it now.
- // Add the byte address to the buffer
- memcpy( newBuffer, byteAddr, byteAddrSize );
-
- // Now add the data the user wanted to write
- memcpy( &newBuffer[byteAddrSize], io_buffer, io_buflen );
+ // Point a uint8_t ptr at io_buffer for array addressing below
+ uint8_t * l_data_ptr = reinterpret_cast<uint8_t*>(io_buffer);
// Lock for operation sequencing
mutex_lock( &g_eepromMutex );
+ unlock = true;
- // Do the actual data write
- err = deviceOp( DeviceFW::WRITE,
- i_target,
- newBuffer,
- newBufLen,
- DEVICE_I2C_ADDRESS( i_i2cInfo.port,
- i_i2cInfo.engine,
- i_i2cInfo.devAddr ) );
+ // variables to store different amount of data length
+ size_t loop_data_length = 0;
+ size_t loop_buffer_length = 0;
+ size_t total_bytes_written = 0;
+
+ for ( uint64_t i = 0 ;
+ (i * i_i2cInfo.writePageSize) < io_buflen ;
+ i++)
+ {
+
+ if ( (io_buflen - (i * i_i2cInfo.writePageSize) )
+ >= i_i2cInfo.writePageSize)
+ {
+ // Data to write >= to writePageSize, so write
+ // the maximum amount: writePageSize
+ loop_data_length = i_i2cInfo.writePageSize;
+ }
+ else
+ {
+ // Less than writePageSize to write
+ loop_data_length = io_buflen % i_i2cInfo.writePageSize;
+ }
+
+ // Update the offset for each loop
+ l_i2cInfo.offset += i * i_i2cInfo.writePageSize;
+
+ err = eepromPrepareAddress( &byteAddr,
+ byteAddrSize,
+ l_i2cInfo );
+ if (err)
+ {
+ break;
+ }
+
+ // Add the byte address to the buffer
+ memcpy( newBuffer,
+ byteAddr,
+ byteAddrSize );
+
+ // Now add the data the user wanted to write
+ memcpy( &newBuffer[byteAddrSize],
+ &l_data_ptr[i * i_i2cInfo.writePageSize],
+ loop_data_length);
+
+ // Calculate Total Length
+ loop_buffer_length = loop_data_length + byteAddrSize;
+
+ TRACUCOMP(g_trac_eeprom,"eepromWrite() Loop: %d/%d/0x%x "
+ "loop=%d, l_b_l=%d, l_d_l=%d, offset=0x%x",
+ i_i2cInfo.port, i_i2cInfo.engine,
+ i_i2cInfo.devAddr, i, loop_buffer_length, loop_data_length,
+ l_i2cInfo.offset);
+
+
+ // Do the actual data write
+ err = deviceOp( DeviceFW::WRITE,
+ i_target,
+ newBuffer,
+ loop_buffer_length,
+ DEVICE_I2C_ADDRESS( i_i2cInfo.port,
+ i_i2cInfo.engine,
+ i_i2cInfo.devAddr ) );
+
+ if( err )
+ {
+ TRACFCOMP(g_trac_eeprom,
+ ERR_MRK"eepromWrite(): I2C Write failed on %d/%d/0x%x "
+ "loop=%d, l_b_l=%d, offset=0x%x",
+ i_i2cInfo.port, i_i2cInfo.engine,
+ i_i2cInfo.devAddr, i, loop_buffer_length, l_i2cInfo.offset);
+
+
+ // Can't assume that anything was written if
+ // there was an error, so no update to total_bytes_written
+ // for this loop
+ break;
+ }
+
+ // Update how much data was written
+ total_bytes_written += loop_data_length;
+ }
+
+ // Release mutex lock
mutex_unlock( &g_eepromMutex );
+ unlock = false;
+
+ // Set how much data was actually written
+ io_buflen = total_bytes_written;
if( err )
{
- // Can't assume that anything was written if
- // there was an error.
- io_buflen = 0;
+ // Leave do-while loop
break;
}
- io_buflen = newBufLen - byteAddrSize;
TRACSCOMP( g_trac_eepromr,
- "EEPROM WRITE END : Chip: %02d : Addr %.2X : Len %d",
- i_i2cInfo.chip, i_i2cInfo.addr, io_buflen );
+ "EEPROM WRITE END : Chip: %02d : Offset %.2X : Len %d",
+ i_i2cInfo.chip, i_i2cInfo.offset, io_buflen );
} while( 0 );
// Free memory
@@ -352,6 +447,12 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target,
free( newBuffer );
}
+ // Catch it if we break out early.
+ if( unlock )
+ {
+ mutex_unlock( & g_eepromMutex );
+ }
+
TRACDCOMP( g_trac_eeprom,
EXIT_MRK"eepromWrite()" );
@@ -376,7 +477,7 @@ errlHndl_t eepromPrepareAddress ( void * o_buffer,
do
{
// --------------------------------------------------------------------
- // TODO - eventually there will be different I2C devices and the way
+ // @todo RTC:72715 - support different I2C devices and the way
// they handle addressing. A new attribute will need to be added to
// EEPROM_ADDR_INFOx to indicate the device type so the addressing
// here can be handled properly.
@@ -389,14 +490,14 @@ errlHndl_t eepromPrepareAddress ( void * o_buffer,
case TWO_BYTE_ADDR:
o_bufSize = 2;
memset( o_buffer, 0x0, o_bufSize );
- *((uint8_t*)o_buffer) = (i_i2cInfo.addr & 0xFF00ull) >> 8;
- *((uint8_t*)o_buffer+1) = (i_i2cInfo.addr & 0x00FFull);
+ *((uint8_t*)o_buffer) = (i_i2cInfo.offset & 0xFF00ull) >> 8;
+ *((uint8_t*)o_buffer+1) = (i_i2cInfo.offset & 0x00FFull);
break;
case ONE_BYTE_ADDR:
o_bufSize = 1;
memset( o_buffer, 0x0, o_bufSize );
- *((uint8_t*)o_buffer) = (i_i2cInfo.addr & 0xFFull);
+ *((uint8_t*)o_buffer) = (i_i2cInfo.offset & 0xFFull);
break;
default:
@@ -410,14 +511,14 @@ errlHndl_t eepromPrepareAddress ( void * o_buffer,
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid EEPROM_PREPAREADDRESS
* @userdata1 Device Type
- * @userdata2 <UNUSED>
+ * @userdata2 EEPROM chip
* @devdesc The Device type was not recognized as one supported.
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
EEPROM_PREPAREADDRESS,
EEPROM_INVALID_DEVICE_TYPE,
i_i2cInfo.deviceType,
- 0x0 );
+ i_i2cInfo.chip );
break;
};
@@ -448,76 +549,191 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target,
do
{
- if( 0 == o_i2cInfo.chip )
+ if( VPD_PRIMARY == o_i2cInfo.chip )
{
- // Read Attributes from EEPROM_ADDR_INFO0
- TARGETING::EepromAddrInfo0 eepromData;
- if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_ADDR_INFO0>( eepromData ) )
+ // Read Attributes from EEPROM_VPD_PRIMARY_INFO
+ TARGETING::EepromVpdPrimaryInfo eepromData;
+ if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO>
+ ( eepromData ) )
{
+ o_i2cInfo.chipTypeEnum = VPD_PRIMARY;
o_i2cInfo.port = eepromData.port;
o_i2cInfo.devAddr = eepromData.devAddr;
o_i2cInfo.engine = eepromData.engine;
- // TODO - eventually read out the slave device type
+ o_i2cInfo.i2cMasterPath = eepromData.i2cMasterPath;
+
+ // @todo RTC:72715 - More attributes to be read
o_i2cInfo.deviceType = TWO_BYTE_ADDR;
+ o_i2cInfo.writePageSize = 128;
+
}
else
{
TRACFCOMP( g_trac_eeprom,
- ERR_MRK"eepromReadAttributes() - ERROR reading attributes for "
- "chip %d!",
+ ERR_MRK"eepromReadAttributes() - ERROR reading "
+ "attributes for chip %d! (VPD_PRIMARY)",
o_i2cInfo.chip );
/*@
* @errortype
- * @reasoncode EEPROM_ADDR_INFO0_NOT_FOUND
+ * @reasoncode EEPROM_VPD_PRIMARY_INFO_NOT_FOUND
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid EEPROM_READATTRIBUTES
- * @userdata1 EEPROM chip
- * @userdata2 Attribute Enumeration
- * @devdesc ATTR_EEPROM_ADDR_INFO0 Attribute was not found
+ * @userdata1 HUID of target
+ * @userdata2[0:31] EEPROM chip
+ * @userdata2[32:63] Attribute Enumeration
+ * @devdesc ATTR_EEPROM_VPD_PRIMARY_INFO Attribute
+ * was not found
*/
- err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_READATTRIBUTES,
- EEPROM_ADDR_INFO0_NOT_FOUND,
- o_i2cInfo.chip,
- TARGETING::ATTR_EEPROM_ADDR_INFO0 );
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_READATTRIBUTES,
+ EEPROM_VPD_PRIMARY_INFO_NOT_FOUND,
+ TARGETING::get_huid(i_target),
+ TWO_UINT32_TO_UINT64(
+ o_i2cInfo.chip,
+ TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO));
break;
}
}
- else if( 1 == o_i2cInfo.chip )
+ else if( VPD_BACKUP == o_i2cInfo.chip )
{
- // Read Attributes from EEPROM_ADDR_INFO1
- TARGETING::EepromAddrInfo1 eepromData;
- if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_ADDR_INFO1>( eepromData ) )
+ // Read Attributes from EEPROM_VPD_BACKUP_INFO
+ TARGETING::EepromVpdBackupInfo eepromData;
+ if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_VPD_BACKUP_INFO>
+ ( eepromData ) )
{
+ o_i2cInfo.chipTypeEnum = VPD_BACKUP;
o_i2cInfo.port = eepromData.port;
o_i2cInfo.devAddr = eepromData.devAddr;
o_i2cInfo.engine = eepromData.engine;
- // TODO - eventually read out the slave device type
+ o_i2cInfo.i2cMasterPath = eepromData.i2cMasterPath;
+
+ // @todo RTC:72715 - More attributes to be read
o_i2cInfo.deviceType = TWO_BYTE_ADDR;
+ o_i2cInfo.writePageSize = 128;
}
else
{
TRACFCOMP( g_trac_eeprom,
- ERR_MRK"eepromReadAttributes() - ERROR reading attributes for "
- "chip %d!",
+ ERR_MRK"eepromReadAttributes() - ERROR reading "
+ "attributes for chip %d! (VPD_BACKUP)",
o_i2cInfo.chip );
/*@
* @errortype
- * @reasoncode EEPROM_ADDR_INFO1_NOT_FOUND
+ * @reasoncode EEPROM_VPD_BACKUP_INFO_NOT_FOUND
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid EEPROM_READATTRIBUTES
- * @userdata1 EEPROM Chip
- * @userdata2 Attribute Enum
- * @devdesc ATTR_EEPROM_ADDR_INFO0 Attribute was not found
+ * @userdata1 HUID of target
+ * @userdata2[0:31] EEPROM chip
+ * @userdata2[32:63] Attribute Enumeration
+ * @devdesc ATTR_EEPROM_VPD_BACKUP_INFO Attribute
+ * was not found
*/
- err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_READATTRIBUTES,
- EEPROM_ADDR_INFO1_NOT_FOUND,
- o_i2cInfo.chip,
- TARGETING::ATTR_EEPROM_ADDR_INFO1 );
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_READATTRIBUTES,
+ EEPROM_VPD_BACKUP_INFO_NOT_FOUND,
+ TARGETING::get_huid(i_target),
+ TWO_UINT32_TO_UINT64(
+ o_i2cInfo.chip,
+ TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO));
+
+ break;
+ }
+ }
+ else if( SBE_PRIMARY == o_i2cInfo.chip )
+ {
+ // Read Attributes from EEPROM_SBE_PRIMARY_INFO
+ TARGETING::EepromSbePrimaryInfo eepromData;
+ if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_SBE_PRIMARY_INFO>
+ ( eepromData ) )
+ {
+ o_i2cInfo.chipTypeEnum = SBE_PRIMARY;
+ o_i2cInfo.port = eepromData.port;
+ o_i2cInfo.devAddr = eepromData.devAddr;
+ o_i2cInfo.engine = eepromData.engine;
+ o_i2cInfo.i2cMasterPath = eepromData.i2cMasterPath;
+
+ // @todo RTC:72715 - More attributes to be read
+ o_i2cInfo.deviceType = TWO_BYTE_ADDR;
+ o_i2cInfo.writePageSize = 128;
+ }
+ else
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromReadAttributes() - ERROR reading "
+ "attributes for chip %d! (SBE_PRIMARY)",
+ o_i2cInfo.chip );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_SBE_PRIMARY_INFO_NOT_FOUND
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid EEPROM_READATTRIBUTES
+ * @userdata1 HUID of target
+ * @userdata2[0:31] EEPROM chip
+ * @userdata2[32:63] Attribute Enumeration
+ * @devdesc ATTR_EEPROM_SBE_PRIMARY_INFO Attribute
+ * was not found
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_READATTRIBUTES,
+ EEPROM_SBE_PRIMARY_INFO_NOT_FOUND,
+ TARGETING::get_huid(i_target),
+ TWO_UINT32_TO_UINT64(
+ o_i2cInfo.chip,
+ TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO));
+
+ break;
+ }
+ }
+ else if( SBE_BACKUP == o_i2cInfo.chip )
+ {
+ // Read Attributes from EEPROM_SBE_BACKUP_INFO
+ TARGETING::EepromSbeBackupInfo eepromData;
+ if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_SBE_BACKUP_INFO>
+ ( eepromData ) )
+ {
+ o_i2cInfo.chipTypeEnum = SBE_BACKUP;
+ o_i2cInfo.port = eepromData.port;
+ o_i2cInfo.devAddr = eepromData.devAddr;
+ o_i2cInfo.engine = eepromData.engine;
+ o_i2cInfo.i2cMasterPath = eepromData.i2cMasterPath;
+
+ // @todo RTC:72715 - More attributes to be read
+ o_i2cInfo.deviceType = TWO_BYTE_ADDR;
+ o_i2cInfo.writePageSize = 128;
+ }
+ else
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromReadAttributes() - ERROR reading "
+ "attributes for chip %d! (SBE_BACKUP)",
+ o_i2cInfo.chip );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_SBE_BACKUP_INFO_NOT_FOUND
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid EEPROM_READATTRIBUTES
+ * @userdata1 HUID of target
+ * @userdata2[0:31] EEPROM chip
+ * @userdata2[32:63] Attribute Enumeration
+ * @devdesc ATTR_EEPROM_SBE_BACKUP_INFO Attribute
+ * was not found
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_READATTRIBUTES,
+ EEPROM_SBE_BACKUP_INFO_NOT_FOUND,
+ TARGETING::get_huid(i_target),
+ TWO_UINT32_TO_UINT64(
+ o_i2cInfo.chip,
+ TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO));
break;
}
@@ -535,14 +751,14 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target,
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid EEPROM_READATTRIBUTES
* @userdata1 EEPROM Chip
- * @userdata2 <UNUSED>
+ * @userdata2 HUID of target
* @devdesc Invalid EEPROM chip to access
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
EEPROM_READATTRIBUTES,
EEPROM_INVALID_CHIP,
o_i2cInfo.chip,
- 0x0 );
+ TARGETING::get_huid(i_target) );
break;
}
@@ -559,6 +775,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target,
// eepromGetI2CMasterTarget
// ------------------------------------------------------------------
errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target,
+ eeprom_addr_t i_i2cInfo,
TARGETING::Target * &o_target )
{
errlHndl_t err = NULL;
@@ -574,14 +791,15 @@ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target,
TARGETING::TargetService& tS = TARGETING::targetService();
// For DIMMs we need to get the parent that contains the
- // I2C Master that talks to the DIMM EEPROM. Read the path
- // from the attributes
- TARGETING::EepromAddrInfo0 eepromData;
- eepromData = i_target->getAttr<TARGETING::ATTR_EEPROM_ADDR_INFO0>();
+ // I2C Master that talks to the DIMM EEPROM
+
+ // The path was read from the attribute via eepromReadAttributes()
+ // and passed to this function in i_i2cInfo
+
// check that the path exists
bool exists = false;
- tS.exists( eepromData.i2cMasterPath,
+ tS.exists( i_i2cInfo.i2cMasterPath,
exists );
if( !exists )
@@ -595,42 +813,43 @@ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target,
* @reasoncode EEPROM_DIMM_I2C_MASTER_PATH_ERROR
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid EEPROM_GETI2CMASTERTARGET
- * @userdata1 Attribute Enum
- * @userdata2 <UNUSED>
+ * @userdata1 Attribute Chip Type Enum
+ * @userdata2 HUID of target
* @devdesc DIMM I2C Master Entity path doesn't exist.
*/
- err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_GETI2CMASTERTARGET,
- EEPROM_DIMM_I2C_MASTER_PATH_ERROR,
- TARGETING::ATTR_EEPROM_ADDR_INFO0,
- 0x0 );
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_GETI2CMASTERTARGET,
+ EEPROM_DIMM_I2C_MASTER_PATH_ERROR,
+ i_i2cInfo.chipTypeEnum,
+ TARGETING::get_huid(i_target) );
break;
}
// Since it exists, convert to a target
- o_target = tS.toTarget( eepromData.i2cMasterPath );
+ o_target = tS.toTarget( i_i2cInfo.i2cMasterPath );
if( NULL == o_target )
{
TRACFCOMP( g_trac_eeprom,
- ERR_MRK"eepromGetI2CMasterTarget() - Parent Processor target "
- "was NULL!" );
+ ERR_MRK"eepromGetI2CMasterTarget() - I2C Master "
+ "Path target was NULL!" );
/*@
* @errortype
* @reasoncode EEPROM_TARGET_NULL
* @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
* @moduleid EEPROM_GETI2CMASTERTARGET
- * @userdata1 <UNUSED>
- * @userdata2 <UNUSED>
- * @devdesc Processor Target is NULL.
+ * @userdata1 Attribute Chip Type Enum
+ * @userdata2 HUID of target
+ * @devdesc I2C Master Path Target is NULL.
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
EEPROM_GETI2CMASTERTARGET,
EEPROM_TARGET_NULL,
- 0x0,
- 0x0 );
+ i_i2cInfo.chipTypeEnum,
+ TARGETING::get_huid(i_target) );
break;
}
diff --git a/src/usr/i2c/eepromdd.H b/src/usr/i2c/eepromdd.H
index ab47f692a..7464e1881 100755
--- a/src/usr/i2c/eepromdd.H
+++ b/src/usr/i2c/eepromdd.H
@@ -1,25 +1,25 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/usr/i2c/eepromdd.H $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/i2c/eepromdd.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
#ifndef __EEPROM_H
#define __EEPROM_H
@@ -33,6 +33,7 @@
// ----------------------------------------------
// Includes
// ----------------------------------------------
+#include <i2c/eepromif.H>
#include <errl/errlentry.H>
namespace EEPROM
@@ -57,9 +58,12 @@ typedef struct
uint64_t port;
uint64_t engine;
uint64_t devAddr;
- uint64_t addr;
int64_t chip;
+ uint64_t offset;
eeprom_device_t deviceType;
+ TARGETING::EntityPath i2cMasterPath;
+ uint64_t writePageSize; // in bytes
+ eeprom_chip_types_t chipTypeEnum;
} eeprom_addr_t;
/**
@@ -85,9 +89,9 @@ typedef struct
* usrif.H
*
* @param [in] i_args - This is an argument list for the device driver
-* framework. This argument list consists of the address to use
-* on the slave I2C device, and the chip number of the EEPROM to
-* access from the given I2C Master target.
+* framework. This argument list consists of the chip number of
+* the EEPROM to access from the given I2C Master target and the
+* internal offset to use on the slave I2C device.
*
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
* error log.
@@ -111,7 +115,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType,
*
* @param[in] i_buflen - Number of bytes to read from the EEPROM device.
*
- * @param[in] i_i2cInfo - Structure of I2C parameters neede to execute
+ * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute
* the command to the I2C device driver.
*
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
@@ -136,7 +140,7 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target,
* OUTPUT: Length of buffer that was written, or length of buffer
* to be read from target device.
*
- * @param[in] i_i2cInfo - Structure of I2C parameters neede to execute
+ * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute
* the command to the I2C device driver.
*
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
@@ -157,7 +161,7 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target,
*
* @param[out] o_bufSize - The size of the buffer to be written.
*
- * @param[in] i_i2cInfo - Structure of I2C parameters neede to execute
+ * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute
* the command to the I2C device driver.
*
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
@@ -192,6 +196,9 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target,
*
* @param[in] i_target - The current Target.
*
+ * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute
+ * the command to the I2C device driver.
+ *
* @param[out] o_target - The "new" target that will be used for all operations
* from this point on. It may be == to i_target, or a completely different
* target. BUT, this target will contain the I2C Master engine that will
@@ -201,6 +208,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target,
* error log.
*/
errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target,
+ eeprom_addr_t i_i2cInfo,
TARGETING::Target * &o_target );
}; // end EEPROM namespace
diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C
index 23398fbc3..0a32c1ca8 100755
--- a/src/usr/i2c/i2c.C
+++ b/src/usr/i2c/i2c.C
@@ -56,6 +56,7 @@ TRAC_INIT( & g_trac_i2c, "I2C", KILOBYTE );
trace_desc_t* g_trac_i2cr = NULL;
TRAC_INIT( & g_trac_i2cr, "I2CR", KILOBYTE );
+
// Easy macro replace for unit testing
//#define TRACUCOMP(args...) TRACFCOMP(args)
#define TRACUCOMP(args...)
@@ -105,7 +106,15 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType,
args.devAddr = va_arg( i_args, uint64_t );
TRACDCOMP( g_trac_i2c,
- ENTER_MRK"i2cPerformOp()" );
+ ENTER_MRK"i2cPerformOp(): i_opType=%d, "
+ "p=%d, engine=%d, devAddr=0x%lx",
+ (uint64_t) i_opType, args.port, args.engine, args.devAddr );
+
+ TRACUCOMP( g_trac_i2c,
+ ENTER_MRK"i2cPerformOp(): i_opType=%d, p/e/devAddr= "
+ "%d/%d/0x%x, len=%d",
+ (uint64_t) i_opType, args.port, args.engine, args.devAddr,
+ io_buflen);
do
{
@@ -135,6 +144,8 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType,
break;
}
+ // @todo RTC:72715 - Check that target is an I2C master
+
// Get the mutex for the requested engine
mutex_t * engineLock = NULL;
switch( args.engine )
@@ -153,8 +164,9 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType,
default:
TRACFCOMP( g_trac_i2c,
- ERR_MRK"Invalid engine for getting Mutex!" );
- // TODO - Create an error here
+ ERR_MRK"Invalid engine for getting Mutex! "
+ "args.engine=%d", args.engine );
+ // @todo RTC:69113 - Create an error here
break;
};
@@ -278,7 +290,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
uint64_t devAddr = i_args.devAddr;
uint64_t port = i_args.port;
- // TODO - hardcoded to 400KHz for now
+ // @todo RTC:72715 - Add multiple bus speed support (set to 400KHz for now)
uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ );
uint64_t timeoutCount = I2C_TIMEOUT_COUNT( interval );
@@ -298,8 +310,8 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
// Do Command/Mode reg setups.
err = i2cSetup( i_target,
i_buflen,
- true,
- true,
+ true, // i_readNotWrite
+ true, // i_withStop
i_args );
if( err )
@@ -324,7 +336,11 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
break;
}
- while( 0 == status.fifo_entry_count )
+ // Wait for 1 of 2 indictators to read from FIFO:
+ // 1) fifo_entry_count !=0
+ // 2) Data Request bit is on
+ while( (0 == status.fifo_entry_count) &&
+ (0 == status.data_request) )
{
nanosleep( 0, (interval * 1000) );
@@ -338,6 +354,12 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
break;
}
+
+ TRACUCOMP( g_trac_i2c, "i2cRead() Wait Loop: status=0x%016llx "
+ ".fifo_entry_count=%d, .data_request=%d",
+ status.value, status.fifo_entry_count, status.data_request);
+
+
if( 0 == timeoutCount-- )
{
TRACFCOMP( g_trac_i2c,
@@ -381,6 +403,10 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
size,
DEVICE_SCOM_ADDRESS( masterAddrs[engine].fifo ) );
+ TRACUCOMP( g_trac_i2c,
+ INFO_MRK"i2cRead() - FIFO[0x%lx] = 0x%016llx",
+ masterAddrs[engine].fifo, fifo.value);
+
if( err )
{
break;
@@ -388,9 +414,11 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
*((uint8_t*)o_buffer + bytesRead) = fifo.byte_0;
- TRACSCOMP( g_trac_i2cr,
- "I2C READ DATA : engine %.2X : devAddr %.2X : byte %d : %.2X",
- engine, devAddr, bytesRead, fifo.byte_0 );
+ TRACUCOMP( g_trac_i2cr,
+ "I2C READ DATA : engine %.2X : port %.2x : "
+ "devAddr %.2X : byte %d : %.2X (0x%lx)",
+ engine, port, devAddr, bytesRead,
+ fifo.byte_0, fifo.value );
}
if( err )
@@ -449,8 +477,8 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
// Do Command/Mode reg setups
err = i2cSetup( i_target,
io_buflen,
- false,
- true,
+ false, // i_readNotWrite
+ true, // i_withStop
i_args );
if( err )
@@ -483,9 +511,11 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
break;
}
- TRACSCOMP( g_trac_i2cr,
- "I2C WRITE DATA : engine %.2X : devAddr %.2X : byte %d : %.2X",
- engine, devAddr, bytesWritten, fifo.byte_0 );
+ TRACUCOMP( g_trac_i2cr,
+ "I2C WRITE DATA : engine %.2X : port %.2X : "
+ "devAddr %.2X : byte %d : %.2X (0x%lx)",
+ engine, port, devAddr, bytesWritten,
+ fifo.byte_0, fifo.value );
}
if( err )
@@ -533,7 +563,8 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
uint64_t devAddr = i_args.devAddr;
TRACDCOMP( g_trac_i2c,
- ENTER_MRK"i2cSetup()" );
+ ENTER_MRK"i2cSetup(): buf_len=%d, r_nw=%d, w_stop=%d",
+ i_buflen, i_readNotWrite, i_withStop );
// Define the registers that we'll use
modereg mode;
@@ -541,8 +572,6 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
do
{
- // TODO - Validate some of the arg values passed in
-
// Wait for Command complete before we start
err = i2cWaitForCmdComp( i_target,
i_args );
@@ -557,16 +586,22 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
// - port number
mode.value = 0x0ull;
- // TODO - Hard code to 400KHz until we get attributes in place to get this from
- // the target.
+
+
+ // @todo RTC:72715 - Add multiple bus speed support
+ // Hard code to 400KHz until we get attributes in place to get
+ // this from the target.
mode.bit_rate_div = I2C_CLOCK_DIVISOR_400KHZ;
mode.port_num = port;
+ TRACUCOMP( g_trac_i2c,"i2cSetup(): set mode = 0x%lx", mode.value);
+
err = deviceWrite( i_target,
&mode.value,
size,
DEVICE_SCOM_ADDRESS( masterAddrs[engine].mode ) );
+
if( err )
{
break;
@@ -581,10 +616,19 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
cmd.with_start = 1;
cmd.with_stop = (i_withStop ? 1 : 0);
cmd.with_addr = 1;
- cmd.device_addr = devAddr;
+
+ // cmd.device_addr is 7 bits
+ // devAddr though is a uint64_t
+ // -- value stored in LSB byte of uint64_t
+ // -- LS-bit is unused, creating the 7 bit cmd.device_addr
+ // So will be masking for LSB, and then shifting to push off LS-bit
+ cmd.device_addr = (0x000000FF & devAddr) >> 1;
+
cmd.read_not_write = (i_readNotWrite ? 1 : 0);
cmd.length_b = i_buflen;
+ TRACUCOMP( g_trac_i2c,"i2cSetup(): set cmd = 0x%lx", cmd.value);
+
err = deviceWrite( i_target,
&cmd.value,
size,
@@ -617,10 +661,13 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
// Define the registers that we'll use
statusreg status;
- // TODO - hardcoded to 400KHz for now.
+ // @todo RTC:72715 - Add multiple bus speed support (set to 400KHz for now)
uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ );
uint64_t timeoutCount = I2C_TIMEOUT_COUNT( interval );
+ TRACUCOMP(g_trac_i2c, "i2cWaitForCmdComp(): timeoutCount=%d, interval=%d",
+ timeoutCount, interval);
+
do
{
// Check the Command Complete bit
@@ -700,6 +747,11 @@ errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target,
break;
}
+ TRACUCOMP(g_trac_i2c,"i2cReadStatusReg(): "
+ INFO_MRK"status[0x%lx]: 0x%016llx",
+ masterAddrs[engine].status, o_statusReg.value );
+
+
// Check for Errors
// Per the specification it is a requirement to check for errors each time
// that the status register is read.
@@ -783,13 +835,6 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
i_statusVal.value );
}
- if( 1 == i_statusVal.data_request )
- {
- errorFound = true;
- TRACFCOMP( g_trac_i2c,
- ERR_MRK"I2C Data Request Error! - status reg: %016llx",
- i_statusVal.value );
- }
if( 1 == i_statusVal.stop_error )
{
@@ -807,6 +852,8 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
i_statusVal.value );
// Get the Interrupt Register value to add to the log
+ // - i2cGetInterrupts() adds intRegVal to trace, so it ill be added
+ // to error log below
err = i2cGetInterrupts( i_target,
i_args,
intRegVal );
@@ -815,6 +862,7 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
{
break;
}
+
}
if( errorFound )
@@ -838,10 +886,7 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
i_statusVal.value,
intRegVal );
- // TODO - RTC entry to be created to allow for adding a target to an errorlog.
- // Once that is implemented, the target will be used here to add to the log.
-
- // TODO - Add I2C traces to this log.
+ // @todo RTC:69113 - Add target and I2C traces to the errorlog.
break;
}
@@ -862,7 +907,7 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
{
errlHndl_t err = NULL;
- // TODO - hardcoded to 400KHz for now
+ // @todo RTC:72715 - support multiple bus speeds (set to 400KHz for now)
uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ );
uint64_t timeoutCount = I2C_TIMEOUT_COUNT( interval );
@@ -885,7 +930,17 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
break;
}
- while( I2C_MAX_FIFO_CAPACITY <= status.fifo_entry_count )
+ TRACUCOMP( g_trac_i2c, "i2cWaitForFifoSpace(): status=0x%016llx "
+ "I2C_MAX_FIFO_CAPACITY=%d, status.fifo_entry_count=%d",
+ status.value, I2C_MAX_FIFO_CAPACITY,
+ status.fifo_entry_count);
+
+
+ // 2 Conditions to wait on:
+ // 1) FIFO is full
+ // 2) Data Request bit is not set
+ while( (I2C_MAX_FIFO_CAPACITY <= status.fifo_entry_count) &&
+ (0 == status.data_request) )
{
// FIFO is full, wait before writing any data
nanosleep( 0, (interval * 1000) );
@@ -958,6 +1013,11 @@ errlHndl_t i2cReset ( TARGETING::Target * i_target,
do
{
reset.value = 0x0;
+
+ TRACUCOMP(g_trac_i2c,"i2cReset() "
+ "reset[0x%lx]: 0x%016llx",
+ masterAddrs[engine].reset, reset.value );
+
err = deviceWrite( i_target,
&reset.value,
size,
@@ -1009,12 +1069,18 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
do
{
mode.value = 0x0ull;
- // TODO - Hard code to 400KHz until we get attributes in place to get this from
- // the target.
+
+ // @todo RTC:72715 - support multiple bus speeds
+ // Hard code to 400KHz until we get attributes in place to get
+ // this from the target.
mode.bit_rate_div = I2C_CLOCK_DIVISOR_400KHZ;
mode.port_num = port;
mode.enhanced_mode = 1;
+ TRACUCOMP(g_trac_i2c,"i2cSendSlaveStop(): "
+ "mode[0x%lx]: 0x%016llx",
+ masterAddrs[engine].mode, mode.value );
+
err = deviceWrite( i_target,
&mode.value,
size,
@@ -1028,6 +1094,10 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
cmd.value = 0x0ull;
cmd.with_stop = 1;
+ TRACUCOMP(g_trac_i2c,"i2cSendSlaveStop(): "
+ "cmd[0x%lx]: 0x%016llx",
+ masterAddrs[engine].command, cmd.value );
+
err = deviceWrite( i_target,
&cmd.value,
size,
@@ -1085,6 +1155,10 @@ errlHndl_t i2cGetInterrupts ( TARGETING::Target * i_target,
break;
}
+ TRACUCOMP(g_trac_i2c,"i2cGetInterrupts(): "
+ "interrupt[0x%lx]: 0x%016llx",
+ masterAddrs[engine].interrupt, intreg.value );
+
// Return the data read
o_intRegValue = intreg.value;
} while( 0 );
@@ -1107,7 +1181,7 @@ errlHndl_t i2cSetupMasters ( void )
modereg mode;
size_t size = sizeof(uint64_t);
- TRACFCOMP( g_trac_i2c,
+ TRACDCOMP( g_trac_i2c,
ENTER_MRK"i2cSetupMasters()" );
do
@@ -1151,7 +1225,7 @@ errlHndl_t i2cSetupMasters ( void )
break;
}
- TRACDCOMP( g_trac_i2c,
+ TRACUCOMP( g_trac_i2c,
INFO_MRK"I2C Master Centaurs: %d",
centList.size() );
@@ -1172,7 +1246,8 @@ errlHndl_t i2cSetupMasters ( void )
// Write Mode Register:
mode.value = 0x0ull;
- // TODO - Hard code to 400KHz until we get attributes in place
+ // @todo RTC:72715 - support multiple bus speeds
+ // Hard code to 400KHz until we get attributes in place
// to get this from the target.
mode.bit_rate_div = I2C_CLOCK_DIVISOR_400KHZ;
err = deviceWrite( centList[centaur],
@@ -1238,7 +1313,7 @@ errlHndl_t i2cSetupMasters ( void )
break;
}
- TRACDCOMP( g_trac_i2c,
+ TRACUCOMP( g_trac_i2c,
INFO_MRK"I2C Master Procs: %d",
procList.size() );
@@ -1259,7 +1334,8 @@ errlHndl_t i2cSetupMasters ( void )
// Write Mode Register:
mode.value = 0x0ull;
- // TODO - Hard code to 400KHz until we get attributes in place
+ // @todo RTC:72715 - support multiple bus speeds
+ // Hard code to 400KHz until we get attributes in place
// to get this from the target.
mode.bit_rate_div = I2C_CLOCK_DIVISOR_400KHZ;
err = deviceWrite( procList[proc],
@@ -1293,10 +1369,11 @@ errlHndl_t i2cSetupMasters ( void )
}
} while( 0 );
- TRACFCOMP( g_trac_i2c,
+ TRACDCOMP( g_trac_i2c,
EXIT_MRK"i2cSetupMasters()" );
return err;
}
+
} // end namespace I2C
diff --git a/src/usr/i2c/test/eepromddtest.H b/src/usr/i2c/test/eepromddtest.H
index 5c622a7f5..71211c08a 100755
--- a/src/usr/i2c/test/eepromddtest.H
+++ b/src/usr/i2c/test/eepromddtest.H
@@ -1,25 +1,25 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/usr/i2c/test/eepromddtest.H $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/i2c/test/eepromddtest.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
#ifndef __EEPROMTEST_H
#define __EEPROMTEST_H
@@ -37,10 +37,18 @@
#include <i2c/eepromddreasoncodes.H>
#include <targeting/common/commontargeting.H>
#include "i2ctest.H"
+#include "../eepromdd.H"
extern trace_desc_t* g_trac_eeprom;
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
using namespace TARGETING;
+using namespace EEPROM;
+
+
class EEPROMTest: public CxxTest::TestSuite
{
@@ -57,32 +65,47 @@ class EEPROMTest: public CxxTest::TestSuite
int fails = 0;
int num_ops = 0;
+ uint8_t* testBuffer = NULL;
+ uint8_t* testBuffer_read = NULL;
+
+
TRACFCOMP( g_trac_eeprom,
"testEEPROMReadWrite - Start" );
struct
{
- uint64_t addr; // Slave Device Address to access
+ uint64_t offset; // Internal Slave Device Offset to access
uint64_t chip; // Which EEPROM chip hung off of the target to access
uint64_t data; // Data to write or compare to
size_t size; // Number of bytes to read/write
bool rnw; // Read (true), Write (false)
} testData[] =
+
{
- { 0x1111, 0x0, 0xfedcba9876543210, 8, false }, // Write data
- { 0x1111, 0x0, 0xfedcba9876543210, 8, true }, // Read data
- { 0x2222, 0x0, 0xaabb000000000000, 2, false },
- { 0x2222, 0x0, 0xaabb000000000000, 2, true },
- { 0x1122, 0x0, 0x1122334400000000, 4, false },
- { 0x1122, 0x0, 0x1122334400000000, 4, true },
+
+
+ // MVPD of processor - chip 0
+ // Write:
+ { 0x0000, VPD_PRIMARY, 0xfedcba9876543210, 8, false },
+ // Read:
+ { 0x0000, VPD_PRIMARY, 0xfedcba9876543210, 8, true },
+
+ // SBE Primary of processor - chip 2
+ // Write:
+ { 0x0100, SBE_PRIMARY, 0xaabb000000000000, 2, false },
+ // Read:
+ { 0x0100, SBE_PRIMARY, 0xaabb000000000000, 2, true },
+
+ // SBE Backup of processor - chip 3
+ // Write:
+ { 0x00F0, SBE_BACKUP, 0x1122334400000000, 4, false },
+ // Read:
+ { 0x00F0, SBE_BACKUP, 0x1122334400000000, 4, true },
};
const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]);
- //@TODO
- //@VBU workaround - Disable I2C test case on fake target
- //Test case use fake targets, which will fail when running
- //on VBU. Need to fix this.
+ // Skipping EEPROM test altogether in VBU/VPO environment
if( TARGETING::is_vpo() )
{
return;
@@ -98,13 +121,10 @@ class EEPROMTest: public CxxTest::TestSuite
TargetHandleList fullList;
fullList.push_back( testTarget );
- // TODO - The following is what I want to use... BUT, since we
- // can't target DIMMs yet, and only Proc 0 has a slave device
- // hung off of it, we can't do that yet. Uncomment the following
- // when it is supported.
+ // Uncomment the following code when other I2C devices
+ // are supported
// TARGETING::TargetService& tS = TARGETING::targetService();
// TARGETING::Target * sysTarget = NULL;
-// TargetHandleList fullList;
// // Get top level system target
// tS.getTopLevelTarget( sysTarget );
@@ -159,8 +179,9 @@ class EEPROMTest: public CxxTest::TestSuite
fullList[j],
&data,
testData[i].size,
- DEVICE_EEPROM_ADDRESS( testData[i].addr,
- testData[i].chip ) );
+ DEVICE_EEPROM_ADDRESS(
+ testData[i].chip,
+ testData[i].offset));
if( err )
{
@@ -189,8 +210,92 @@ class EEPROMTest: public CxxTest::TestSuite
}
}
}
+
+ // Test EEPROM Write of large size
+ // @todo RTC:69113 - will clean this up:
+ // 1) Make its own testcase function
+ // 2) Will use a larger data set: Plan on using 4K header of
+ // test_signed_container and putting it into un-used area of
+ // SBE_BACKUP
+ // 3) Will restore original data just in case
+ uint64_t testBufLen = 0xF1;
+ testBuffer = static_cast<uint8_t*>(malloc(testBufLen));
+ memset(testBuffer, 0xFE, testBufLen);
+
+ // Randomize the Data a bit
+ for (uint64_t i = 0;
+ i < ((testBufLen / 8) + 1);
+ i++)
+ testBuffer[i*8] = i;
+
+ for (uint64_t k = 0; k < 8; k++)
+ testBuffer[k] = k;
+
+ // do the Write operation
+ err = deviceOp( DeviceFW::WRITE,
+ fullList[0],
+ testBuffer,
+ testBufLen,
+ DEVICE_EEPROM_ADDRESS(SBE_BACKUP,0x0));
+ if( err )
+ {
+ TS_FAIL( "testEEPROMReadWrite - FAIL on large Data Write");
+ errlCommit( err,
+ EEPROM_COMP_ID );
+ delete err;
+ break;
+ }
+
+ // Read Back and Compare
+ testBuffer_read = static_cast<uint8_t*>(malloc( testBufLen ));
+
+ // clear read buffer
+ memset (testBuffer_read, 0, testBufLen);
+
+ // do the Read operation
+ err = deviceOp( DeviceFW::READ,
+ fullList[0],
+ testBuffer_read,
+ testBufLen,
+ DEVICE_EEPROM_ADDRESS(SBE_BACKUP,0x0));
+
+
+ if( err )
+ {
+ TS_FAIL( "testEEPROMReadWrite - FAIL on large Data Read");
+ errlCommit( err,
+ EEPROM_COMP_ID );
+ delete err;
+ break;
+ }
+
+
+ // Compare the data
+ if ( memcmp( testBuffer, testBuffer_read, testBufLen) )
+ {
+ TS_FAIL( "testEEPROMReadWrite - MISCOMPARE on large Data");
+ break;
+ }
+ else
+ {
+ TRACUCOMP( g_trac_eeprom, "testEEPROMReadWrite - large "
+ "Data R/W Successful");
+ }
+
} while( 0 );
+ // Clean up malloc'ed buffers
+ if ( testBuffer != NULL)
+ {
+ free(testBuffer);
+ }
+
+ if ( testBuffer_read != NULL)
+ {
+ free(testBuffer_read);
+ }
+
+
TRACFCOMP( g_trac_eeprom,
"testEEPROMReadWrite - %d/%d fails",
fails, num_ops );
@@ -260,7 +365,6 @@ class EEPROMTest: public CxxTest::TestSuite
uint64_t data = 0x0ull;
size_t dataSize = 8;
- const int64_t CHIP_NUM = 20;
do
{
@@ -283,14 +387,14 @@ class EEPROMTest: public CxxTest::TestSuite
testTarget,
&data,
dataSize,
- DEVICE_EEPROM_ADDRESS( 0x0,
- CHIP_NUM ) );
+ DEVICE_EEPROM_ADDRESS( LAST_CHIP_TYPE,
+ 0x0 ) );
if( NULL == err )
{
fails++;
TS_FAIL( "Error should've resulted in using EEPROM chip %d!",
- CHIP_NUM );
+ LAST_CHIP_TYPE );
}
else
{
diff --git a/src/usr/i2c/test/i2ctest.H b/src/usr/i2c/test/i2ctest.H
index 95f1cc16d..d98858451 100755
--- a/src/usr/i2c/test/i2ctest.H
+++ b/src/usr/i2c/test/i2ctest.H
@@ -1,25 +1,25 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/usr/i2c/test/i2ctest.H $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/i2c/test/i2ctest.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2011,2013 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
#ifndef __I2CTEST_H
#define __I2CTEST_H
@@ -42,12 +42,21 @@ extern trace_desc_t* g_trac_i2c;
using namespace TARGETING;
+
+// Used to ignore comparing data on reads
+#define I2C_TEST_IGNORE_DATA_COMPARE 0xFFFFFFFFFFFFFFFF
+
+// @todo RTC:72715: Re-visit the use of this function when we have full
+// Attribute support
bool isI2CAvailable( TARGETING::Target * i_target )
{
bool avail = true;
- EepromAddrInfo0 eepromData;
- if( i_target->tryGetAttr<ATTR_EEPROM_ADDR_INFO0>( eepromData ) )
+
+ // Rudimentary Check - Every I2C Master has VPD Primary Attribute
+ EepromVpdPrimaryInfo eepromData;
+ if( i_target->tryGetAttr<ATTR_EEPROM_VPD_PRIMARY_INFO>( eepromData ) )
{
+
if( ( 0x80 == eepromData.port ) &&
( 0x80 == eepromData.devAddr ) &&
( 0x80 == eepromData.engine ) )
@@ -74,10 +83,10 @@ class I2CTest: public CxxTest::TestSuite
* This test will test a variety of reads/writes and lengths
* across slave devices.
*
- * TODO - Currently there is only 1 dummy I2C device that is
- * accessible via Simics. Once another is added the structure
- * used to direct commands will be altered to use the new device
- * and also be changed to not be destructive as they are currently.
+ * Currently only Processor targets are supported in simics.
+ *
+ * Add other targets to this testcase when their support is
+ * added.
*/
void testI2CReadWrite ( void )
{
@@ -99,28 +108,97 @@ class I2CTest: public CxxTest::TestSuite
uint64_t port; // Master engine port
uint64_t engine; // Master engine
uint64_t devAddr; // Slave Device address
+
uint64_t data; // Data to write or compare to
+ // if data = I2C_TEST_IGNORE_DATA_COMPARE
+ // than ignore data compare
+
size_t size; // Number of Bytes to read/write
bool rnw; // Read (true), Write (false)
targetType_t type; // Target Type
} testData[] =
{
- // Dummy I2C Device in Simics
- { 0x00, 0x00, 0x50, 0x1234BA9876543210,
- 8, false, I2C_PROC_TARGET }, // Write data
- { 0x00, 0x00, 0x50, 0x1234000000000000,
- 2, false, I2C_PROC_TARGET }, // Write addr for read
- { 0x00, 0x00, 0x50, 0xba98765432100000,
- 6, true, I2C_PROC_TARGET }, // Read data back
- { 0x00, 0x00, 0x50, 0x1100556677880000,
- 6, false, I2C_PROC_TARGET },
- { 0x00, 0x00, 0x50, 0x1100000000000000,
- 2, false, I2C_PROC_TARGET },
- { 0x00, 0x00, 0x50, 0x5566778800000000,
- 4, true, I2C_PROC_TARGET },
-
- // TODO - Once these commands are working with Simics, they
- // can be enabled. No target date.
+
+ // PROCESSOR TESTS
+ // -- For Processor SEEPROM's, ONLY USE ENGINE 0
+
+ // READ All 3 at address 0 for 8 bytes first
+ // Ignore data compare as we're not sure what's
+ // been writted there
+
+ // Read SBE Primary: Murano-0, port-0
+ { 0x00, 0x00, 0xAC, I2C_TEST_IGNORE_DATA_COMPARE,
+ 8, true, I2C_PROC_TARGET }, // Read
+
+ // Read SBE Backup: Murano-0, port-0
+ { 0x00, 0x00, 0xAE, I2C_TEST_IGNORE_DATA_COMPARE,
+ 8, true, I2C_PROC_TARGET }, // Read
+
+ // Read From MVPD: Murano-0, port 1
+ { 0x01, 0x00, 0xA4, I2C_TEST_IGNORE_DATA_COMPARE,
+ 8, true, I2C_PROC_TARGET }, // Read data back
+
+
+ // Read/Write SBE Primary: Murano-0, port-0
+ // Safe to write to first 1K: 0x-0x400
+
+ { 0x00, 0x00, 0xAC, 0x0000ababcdcdefef,
+ 8, false, I2C_PROC_TARGET }, // Write data to 0x0000
+
+ { 0x00, 0x00, 0xAC, 0x0000000000000000,
+ 2, false, I2C_PROC_TARGET }, // Write addr for read
+
+ { 0x00, 0x00, 0xAc, 0xababcdcdefef0000,
+ 6, true, I2C_PROC_TARGET }, // Read data back
+
+ { 0x00, 0x00, 0xAC, 0x0003000000000000,
+ 2, false, I2C_PROC_TARGET }, // Write addr for read
+
+ { 0x00, 0x00, 0xAC, 0xcdefef0000000000,
+ 3, true, I2C_PROC_TARGET }, // Read data back
+
+ { 0x00, 0x00, 0xAC, 0x0005ee1200000000,
+ 4, false, I2C_PROC_TARGET }, // Write data to 0x0005
+
+ { 0x00, 0x00, 0xAC, 0x0005000000000000,
+ 2, false, I2C_PROC_TARGET }, // Write addr for read
+
+ { 0x00, 0x00, 0xAC, 0xee12000000000000,
+ 2, true, I2C_PROC_TARGET }, // Read data back
+
+
+
+ // Read/Write SBE Backup: Murano-0, port-0
+ // Safe to write to first 1K: 0x-0x400
+
+ { 0x00, 0x00, 0xAE, 0x0000ababcdcdefef,
+ 8, false, I2C_PROC_TARGET }, // Write data to 0x0000
+
+ { 0x00, 0x00, 0xAE, 0x0000000000000000,
+ 2, false, I2C_PROC_TARGET }, // Write addr for read
+
+ { 0x00, 0x00, 0xAE, 0xababcdcdefef0000,
+ 6, true, I2C_PROC_TARGET }, // Read data back
+
+ { 0x00, 0x00, 0xAE, 0x0003000000000000,
+ 2, false, I2C_PROC_TARGET }, // Write addr for read
+
+ { 0x00, 0x00, 0xAE, 0xcdefef0000000000,
+ 3, true, I2C_PROC_TARGET }, // Read data back
+
+ { 0x00, 0x00, 0xAE, 0x0005ee1200000000,
+ 4, false, I2C_PROC_TARGET }, // Write data to 0x0005
+
+ { 0x00, 0x00, 0xAE, 0x0005000000000000,
+ 2, false, I2C_PROC_TARGET }, // Write addr for read
+
+ { 0x00, 0x00, 0xAE, 0xee12000000000000,
+ 2, true, I2C_PROC_TARGET }, // Read data back
+
+
+ // MEMBUF TESTS
+ // Use the following commands when Centaur devices are
+ // supported in simics. No target date.
// Real Centaur Devices
// { 0x00, 0x00, 0x51, 0x1111000000000000,
// 2, false, I2C_CENTAUR_TARGET }, // Write addr of 0x0000
@@ -134,10 +212,8 @@ class I2CTest: public CxxTest::TestSuite
const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]);
- //@TODO
- //@VBU workaround - Disable I2C test case on fake target
- //Test case use fake targets, which will fail when running
- //on VBU. Need to fix this.
+
+ // Skipping I2C test altogether in VBU/VPO environment
if( TARGETING::is_vpo() )
{
return;
@@ -168,7 +244,18 @@ class I2CTest: public CxxTest::TestSuite
for( uint32_t i = 0; i < NUM_CMDS; i++ )
{
+
+ // Make sure size is less than or = to 8 bytes
+ // to fit into data
uint64_t data;
+ if (testData[i].size > 8)
+ {
+ TRACFCOMP( g_trac_i2c,
+ "testI2ReadWrite Size (%d) is greater than"
+ " 8 bytes. Skipping test %d",
+ testData[i].size, i );
+ continue;
+ }
// if a read, initialize data, else, set data to write
if( testData[i].rnw )
@@ -220,7 +307,7 @@ class I2CTest: public CxxTest::TestSuite
if( !isI2CAvailable( theTarget ) )
{
TRACFCOMP( g_trac_i2c,
- "testI2ReadWrite Operation - no i2c function" );
+ "testI2CReadWrite Operation - no i2c function" );
continue;
@@ -259,8 +346,10 @@ class I2CTest: public CxxTest::TestSuite
continue;
}
- // compare data for the read
- if( testData[i].rnw )
+ // compare data for the read, but ignore case where
+ // data = I2C_TEST_IGNORE_DATA_COMPARE
+ if( ( testData[i].rnw ) &&
+ ( testData[i].data != I2C_TEST_IGNORE_DATA_COMPARE ))
{
if( data != testData[i].data )
{
OpenPOWER on IntegriCloud