diff options
author | Mike Baiocchi <baiocchi@us.ibm.com> | 2013-07-22 14:48:25 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-08-08 15:16:29 -0500 |
commit | b390d78d49a76b69c80afe036ee5350878686152 (patch) | |
tree | 053b958bc54911138b6c69a6ccccbff2e24a3d75 /src/usr/i2c | |
parent | 96d2b18667f66fc4997ca354c4098de5ca382625 (diff) | |
download | talos-hostboot-b390d78d49a76b69c80afe036ee5350878686152.tar.gz talos-hostboot-b390d78d49a76b69c80afe036ee5350878686152.zip |
New I2C Interface that adds device offset parameter
Adding an I2C Device Driver interface that has an additional
offset paramter which allows for a single operation to set both the
device's internal offset and then do a read or write to the device.
RTC: 73815
Change-Id: Ib77682f3b7e2088d77ce28b885c544e5cb785f6a
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5524
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-x | src/usr/i2c/eepromdd.C | 52 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.C | 168 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.H | 14 | ||||
-rwxr-xr-x | src/usr/i2c/test/eepromddtest.H | 5 | ||||
-rwxr-xr-x | src/usr/i2c/test/i2ctest.H | 376 |
5 files changed, 506 insertions, 109 deletions
diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index b5ba280e5..f734b66cc 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -233,38 +233,48 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target, // Only write the byte address if we have data to write if( 0 != byteAddrSize ) { - // Write the Byte Address of the Slave Device - err = deviceOp( DeviceFW::WRITE, + + // Use the I2C OFFSET Interface for the READ + err = deviceOp( DeviceFW::READ, + i_target, + o_buffer, + i_buflen, + DEVICE_I2C_ADDRESS_OFFSET( + i_i2cInfo.port, + i_i2cInfo.engine, + i_i2cInfo.devAddr, + byteAddrSize, + reinterpret_cast<uint8_t*>(&byteAddr))); + + if( err ) + { + TRACFCOMP(g_trac_eeprom, + ERR_MRK"eepromRead(): I2C Read-Offset failed on " + "%d/%d/0x%x", + i_i2cInfo.port, i_i2cInfo.engine, i_i2cInfo.devAddr); + break; + } + } + else + { + // Do the actual read via I2C + err = deviceOp( DeviceFW::READ, i_target, - &byteAddr, - byteAddrSize, + o_buffer, + i_buflen, DEVICE_I2C_ADDRESS( i_i2cInfo.port, i_i2cInfo.engine, i_i2cInfo.devAddr ) ); 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; } } - // Do the actual read via I2C - err = deviceOp( DeviceFW::READ, - i_target, - o_buffer, - i_buflen, - DEVICE_I2C_ADDRESS( i_i2cInfo.port, - i_i2cInfo.engine, - i_i2cInfo.devAddr ) ); - - 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; - } - mutex_unlock( &g_eepromMutex ); unlock = false; diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C index 0a32c1ca8..66d39bc6e 100755 --- a/src/usr/i2c/i2c.C +++ b/src/usr/i2c/i2c.C @@ -97,6 +97,8 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, va_list i_args ) { errlHndl_t err = NULL; + bool l_withStop = false; + bool l_skipModeSetup = false; // Get the input args our of the va_list // Address, Port, Engine, Device Addr. @@ -105,16 +107,30 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, args.engine = va_arg( i_args, uint64_t ); args.devAddr = va_arg( i_args, uint64_t ); + + // These are additional parms in the case an offset is passed in + // via va_list, as well + uint64_t l_offset_length = 0; + uint8_t * l_offset_buffer = NULL; + + l_offset_length = va_arg( i_args, uint64_t); + + if ( l_offset_length != 0) + { + l_offset_buffer = reinterpret_cast<uint8_t*>(va_arg(i_args, uint64_t)); + } + TRACDCOMP( g_trac_i2c, - ENTER_MRK"i2cPerformOp(): i_opType=%d, " - "p=%d, engine=%d, devAddr=0x%lx", - (uint64_t) i_opType, args.port, args.engine, args.devAddr ); + ENTER_MRK"i2cPerformOp(): i_opType=%d, aType=%d, " + "p/e/devAddr= %d/%d/0x%X, len=%d, offset=%d/%p", + (uint64_t) i_opType, i_accessType, args.port, args.engine, + args.devAddr, io_buflen, l_offset_length, l_offset_buffer); 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); + ENTER_MRK"i2cPerformOp(): i_opType=%d, aType=%d, " + "p/e/devAddr= %d/%d/0x%x, len=%d, offset=%d/%p", + (uint64_t) i_opType, i_accessType, args.port, args.engine, + args.devAddr, io_buflen, l_offset_length, l_offset_buffer); do { @@ -205,25 +221,96 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, nanosleep( 0, I2C_RETRY_DELAY ); } - if( i_opType == DeviceFW::READ ) + + if( i_opType == DeviceFW::READ && + l_offset_length != 0 ) + { + + // First WRITE offset to device without a stop + l_withStop = false; + + err = i2cWrite( i_target, + l_offset_buffer, + l_offset_length, + l_withStop, + args ); + + + + // Now do the READ with a stop (reads always have 'stop') + // Skip mode setup on this cmd - already set with previous cmd + l_skipModeSetup = true; + + err = i2cRead( i_target, + io_buffer, + io_buflen, + l_skipModeSetup, + args ); + } + + else if( i_opType == DeviceFW::WRITE && + l_offset_length != 0 ) + { + + // Add the Offset Information to the start of the data and + // then send as a single write operation + + size_t newBufLen = l_offset_length + io_buflen; + uint8_t * newBuffer = static_cast<uint8_t*>(malloc(newBufLen)); + + // Add the Offset to the buffer + memcpy( newBuffer, l_offset_buffer, l_offset_length); + + // Now add the data the user wanted to write + memcpy( &newBuffer[l_offset_length], io_buffer, io_buflen); + + // Other parms: + l_withStop = true; + l_skipModeSetup = false; + + err = i2cWrite( i_target, + newBuffer, + newBufLen, + l_withStop, + args ); + + + free( newBuffer ); + + } + + else if ( i_opType == DeviceFW::READ && + l_offset_length == 0 ) { + // Do a direct READ + l_skipModeSetup = false; + err = i2cRead( i_target, io_buffer, io_buflen, + l_skipModeSetup, args ); } - else if( i_opType == DeviceFW::WRITE ) + + + else if( i_opType == DeviceFW::WRITE && + l_offset_length == 0 ) { + // Do a direct WRITE with a stop + l_withStop = true; err = i2cWrite( i_target, io_buffer, io_buflen, + l_withStop, args ); } else { - TRACFCOMP( g_trac_i2c, - ERR_MRK"i2cPerformOp() - Unknown Operation Type!" ); - uint64_t userdata2 = args.port; + TRACFCOMP( g_trac_i2c, ERR_MRK"i2cPerformOp() - " + "Unsupported Op/Offset-Type Combination=%d/%d", + i_opType, l_offset_length ); + uint64_t userdata2 = l_offset_length; + userdata2 = (userdata2 << 16) | args.port; userdata2 = (userdata2 << 16) | args.engine; userdata2 = (userdata2 << 16) | args.devAddr; @@ -233,7 +320,7 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, * @severity ERRL_SEV_UNRECOVERABLE * @moduleid I2C_PERFORM_OP * @userdata1 i_opType - * @userdata2[0:15] <UNUSED> + * @userdata2[0:15] Offset Length * @userdata2[16:31] Master Port * @userdata2[32:47] Master Engine * @userdata2[48:63] Slave Device Address @@ -249,7 +336,7 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, } // If no errors, break here - if( NULL == err ) + if( err == NULL ) { break; } @@ -280,6 +367,7 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, errlHndl_t i2cRead ( TARGETING::Target * i_target, void * o_buffer, size_t & i_buflen, + bool & i_skipModeSetup, input_args_t i_args ) { errlHndl_t err = NULL; @@ -312,6 +400,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, i_buflen, true, // i_readNotWrite true, // i_withStop + i_skipModeSetup, i_args ); if( err ) @@ -414,6 +503,9 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, *((uint8_t*)o_buffer + bytesRead) = fifo.byte_0; + // Everytime FIFO is read, reset timeout count + timeoutCount = I2C_TIMEOUT_COUNT( interval ); + TRACUCOMP( g_trac_i2cr, "I2C READ DATA : engine %.2X : port %.2x : " "devAddr %.2X : byte %d : %.2X (0x%lx)", @@ -452,6 +544,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, errlHndl_t i2cWrite ( TARGETING::Target * i_target, void * i_buffer, size_t & io_buflen, + bool & i_withStop, input_args_t i_args ) { errlHndl_t err = NULL; @@ -478,7 +571,8 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target, err = i2cSetup( i_target, io_buflen, false, // i_readNotWrite - true, // i_withStop + i_withStop, + false, // i_skipModeSetup, i_args ); if( err ) @@ -523,7 +617,7 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target, break; } - // Check for Command complete, and make sure no errors + // Check for Command complete err = i2cWaitForCmdComp( i_target, i_args ); @@ -553,6 +647,7 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, size_t & i_buflen, bool i_readNotWrite, bool i_withStop, + bool i_skipModeSetup, input_args_t i_args ) { errlHndl_t err = NULL; @@ -581,32 +676,37 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, break; } - // Write Mode Register: - // - bit rate divisor - // - port number - mode.value = 0x0ull; - + // Skip mode setup on 2nd of 2 cmd strung together - like when sending + // device offset first before read or write - // @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; + if ( i_skipModeSetup == false) + { + // Write Mode Register: + // - bit rate divisor + // - port number + mode.value = 0x0ull; - TRACUCOMP( g_trac_i2c,"i2cSetup(): set mode = 0x%lx", mode.value); + // @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; - err = deviceWrite( i_target, - &mode.value, - size, - DEVICE_SCOM_ADDRESS( masterAddrs[engine].mode ) ); + 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; + if( err ) + { + break; + } } + // Write Command Register: // - with start // - with stop diff --git a/src/usr/i2c/i2c.H b/src/usr/i2c/i2c.H index a5448a175..d1b3b2afd 100755 --- a/src/usr/i2c/i2c.H +++ b/src/usr/i2c/i2c.H @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ /* */ /* p1 */ /* */ @@ -451,6 +451,9 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, * @param[in] i_buflen - The size of the data to read and place in the * buffer. * + * @param[in] i_skipModeSetup - true if mode register setup needs to be + * skipped + * * @param[in] i_args - Structure containing arguments needed for a command * transaction. * @@ -460,6 +463,7 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, errlHndl_t i2cRead ( TARGETING::Target * i_target, void * o_buffer, size_t & i_buflen, + bool & i_skipModeSetup, input_args_t i_args ); /** @@ -474,6 +478,9 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, * @param[in/out] io_buflen - INPUT: The size of the data to write to the * target device. OUTPUT: The size of the data buffer written. * + * @param[in] i_withStop - true if with_stop bit is to be set on operation; + * otherwise, with_stop bit will be set to zero. + * * @param[in] i_args - Structure containing arguments needed for a command * transaction. * @@ -484,6 +491,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, errlHndl_t i2cWrite ( TARGETING::Target * i_target, void * i_buffer, size_t & io_buflen, + bool & i_withStop, input_args_t i_args ); /** @@ -500,6 +508,9 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target, * @param[in] i_withStop - true if with_stop bit is to be set, otherwise * with_stop will be set to zero. * + * @param[in] i_skipModeSetup - true if mode register setup needs to be + * skipped + * * @param[in] i_args - Structure containing arguments needed for a command * transaction. * @@ -510,6 +521,7 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, size_t & i_buflen, bool i_readNotWrite, bool i_withStop, + bool i_skipModeSetup, input_args_t i_args ); /** diff --git a/src/usr/i2c/test/eepromddtest.H b/src/usr/i2c/test/eepromddtest.H index 71211c08a..48b6329cc 100755 --- a/src/usr/i2c/test/eepromddtest.H +++ b/src/usr/i2c/test/eepromddtest.H @@ -41,9 +41,7 @@ extern trace_desc_t* g_trac_eeprom; -// Easy macro replace for unit testing -//#define TRACUCOMP(args...) TRACFCOMP(args) -#define TRACUCOMP(args...) +// NOTE: TRACUCOMP defined/controlled in i2ctest.H using namespace TARGETING; using namespace EEPROM; @@ -83,7 +81,6 @@ class EEPROMTest: public CxxTest::TestSuite { - // MVPD of processor - chip 0 // Write: { 0x0000, VPD_PRIMARY, 0xfedcba9876543210, 8, false }, diff --git a/src/usr/i2c/test/i2ctest.H b/src/usr/i2c/test/i2ctest.H index d98858451..12b12385f 100755 --- a/src/usr/i2c/test/i2ctest.H +++ b/src/usr/i2c/test/i2ctest.H @@ -40,6 +40,10 @@ extern trace_desc_t* g_trac_i2c; +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + using namespace TARGETING; @@ -79,29 +83,24 @@ class I2CTest: public CxxTest::TestSuite public: /** - * @brief I2C Read/Write Test - * This test will test a variety of reads/writes and lengths - * across slave devices. + * @brief I2C Direct Test + * This test will test a variety of direct reads and writes + * with various lengths across slave devices. * * Currently only Processor targets are supported in simics. * * Add other targets to this testcase when their support is * added. */ - void testI2CReadWrite ( void ) + void testI2CDirect ( void ) { + errlHndl_t err = NULL; int cmds = 0; int fails = 0; TRACFCOMP( g_trac_i2c, - "testI2CReadWrite - Start" ); - - typedef enum - { - I2C_PROC_TARGET, - I2C_CENTAUR_TARGET, - } targetType_t; + "testI2CDirect - Start" ); struct { @@ -113,9 +112,9 @@ class I2CTest: public CxxTest::TestSuite // 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 + size_t size; // Number of Bytes to read/write + bool rnw; // Read (true), Write (false) + TARGETING::TYPE type; // Target Type } testData[] = { @@ -128,43 +127,43 @@ class I2CTest: public CxxTest::TestSuite // Read SBE Primary: Murano-0, port-0 { 0x00, 0x00, 0xAC, I2C_TEST_IGNORE_DATA_COMPARE, - 8, true, I2C_PROC_TARGET }, // Read + 8, true, TARGETING::TYPE_PROC }, // Read // Read SBE Backup: Murano-0, port-0 { 0x00, 0x00, 0xAE, I2C_TEST_IGNORE_DATA_COMPARE, - 8, true, I2C_PROC_TARGET }, // Read + 8, true, TARGETING::TYPE_PROC }, // Read // Read From MVPD: Murano-0, port 1 { 0x01, 0x00, 0xA4, I2C_TEST_IGNORE_DATA_COMPARE, - 8, true, I2C_PROC_TARGET }, // Read data back + 8, true, TARGETING::TYPE_PROC }, // 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 + 8, false, TARGETING::TYPE_PROC }, // Write data to 0x0000 { 0x00, 0x00, 0xAC, 0x0000000000000000, - 2, false, I2C_PROC_TARGET }, // Write addr for read + 2, false, TARGETING::TYPE_PROC }, // Write addr for read { 0x00, 0x00, 0xAc, 0xababcdcdefef0000, - 6, true, I2C_PROC_TARGET }, // Read data back + 6, true, TARGETING::TYPE_PROC }, // Read data back { 0x00, 0x00, 0xAC, 0x0003000000000000, - 2, false, I2C_PROC_TARGET }, // Write addr for read + 2, false, TARGETING::TYPE_PROC }, // Write addr for read { 0x00, 0x00, 0xAC, 0xcdefef0000000000, - 3, true, I2C_PROC_TARGET }, // Read data back + 3, true, TARGETING::TYPE_PROC }, // Read data back { 0x00, 0x00, 0xAC, 0x0005ee1200000000, - 4, false, I2C_PROC_TARGET }, // Write data to 0x0005 + 4, false, TARGETING::TYPE_PROC }, // Write data to 0x0005 { 0x00, 0x00, 0xAC, 0x0005000000000000, - 2, false, I2C_PROC_TARGET }, // Write addr for read + 2, false, TARGETING::TYPE_PROC }, // Write addr for read { 0x00, 0x00, 0xAC, 0xee12000000000000, - 2, true, I2C_PROC_TARGET }, // Read data back + 2, true, TARGETING::TYPE_PROC }, // Read data back @@ -172,28 +171,28 @@ class I2CTest: public CxxTest::TestSuite // Safe to write to first 1K: 0x-0x400 { 0x00, 0x00, 0xAE, 0x0000ababcdcdefef, - 8, false, I2C_PROC_TARGET }, // Write data to 0x0000 + 8, false, TARGETING::TYPE_PROC }, // Write data to 0x0000 { 0x00, 0x00, 0xAE, 0x0000000000000000, - 2, false, I2C_PROC_TARGET }, // Write addr for read + 2, false, TARGETING::TYPE_PROC }, // Write addr for read { 0x00, 0x00, 0xAE, 0xababcdcdefef0000, - 6, true, I2C_PROC_TARGET }, // Read data back + 6, true, TARGETING::TYPE_PROC }, // Read data back { 0x00, 0x00, 0xAE, 0x0003000000000000, - 2, false, I2C_PROC_TARGET }, // Write addr for read + 2, false, TARGETING::TYPE_PROC }, // Write addr for read { 0x00, 0x00, 0xAE, 0xcdefef0000000000, - 3, true, I2C_PROC_TARGET }, // Read data back + 3, true, TARGETING::TYPE_PROC }, // Read data back { 0x00, 0x00, 0xAE, 0x0005ee1200000000, - 4, false, I2C_PROC_TARGET }, // Write data to 0x0005 + 4, false, TARGETING::TYPE_PROC }, // Write data to 0x0005 { 0x00, 0x00, 0xAE, 0x0005000000000000, - 2, false, I2C_PROC_TARGET }, // Write addr for read + 2, false, TARGETING::TYPE_PROC }, // Write addr for read { 0x00, 0x00, 0xAE, 0xee12000000000000, - 2, true, I2C_PROC_TARGET }, // Read data back + 2, true, TARGETING::TYPE_PROC }, // Read data back // MEMBUF TESTS @@ -201,13 +200,13 @@ class I2CTest: public CxxTest::TestSuite // supported in simics. No target date. // Real Centaur Devices // { 0x00, 0x00, 0x51, 0x1111000000000000, -// 2, false, I2C_CENTAUR_TARGET }, // Write addr of 0x0000 +// 2, false, TARGETING::TYPE_MEMBUF }, // Write addr 0x0000 // { 0x00, 0x00, 0x51, 0x0000000000000000, -// 8, true, I2C_CENTAUR_TARGET }, // Read 8 bytes +// 8, true, TARGETING::TYPE_MEMBUF }, // Read 8 bytes // { 0x00, 0x00, 0x53, 0x0000000000000000, -// 2, false, I2C_CENTAUR_TARGET }, // Write addr of 0x0000 +// 2, false, TARGETING::TYPE_MEMBUF }, // Write addr 0x0000 // { 0x00, 0x00, 0x53, 0x0000000000000000, -// 8, true, I2C_CENTAUR_TARGET }, // Read 8 bytes +// 8, true, TARGETING::TYPE_MEMBUF }, // Read 8 bytes }; const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]); @@ -251,7 +250,7 @@ class I2CTest: public CxxTest::TestSuite if (testData[i].size > 8) { TRACFCOMP( g_trac_i2c, - "testI2ReadWrite Size (%d) is greater than" + "testI2CDirect Size (%d) is greater than" " 8 bytes. Skipping test %d", testData[i].size, i ); continue; @@ -270,7 +269,7 @@ class I2CTest: public CxxTest::TestSuite // Decide which target to use switch( testData[i].type ) { - case I2C_PROC_TARGET: + case TARGETING::TYPE_PROC: if( NULL == procTarget ) { TRACFCOMP( g_trac_i2c, @@ -282,7 +281,7 @@ class I2CTest: public CxxTest::TestSuite theTarget = procTarget; break; - case I2C_CENTAUR_TARGET: + case TARGETING::TYPE_MEMBUF: if( ( 0 == centList.size() ) || ( NULL == centList[0] ) ) { @@ -307,9 +306,7 @@ class I2CTest: public CxxTest::TestSuite if( !isI2CAvailable( theTarget ) ) { TRACFCOMP( g_trac_i2c, - "testI2CReadWrite Operation - no i2c function" ); - - + "testI2CDirect Operation - no i2c function" ); continue; } @@ -320,7 +317,7 @@ class I2CTest: public CxxTest::TestSuite { TRACFCOMP( g_trac_i2c, - "testI2ReadWrite Operation - target not functional" ); + "testI2CDirect Operation - target not functional"); continue; } @@ -337,7 +334,7 @@ class I2CTest: public CxxTest::TestSuite if( err ) { - TS_FAIL( "testI2CReadWrite - fail on cmd %d out of %d", + TS_FAIL( "testI2CDirect - fail on cmd %d out of %d", i, NUM_CMDS ); errlCommit( err, I2C_COMP_ID ); @@ -354,10 +351,10 @@ class I2CTest: public CxxTest::TestSuite if( data != testData[i].data ) { TRACFCOMP( g_trac_i2c, - "testI2CReadWrite - cmd: %d/%d, Data read: %016llx, " - "expected: %016llx", + "testI2CDirect - cmd: %d/%d, Data read:" + " %016llx, expected: %016llx", i, NUM_CMDS, data, testData[i].data ); - TS_FAIL( "testI2CReadWrite - Failure comparing read data!" ); + TS_FAIL( "testI2CDirect - Failure comparing read data!" ); fails++; continue; } @@ -366,11 +363,292 @@ class I2CTest: public CxxTest::TestSuite } while( 0 ); TRACFCOMP( g_trac_i2c, - "testI2CReadWrite - %d/%d fails", + "testI2CDirect - %d/%d fails", fails, cmds ); } /** + * @brief I2C Offset + * This test will use the I2C interface where an offset for + * the device is provided before the reads or write. + * + * Currently only Processor targets are supported in simics. + * + * Add other targets to this testcase when their support is + * added. + */ + void testI2COffset ( void ) + { + + errlHndl_t err = NULL; + int cmds = 0; + int fails = 0; + uint64_t original_data = 0; + uint64_t data = 0; + + TRACFCOMP( g_trac_i2c, + "testI2COffset - Start" ); + + struct + { + uint64_t port; // Master engine port + uint64_t engine; // Master engine + uint64_t devAddr; // Slave Device address + uint16_t offset; // Slave Device offset - 2 bytes + uint64_t data; // Data to write + size_t size; // Number of Bytes to read/write + TARGETING::TYPE type; // Target Type + } testData[] = + { + + // PROCESSOR TESTS + + // Read/Write SBE Backup: Murano-0, port-0 + // Safe to write to first 1K: 0x-0x400 + { 0x00, 0x00, 0xAE, 0x0123, + 0xFEFEDADA57579191, 8, TARGETING::TYPE_PROC }, + + // Read/Write SBE Primary: Murano-0, port-0 + // Safe to write to first 1K: 0x-0x400 + { 0x00, 0x00, 0xAC, 0x02FC, + 0x5ABC310000000000, 3, TARGETING::TYPE_PROC }, + }; + + const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]); + + + // Skipping I2C test altogether in VBU/VPO environment + if( TARGETING::is_vpo() ) + { + return; + } + + do + { + + // Get top level system target + TARGETING::TargetService& tS = TARGETING::targetService(); + TARGETING::Target * sysTarget = NULL; + TARGETING::Target * theTarget = NULL; + tS.getTopLevelTarget( sysTarget ); + assert( sysTarget != NULL ); + + // Get the Proc Target + TARGETING::Target* procTarget = NULL; + tS.masterProcChipTargetHandle( procTarget ); + + // Get a Centaur Target + TargetHandleList centList; + TARGETING::PredicateCTM predCent( TARGETING::CLASS_CHIP, + TARGETING::TYPE_MEMBUF ); + tS.getAssociated( centList, + sysTarget, + TARGETING::TargetService::CHILD, + TARGETING::TargetService::ALL, + &predCent ); + + for ( uint32_t i = 0; i < NUM_CMDS; i++ ) + { + TRACUCOMP( g_trac_i2c,"testI2COffset: Outer Loop i= " + "%d, NUM_CMDS = %d", i, NUM_CMDS); + + // Make sure size is less than or = to 8 bytes + // to fit into data + if (testData[i].size > 8) + { + TRACFCOMP( g_trac_i2c, + "testI2COffset: Size (%d) is greater than" + " 8 bytes. Skipping test %d", + testData[i].size, i ); + continue; + } + + // Decide which target to use + switch( testData[i].type ) + { + case TARGETING::TYPE_PROC: + if( NULL == procTarget ) + { + TRACFCOMP( g_trac_i2c, + ERR_MRK"Processor Target is NULL, " + "go to next operation!" ); + continue; + } + + theTarget = procTarget; + break; + + case TARGETING::TYPE_MEMBUF: + if( ( 0 == centList.size() ) || + ( NULL == centList[0] ) ) + { + TRACFCOMP( g_trac_i2c, + ERR_MRK"Centaur List has %d entries." + " Either empty or first target is " + "NULL!", + centList.size() ); + continue; + } + + theTarget = centList[0]; + break; + + default: + TS_FAIL( "Invalid Chip type specificed in testData!" ); + fails++; + continue; + break; + }; + + + // Check to see if I2C function is there + if( !isI2CAvailable( theTarget ) ) + { + TRACFCOMP( g_trac_i2c, + "testI2COfset Operation - no i2c function" ); + continue; + } + + // check to see if the target is functional before we + // continue.. + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_i2c, + "testI2COffset Operation - target not functional"); + + continue; + } + + + // For Each Set of Data, 5 operations: + // 1) Read Original Data and Save It + // 2) Write New Data + // 3) Read New Data and Compare + // 4) Write Back Original Data + // 5) Read Back Original Data and Compare + + // Before starting, clear original data buffer + original_data = 0x0ull; + + + for (uint8_t j = 1; j <= 5; j++) + { + + // Clear data variable + data = 0x0ull; + + // For Loop 2: set data to new data + if ( j == 2 ) + data = testData[i].data; + + // For Loop 4: set data to original_data + if ( j == 4 ) + data = original_data; + + // increment cmd op counter + cmds++; + + err = deviceOp( + (j%2) ? DeviceFW::READ : DeviceFW::WRITE, + theTarget, + &data, + testData[i].size, + DEVICE_I2C_ADDRESS_OFFSET( + testData[i].port, + testData[i].engine, + testData[i].devAddr, + sizeof(testData[i].offset), + reinterpret_cast<uint8_t*>( + &(testData[i].offset)))); + + if( err ) + { + TS_FAIL( "testI2COffset - OP %d FAILED " + "- cmd %d out of %d", + j, i, NUM_CMDS ); + errlCommit( err, + I2C_COMP_ID ); + delete err; + fails++; + continue; + } + + // Handle loop-specific results + + // For Loop 1: save original data + if ( j == 1 ) + { + original_data = data; + + // Always trace original data - just in case + TRACFCOMP(g_trac_i2c,"testI2COffset: " + "original_data=0x%x", original_data); + } + + + // For Loop 3: compare new data + if ( j == 3 ) + { + + TRACUCOMP( g_trac_i2c,"testI2COffset: " + "New Data Compare: " + "written=0x%016llx, read_back=0x%016llx", + testData[i].data, data); + + if( data != testData[i].data ) + { + TRACFCOMP(g_trac_i2c,"testI2COffset: New " + "Data Compare Fail: wrote=%016llx, " + "read back=%016llx. cmd: %d/%d (%d)", + testData[i].data, data, i, NUM_CMDS, j); + TS_FAIL( "testI2COffset - Failure comparing new data!" ); + fails++; + + // Don't break - try to write back original data + continue; + } + + } + + // For Loop 5: compare writing-back original data + if ( j == 5 ) + { + TRACUCOMP( g_trac_i2c,"testI2COffset: " + "Original Data Compare: " + "original=0x%016llx, read_back=0x%016llx", + original_data, data); + + if( data != original_data ) + { + TRACFCOMP(g_trac_i2c,"testI2COffset: New " + "Data Compare Fail: original=%016llx, " + "read back=%016llx. cmd: %d/%d (%d)", + original_data, data, i, NUM_CMDS, j); + TS_FAIL( "testI2COffset - Failure comparing original data!" ); + fails++; + + // Break: stop testing if we can't write back + // original data successfully + break; + } + } + + } // end of 'j' loop: 5 ops per testData[i] + + } // end of 'i' loop: unique testData[i] sets + + } while( 0 ); + + TRACFCOMP( g_trac_i2c, + "testI2COffset - %d/%d fails", + fails, cmds ); + } + + + + /** * @brief I2C Invalid Target test * This test will pass in the Master Sentinel chip in as a target * to be sure that an error is returned, and that the error returned |