summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/devicefw/driverif.H19
-rw-r--r--src/include/usr/hbotcompid.H8
-rw-r--r--src/include/usr/i2c/eepromddreasoncodes.H77
-rw-r--r--src/include/usr/i2c/i2creasoncodes.H19
-rw-r--r--src/include/usr/initservice/initsvcreasoncodes.H1
-rw-r--r--src/makefile2
-rwxr-xr-xsrc/usr/errl/parser/scanforsrcs.pl29
-rwxr-xr-xsrc/usr/i2c/eepromdd.C662
-rwxr-xr-xsrc/usr/i2c/eepromdd.H208
-rwxr-xr-xsrc/usr/i2c/i2c.C607
-rwxr-xr-xsrc/usr/i2c/i2c.H95
-rw-r--r--src/usr/i2c/makefile2
-rwxr-xr-xsrc/usr/i2c/test/eepromddtest.H278
-rwxr-xr-xsrc/usr/i2c/test/i2ctest.H325
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H42
-rw-r--r--src/usr/targeting/targetservice.C13
-rw-r--r--src/usr/targeting/xmltohb/attribute_types.xml106
-rw-r--r--src/usr/targeting/xmltohb/simics_SALERNO.system.xml21
-rw-r--r--src/usr/targeting/xmltohb/simics_VENICE.system.xml18
-rw-r--r--src/usr/targeting/xmltohb/target_types.xml89
20 files changed, 2189 insertions, 432 deletions
diff --git a/src/include/usr/devicefw/driverif.H b/src/include/usr/devicefw/driverif.H
index 0c5f874b6..939190459 100644
--- a/src/include/usr/devicefw/driverif.H
+++ b/src/include/usr/devicefw/driverif.H
@@ -46,6 +46,7 @@ namespace DeviceFW
XSCOM = LAST_ACCESS_TYPE,
I2C,
FSISCOM,
+ EEPROM,
LAST_DRIVER_ACCESS_TYPE
};
@@ -85,17 +86,23 @@ namespace DeviceFW
/**
* Construct the device addressing parameters for the I2C device ops.
- * @param[in] i_address - I2C address to access on slave device.
* @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.
*/
- #define DEVICE_I2C_ADDRESS( i_address, i_port, i_engine, i_devAddr )\
- DeviceFW::I2C, static_cast<uint64_t>(( i_address )),\
- static_cast<uint64_t>(( i_port )),\
- static_cast<uint64_t>(( i_engine )),\
- static_cast<uint64_t>(( i_devAddr ))
+ #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 ))
+ /**
+ * Construct the device addressing parameters for the EEPROM device ops.
+ * @param[in] i_address - The address of the I2C slave device.
+ * @param[in] i_chip - The chip number of the EEPROM to access.
+ */
+ #define DEVICE_EEPROM_ADDRESS( i_address, i_chip )\
+ DeviceFW::EEPROM, static_cast<uint64_t>(( i_address )),\
+ static_cast<uint64_t>(( i_chip ))
/** @class InvalidParameterType
* @brief Unused type to cause compiler fails for invalid template types.
diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H
index bc742e230..48d6c71c5 100644
--- a/src/include/usr/hbotcompid.H
+++ b/src/include/usr/hbotcompid.H
@@ -164,6 +164,14 @@ const compId_t FSISCOM_COMP_ID = 0x0D00;
const char FSISCOM_COMP_NAME[] = "fsiscom";
//@}
+/** @name EEPROM
+ * EEPROM device driver component
+ */
+//@{
+const compId_t EEPROM_COMP_ID = 0x0E00;
+const char EEPROM_COMP_NAME[] = "eeprom";
+//@}
+
// ----------------------------------------------------------
// CXXTEST Unit Test, reserve compid near the end...
/** @name CXXTEST
diff --git a/src/include/usr/i2c/eepromddreasoncodes.H b/src/include/usr/i2c/eepromddreasoncodes.H
new file mode 100644
index 000000000..092f0c5bc
--- /dev/null
+++ b/src/include/usr/i2c/eepromddreasoncodes.H
@@ -0,0 +1,77 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/i2c/eepromddreasoncodes.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
+/**
+ * @file eepromddreasoncodes.H
+ *
+ * @brief Reason codes and module ids for the EEPROM device driver
+ *
+ */
+#ifndef __EEPROMDDREASONCODES_H
+#define __EEPROMDDREASONCODES_H
+// -----------------------------------------------
+// Includes
+// -----------------------------------------------
+#include <hbotcompid.H>
+
+namespace EEPROM
+{
+
+/**
+* @enum eepromModuleid
+*
+* @brief Module Ids used in created errorlogs. Indicates which
+* functions an error log was created in.
+*
+*/
+enum eepromModuleId
+{
+ EEPROM_INVALID_MODULE = 0x00, // Invalid Module Id
+ EEPROM_PERFORM_OP = 0x01,
+ EEPROM_READ = 0x02,
+ EEPROM_WRITE = 0x03,
+ EEPROM_PREPAREADDRESS = 0x04,
+ EEPROM_READATTRIBUTES = 0x05,
+ EEPROM_GETI2CMASTERTARGET = 0x06,
+};
+
+/**
+ * @enum eepromReasonCode
+ *
+ * @brief Reasoncodes used to describe what errors are being indicated.
+ *
+ */
+enum eepromReasonCode
+{
+ EEPROM_INVALID_REASONCODE = EEPROM_COMP_ID | 0x00, // Invalid Reasoncode
+ EEPROM_INVALID_OPERATION = EEPROM_COMP_ID | 0x01,
+ EEPROM_INVALID_DEVICE_TYPE = EEPROM_COMP_ID | 0x02,
+ EEPROM_ADDR_INFO0_NOT_FOUND = EEPROM_COMP_ID | 0x03,
+ EEPROM_ADDR_INFO1_NOT_FOUND = EEPROM_COMP_ID | 0x04,
+ EEPROM_INVALID_CHIP = EEPROM_COMP_ID | 0x05,
+ EEPROM_DIMM_I2C_MASTER_PATH_ERROR = EEPROM_COMP_ID | 0x06,
+ EEPROM_TARGET_NULL = EEPROM_COMP_ID | 0x07,
+};
+
+}; // end EEPROM
+
+#endif
diff --git a/src/include/usr/i2c/i2creasoncodes.H b/src/include/usr/i2c/i2creasoncodes.H
index 52b65770e..ce2af7327 100644
--- a/src/include/usr/i2c/i2creasoncodes.H
+++ b/src/include/usr/i2c/i2creasoncodes.H
@@ -66,20 +66,11 @@ enum i2cReasonCode
I2C_INVALID_REASONCODE = I2C_COMP_ID | 0x00, // Invalid Reasoncode
I2C_INVALID_DATA_BUFFER = I2C_COMP_ID | 0x01, // Invalid Data Buffer pointer
I2C_INVALID_OP_TYPE = I2C_COMP_ID | 0x02, // Invalid Operation type
- I2C_INVALID_COMMAND = I2C_COMP_ID | 0x03, // Invalid Command Status
- I2C_LBUS_PARITY_ERROR = I2C_COMP_ID | 0x04, // Local Bus Parity Error
- I2C_BACKEND_OVERRUN_ERROR = I2C_COMP_ID | 0x05, // Backend overrun Error
- I2C_BACKEND_ACCESS_ERROR = I2C_COMP_ID | 0x06, // Backend access Error
- I2C_ARBITRATION_LOST_ERROR = I2C_COMP_ID | 0x07, // Arbitration lost
- I2C_NACK_RECEIVED = I2C_COMP_ID | 0x08, // NACK Received
- I2C_DATA_REQUEST = I2C_COMP_ID | 0x09, // Data Request
- I2C_STOP_ERROR = I2C_COMP_ID | 0x0A, // Stop Error
- I2C_INTERRUPT = I2C_COMP_ID | 0x0B, // Interrupt Present - TODO - more to be added when bad machine path code is added.
- I2C_FIFO_TIMEOUT = I2C_COMP_ID | 0x0C, // Timed out waiting on FIFO
- I2C_BUS_NOT_READY = I2C_COMP_ID | 0x0D, // Bus Not ready
- I2C_CMD_COMP_TIMEOUT = I2C_COMP_ID | 0x0E, // Timeout waiting for Cmd Complete
- I2C_HW_ERROR_FOUND = I2C_COMP_ID | 0x0F, // Error found in Status register
- I2C_MASTER_SENTINEL_TARGET = I2C_COMP_ID | 0x10, // Master Sentinel used as target
+ I2C_FIFO_TIMEOUT = I2C_COMP_ID | 0x03, // Timed out waiting on FIFO
+ I2C_BUS_NOT_READY = I2C_COMP_ID | 0x04, // Bus Not ready
+ I2C_CMD_COMP_TIMEOUT = I2C_COMP_ID | 0x05, // Timeout waiting for Cmd Complete
+ I2C_HW_ERROR_FOUND = I2C_COMP_ID | 0x06, // Error found in Status register
+ I2C_MASTER_SENTINEL_TARGET = I2C_COMP_ID | 0x07, // Master Sentinel used as target
};
}; // end I2C
diff --git a/src/include/usr/initservice/initsvcreasoncodes.H b/src/include/usr/initservice/initsvcreasoncodes.H
index d3ccc37fb..2f61cd460 100644
--- a/src/include/usr/initservice/initsvcreasoncodes.H
+++ b/src/include/usr/initservice/initsvcreasoncodes.H
@@ -62,6 +62,7 @@ enum InitServiceModuleID
START_FSIDD_ERRL_ID = 0x16,
START_FSISCOM_ERRL_ID = 0x17,
START_TARGETING_ERRL_ID = 0x18,
+ START_I2C_ERRL_ID = 0x19,
// Internal InitService codes
diff --git a/src/makefile b/src/makefile
index 322496a98..28e426357 100644
--- a/src/makefile
+++ b/src/makefile
@@ -45,7 +45,7 @@ DIRECT_BOOT_OBJECTS = start.o kernel.o taskmgr.o cpumgr.o syscall.o \
RUNTIME_OBJECTS =
BASE_MODULES = trace errl devicefw scom xscom initservice taskargs \
- pnor i2c vfs
+ pnor vfs i2c
EXTENDED_MODULES = targeting ecmddatabuffer fapi hwp plat \
extinitsvc istepdisp hwas fsi fsiscom
diff --git a/src/usr/errl/parser/scanforsrcs.pl b/src/usr/errl/parser/scanforsrcs.pl
index c54df9fb1..d6d594a18 100755
--- a/src/usr/errl/parser/scanforsrcs.pl
+++ b/src/usr/errl/parser/scanforsrcs.pl
@@ -373,7 +373,6 @@ sub getFiles
opendir(DH, $l_input_dir) or die("Cannot open $l_input_dir: $!");
# skip the dots
@dir_entry = grep { !/^\./ } readdir(DH);
- #@dir_entry = readdir(DH);
closedir(DH);
while (@dir_entry)
{
@@ -382,12 +381,6 @@ sub getFiles
debugMsg( "getFiles: Full Path: $full_path" );
-# if ($full_path =~ /\/$comp\/test/g) # skip the test dirs
-# {
-# debugMsg( "Found test dir - next!!" );
-# next;
-# }
-# elsif ($l_entry =~ /\.[H|C]$/)
if ($l_entry =~ /\.[H|C]$/)
{
$l_input_files{$l_entry} = $full_path;
@@ -466,18 +459,6 @@ sub includeReasonCodes
{
debugMsg( "includeReasonCodes file: $file" );
my @allDirs = split( '/', $file );
-# $tmpParent = pop @allDirs;
-
-# if( $parentDir ne "" )
-# {
-# $parentDir = $parentDir."/$tmpParent";
-# }
-# else
-# {
-# $parentDir = $tmpParent;
-# }
-# debugMsg( "includeReasonCodes parent dir: $parentDir" );
-# debugMsg( "includeReasonCodes tmpparent: $tmpParent" );
if( $file =~ m/reasoncodes/i )
{
@@ -498,10 +479,13 @@ sub includeReasonCodes
debugMsg( "Include string: $incFileName" );
print $fh "#include <$incFileName>\n";
-# print $fh "#include <$parentDir>\n";
# Find the namespace of the reason codes
- findNameSpace( $file )
+ findNameSpace( $file );
+
+ # Clear out incFileName, in case there are 2 reason code files
+ # in the same directory
+ $incFileName = "";
}
elsif( -d $file )
{
@@ -509,9 +493,6 @@ sub includeReasonCodes
# Recursion is done here.
includeReasonCodes( $fh, $file."/*", ($level+1) );
}
-
-# $parentDir = "";
-# $tmpParent = "";
}
}
diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C
new file mode 100755
index 000000000..e57647d27
--- /dev/null
+++ b/src/usr/i2c/eepromdd.C
@@ -0,0 +1,662 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/i2c/eepromdd.C $
+//
+// 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
+/**
+ * @file eepromdd.C
+ *
+ * @brief Implementation of the EEPROM device driver,
+ * which will access various EEPROMs within the
+ * system via the I2C device driver
+ *
+ */
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <string.h>
+#include <sys/time.h>
+
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <targeting/targetservice.H>
+#include <devicefw/driverif.H>
+#include <i2c/eepromddreasoncodes.H>
+
+#include "eepromdd.H"
+// ----------------------------------------------
+// Globals
+// ----------------------------------------------
+mutex_t g_eepromMutex;
+bool g_initEepromMutex = true;
+
+// ----------------------------------------------
+// Trace definitions
+// ----------------------------------------------
+trace_desc_t* g_trac_eeprom = NULL;
+TRAC_INIT( & g_trac_eeprom, "EEPROM", 4096 );
+
+trace_desc_t* g_trac_eepromr = NULL;
+TRAC_INIT( & g_trac_eepromr, "EEPROMR", 4096 );
+
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+// ----------------------------------------------
+// Defines
+// ----------------------------------------------
+#define MAX_BYTE_ADDR 2
+// ----------------------------------------------
+
+namespace EEPROM
+{
+
+// Register the perform Op with the routing code for Procs.
+DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD,
+ DeviceFW::EEPROM,
+ TARGETING::TYPE_PROC,
+ eepromPerformOp );
+
+// Register the perform Op with the routing code for DIMMs.
+DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD,
+ DeviceFW::EEPROM,
+ TARGETING::TYPE_DIMM,
+ eepromPerformOp );
+
+// Register the perform Op with the routing code for Memory Buffers.
+DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD,
+ DeviceFW::EEPROM,
+ TARGETING::TYPE_MEMBUF,
+ eepromPerformOp );
+
+// ------------------------------------------------------------------
+// eepromPerformOp
+// ------------------------------------------------------------------
+errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ int64_t i_accessType,
+ va_list i_args )
+{
+ errlHndl_t err = NULL;
+ TARGETING::Target * theTarget = NULL;
+ 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 );
+
+ TRACDCOMP( g_trac_eeprom,
+ ENTER_MRK"eepromPerformOp()" );
+
+ do
+ {
+ if( g_initEepromMutex )
+ {
+ mutex_init( &g_eepromMutex );
+ g_initEepromMutex = false;
+ }
+
+ // Read Attributes needed to complete the operation
+ err = eepromReadAttributes( i_target,
+ i2cInfo );
+
+ if( err )
+ {
+ break;
+ }
+
+ // Check to see if we need to find a new target for
+ // the I2C Master
+ err = eepromGetI2CMasterTarget( i_target,
+ theTarget );
+
+ if( err )
+ {
+ break;
+ }
+
+ // Do the read or write
+ if( i_opType == DeviceFW::READ )
+ {
+ err = eepromRead( theTarget,
+ io_buffer,
+ io_buflen,
+ i2cInfo );
+
+ if( err )
+ {
+ break;
+ }
+ }
+ else if( i_opType == DeviceFW::WRITE )
+ {
+ err = eepromWrite( theTarget,
+ io_buffer,
+ io_buflen,
+ i2cInfo );
+
+ if( err )
+ {
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"Invalid EEPROM Operation!" );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_INVALID_OPERATION
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid EEPROM_PERFORM_OP
+ * @userdata1 Operation Type
+ * @userdata2 Chip to Access
+ * @devdesc Invalid Operation type.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_PERFORM_OP,
+ EEPROM_INVALID_OPERATION,
+ i_opType,
+ i2cInfo.chip );
+
+ break;
+ }
+ } while( 0 );
+
+ TRACDCOMP( g_trac_eeprom,
+ EXIT_MRK"eepromPerformOp() - %s",
+ ((NULL == err) ? "No Error" : "With Error") );
+
+ return err;
+} // end eepromPerformOp
+
+
+// ------------------------------------------------------------------
+// eepromRead
+// ------------------------------------------------------------------
+errlHndl_t eepromRead ( TARGETING::Target * i_target,
+ void * o_buffer,
+ size_t i_buflen,
+ eeprom_addr_t i_i2cInfo )
+{
+ errlHndl_t err = NULL;
+ uint8_t byteAddr[MAX_BYTE_ADDR];
+ size_t byteAddrSize = 0;
+ bool unlock = false;
+
+ TRACDCOMP( g_trac_eeprom,
+ ENTER_MRK"eepromRead()" );
+
+ do
+ {
+ TRACSCOMP( g_trac_eepromr,
+ "EEPROM READ START : Chip: %02d : Addr %.2X : Len %d",
+ i_i2cInfo.chip, i_i2cInfo.addr, i_buflen );
+
+ err = eepromPrepareAddress( &byteAddr,
+ byteAddrSize,
+ i_i2cInfo );
+
+ if( err )
+ {
+ break;
+ }
+
+ // Lock to sequence operations
+ mutex_lock( &g_eepromMutex );
+ unlock = true;
+
+ // 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,
+ i_target,
+ &byteAddr,
+ byteAddrSize,
+ DEVICE_I2C_ADDRESS( i_i2cInfo.port,
+ i_i2cInfo.engine,
+ i_i2cInfo.devAddr ) );
+
+ if( err )
+ {
+ 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 )
+ {
+ break;
+ }
+
+ mutex_unlock( &g_eepromMutex );
+ 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) );
+ } while( 0 );
+
+ // Catch it if we break out early.
+ if( unlock )
+ {
+ mutex_unlock( & g_eepromMutex );
+ }
+
+ TRACDCOMP( g_trac_eeprom,
+ EXIT_MRK"eepromRead()" );
+
+ return err;
+} // end eepromRead
+
+
+// ------------------------------------------------------------------
+// eepromWrite
+// ------------------------------------------------------------------
+errlHndl_t eepromWrite ( TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t io_buflen,
+ eeprom_addr_t i_i2cInfo )
+{
+ errlHndl_t err = NULL;
+ uint8_t byteAddr[MAX_BYTE_ADDR];
+ size_t byteAddrSize = 0;
+ uint8_t * newBuffer = NULL;
+ bool needFree = true;
+
+ TRACDCOMP( g_trac_eeprom,
+ ENTER_MRK"eepromWrite()" );
+
+ 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) );
+
+ err = eepromPrepareAddress( &byteAddr,
+ byteAddrSize,
+ i_i2cInfo );
+
+ if( err )
+ {
+ break;
+ }
+
+ size_t newBufLen = byteAddrSize + io_buflen;
+ newBuffer = static_cast<uint8_t*>(malloc( newBufLen ));
+ needFree = true;
+
+ TRACFCOMP( g_trac_eeprom,
+ "OPIET: byteAddrSize: %d, io_buflen: %d, newBufLen: %d",
+ byteAddrSize, io_buflen, newBufLen );
+
+ // 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 );
+
+ // Lock for operation sequencing
+ mutex_lock( &g_eepromMutex );
+
+ // 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 ) );
+
+ mutex_unlock( &g_eepromMutex );
+
+ if( err )
+ {
+ // Can't assume that anything was written if
+ // there was an error.
+ io_buflen = 0;
+ 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 );
+ } while( 0 );
+
+ // Free memory
+ if( needFree )
+ {
+ free( newBuffer );
+ }
+
+ TRACDCOMP( g_trac_eeprom,
+ EXIT_MRK"eepromWrite()" );
+
+ return err;
+} // end eepromWrite
+
+
+// ------------------------------------------------------------------
+// eepromPrepareAddress
+// ------------------------------------------------------------------
+errlHndl_t eepromPrepareAddress ( void * o_buffer,
+ size_t & o_bufSize,
+ eeprom_addr_t i_i2cInfo )
+{
+ errlHndl_t err = NULL;
+
+ o_bufSize = 0;
+
+ TRACDCOMP( g_trac_eeprom,
+ ENTER_MRK"eepromPrepareAddress()" );
+
+ do
+ {
+ // --------------------------------------------------------------------
+ // TODO - eventually there will be 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.
+ //
+ // Until we get a different device, we'll just code for the 2 examples
+ // that I know of now.
+ // --------------------------------------------------------------------
+ switch( i_i2cInfo.deviceType )
+ {
+ 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);
+ break;
+
+ case ONE_BYTE_ADDR:
+ o_bufSize = 1;
+ memset( o_buffer, 0x0, o_bufSize );
+ *((uint8_t*)o_buffer) = (i_i2cInfo.addr & 0xFFull);
+ break;
+
+ default:
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromPrepareAddress() - Invalid device type: %08x",
+ i_i2cInfo.deviceType );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_INVALID_DEVICE_TYPE
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid EEPROM_PREPAREADDRESS
+ * @userdata1 Device Type
+ * @userdata2 <UNUSED>
+ * @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 );
+
+ break;
+ };
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ TRACDCOMP( g_trac_eeprom,
+ EXIT_MRK"eepromPrepareAddress()" );
+
+ return err;
+} // end eepromPrepareAddress
+
+
+// ------------------------------------------------------------------
+// eepromReadAttributes
+// ------------------------------------------------------------------
+errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target,
+ eeprom_addr_t & o_i2cInfo )
+{
+ errlHndl_t err = NULL;
+
+ TRACDCOMP( g_trac_eeprom,
+ ENTER_MRK"eepromReadAttributes()" );
+
+ do
+ {
+ if( 0 == o_i2cInfo.chip )
+ {
+ // Read Attributes from EEPROM_ADDR_INFO0
+ TARGETING::EepromAddrInfo0 eepromData;
+ if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_ADDR_INFO0>( eepromData ) )
+ {
+ 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.deviceType = TWO_BYTE_ADDR;
+ }
+ else
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromReadAttributes() - ERROR reading attributes for "
+ "chip %d!",
+ o_i2cInfo.chip );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_ADDR_INFO0_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
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_READATTRIBUTES,
+ EEPROM_ADDR_INFO0_NOT_FOUND,
+ o_i2cInfo.chip,
+ TARGETING::ATTR_EEPROM_ADDR_INFO0 );
+
+ break;
+ }
+ }
+ else if( 1 == o_i2cInfo.chip )
+ {
+ // Read Attributes from EEPROM_ADDR_INFO1
+ TARGETING::EepromAddrInfo1 eepromData;
+ if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_ADDR_INFO1>( eepromData ) )
+ {
+ 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.deviceType = TWO_BYTE_ADDR;
+ }
+ else
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromReadAttributes() - ERROR reading attributes for "
+ "chip %d!",
+ o_i2cInfo.chip );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_ADDR_INFO1_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
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_READATTRIBUTES,
+ EEPROM_ADDR_INFO1_NOT_FOUND,
+ o_i2cInfo.chip,
+ TARGETING::ATTR_EEPROM_ADDR_INFO1 );
+
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromReadAttributes() - Invalid chip (%d) to read "
+ "attributes from!",
+ o_i2cInfo.chip );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_INVALID_CHIP
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid EEPROM_READATTRIBUTES
+ * @userdata1 EEPROM Chip
+ * @userdata2 <UNUSED>
+ * @devdesc Invalid EEPROM chip to access
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_READATTRIBUTES,
+ EEPROM_INVALID_CHIP,
+ o_i2cInfo.chip,
+ 0x0 );
+
+ break;
+ }
+ } while( 0 );
+
+ TRACDCOMP( g_trac_eeprom,
+ EXIT_MRK"eepromReadAttributes()" );
+
+ return err;
+} // end eepromReadAttributes
+
+
+// ------------------------------------------------------------------
+// eepromGetI2CMasterTarget
+// ------------------------------------------------------------------
+errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target,
+ TARGETING::Target * &o_target )
+{
+ errlHndl_t err = NULL;
+ o_target = NULL;
+
+ TRACDCOMP( g_trac_eeprom,
+ ENTER_MRK"eepromGetI2CMasterTarget()" );
+
+ do
+ {
+ if( TARGETING::TYPE_DIMM == i_target->getAttr<TARGETING::ATTR_TYPE>() )
+ {
+ 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>();
+
+ // check that the path exists
+ bool exists = false;
+ tS.exists( eepromData.i2cMasterPath,
+ exists );
+
+ if( !exists )
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromGetI2CMasterTarget() - i2cMasterPath attribute path "
+ "doesn't exist!" );
+
+ /*@
+ * @errortype
+ * @reasoncode EEPROM_DIMM_I2C_MASTER_PATH_ERROR
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid EEPROM_GETI2CMASTERTARGET
+ * @userdata1 Attribute Enum
+ * @userdata2 <UNUSED>
+ * @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 );
+
+ break;
+ }
+
+ // Since it exists, convert to a target
+ o_target = tS.toTarget( eepromData.i2cMasterPath );
+
+ if( NULL == o_target )
+ {
+ TRACFCOMP( g_trac_eeprom,
+ ERR_MRK"eepromGetI2CMasterTarget() - Parent Processor 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.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_GETI2CMASTERTARGET,
+ EEPROM_TARGET_NULL,
+ 0x0,
+ 0x0 );
+
+ break;
+ }
+ }
+ else
+ {
+ // Since current target is not a DIMM, use the target we have
+ o_target = i_target;
+ }
+ } while( 0 );
+
+ TRACDCOMP( g_trac_eeprom,
+ EXIT_MRK"eepromGetI2CMasterTarget()" );
+
+ return err;
+} // end eepromGetI2CMasterTarget
+
+} // end namespace EEPROM
diff --git a/src/usr/i2c/eepromdd.H b/src/usr/i2c/eepromdd.H
new file mode 100755
index 000000000..35ae315a7
--- /dev/null
+++ b/src/usr/i2c/eepromdd.H
@@ -0,0 +1,208 @@
+// 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
+#ifndef __EEPROM_H
+#define __EEPROM_H
+
+/**
+ * @file eepromdd.H
+ *
+ * @brief Provides the interfaces for accessing EEPROMs within
+ * the system via the I2C device driver.
+ */
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <errl/errltypes.H>
+
+namespace EEPROM
+{
+
+/**
+* @brief Enumerations to describe the type of devices to be accessed.
+*/
+typedef enum
+{
+ TWO_BYTE_ADDR,
+ ONE_BYTE_ADDR,
+ LAST_DEVICE_TYPE
+} eeprom_device_t;
+
+/**
+ * @brief Structure of common parameters needed by different parts of
+ * the code.
+ */
+typedef struct
+{
+ uint64_t port;
+ uint64_t engine;
+ uint64_t devAddr;
+ uint64_t addr;
+ int64_t chip;
+ eeprom_device_t deviceType;
+} eeprom_addr_t;
+
+/**
+*
+* @brief Perform an EEPROM access operation.
+*
+* @param[in] i_opType - Operation Type - See DeviceFW::OperationType in
+* driververif.H
+*
+* @param[in] i_target - Target device.
+*
+* @param[in/out] io_buffer
+* INPUT: Pointer to the data that will be written to the target
+* device.
+* OUTPUT: Pointer to the data that was read from the target device.
+*
+* @param[in/out] io_buflen
+* INPUT: Length of the buffer to be written to target device.
+* OUTPUT: Length of buffer that was written, or length of buffer
+* to be read from target device.
+*
+* @param [in] i_accessType - Access Type - See DeviceFW::AccessType in
+* 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.
+*
+* @return errlHndl_t - NULL if successful, otherwise a pointer to the
+* error log.
+*
+*/
+errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ int64_t i_accessType,
+ va_list i_args );
+
+/**
+ * @brief This function peforms the sequencing to do a read of the
+ * EEPROM that is identified.
+ *
+ * @param[in] i_target - Target device.
+ *
+ * @param[out] o_buffer - The buffer that will return the data read
+ * from the EEPROM device.
+ *
+ * @param[in] i_buflen - Number of bytes to read from the EEPROM device.
+ *
+ * @param[in] i_i2cInfo - Structure of I2C parameters neede to execute
+ * the command to the I2C device driver.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t eepromRead ( TARGETING::Target * i_target,
+ void * o_buffer,
+ size_t i_buflen,
+ eeprom_addr_t i_i2cInfo );
+
+/**
+ * @brief This function peforms the sequencing to do a write of the
+ * EEPROM that is identified.
+ *
+ * @param[in] i_target - Target device.
+ *
+ * @param[in] io_buffer - The buffer that contains the data to be written
+ * to the EEPROM device.
+ *
+ * @param[in/out] io_buflen
+* INPUT: Length of the buffer to be written to target device.
+* 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
+ * the command to the I2C device driver.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t eepromWrite ( TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t io_buflen,
+ eeprom_addr_t i_i2cInfo );
+
+/**
+ * @brief This function prepares the I2C byte address for adding to the
+ * existing buffer (for Writes), or as a separate write operation
+ * (for Reads).
+ *
+ * @param[out] o_buffer - The buffer to be written as a byte address to
+ * the EEPROM device.
+ *
+ * @param[out] o_bufSize - The size of the buffer to be written.
+ *
+ * @param[in] i_i2cInfo - Structure of I2C parameters neede to execute
+ * the command to the I2C device driver.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t eepromPrepareAddress ( void * o_buffer,
+ size_t & o_bufSize,
+ eeprom_addr_t i_i2cInfo );
+
+/**
+ * @brief this function will read all of the associated attributes needed
+ * to access the intended EEPROM. These attributes will be used to
+ * determine the type of I2C device as well as how to address it via
+ * the I2C device driver.
+ *
+ * @param[in] i_target - Target device.
+ *
+ * @param[out] o_i2cInfo - The structure that will contain the attribute data
+ * read from the target device.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target,
+ eeprom_addr_t & o_i2cInfo );
+
+/**
+ * @brief This function decides whether or not the target passed into the
+ * EEPROM device driver actually contains the I2C Master engines. If
+ * not, it will then read the attribute of the target to get the path
+ * of the target which does contain the I2C Master engine.
+ *
+ * @param[in] i_target - The current Target.
+ *
+ * @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
+ * allow operations to the target EEPROM.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target,
+ TARGETING::Target * &o_target );
+
+}; // end EEPROM namespace
+
+#endif // __EEPROM_H
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
diff --git a/src/usr/i2c/i2c.H b/src/usr/i2c/i2c.H
index 86500dfa6..ea513f6db 100755
--- a/src/usr/i2c/i2c.H
+++ b/src/usr/i2c/i2c.H
@@ -110,8 +110,10 @@ typedef struct
uint64_t fifo;
uint64_t command;
uint64_t mode;
- // TODO - More to add for Interrupts when Bad Machine path is started
+ uint64_t intmask; // Not Currently used
+ uint64_t interrupt;
uint64_t status;
+ uint64_t reset;
} i2c_addrs_t;
// Addresses for each of the registers in each engine.
@@ -121,19 +123,28 @@ static i2c_addrs_t masterAddrs[] =
I2C_MASTER0_ADDR | 0x4, // FIFO
I2C_MASTER0_ADDR | 0x5, // Command Register
I2C_MASTER0_ADDR | 0x6, // Mode Register
- I2C_MASTER0_ADDR | 0xB, // Status Register
+ I2C_MASTER0_ADDR | 0x8, // Interrupt Mask Register
+ I2C_MASTER0_ADDR | 0xA, // Interrupt Register
+ I2C_MASTER0_ADDR | 0xB, // Status Register (Read)
+ I2C_MASTER0_ADDR | 0xB, // Reset (Write)
},
{ /* Master 1 */
I2C_MASTER1_ADDR | 0x4, // FIFO
I2C_MASTER1_ADDR | 0x5, // Command Register
I2C_MASTER1_ADDR | 0x6, // Mode Register
- I2C_MASTER1_ADDR | 0xB, // Status Register
+ I2C_MASTER1_ADDR | 0x8, // Interrupt Mask Register
+ I2C_MASTER1_ADDR | 0xA, // Interrupt Register
+ I2C_MASTER1_ADDR | 0xB, // Status Register (Read)
+ I2C_MASTER1_ADDR | 0xB, // Reset (Write)
},
{ /* Master 2 */
I2C_MASTER2_ADDR | 0x4, // FIFO
I2C_MASTER2_ADDR | 0x5, // Command Register
I2C_MASTER2_ADDR | 0x6, // Mode Register
- I2C_MASTER2_ADDR | 0xB, // Status Register
+ I2C_MASTER2_ADDR | 0x8, // Interrupt Mask Register
+ I2C_MASTER2_ADDR | 0xA, // Interrupt Register
+ I2C_MASTER2_ADDR | 0xB, // Status Register (Read)
+ I2C_MASTER2_ADDR | 0xB, // Reset (Write)
}
};
@@ -383,7 +394,6 @@ union residuallengthreg
typedef struct
{
- uint64_t addr;
uint64_t port;
uint64_t engine;
uint64_t devAddr;
@@ -415,9 +425,9 @@ typedef struct
* usrif.H
*
* @param [in] i_args - This is an argument list for the device driver
-* framework. In this function there is only one argument, which
-* is the I2C Address that is needed for bits 8:14 of the I2C
-* Command register.
+* framework. This list of arguments consists of the I2C Master
+* engine, which port from the I2C master to use, and the slave's
+* device address.
*
* @return errlHndl_t - NULL if successful, otherwise a pointer to the
* error log.
@@ -508,11 +518,14 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target,
*
* @param[in] i_target - The I2C master target.
*
+ * @param[in] i_args - Structure containing arguments needed for a command
+ * transaction.
+ *
* @return errlHndl_t - NULL if successful, otherwise a pointer to
* the error log.
*/
errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
- uint64_t i_engine );
+ input_args_t i_args );
/**
* @brief This function will read the I2C Master engine status register
@@ -520,7 +533,8 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
*
* @param[in] i_target - The I2C master target.
*
- * @param[in] i_engine - The I2C Master engine that is to be read.
+ * @param[in] i_args - Structure containing arguments needed for a command
+ * transaction.
*
* @param[out] o_statusReg - The value of the status register read.
*
@@ -528,7 +542,7 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target,
* the error log.
*/
errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target,
- uint64_t i_engine,
+ input_args_t i_args,
statusreg & o_statusReg );
/**
@@ -537,45 +551,84 @@ errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target,
*
* @param[in] i_target - The I2C master target.
*
+ * @param[in] i_args - Structure containing arguments needed for a command
+ * transaction.
+ *
* @param[in] i_statusVal - The value of the Status Register.
*
* @return errlHndl_t - NULL if successful, otherwise a pointer to
* the error log.
*/
errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target,
+ input_args_t i_args,
statusreg i_statusVal );
/**
- * @brief This function will take the 2 byte address to be accessed
- * on the slave and write it to the FIFO.
+ * @brief This function will read the status register and not return
+ * until there is room in the FIFO for data to be written. An
+ * error will be returned if it times out waiting for space in
+ * the FIFO.
*
* @param[in] i_target - The I2C master target.
*
* @param[in] i_args - Structure containing arguments needed for a command
* transaction.
*
- * @return errlHndl_t - NULL if successful, otherwise a pointer to
+ * @return errHndl_t - NULL if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
+ input_args_t i_args );
+
+/**
+ * @brief This function will reset the I2C Master engine specified
+ * by the args. It will also then initiate a Stop cmd to the
+ * slave device.
+ *
+ * @param[in] i_target - The I2C master target.
+ *
+ * @param[in] i_args - Structure containing arguments needed for a command
+ * transaction.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to
* the error log.
*/
-errlHndl_t i2cWriteByteAddr ( TARGETING::Target * i_target,
+errlHndl_t i2cReset ( TARGETING::Target * i_target,
+ input_args_t i_args );
+
+/**
+ * @brief This function will send the Stop command to the slave device
+ * defined by the args passed in.
+ *
+ * @param[in] i_target - The I2C master target.
+ *
+ * @param[in] i_args - Structure containing arguments needed for a command
+ * transaction.
+ *
+ * @return errHndl_t - NULL if successful, otherwise a pointer to
+ * the error log.
+ */
+errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
input_args_t i_args );
/**
- * @brief This function will read the status register and not return
- * until there is room in the FIFO for data to be written. An
- * error will be returned if it times out waiting for space in
- * the FIFO.
+ * @brief This function will read the interrupt register and return the
+ * value.
*
* @param[in] i_target - The I2C master target.
*
* @param[in] i_args - Structure containing arguments needed for a command
* transaction.
*
+ * @param[out] o_intRegValue - The value of the Interrupt register that
+ * was read.
+ *
* @return errHndl_t - NULL if successful, otherwise a pointer to
* the error log.
*/
-errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target,
- input_args_t i_args );
+errlHndl_t i2cGetInterrupts ( TARGETING::Target * i_target,
+ input_args_t i_args,
+ uint64_t & o_intRegValue );
}; // end I2C namespace
diff --git a/src/usr/i2c/makefile b/src/usr/i2c/makefile
index d53dfad11..568ecbd69 100644
--- a/src/usr/i2c/makefile
+++ b/src/usr/i2c/makefile
@@ -23,7 +23,7 @@
ROOTPATH = ../../..
MODULE = i2c
-OBJS = i2c.o
+OBJS = i2c.o eepromdd.o
SUBDIRS = test.d
diff --git a/src/usr/i2c/test/eepromddtest.H b/src/usr/i2c/test/eepromddtest.H
new file mode 100755
index 000000000..1cc815a57
--- /dev/null
+++ b/src/usr/i2c/test/eepromddtest.H
@@ -0,0 +1,278 @@
+// 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
+#ifndef __EEPROMTEST_H
+#define __EEPROMTEST_H
+
+/**
+ * @file eepromtest.H
+ *
+ * @brief Test cases for the eeprom dd code
+ */
+#include <sys/time.h>
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <errl/errltypes.H>
+#include <devicefw/driverif.H>
+#include <i2c/eepromddreasoncodes.H>
+#include <targeting/predicates/predicatectm.H>
+#include <targeting/predicates/predicatepostfixexpr.H>
+
+extern trace_desc_t* g_trac_eeprom;
+
+using namespace TARGETING;
+
+class EEPROMTest: public CxxTest::TestSuite
+{
+ public:
+
+ /**
+ * @brief EEPROM Read/Write Test
+ * This test will test a variety of reads/writes and lengths
+ * across slave devices.
+ */
+ void testEEPROMReadWrite ( void )
+ {
+ errlHndl_t err = NULL;
+ int fails = 0;
+ int num_ops = 0;
+
+ TRACFCOMP( g_trac_eeprom,
+ "testEEPROMReadWrite - Start" );
+
+ struct
+ {
+ uint64_t addr; // Slave Device Address 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 },
+ };
+
+ const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]);
+
+ do
+ {
+ // Get a processor Target
+ TARGETING::TargetService& l_targetService = TARGETING::targetService();
+ TARGETING::Target* testTarget = NULL;
+ l_targetService.masterProcChipTargetHandle( testTarget );
+ assert(testTarget != NULL);
+ 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.
+// TARGETING::TargetService& tS = TARGETING::targetService();
+// TARGETING::Target * sysTarget = NULL;
+// TargetHandleList fullList;
+
+// // Get top level system target
+// tS.getTopLevelTarget( sysTarget );
+// assert( sysTarget != NULL );
+
+// // Predicate for the Procs
+// TARGETING::PredicateCTM predProc( TARGETING::CLASS_CHIP,
+// TARGETING::TYPE_PROC );
+
+// // Predicate for the DIMMs
+// TARGETING::PredicateCTM predDimm( TARGETING::CLASS_CARD,
+// TARGETING::TYPE_DIMM );
+
+// // Expression to get both Procs and DIMMs.
+// PredicatePostfixExpr query;
+// query.push( &predProc ).push( &predDimm ).Or();
+// tS.getAssociated( fullList,
+// sysTarget,
+// TARGETING::TargetService::CHILD,
+// TARGETING::TargetService::ALL,
+// &query );
+// assert( 0 != fullList.size() );
+
+ // Number of total operations
+ num_ops = fullList.size() * NUM_CMDS;
+
+ for( uint32_t j = 0; j < fullList.size(); j++ )
+ {
+ for( uint32_t i = 0; i < NUM_CMDS; i++ )
+ {
+ uint64_t data;
+
+ // if a read, initialize data, else, set data to write
+ if( testData[i].rnw )
+ {
+ data = 0x0ull;
+ }
+ else
+ {
+ data = testData[i].data;
+ }
+
+ // do the operation
+ err = deviceOp( (testData[i].rnw ? DeviceFW::READ : DeviceFW::WRITE),
+ fullList[j],
+ &data,
+ testData[i].size,
+ DEVICE_EEPROM_ADDRESS( testData[i].addr,
+ testData[i].chip ) );
+
+ if( err )
+ {
+ TS_FAIL( "testEEPROMReadWrite - fail on cmd %d out of %d",
+ i, NUM_CMDS );
+ errlCommit( err,
+ EEPROM_COMP_ID );
+ delete err;
+ fails++;
+ continue;
+ }
+
+ // compare data for the read
+ if( testData[i].rnw )
+ {
+ if( data != testData[i].data )
+ {
+ TRACFCOMP( g_trac_eeprom,
+ "testEEPROMReadWrite - cmd: %d/%d, Data read: %016llx, "
+ "expected: %016llx",
+ i, NUM_CMDS, data, testData[i].data );
+ TS_FAIL( "testEEPROMReadWrite - Failure comparing read data!" );
+ fails++;
+ continue;
+ }
+ }
+ }
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_eeprom,
+ "testEEPROMReadWrite - %d/%d fails",
+ fails, num_ops );
+ }
+
+ /**
+ * @brief EEPROM Invalid Operation Test
+ * This test will pass in an invalid Operation type. It
+ * is expected that an error log is to be returned.
+ */
+ void testEEPROMInvalidOperation ( void )
+ {
+ errlHndl_t err = NULL;
+ int64_t fails = 0, num_ops = 0;
+ uint64_t data = 0x0ull;
+ size_t dataSize = 8;
+
+ do
+ {
+ // Get a processor Target
+ TARGETING::TargetService& tS = TARGETING::targetService();
+ TARGETING::Target* testTarget = NULL;
+ tS.masterProcChipTargetHandle( testTarget );
+ assert(testTarget != NULL);
+
+ num_ops++;
+ err = deviceOp( DeviceFW::LAST_OP_TYPE,
+ testTarget,
+ &data,
+ dataSize,
+ DEVICE_EEPROM_ADDRESS( 0x0,
+ 0x0 ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "Error should've resulted in Operation type of LAST_OP_TYPE!" );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+ TRACFCOMP( g_trac_eeprom,
+ "testEEPROMInvalidOperation - %d/%d fails",
+ fails, num_ops );
+ }
+
+ /**
+ * @brief EEPROM Invalid Chip Test
+ * This test will pass in an invalid chip identifier which should
+ * result in an error being returned back from
+ */
+ void testEEPROMInvalidChip ( void )
+ {
+ errlHndl_t err = NULL;
+ int64_t fails = 0, num_ops = 0;
+ uint64_t data = 0x0ull;
+ size_t dataSize = 8;
+
+ const int64_t CHIP_NUM = 20;
+
+ do
+ {
+ // Get a processor Target
+ TARGETING::TargetService& tS = TARGETING::targetService();
+ TARGETING::Target* testTarget = NULL;
+ tS.masterProcChipTargetHandle( testTarget );
+ assert(testTarget != NULL);
+
+ num_ops++;
+ err = deviceOp( DeviceFW::WRITE,
+ testTarget,
+ &data,
+ dataSize,
+ DEVICE_EEPROM_ADDRESS( 0x0,
+ CHIP_NUM ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "Error should've resulted in using EEPROM chip %d!",
+ CHIP_NUM );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_eeprom,
+ "testEEPROMInvalidChip - %d/%d fails",
+ fails, num_ops );
+ }
+
+};
+
+#endif
diff --git a/src/usr/i2c/test/i2ctest.H b/src/usr/i2c/test/i2ctest.H
index dca02d4e5..f5ed88ca2 100755
--- a/src/usr/i2c/test/i2ctest.H
+++ b/src/usr/i2c/test/i2ctest.H
@@ -26,7 +26,7 @@
/**
* @file i2ctest.H
*
- * @brief Test case for I2C code
+ * @brief Test cases for I2C code
*/
#include <sys/time.h>
@@ -36,47 +36,83 @@
#include <errl/errltypes.H>
#include <devicefw/driverif.H>
#include <i2c/i2creasoncodes.H>
+#include <targeting/predicates/predicatectm.H>
extern trace_desc_t* g_trac_i2c;
using namespace TARGETING;
-// Address and data to read/write
-struct testI2CParms
-{
- uint64_t port;
- uint64_t engine;
- uint64_t addr;
- uint64_t devAddr;
- uint64_t data;
- size_t size;
-};
-
-// Test table values
-const testI2CParms g_i2cWriteCmdTable[] =
-{
- { 0x00, 0x00, 0x1234, 0x50, 0xFEDCBA9876543210, 8 },
- { 0x00, 0x00, 0x1234, 0x50, 0xFEDCBA9876543210, 8 },
-};
-
-const uint32_t g_i2cWriteCmdTableSz =
-sizeof(g_i2cWriteCmdTable)/sizeof(testI2CParms);
-
-
class I2CTest: public CxxTest::TestSuite
{
public:
/**
- * @brief I2C test #1
- * Write value and read back to verify
- * Currently only 1 operation
+ * @brief I2C Read/Write Test
+ * 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.
*/
- void testI2C1(void)
+ void testI2CReadWrite ( void )
{
+ return;
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;
+
+ struct
+ {
+ 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
+ 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.
+ // Real Centaur Devices
+// { 0x00, 0x00, 0x51, 0x1111000000000000,
+// 2, false, I2C_CENTAUR_TARGET }, // Write addr of 0x0000
+// { 0x00, 0x00, 0x51, 0x0000000000000000,
+// 8, true, I2C_CENTAUR_TARGET }, // Read 8 bytes
+// { 0x00, 0x00, 0x53, 0x0000000000000000,
+// 2, false, I2C_CENTAUR_TARGET }, // Write addr of 0x0000
+// { 0x00, 0x00, 0x53, 0x0000000000000000,
+// 8, true, I2C_CENTAUR_TARGET }, // Read 8 bytes
+ };
+
+ const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]);
- //@todo
+ //@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.
@@ -91,72 +127,211 @@ class I2CTest: public CxxTest::TestSuite
return;
}
- TS_TRACE( "I2C Test 1: its running!" );
-
do
{
- TARGETING::TargetService& l_targetService = TARGETING::targetService();
- TARGETING::Target* testTarget = NULL;
- l_targetService.masterProcChipTargetHandle( testTarget );
- assert(testTarget != NULL);
+ // Get top level system target
+ TARGETING::TargetService& tS = TARGETING::targetService();
+ TARGETING::Target * sysTarget = NULL;
+ TARGETING::Target * theTarget = NULL;
+ tS.getTopLevelTarget( sysTarget );
+ assert( sysTarget != NULL );
- testI2CParms testEntry = g_i2cWriteCmdTable[0];
+ // Get the Proc Target
+ TARGETING::Target* procTarget = NULL;
+ tS.masterProcChipTargetHandle( procTarget );
- // Perform I2C write
- uint64_t data = testEntry.data;
- TS_TRACE( "I2C - calling from Write" );
- err = deviceOp( DeviceFW::WRITE,
- testTarget,
- &data,
- testEntry.size,
- DEVICE_I2C_ADDRESS( testEntry.addr,
- testEntry.port,
- testEntry.engine,
- testEntry.devAddr ) );
-
- TS_TRACE( "I2C - returned from Write" );
- if( err )
+ // 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++ )
{
- break;
- }
+ uint64_t data;
- // Perform I2C read
- err = deviceOp( DeviceFW::READ,
- testTarget,
- &data,
- testEntry.size,
- DEVICE_I2C_ADDRESS( testEntry.addr,
- testEntry.port,
- testEntry.engine,
- testEntry.devAddr ) );
+ // if a read, initialize data, else, set data to write
+ if( testData[i].rnw )
+ {
+ data = 0x0ull;
+ }
+ else
+ {
+ data = testData[i].data;
+ }
- if( err )
- {
- break;
- }
+ // Decide which target to use
+ switch( testData[i].type )
+ {
+ case I2C_PROC_TARGET:
+ if( NULL == procTarget )
+ {
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"Processor Target is NULL, go to next "
+ "operation!" );
+ continue;
+ }
- // check the data read
- if( testEntry.data != data )
- {
- TS_FAIL( "testI2C1 failed! - Data read does not match what was written!" );
- TS_TRACE( "testI2C1 - Data Written: %016llx, Data Read: %016llx",
- testEntry.data, data );
+ theTarget = procTarget;
+ break;
+
+ case I2C_CENTAUR_TARGET:
+ 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;
+ };
+
+ // do the operation
+ cmds++;
+ err = deviceOp( (testData[i].rnw ? DeviceFW::READ : DeviceFW::WRITE),
+ theTarget,
+ &data,
+ testData[i].size,
+ DEVICE_I2C_ADDRESS( testData[i].port,
+ testData[i].engine,
+ testData[i].devAddr ) );
+ if( err )
+ {
+ TS_FAIL( "testI2CReadWrite - fail on cmd %d out of %d",
+ i, NUM_CMDS );
+ errlCommit( err,
+ I2C_COMP_ID );
+ delete err;
+ fails++;
+ continue;
+ }
+
+ // compare data for the read
+ if( testData[i].rnw )
+ {
+ if( data != testData[i].data )
+ {
+ TRACFCOMP( g_trac_i2c,
+ "testI2CReadWrite - cmd: %d/%d, Data read: %016llx, "
+ "expected: %016llx",
+ i, NUM_CMDS, data, testData[i].data );
+ TS_FAIL( "testI2CReadWrite - Failure comparing read data!" );
+ fails++;
+ continue;
+ }
+ }
}
} while( 0 );
- if ( err )
+ TRACFCOMP( g_trac_i2c,
+ "testI2CReadWrite - %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
+ * is the correct error.
+ */
+ void testI2CInvalidTarget ( void )
+ {
+ errlHndl_t err = NULL;
+ int fails = 0;
+ const int NUM_CMDS = 1;
+
+ TRACFCOMP( g_trac_i2c,
+ "testI2CInvalidTarget - Start" );
+
+ // Set processor chip to the master
+ TARGETING::Target* testTarget = MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ uint64_t data = 0x0ull;
+ size_t size = sizeof(uint64_t);
+
+ err = deviceOp( DeviceFW::READ,
+ testTarget,
+ &data,
+ size,
+ DEVICE_I2C_ADDRESS( 0x0,
+ 0x0,
+ 0x50 ) );
+
+ if( !err )
{
- TS_FAIL( "testI2C1 failed! Error committed." );
- errlCommit( err, I2C_COMP_ID );
+ TS_FAIL( "Failure to return error using Master Sentinel Chip!" );
+ fails++;
}
else
{
- TS_TRACE( "testI2C1 runs successfully!" );
+ delete err;
+ err = NULL;
}
- return;
+ TRACFCOMP( g_trac_i2c,
+ "testI2CInvalidTarget - %d/%d fails",
+ fails, NUM_CMDS );
}
+
+ /**
+ * @brief I2C Invalid Operation Test
+ * This test will pass in an invalid Operation type. It
+ * is expected that an error log is to be returned.
+ */
+ void testI2CInvalidOperation ( void )
+ {
+ errlHndl_t err = NULL;
+ int64_t fails = 0, num_ops = 0;
+ uint64_t data = 0x0ull;
+ size_t dataSize = 8;
+
+ do
+ {
+ // Get a processor Target
+ TARGETING::TargetService& tS = TARGETING::targetService();
+ TARGETING::Target* testTarget = NULL;
+ tS.masterProcChipTargetHandle( testTarget );
+ assert(testTarget != NULL);
+
+ num_ops++;
+ err = deviceOp( DeviceFW::LAST_OP_TYPE,
+ testTarget,
+ &data,
+ dataSize,
+ DEVICE_I2C_ADDRESS( 0x0,
+ 0x0,
+ 0x50 ) );
+
+ if( NULL == err )
+ {
+ fails++;
+ TS_FAIL( "Error should've resulted in Operation type of LAST_OP_TYPE!" );
+ }
+ else
+ {
+ delete err;
+ err = NULL;
+ }
+ } while( 0 );
+ TRACFCOMP( g_trac_i2c,
+ "testI2CInvalidOperation - %d/%d fails",
+ fails, num_ops );
+ }
+
};
#endif
diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H
index 1cf6e3026..fb8dfa1a6 100644
--- a/src/usr/initservice/extinitsvc/extinitsvctasks.H
+++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H
@@ -56,20 +56,6 @@ const TaskInfo g_exttaskinfolist[] = {
},
/**
- * @brief targeting task,
- *
- */
- {
- "libtargeting.so" , // taskname
- NULL, // no pointer to fn
- {
- START_TASK, // task type
- EXT_IMAGE, // Extended Module
- START_TARGETING_ERRL_ID, // module id
- }
- },
-
- /**
* @brief fapi task,
*/
{
@@ -153,6 +139,32 @@ const TaskInfo g_exttaskinfolist[] = {
}
},
+ /**
+ * @brief I2C Device Driver
+ */
+ {
+ "libi2c.so" , // taskname
+ NULL, // no pointer to fn
+ {
+ INIT_TASK, // task type
+ EXT_IMAGE, // Extended Module
+ START_I2C_ERRL_ID, // module id
+ }
+ },
+
+ /**
+ * @brief targeting task,
+ */
+ {
+ "libtargeting.so" , // taskname
+ NULL, // no pointer to fn
+ {
+ START_TASK, // task type
+ EXT_IMAGE, // Extended Module
+ START_TARGETING_ERRL_ID, // module id
+ }
+ },
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// NOTE: libistepdisp.so needs to always be last in this list!!
@@ -171,7 +183,7 @@ const TaskInfo g_exttaskinfolist[] = {
EXECUTE_ISTEPS_ERRL_ID, // module id
}
},
-
+ // NOTE: libistepdisp.so needs to always be last in this list!!
// ---------------------------------------------------------------
// ----- END OF LIST!!! ---------------------------------------
diff --git a/src/usr/targeting/targetservice.C b/src/usr/targeting/targetservice.C
index 9397a3ec0..7ec8ab22d 100644
--- a/src/usr/targeting/targetservice.C
+++ b/src/usr/targeting/targetservice.C
@@ -545,19 +545,6 @@ void TargetService::dump() const
TARG_INF("XSCOM Node ID = 0x%X",l_xscomChipInfo.nodeId);
TARG_INF("XSCOM Chip ID = 0x%X",l_xscomChipInfo.chipId);
}
-
- I2cChipInfo l_i2cChipInfo = {0};
- if( (*iv_targets)[i].tryGetAttr<ATTR_I2C_CHIP_INFO>( l_i2cChipInfo ) )
- {
- TARG_INF( "I2C Bus Speed = 0x%X",
- l_i2cChipInfo.busSpeed );
- TARG_INF( "I2C Device Address = 0x%X",
- l_i2cChipInfo.deviceAddr );
- TARG_INF( "I2C Device Port = 0x%X",
- l_i2cChipInfo.devicePort );
- TARG_INF( "I2C Master Engine = 0x%X",
- l_i2cChipInfo.deviceMasterEng );
- }
}
return;
diff --git a/src/usr/targeting/xmltohb/attribute_types.xml b/src/usr/targeting/xmltohb/attribute_types.xml
index 18615b0ef..c4d8d2e67 100644
--- a/src/usr/targeting/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/xmltohb/attribute_types.xml
@@ -690,42 +690,6 @@
</attribute>
<attribute>
- <id>I2C_CHIP_INFO</id>
- <description>Attribute which describes I2C chip info</description>
- <complexType>
- <description>Structure which defines info necessary for I2C. Only
- applicable for chip targets which support I2C. Structure is
- read-only.</description>
- <field>
- <name>busSpeed</name>
- <description>Slave device bus speed</description>
- <type>uint32_t</type>
- <default>0</default>
- </field>
- <field>
- <name>deviceAddr</name>
- <description>Slave device address</description>
- <type>uint32_t</type>
- <default>0</default>
- </field>
- <field>
- <name>devicePort</name>
- <description>Slave device port location</description>
- <type>uint32_t</type>
- <default>0</default>
- </field>
- <field>
- <name>deviceMasterEng</name>
- <description>Master I2C engine slave is hung off of</description>
- <type>uint32_t</type>
- <default>0</default>
- </field>
- </complexType>
- <persistency>non-volatile</persistency>
- <readable/>
-</attribute>
-
-<attribute>
<id>FSI_MASTER_CHIP</id>
<description>Chip which contains the FSI master logic that drives this slave</description>
<nativeType>
@@ -977,5 +941,75 @@
<writeable/>
</attribute>
+<attribute>
+ <id>EEPROM_ADDR_INFO0</id>
+ <description>Information needed to address the EEPROM slaves</description>
+ <complexType>
+ <description>Structure to define the addressing for an I2C slave device.</description>
+ <field>
+ <name>i2cMasterPath</name>
+ <description>Entity path to the processor containing the I2C master (FOR DIMMS
+ ONLY)</description>
+ <type>EntityPath</type>
+ <default>physical:sys-0</default>
+ </field>
+ <field>
+ <name>port</name>
+ <description>Port from the I2C Master device. This is a 6-bit value.</description>
+ <type>uint8_t</type>
+ <default>0</default>
+ </field>
+ <field>
+ <name>devAddr</name>
+ <description>Device address on the I2C bus. This is a 7-bit value.</description>
+ <type>uint8_t</type>
+ <default>0</default>
+ </field>
+ <field>
+ <name>engine</name>
+ <description>I2C master engine. This is a 2-bit value.</description>
+ <type>uint8_t</type>
+ <default>0</default>
+ </field>
+ </complexType>
+ <persistency>non-volatile</persistency>
+ <readable/>
+</attribute>
+
+<attribute>
+ <id>EEPROM_ADDR_INFO1</id>
+ <description>Information needed to address the EERPROM slaves</description>
+ <complexType>
+ <description>Structure to define the addressing for an I2C slave device.</description>
+ <field>
+ <name>i2cMasterPath</name>
+ <description>Entity path to the processor containing the I2C master (FOR DIMMS
+ ONLY)</description>
+ <type>EntityPath</type>
+ <default>physical:sys-0</default>
+ </field>
+ <field>
+ <name>port</name>
+ <description>Port from the I2C Master device. This is a 6-bit value.</description>
+ <type>uint8_t</type>
+ <default>0</default>
+ </field>
+ <field>
+ <name>devAddr</name>
+ <description>Device address on the I2C bus. This is a 7-bit value.</description>
+ <type>uint8_t</type>
+ <default>0</default>
+ </field>
+ <field>
+ <name>engine</name>
+ <description>I2C master engine. This is a 2-bit value.</description>
+ <type>uint8_t</type>
+ <default>0</default>
+ </field>
+ </complexType>
+ <persistency>non-volatile</persistency>
+ <readable/>
+</attribute>
+
</attributes>
diff --git a/src/usr/targeting/xmltohb/simics_SALERNO.system.xml b/src/usr/targeting/xmltohb/simics_SALERNO.system.xml
index b16fffb10..9dfa90433 100644
--- a/src/usr/targeting/xmltohb/simics_SALERNO.system.xml
+++ b/src/usr/targeting/xmltohb/simics_SALERNO.system.xml
@@ -421,5 +421,26 @@
</attribute>
</targetInstance>
+<targetInstance>
+ <id>sys0node0proc0dimm0</id>
+ <type>card-dimm</type>
+ <attribute>
+ <id>PHYS_PATH</id>
+ <default>physical:sys-0/node-0/dimm-0</default>
+ </attribute>
+ <attribute>
+ <id>AFFINITY_PATH</id>
+ <default>affinity:sys-0/node-0/proc-0/mcs-0/mbs-0/mba-0/mem_port-0/dimm-0</default>
+ </attribute>
+ <attribute>
+ <id>EEPROM_ADDR_INFO0</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0/node-0/proc-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x50</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
+</targetInstance>
</attributes>
diff --git a/src/usr/targeting/xmltohb/simics_VENICE.system.xml b/src/usr/targeting/xmltohb/simics_VENICE.system.xml
index c21de0b10..196d449a2 100644
--- a/src/usr/targeting/xmltohb/simics_VENICE.system.xml
+++ b/src/usr/targeting/xmltohb/simics_VENICE.system.xml
@@ -3180,6 +3180,24 @@
<id>FSI_OPTION_FLAGS</id>
<default>0</default>
</attribute>
+ <attribute>
+ <id>EEPROM_ADDR_INFO0</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x51</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
+ <attribute>
+ <id>EEPROM_ADDR_INFO1</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x53</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
</targetInstance>
<!-- Centaur MBS affiliated with membuf0 -->
diff --git a/src/usr/targeting/xmltohb/target_types.xml b/src/usr/targeting/xmltohb/target_types.xml
index 6ad13d257..5ea70b800 100644
--- a/src/usr/targeting/xmltohb/target_types.xml
+++ b/src/usr/targeting/xmltohb/target_types.xml
@@ -154,6 +154,26 @@
<id>MODEL</id>
<default>SALERNO</default>
</attribute>
+ <!-- Defaulting this info to the one Simics Dummy device that we have -->
+ <attribute>
+ <id>EEPROM_ADDR_INFO0</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x50</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
+ <!-- Defaulting this info to the one Simics Dummy device that we have -->
+ <attribute>
+ <id>EEPROM_ADDR_INFO1</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x50</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
</targetType>
<targetType>
@@ -163,6 +183,28 @@
<id>MODEL</id>
<default>VENICE</default>
</attribute>
+ <attribute><id>DUMMY_RW</id></attribute>
+ <attribute><id>DUMMY_HEAP_ZERO_DEFAULT</id></attribute>
+ <!-- Defaulting this info to the one Simics Dummy device that we have -->
+ <attribute>
+ <id>EEPROM_ADDR_INFO0</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x50</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
+ <!-- Defaulting this info to the one Simics Dummy device that we have -->
+ <attribute>
+ <id>EEPROM_ADDR_INFO1</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x50</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
</targetType>
<targetType>
@@ -485,6 +527,24 @@
<field><id>reserved</id><value>0</value></field>
</default>
</attribute>
+ <attribute>
+ <id>EEPROM_ADDR_INFO0</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x51</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
+ <attribute>
+ <id>EEPROM_ADDR_INFO1</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x53</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
</targetType>
<!-- Centaur MBS -->
@@ -547,4 +607,33 @@
</attribute>
</targetType>
+<!--Dummy card to use as a DIMM for initial I2C/EEPROM testing -->
+<targetType>
+ <id>card</id>
+ <parent>base</parent>
+ <attribute>
+ <id>CLASS</id>
+ <default>CARD</default>
+ </attribute>
+</targetType>
+
+<targetType>
+ <id>card-dimm</id>
+ <parent>card</parent>
+ <attribute>
+ <id>TYPE</id>
+ <default>DIMM</default>
+ </attribute>
+ <!-- Defaulting this info to the one Simics Dummy device that we have -->
+ <attribute>
+ <id>EEPROM_ADDR_INFO0</id>
+ <default>
+ <field><id>i2cMasterPath</id><value>physical:sys-0</value></field>
+ <field><id>port</id><value>0</value></field>
+ <field><id>devAddr</id><value>0x50</value></field>
+ <field><id>engine</id><value>0</value></field>
+ </default>
+ </attribute>
+</targetType>
+
</attributes>
OpenPOWER on IntegriCloud