diff options
-rw-r--r-- | src/include/usr/devicefw/driverif.H | 19 | ||||
-rw-r--r-- | src/include/usr/hbotcompid.H | 8 | ||||
-rw-r--r-- | src/include/usr/i2c/eepromddreasoncodes.H | 77 | ||||
-rw-r--r-- | src/include/usr/i2c/i2creasoncodes.H | 19 | ||||
-rw-r--r-- | src/include/usr/initservice/initsvcreasoncodes.H | 1 | ||||
-rw-r--r-- | src/makefile | 2 | ||||
-rwxr-xr-x | src/usr/errl/parser/scanforsrcs.pl | 29 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 662 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.H | 208 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.C | 607 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.H | 95 | ||||
-rw-r--r-- | src/usr/i2c/makefile | 2 | ||||
-rwxr-xr-x | src/usr/i2c/test/eepromddtest.H | 278 | ||||
-rwxr-xr-x | src/usr/i2c/test/i2ctest.H | 325 | ||||
-rw-r--r-- | src/usr/initservice/extinitsvc/extinitsvctasks.H | 42 | ||||
-rw-r--r-- | src/usr/targeting/targetservice.C | 13 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/attribute_types.xml | 106 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/simics_SALERNO.system.xml | 21 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/simics_VENICE.system.xml | 18 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/target_types.xml | 89 |
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> |