summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c
diff options
context:
space:
mode:
authorMike Baiocchi <baiocchi@us.ibm.com>2013-05-23 08:56:11 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-07-02 15:28:45 -0500
commit47e1255f110771d5042e322d207111abcd430bc3 (patch)
tree9a917efce461ed45d2f4f77632ec64c8fe25f1eb /src/usr/i2c
parentb152baa74e1df1d85951ddcbbf0ae393544f68b6 (diff)
downloadtalos-hostboot-47e1255f110771d5042e322d207111abcd430bc3.tar.gz
talos-hostboot-47e1255f110771d5042e322d207111abcd430bc3.zip
Updates to I2C and EEPROM Device Drivers to work for P8
There were several changes required for successful operation of the I2C and EEPROM Device Drivers based on HW Testing. There was also a need to upddate the attribute files and various testcases for processor support. Change-Id: Idd9351ffb01a992c835f99d06ef1246709eceb8b RTC: 64765 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/4678 Tested-by: Jenkins Server Reviewed-by: ADAM R. MUHLE <armuhle@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
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