summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c/i2c.C
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 /src/usr/i2c/i2c.C
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>
Diffstat (limited to 'src/usr/i2c/i2c.C')
-rwxr-xr-xsrc/usr/i2c/i2c.C168
1 files changed, 134 insertions, 34 deletions
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
OpenPOWER on IntegriCloud