summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Baiocchi <baiocchi@us.ibm.com>2013-07-22 14:48:25 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-08-08 15:16:29 -0500
commitb390d78d49a76b69c80afe036ee5350878686152 (patch)
tree053b958bc54911138b6c69a6ccccbff2e24a3d75
parent96d2b18667f66fc4997ca354c4098de5ca382625 (diff)
downloadtalos-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>
-rw-r--r--src/include/usr/devicefw/driverif.H20
-rwxr-xr-xsrc/usr/i2c/eepromdd.C52
-rwxr-xr-xsrc/usr/i2c/i2c.C168
-rwxr-xr-xsrc/usr/i2c/i2c.H14
-rwxr-xr-xsrc/usr/i2c/test/eepromddtest.H5
-rwxr-xr-xsrc/usr/i2c/test/i2ctest.H376
6 files changed, 525 insertions, 110 deletions
diff --git a/src/include/usr/devicefw/driverif.H b/src/include/usr/devicefw/driverif.H
index eab488baf..f1a52e98f 100644
--- a/src/include/usr/devicefw/driverif.H
+++ b/src/include/usr/devicefw/driverif.H
@@ -102,11 +102,29 @@ namespace DeviceFW
* @param[in] i_port - Which port to use from the I2C master.
* @param[in] i_engine - Which I2C master engine to use.
* @param[in] i_devAddr - The device address on a given engine/port.
+ * @note '0' and 'NULL' added to line up with other DeviceFW::I2C
*/
#define DEVICE_I2C_ADDRESS( i_port, i_engine, i_devAddr )\
DeviceFW::I2C, static_cast<uint64_t>(( i_port )),\
static_cast<uint64_t>(( i_engine )),\
- static_cast<uint64_t>(( i_devAddr ))
+ static_cast<uint64_t>(( i_devAddr )),\
+ 0,\
+ NULL
+
+ /**
+ * Construct the device addressing parameters for the I2C-offset device ops.
+ * @param[in] i_port - Which port to use from the I2C master.
+ * @param[in] i_engine - Which I2C master engine to use.
+ * @param[in] i_devAddr - The device address on a given engine/port.
+ * @param[in] i_offset_len - Length of offset (in bytes)
+ * @param[in] i_offset - Offset into I2C device
+ */
+ #define DEVICE_I2C_ADDRESS_OFFSET( i_port, i_engine, i_devAddr, i_offset_len, i_offset)\
+ DeviceFW::I2C, static_cast<uint64_t>(( i_port )),\
+ static_cast<uint64_t>(( i_engine )),\
+ static_cast<uint64_t>(( i_devAddr )),\
+ static_cast<uint64_t>(( i_offset_len )),\
+ static_cast<uint8_t*>(( i_offset ))
/** @class InvalidParameterType
* @brief Unused type to cause compiler fails for invalid template types.
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
OpenPOWER on IntegriCloud