summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c/i2c.C
diff options
context:
space:
mode:
authorTerry J. Opie <opiet@us.ibm.com>2011-10-27 12:48:46 -0500
committerTerry J. Opie <opiet@us.ibm.com>2011-12-01 15:47:22 -0600
commitdddd1ef3658b3a3a846ec64c3e6ba9ba1f7b746e (patch)
tree3cad9b232c35e09596f862fc301788a7a4b71339 /src/usr/i2c/i2c.C
parent4a353d7840f632640e78cafc7052e2e5a99ad564 (diff)
downloadtalos-hostboot-dddd1ef3658b3a3a846ec64c3e6ba9ba1f7b746e.tar.gz
talos-hostboot-dddd1ef3658b3a3a846ec64c3e6ba9ba1f7b746e.zip
I2C Bad Machine Path and Cxx Testcases as well as the EEPROM device driver.
Change-Id: Ia89d3aecb3192a2f99ef9fbb5abe0ce1d528a481 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/506 Tested-by: Jenkins Server Reviewed-by: Terry J. Opie <opiet@us.ibm.com>
Diffstat (limited to 'src/usr/i2c/i2c.C')
-rwxr-xr-xsrc/usr/i2c/i2c.C607
1 files changed, 381 insertions, 226 deletions
diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C
index 8b2239b63..9d7c64464 100755
--- a/src/usr/i2c/i2c.C
+++ b/src/usr/i2c/i2c.C
@@ -42,12 +42,32 @@
#include "i2c.H"
// ----------------------------------------------
+// Globals
+// ----------------------------------------------
+// TODO - These are temporary until we get some sort of locking mutex
+// in the attributes for each master target. All operations will be
+// sequential no matter what target or what engine.
+mutex_t g_i2cMutex;
+bool g_initI2CMutex = true;
+
+// ----------------------------------------------
// Trace definitions
+// ----------------------------------------------
trace_desc_t* g_trac_i2c = NULL;
TRAC_INIT( & g_trac_i2c, "I2C", 4096 );
trace_desc_t* g_trac_i2cr = NULL;
TRAC_INIT( & g_trac_i2cr, "I2CR", 4096 );
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
+// ----------------------------------------------
+// Defines
+// ----------------------------------------------
+#define I2C_COMMAND_ATTEMPTS 2 // 1 Retry on failure
+#define I2C_RETRY_DELAY 10000000 // Sleep for 10 ms before retrying
+// ----------------------------------------------
namespace I2C
{
@@ -79,7 +99,6 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType,
// Get the input args our of the va_list
// Address, Port, Engine, Device Addr.
input_args_t args;
- args.addr = va_arg( i_args, uint64_t );
args.port = va_arg( i_args, uint64_t );
args.engine = va_arg( i_args, uint64_t );
args.devAddr = va_arg( i_args, uint64_t );
@@ -89,6 +108,12 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType,
do
{
+ if( g_initI2CMutex )
+ {
+ mutex_init( &g_i2cMutex );
+ g_initI2CMutex = false;
+ }
+
// Check for Master Sentinel chip
if( TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL == i_target )
{
@@ -118,51 +143,89 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType,
// TODO - Locking needs to be implemented for each engine on each
// possible chip. The details of this still need to be worked out.
// This will be implemented with the bad machine path story (3629).
-
- if( i_opType == DeviceFW::READ )
+ // TODO - Locking will be waiting on Story 4158 to see how we can
+ // handle the mutexes in the attributes... Use the global mutex
+ // until then.
+ mutex_lock( &g_i2cMutex );
+ for( int attempt = 0; attempt < I2C_COMMAND_ATTEMPTS; attempt++ )
{
- err = i2cRead( i_target,
- io_buffer,
- io_buflen,
- args );
-
if( err )
{
+ // Catch and commit the log here if we failed on first attempt.
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"Error Encountered, Attempt %d out of %d",
+ (attempt + 1), // Add 1 since we started counting at 0
+ I2C_COMMAND_ATTEMPTS );
+
+ errlCommit( err,
+ I2C_COMP_ID );
+
+ // Reset the I2C Master
+ err = i2cReset( i_target,
+ args );
+
+ if( err )
+ {
+ break;
+ }
+
+ // Sleep before trying again.
+ nanosleep( 0, I2C_RETRY_DELAY );
+ }
+
+ if( i_opType == DeviceFW::READ )
+ {
+ err = i2cRead( i_target,
+ io_buffer,
+ io_buflen,
+ args );
+ }
+ else if( i_opType == DeviceFW::WRITE )
+ {
+ err = i2cWrite( i_target,
+ io_buffer,
+ io_buflen,
+ args );
+ }
+ else
+ {
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"i2cPerformOp() - Unknown Operation Type!" );
+ uint64_t userdata2 = args.port;
+ userdata2 = (userdata2 << 16) | args.engine;
+ userdata2 = (userdata2 << 16) | args.devAddr;
+
+ /*@
+ * @errortype
+ * @reasoncode I2C_INVALID_OP_TYPE
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid I2C_PERFORM_OP
+ * @userdata1 i_opType
+ * @userdata2[0:15] <UNUSED>
+ * @userdata2[16:31] Master Port
+ * @userdata2[32:47] Master Engine
+ * @userdata2[48:63] Slave Device Address
+ * @devdesc Invalid Operation type.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ I2C_PERFORM_OP,
+ I2C_INVALID_OP_TYPE,
+ i_opType,
+ userdata2 );
+
break;
}
- }
- else if( i_opType == DeviceFW::WRITE )
- {
- err = i2cWrite( i_target,
- io_buffer,
- io_buflen,
- args );
- if( err )
+ // If no errors, break here
+ if( NULL == err )
{
break;
}
}
- else
- {
- TRACFCOMP( g_trac_i2c,
- ERR_MRK"i2cPerformOp() - Unknown Operation Type!" );
-
- /*@
- * @errortype
- * @reasoncode I2C_INVALID_OP_TYPE
- * @severity ERRL_SEV_UNRECOVERABLE
- * @moduleid I2C_PERFORM_OP
- * @userdata1 i_opType
- * @userdata2 addr
- * @devdesc Invalid Operation type.
- */
- err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- I2C_PERFORM_OP,
- I2C_INVALID_OP_TYPE,
- i_opType,
- args.addr );
+ mutex_unlock( &g_i2cMutex );
+ if( err )
+ {
break;
}
} while( 0 );
@@ -186,16 +249,15 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
size_t size = sizeof(uint64_t);
uint64_t bytesRead = 0x0;
- uint64_t addr = i_args.addr;
uint64_t engine = i_args.engine;
uint64_t devAddr = i_args.devAddr;
+ uint64_t port = i_args.port;
// TODO - hardcoded to 400KHz for now
uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ );
uint64_t timeoutCount = I2C_TIMEOUT_COUNT( interval );
// Define the regs we'll be using
- cmdreg cmd;
statusreg status;
fiforeg fifo;
@@ -203,17 +265,16 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
ENTER_MRK"i2cRead()" );
TRACSCOMP( g_trac_i2cr,
- "I2C READ START : engine %.2X : devAddr %.2X : addr %.4X : len %d",
- engine, devAddr, addr, i_buflen );
+ "I2C READ START : engine %.2X : port %.2X : devAddr %.2X : len %d",
+ engine, port, devAddr, i_buflen );
do
{
// Do Command/Mode reg setups.
- size_t tmpSize = 0;
err = i2cSetup( i_target,
- tmpSize, // First length is always 0 for reads (byte addr)
- false, // RnW, false to do initial setup of byte addr
- false,
+ i_buflen,
+ true,
+ true,
i_args );
if( err )
@@ -221,43 +282,6 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
break;
}
- // Write the 2byte address to the FIFO
- err = i2cWriteByteAddr( i_target,
- i_args );
-
- if( err )
- {
- break;
- }
-
- // Wait for cmd complete before continuing
- err = i2cWaitForCmdComp( i_target,
- engine );
-
- if( err )
- {
- break;
- }
-
- // Setup the Command register to start the read operation
- cmd.value = 0x0ull;
- cmd.with_start = 1;
- cmd.with_stop = 1;
- cmd.with_addr = 1;
- cmd.device_addr = devAddr;
- cmd.read_not_write = 1; // Now doing a read
- cmd.length_b = i_buflen;
-
- err = deviceWrite( i_target,
- &cmd.value,
- size,
- DEVICE_SCOM_ADDRESS( masterAddrs[engine].command ) );
-
- if( err )
- {
- break;
- }
-
for( bytesRead = 0; bytesRead < i_buflen; bytesRead++ )
{
TRACDCOMP( g_trac_i2c,
@@ -267,7 +291,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
// Read the status reg to see if there is data in the FIFO
status.value = 0x0ull;
err = i2cReadStatusReg( i_target,
- engine,
+ i_args,
status );
if( err )
@@ -281,7 +305,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
status.value = 0x0ull;
err = i2cReadStatusReg( i_target,
- engine,
+ i_args,
status );
if( err )
@@ -294,20 +318,27 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
TRACFCOMP( g_trac_i2c,
ERR_MRK"i2cRead() - Timed out waiting for data in FIFO!" );
+ uint64_t userdata2 = i_args.port;
+ userdata2 = (userdata2 << 16) | engine;
+ userdata2 = (userdata2 << 16) | devAddr;
+
/*@
* @errortype
- * @reasoncode I2C_FIFO_TIMEOUT
- * @severity ERRL_SEV_UNRECOVERABLE
- * @moduleid I2C_READ
- * @userdata1 Status Register Value
- * @userdata2 Byte Address of write
- * @devdesc Timed out waiting for data in FIFO to read
+ * @reasoncode I2C_FIFO_TIMEOUT
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid I2C_READ
+ * @userdata1 Status Register Value
+ * @userdata2[0:15] <UNUSED>
+ * @userdata2[16:31] Master Port
+ * @userdata2[32:47] Master Engine
+ * @userdata2[48:63] Slave Device Address
+ * @devdesc Timed out waiting for data in FIFO to read
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
I2C_READ,
I2C_FIFO_TIMEOUT,
status.value,
- addr );
+ userdata2 );
break;
}
@@ -333,11 +364,8 @@ 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 : addr %.4X : "
- // TODO - when trace parameter limit is lifted, add byte count back in
-// "byte %d : %.2X",
- "%.2X",
- engine, devAddr, addr, /*bytesRead,*/ fifo.byte_0 );
+ "I2C READ DATA : engine %.2X : devAddr %.2X : byte %d : %.2X",
+ engine, devAddr, bytesRead, fifo.byte_0 );
}
if( err )
@@ -347,7 +375,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
// Poll for Command Complete
err = i2cWaitForCmdComp( i_target,
- engine );
+ i_args );
if( err )
{
@@ -356,8 +384,8 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target,
} while( 0 );
TRACSCOMP( g_trac_i2cr,
- "I2C READ END : engine %.2X : devAddr %.2X : addr %.4X : len %d",
- engine, devAddr, addr, i_buflen );
+ "I2C READ END : engine %.2X : port %.2x : devAddr %.2X : len %d",
+ engine, port, devAddr, i_buflen );
TRACDCOMP( g_trac_i2c,
EXIT_MRK"i2cRead()" );
@@ -377,9 +405,9 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
size_t size = sizeof(uint64_t);
uint64_t bytesWritten = 0x0;
- uint64_t addr = i_args.addr;
uint64_t engine = i_args.engine;
uint64_t devAddr = i_args.devAddr;
+ uint64_t port = i_args.port;
// Define regs we'll be using
fiforeg fifo;
@@ -388,8 +416,8 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
ENTER_MRK"i2cWrite()" );
TRACSCOMP( g_trac_i2cr,
- "I2C WRITE START : engine %.2X : devAddr %.2X : addr %.4X : len %d",
- engine, devAddr, addr, io_buflen );
+ "I2C WRITE START : engine %.2X : port %.2X : devAddr %.2X : len %d",
+ engine, port, devAddr, io_buflen );
do
{
@@ -405,15 +433,6 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
break;
}
- // Write the 2 byte address to the FIFO
- err = i2cWriteByteAddr( i_target,
- i_args );
-
- if( err )
- {
- break;
- }
-
for( bytesWritten = 0x0; bytesWritten < io_buflen; bytesWritten++ )
{
// Wait for FIFO space to be available for the write
@@ -440,11 +459,8 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
}
TRACSCOMP( g_trac_i2cr,
- "I2C WRITE DATA : engine %.2X : devAddr %.2X : addr %.4X : "
- // TODO - Once trace paramenter limit is lifted add byte count in
- "%.2X",
-// "byte %d : %.2X",
- engine, devAddr, addr, /*bytesWritten,*/ fifo.byte_0 );
+ "I2C WRITE DATA : engine %.2X : devAddr %.2X : byte %d : %.2X",
+ engine, devAddr, bytesWritten, fifo.byte_0 );
}
if( err )
@@ -454,7 +470,7 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
// Check for Command complete, and make sure no errors
err = i2cWaitForCmdComp( i_target,
- engine );
+ i_args );
if( err )
{
@@ -466,8 +482,8 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target,
} while( 0 );
TRACSCOMP( g_trac_i2cr,
- "I2C WRITE END : engine %.2X : devAddr %.2X : addr %.4X : len %d",
- engine, devAddr, addr, io_buflen );
+ "I2C WRITE END : engine %.2X: port %.2X : devAddr %.2X : len %d",
+ engine, port, devAddr, io_buflen );
TRACDCOMP( g_trac_i2c,
EXIT_MRK"i2cWrite()" );
@@ -506,7 +522,7 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
// Wait for Command complete before we start
status.value = 0x0ull;
err = i2cWaitForCmdComp( i_target,
- engine );
+ i_args );
if( err )
{
@@ -518,7 +534,7 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
// - port number
mode.value = 0x0ull;
- // Hard code to 400KHz until we get attributes in place to get this from
+ // TODO - 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;
@@ -544,10 +560,7 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
cmd.with_addr = 1;
cmd.device_addr = devAddr;
cmd.read_not_write = (i_readNotWrite ? 1 : 0);
-
- // Need to accomodate the byte addr length when writing
- // to the FIFO, so add 2 bytes to the length.
- cmd.length_b = i_buflen + 2;
+ cmd.length_b = i_buflen;
err = deviceWrite( i_target,
&cmd.value,
@@ -570,9 +583,10 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
// i2cWaitForCmdComp
// ------------------------------------------------------------------
errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
- uint64_t i_engine )
+ input_args_t i_args )
{
errlHndl_t err = NULL;
+ uint64_t engine = i_args.engine;
TRACDCOMP( g_trac_i2c,
ENTER_MRK"i2cWaitForCmdComp()" );
@@ -592,7 +606,7 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
nanosleep( 0, (interval * 1000) );
status.value = 0x0ull;
err = i2cReadStatusReg( i_target,
- i_engine,
+ i_args,
status );
if( err )
@@ -618,7 +632,7 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
I2C_WAIT_FOR_CMD_COMP,
I2C_CMD_COMP_TIMEOUT,
status.value,
- i_engine );
+ engine );
break;
}
@@ -640,11 +654,12 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
// i2cReadStatusReg
// ------------------------------------------------------------------
errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target,
- uint64_t i_engine,
+ input_args_t i_args,
statusreg & o_statusReg )
{
errlHndl_t err = NULL;
size_t size = sizeof(uint64_t);
+ uint64_t engine = i_args.engine;
TRACDCOMP( g_trac_i2c,
ENTER_MRK"i2cReadStatusReg()" );
@@ -655,7 +670,7 @@ errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target,
err = deviceRead( i_target,
&o_statusReg.value,
size,
- DEVICE_SCOM_ADDRESS( masterAddrs[i_engine].status ) );
+ DEVICE_SCOM_ADDRESS( masterAddrs[engine].status ) );
if( err )
{
@@ -666,6 +681,7 @@ errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target,
// Per the specification it is a requirement to check for errors each time
// that the status register is read.
err = i2cCheckForErrors( i_target,
+ i_args,
o_statusReg );
if( err )
@@ -684,10 +700,12 @@ errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target,
// i2cCheckForErrors
// ------------------------------------------------------------------
errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
+ input_args_t i_args,
statusreg i_statusVal )
{
errlHndl_t err = NULL;
- i2cReasonCode reasonCode = I2C_INVALID_REASONCODE;
+ bool errorFound = false;
+ uint64_t intRegVal = 0x0;
TRACDCOMP( g_trac_i2c,
ENTER_MRK"i2cCheckForErrors()" );
@@ -696,67 +714,112 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
{
if( 1 == i_statusVal.invalid_cmd )
{
- reasonCode = I2C_INVALID_COMMAND;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C Invalid Command! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.lbus_parity_error )
+
+ if( 1 == i_statusVal.lbus_parity_error )
{
- reasonCode = I2C_LBUS_PARITY_ERROR;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C Local Bus Parity Error! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.backend_overrun_error )
+
+ if( 1 == i_statusVal.backend_overrun_error )
{
- reasonCode = I2C_BACKEND_OVERRUN_ERROR;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C BackEnd OverRun Error! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.backend_access_error )
+
+ if( 1 == i_statusVal.backend_access_error )
{
- reasonCode = I2C_BACKEND_ACCESS_ERROR;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C BackEnd Access Error! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.arbitration_lost_error )
+
+ if( 1 == i_statusVal.arbitration_lost_error )
{
- reasonCode = I2C_ARBITRATION_LOST_ERROR;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C Arbitration Lost! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.nack_received )
+
+ if( 1 == i_statusVal.nack_received )
{
- reasonCode = I2C_NACK_RECEIVED;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C NACK Received! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.data_request )
+
+ if( 1 == i_statusVal.data_request )
{
- reasonCode = I2C_DATA_REQUEST;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C Data Request Error! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.stop_error )
+
+ if( 1 == i_statusVal.stop_error )
{
- reasonCode = I2C_STOP_ERROR;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C STOP Error! - status reg: %016llx",
+ i_statusVal.value );
}
- else if( 1 == i_statusVal.any_i2c_interrupt )
+
+ if( 1 == i_statusVal.any_i2c_interrupt )
{
- // TODO - This will be expanded during bad machine path to specify
- // which interrupts have fired.
- reasonCode = I2C_INTERRUPT;
+ errorFound = true;
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C Interrupt Detected! - status reg: %016llx",
+ i_statusVal.value );
+
+ // Get the Interrupt Register value to add to the log
+ err = i2cGetInterrupts( i_target,
+ i_args,
+ intRegVal );
+
+ if( err )
+ {
+ break;
+ }
}
- if( I2C_INVALID_REASONCODE != reasonCode )
+ if( errorFound )
{
TRACFCOMP( g_trac_i2c,
- ERR_MRK"i2cCheckForErrors() - Error found after command complete!" );
+ ERR_MRK"i2cCheckForErrors() - Error(s) found after command complete!" );
/*@
* @errortype
* @reasoncode I2C_HW_ERROR_FOUND
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid I2C_CHECK_FOR_ERRORS
- * @userdata1 Reasoncode
- * @userdata2 <UNUSED>
+ * @userdata1 Status Register Value
+ * @userdata2 Interrupt Register Value (only valid in Interrupt case)
* @devdesc Error was found in I2C status register. Check userdata1
* to determine what the error was.
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
I2C_CHECK_FOR_ERRORS,
I2C_HW_ERROR_FOUND,
- reasonCode,
- 0x0 );
+ 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.
+
break;
}
} while( 0 );
@@ -767,72 +830,6 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
return err;
} // end i2cCheckForErrors
-// ------------------------------------------------------------------
-// i2cWriteByteAddr
-// ------------------------------------------------------------------
-errlHndl_t i2cWriteByteAddr ( TARGETING::Target * i_target,
- input_args_t i_args )
-{
- errlHndl_t err = NULL;
- size_t size = sizeof(uint64_t);
-
- uint64_t engine = i_args.engine;
- uint64_t addr = i_args.addr;
-
- // Define the reg(s) we'll be accessing
- fiforeg fifo;
-
- TRACDCOMP( g_trac_i2c,
- ENTER_MRK"i2cWriteByteAddr( %04x )",
- addr );
-
- do
- {
- // Make sure there is space in the FIFO
- err = i2cWaitForFifoSpace( i_target,
- i_args );
-
- if( err )
- {
- break;
- }
-
- // Write first byte of address to the FIFO
- fifo.value = 0x0ull;
- fifo.byte_0 = ((addr & 0xFF00) >> 8);
-
- err = deviceWrite( i_target,
- &fifo.value,
- size,
- DEVICE_SCOM_ADDRESS( masterAddrs[engine].fifo ) );
-
- if( err )
- {
- break;
- }
-
- // Write 2nd byte of address to the FIFO
- fifo.value = 0x0ull;
- fifo.byte_0 = (addr & 0xFF);
-
- err = deviceWrite( i_target,
- &fifo.value,
- size,
- DEVICE_SCOM_ADDRESS( masterAddrs[engine].fifo ) );
-
- if( err )
- {
- break;
- }
- } while( 0 );
-
- TRACDCOMP( g_trac_i2c,
- EXIT_MRK"i2cWriteByteAddr( %04x )",
- addr );
-
- return err;
-} // end i2cWriteByteAddr
-
// ------------------------------------------------------------------
// i2cWaitForFifoSpace
@@ -841,8 +838,6 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
input_args_t i_args )
{
errlHndl_t err = NULL;
- uint64_t engine = i_args.engine;
- uint64_t addr = i_args.addr;
// TODO - hardcoded to 400KHz for now
uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ );
@@ -859,7 +854,7 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
// Read Status reg to get available FIFO bytes
status.value = 0x0ull;
err = i2cReadStatusReg( i_target,
- engine,
+ i_args,
status );
if( err )
@@ -874,7 +869,7 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
status.value = 0x0ull;
err = i2cReadStatusReg( i_target,
- engine,
+ i_args,
status );
if( err )
@@ -893,14 +888,14 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid I2C_WRITE
* @userdata1 Status Register Value
- * @userdata2 Requested Byte Address
+ * @userdata2 <UNUSED>
* @devdesc Timed out waiting for space to write into FIFO.
*/
err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
I2C_WRITE,
I2C_FIFO_TIMEOUT,
status.value,
- addr );
+ 0x0 );
break;
}
@@ -918,4 +913,164 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
return err;
} // end i2cWaitForFifoSpace
+
+// ------------------------------------------------------------------
+// i2cReset
+// ------------------------------------------------------------------
+errlHndl_t i2cReset ( TARGETING::Target * i_target,
+ input_args_t i_args )
+{
+ errlHndl_t err = NULL;
+ size_t size = sizeof(uint64_t);
+
+ // Get Args
+ uint64_t engine = i_args.engine;
+
+ TRACDCOMP( g_trac_i2c,
+ ENTER_MRK"i2cReset()" );
+
+ // Writing to the Status Register does a full I2C reset.
+ statusreg reset;
+
+ do
+ {
+ reset.value = 0x0;
+ err = deviceWrite( i_target,
+ &reset.value,
+ size,
+ DEVICE_SCOM_ADDRESS( masterAddrs[engine].reset ) );
+
+ if( err )
+ {
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"I2C Reset Failed!!" );
+ break;
+ }
+
+ // Part of doing the I2C Master reset is also sending a stop
+ // command to the slave device.
+ err = i2cSendSlaveStop( i_target,
+ i_args );
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ TRACDCOMP( g_trac_i2c,
+ EXIT_MRK"i2cReset()" );
+
+ return err;
+} // end i2cReset
+
+
+// ------------------------------------------------------------------
+// i2cSendSlaveStop
+// ------------------------------------------------------------------
+errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
+ input_args_t i_args )
+{
+ errlHndl_t err = NULL;
+ size_t size = sizeof(uint64_t);
+ uint64_t engine = i_args.engine;
+ uint64_t port = i_args.port;
+
+ // Master Registers
+ modereg mode;
+ cmdreg cmd;
+
+ TRACDCOMP( g_trac_i2c,
+ ENTER_MRK"i2cSendSlaveStop()" );
+
+ do
+ {
+ mode.value = 0x0ull;
+ // TODO - 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;
+
+ err = deviceWrite( i_target,
+ &mode.value,
+ size,
+ DEVICE_SCOM_ADDRESS( masterAddrs[engine].mode ) );
+
+ if( err )
+ {
+ break;
+ }
+
+ cmd.value = 0x0ull;
+ cmd.with_stop = 1;
+
+ err = deviceWrite( i_target,
+ &cmd.value,
+ size,
+ DEVICE_SCOM_ADDRESS( masterAddrs[engine].command ) );
+
+ if( err )
+ {
+ break;
+ }
+
+ // Now wait for cmd Complete
+ err = i2cWaitForCmdComp( i_target,
+ i_args );
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ TRACDCOMP( g_trac_i2c,
+ EXIT_MRK"i2cSendSlaveStop()" );
+
+ return err;
+} // end i2cSendSlaveStop
+
+
+// ------------------------------------------------------------------
+// i2cGetInterrupts
+// ------------------------------------------------------------------
+errlHndl_t i2cGetInterrupts ( TARGETING::Target * i_target,
+ input_args_t i_args,
+ uint64_t & o_intRegValue )
+{
+ errlHndl_t err = NULL;
+ size_t size = sizeof(uint64_t);
+ uint64_t engine = i_args.engine;
+
+ // Master Regs
+ interruptreg intreg;
+
+ TRACDCOMP( g_trac_i2c,
+ ENTER_MRK"i2cGetInterrupts()" );
+
+ do
+ {
+ intreg.value = 0x0;
+ err = deviceRead( i_target,
+ &intreg.value,
+ size,
+ DEVICE_SCOM_ADDRESS( masterAddrs[engine].interrupt ) );
+
+ if( err )
+ {
+ break;
+ }
+
+ // Return the data read
+ o_intRegValue = intreg.value;
+ } while( 0 );
+
+ TRACDCOMP( g_trac_i2c,
+ EXIT_MRK"i2cGetInterrupts( int reg val: %016llx)",
+ o_intRegValue );
+
+ return err;
+} // end i2cGetInterrupts
+
} // end namespace I2C
OpenPOWER on IntegriCloud