diff options
Diffstat (limited to 'src/usr/i2c')
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 401 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.H | 66 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.C | 163 | ||||
-rwxr-xr-x | src/usr/i2c/test/eepromddtest.H | 192 | ||||
-rwxr-xr-x | src/usr/i2c/test/i2ctest.H | 191 |
5 files changed, 755 insertions, 258 deletions
diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index c4a785c30..b5ba280e5 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ /* */ /* p1 */ /* */ @@ -42,7 +42,9 @@ #include <devicefw/driverif.H> #include <i2c/eepromddreasoncodes.H> +#include <i2c/eepromif.H> #include "eepromdd.H" + // ---------------------------------------------- // Globals // ---------------------------------------------- @@ -60,6 +62,7 @@ TRAC_INIT( & g_trac_eepromr, "EEPROMR", KILOBYTE ); // Easy macro replace for unit testing //#define TRACUCOMP(args...) TRACFCOMP(args) #define TRACUCOMP(args...) + // ---------------------------------------------- // Defines // ---------------------------------------------- @@ -102,12 +105,17 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, 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 ); + i2cInfo.offset = va_arg( i_args, uint64_t ); TRACDCOMP( g_trac_eeprom, ENTER_MRK"eepromPerformOp()" ); + TRACUCOMP (g_trac_eeprom, ENTER_MRK"eepromPerformOp(): " + "i_opType=%d, chip=%d, offset=%d, len=%d", + (uint64_t) i_opType, i2cInfo.chip, i2cInfo.offset, io_buflen); + + do { // Read Attributes needed to complete the operation @@ -122,6 +130,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, // Check to see if we need to find a new target for // the I2C Master err = eepromGetI2CMasterTarget( i_target, + i2cInfo, theTarget ); if( err ) @@ -157,7 +166,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, else { TRACFCOMP( g_trac_eeprom, - ERR_MRK"Invalid EEPROM Operation!" ); + ERR_MRK"eepromPerformOp(): Invalid EEPROM Operation!"); /*@ * @errortype @@ -205,8 +214,8 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target, do { TRACSCOMP( g_trac_eepromr, - "EEPROM READ START : Chip: %02d : Addr %.2X : Len %d", - i_i2cInfo.chip, i_i2cInfo.addr, i_buflen ); + "EEPROM READ START : Chip: %02d : Offset %.2X : Len %d", + i_i2cInfo.chip, i_i2cInfo.offset, i_buflen ); err = eepromPrepareAddress( &byteAddr, byteAddrSize, @@ -250,6 +259,9 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target, if( err ) { + TRACFCOMP( g_trac_eeprom, + ERR_MRK"eepromRead(): I2C Read failed on %d/%d/0x%x", + i_i2cInfo.port, i_i2cInfo.engine, i_i2cInfo.devAddr ); break; } @@ -257,8 +269,10 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target, 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) ); + "EEPROM READ END : Chip: %02d : Offset %.2X : Len %d : %016llx", + i_i2cInfo.chip, i_i2cInfo.offset, i_buflen, + *((uint64_t*)o_buffer) ); + } while( 0 ); // Catch it if we break out early. @@ -286,7 +300,9 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, uint8_t byteAddr[MAX_BYTE_ADDR]; size_t byteAddrSize = 0; uint8_t * newBuffer = NULL; - bool needFree = true; + bool needFree = false; + bool unlock = false; + eeprom_addr_t l_i2cInfo = i_i2cInfo; TRACDCOMP( g_trac_eeprom, ENTER_MRK"eepromWrite()" ); @@ -294,8 +310,9 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, 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) ); + "EEPROM WRITE START : Chip: %02d : Offset %.2X : Len %d : %016llx", + i_i2cInfo.chip, i_i2cInfo.offset, io_buflen, + *((uint64_t*)io_buffer) ); err = eepromPrepareAddress( &byteAddr, byteAddrSize, @@ -306,44 +323,122 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, break; } - size_t newBufLen = byteAddrSize + io_buflen; + + // EEPROM devices have write page boundaries, so when necessary + // need to split up command into multiple write operations + + // Setup a max-size buffer of byteAddrSize + writePageSize + size_t newBufLen = byteAddrSize + i_i2cInfo.writePageSize; newBuffer = static_cast<uint8_t*>(malloc( newBufLen )); needFree = true; - // 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 ); + // Point a uint8_t ptr at io_buffer for array addressing below + uint8_t * l_data_ptr = reinterpret_cast<uint8_t*>(io_buffer); // Lock for operation sequencing mutex_lock( &g_eepromMutex ); + unlock = true; - // 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 ) ); + // variables to store different amount of data length + size_t loop_data_length = 0; + size_t loop_buffer_length = 0; + size_t total_bytes_written = 0; + + for ( uint64_t i = 0 ; + (i * i_i2cInfo.writePageSize) < io_buflen ; + i++) + { + + if ( (io_buflen - (i * i_i2cInfo.writePageSize) ) + >= i_i2cInfo.writePageSize) + { + // Data to write >= to writePageSize, so write + // the maximum amount: writePageSize + loop_data_length = i_i2cInfo.writePageSize; + } + else + { + // Less than writePageSize to write + loop_data_length = io_buflen % i_i2cInfo.writePageSize; + } + + // Update the offset for each loop + l_i2cInfo.offset += i * i_i2cInfo.writePageSize; + + err = eepromPrepareAddress( &byteAddr, + byteAddrSize, + l_i2cInfo ); + if (err) + { + break; + } + + // Add the byte address to the buffer + memcpy( newBuffer, + byteAddr, + byteAddrSize ); + + // Now add the data the user wanted to write + memcpy( &newBuffer[byteAddrSize], + &l_data_ptr[i * i_i2cInfo.writePageSize], + loop_data_length); + + // Calculate Total Length + loop_buffer_length = loop_data_length + byteAddrSize; + + TRACUCOMP(g_trac_eeprom,"eepromWrite() Loop: %d/%d/0x%x " + "loop=%d, l_b_l=%d, l_d_l=%d, offset=0x%x", + i_i2cInfo.port, i_i2cInfo.engine, + i_i2cInfo.devAddr, i, loop_buffer_length, loop_data_length, + l_i2cInfo.offset); + + + // Do the actual data write + err = deviceOp( DeviceFW::WRITE, + i_target, + newBuffer, + loop_buffer_length, + DEVICE_I2C_ADDRESS( i_i2cInfo.port, + i_i2cInfo.engine, + i_i2cInfo.devAddr ) ); + + if( err ) + { + TRACFCOMP(g_trac_eeprom, + ERR_MRK"eepromWrite(): I2C Write failed on %d/%d/0x%x " + "loop=%d, l_b_l=%d, offset=0x%x", + i_i2cInfo.port, i_i2cInfo.engine, + i_i2cInfo.devAddr, i, loop_buffer_length, l_i2cInfo.offset); + + + // Can't assume that anything was written if + // there was an error, so no update to total_bytes_written + // for this loop + break; + } + + // Update how much data was written + total_bytes_written += loop_data_length; + } + + // Release mutex lock mutex_unlock( &g_eepromMutex ); + unlock = false; + + // Set how much data was actually written + io_buflen = total_bytes_written; if( err ) { - // Can't assume that anything was written if - // there was an error. - io_buflen = 0; + // Leave do-while loop 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 ); + "EEPROM WRITE END : Chip: %02d : Offset %.2X : Len %d", + i_i2cInfo.chip, i_i2cInfo.offset, io_buflen ); } while( 0 ); // Free memory @@ -352,6 +447,12 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, free( newBuffer ); } + // Catch it if we break out early. + if( unlock ) + { + mutex_unlock( & g_eepromMutex ); + } + TRACDCOMP( g_trac_eeprom, EXIT_MRK"eepromWrite()" ); @@ -376,7 +477,7 @@ errlHndl_t eepromPrepareAddress ( void * o_buffer, do { // -------------------------------------------------------------------- - // TODO - eventually there will be different I2C devices and the way + // @todo RTC:72715 - support 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. @@ -389,14 +490,14 @@ errlHndl_t eepromPrepareAddress ( void * o_buffer, 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); + *((uint8_t*)o_buffer) = (i_i2cInfo.offset & 0xFF00ull) >> 8; + *((uint8_t*)o_buffer+1) = (i_i2cInfo.offset & 0x00FFull); break; case ONE_BYTE_ADDR: o_bufSize = 1; memset( o_buffer, 0x0, o_bufSize ); - *((uint8_t*)o_buffer) = (i_i2cInfo.addr & 0xFFull); + *((uint8_t*)o_buffer) = (i_i2cInfo.offset & 0xFFull); break; default: @@ -410,14 +511,14 @@ errlHndl_t eepromPrepareAddress ( void * o_buffer, * @severity ERRL_SEV_UNRECOVERABLE * @moduleid EEPROM_PREPAREADDRESS * @userdata1 Device Type - * @userdata2 <UNUSED> + * @userdata2 EEPROM chip * @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 ); + i_i2cInfo.chip ); break; }; @@ -448,76 +549,191 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, do { - if( 0 == o_i2cInfo.chip ) + if( VPD_PRIMARY == o_i2cInfo.chip ) { - // Read Attributes from EEPROM_ADDR_INFO0 - TARGETING::EepromAddrInfo0 eepromData; - if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_ADDR_INFO0>( eepromData ) ) + // Read Attributes from EEPROM_VPD_PRIMARY_INFO + TARGETING::EepromVpdPrimaryInfo eepromData; + if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO> + ( eepromData ) ) { + o_i2cInfo.chipTypeEnum = VPD_PRIMARY; 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.i2cMasterPath = eepromData.i2cMasterPath; + + // @todo RTC:72715 - More attributes to be read o_i2cInfo.deviceType = TWO_BYTE_ADDR; + o_i2cInfo.writePageSize = 128; + } else { TRACFCOMP( g_trac_eeprom, - ERR_MRK"eepromReadAttributes() - ERROR reading attributes for " - "chip %d!", + ERR_MRK"eepromReadAttributes() - ERROR reading " + "attributes for chip %d! (VPD_PRIMARY)", o_i2cInfo.chip ); /*@ * @errortype - * @reasoncode EEPROM_ADDR_INFO0_NOT_FOUND + * @reasoncode EEPROM_VPD_PRIMARY_INFO_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 + * @userdata1 HUID of target + * @userdata2[0:31] EEPROM chip + * @userdata2[32:63] Attribute Enumeration + * @devdesc ATTR_EEPROM_VPD_PRIMARY_INFO 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 ); + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + EEPROM_READATTRIBUTES, + EEPROM_VPD_PRIMARY_INFO_NOT_FOUND, + TARGETING::get_huid(i_target), + TWO_UINT32_TO_UINT64( + o_i2cInfo.chip, + TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO)); break; } } - else if( 1 == o_i2cInfo.chip ) + else if( VPD_BACKUP == o_i2cInfo.chip ) { - // Read Attributes from EEPROM_ADDR_INFO1 - TARGETING::EepromAddrInfo1 eepromData; - if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_ADDR_INFO1>( eepromData ) ) + // Read Attributes from EEPROM_VPD_BACKUP_INFO + TARGETING::EepromVpdBackupInfo eepromData; + if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_VPD_BACKUP_INFO> + ( eepromData ) ) { + o_i2cInfo.chipTypeEnum = VPD_BACKUP; 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.i2cMasterPath = eepromData.i2cMasterPath; + + // @todo RTC:72715 - More attributes to be read o_i2cInfo.deviceType = TWO_BYTE_ADDR; + o_i2cInfo.writePageSize = 128; } else { TRACFCOMP( g_trac_eeprom, - ERR_MRK"eepromReadAttributes() - ERROR reading attributes for " - "chip %d!", + ERR_MRK"eepromReadAttributes() - ERROR reading " + "attributes for chip %d! (VPD_BACKUP)", o_i2cInfo.chip ); /*@ * @errortype - * @reasoncode EEPROM_ADDR_INFO1_NOT_FOUND + * @reasoncode EEPROM_VPD_BACKUP_INFO_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 + * @userdata1 HUID of target + * @userdata2[0:31] EEPROM chip + * @userdata2[32:63] Attribute Enumeration + * @devdesc ATTR_EEPROM_VPD_BACKUP_INFO 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 ); + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + EEPROM_READATTRIBUTES, + EEPROM_VPD_BACKUP_INFO_NOT_FOUND, + TARGETING::get_huid(i_target), + TWO_UINT32_TO_UINT64( + o_i2cInfo.chip, + TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO)); + + break; + } + } + else if( SBE_PRIMARY == o_i2cInfo.chip ) + { + // Read Attributes from EEPROM_SBE_PRIMARY_INFO + TARGETING::EepromSbePrimaryInfo eepromData; + if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_SBE_PRIMARY_INFO> + ( eepromData ) ) + { + o_i2cInfo.chipTypeEnum = SBE_PRIMARY; + o_i2cInfo.port = eepromData.port; + o_i2cInfo.devAddr = eepromData.devAddr; + o_i2cInfo.engine = eepromData.engine; + o_i2cInfo.i2cMasterPath = eepromData.i2cMasterPath; + + // @todo RTC:72715 - More attributes to be read + o_i2cInfo.deviceType = TWO_BYTE_ADDR; + o_i2cInfo.writePageSize = 128; + } + else + { + TRACFCOMP( g_trac_eeprom, + ERR_MRK"eepromReadAttributes() - ERROR reading " + "attributes for chip %d! (SBE_PRIMARY)", + o_i2cInfo.chip ); + + /*@ + * @errortype + * @reasoncode EEPROM_SBE_PRIMARY_INFO_NOT_FOUND + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid EEPROM_READATTRIBUTES + * @userdata1 HUID of target + * @userdata2[0:31] EEPROM chip + * @userdata2[32:63] Attribute Enumeration + * @devdesc ATTR_EEPROM_SBE_PRIMARY_INFO Attribute + * was not found + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + EEPROM_READATTRIBUTES, + EEPROM_SBE_PRIMARY_INFO_NOT_FOUND, + TARGETING::get_huid(i_target), + TWO_UINT32_TO_UINT64( + o_i2cInfo.chip, + TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO)); + + break; + } + } + else if( SBE_BACKUP == o_i2cInfo.chip ) + { + // Read Attributes from EEPROM_SBE_BACKUP_INFO + TARGETING::EepromSbeBackupInfo eepromData; + if( i_target->tryGetAttr<TARGETING::ATTR_EEPROM_SBE_BACKUP_INFO> + ( eepromData ) ) + { + o_i2cInfo.chipTypeEnum = SBE_BACKUP; + o_i2cInfo.port = eepromData.port; + o_i2cInfo.devAddr = eepromData.devAddr; + o_i2cInfo.engine = eepromData.engine; + o_i2cInfo.i2cMasterPath = eepromData.i2cMasterPath; + + // @todo RTC:72715 - More attributes to be read + o_i2cInfo.deviceType = TWO_BYTE_ADDR; + o_i2cInfo.writePageSize = 128; + } + else + { + TRACFCOMP( g_trac_eeprom, + ERR_MRK"eepromReadAttributes() - ERROR reading " + "attributes for chip %d! (SBE_BACKUP)", + o_i2cInfo.chip ); + + /*@ + * @errortype + * @reasoncode EEPROM_SBE_BACKUP_INFO_NOT_FOUND + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid EEPROM_READATTRIBUTES + * @userdata1 HUID of target + * @userdata2[0:31] EEPROM chip + * @userdata2[32:63] Attribute Enumeration + * @devdesc ATTR_EEPROM_SBE_BACKUP_INFO Attribute + * was not found + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + EEPROM_READATTRIBUTES, + EEPROM_SBE_BACKUP_INFO_NOT_FOUND, + TARGETING::get_huid(i_target), + TWO_UINT32_TO_UINT64( + o_i2cInfo.chip, + TARGETING::ATTR_EEPROM_VPD_PRIMARY_INFO)); break; } @@ -535,14 +751,14 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid EEPROM_READATTRIBUTES * @userdata1 EEPROM Chip - * @userdata2 <UNUSED> + * @userdata2 HUID of target * @devdesc Invalid EEPROM chip to access */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, EEPROM_READATTRIBUTES, EEPROM_INVALID_CHIP, o_i2cInfo.chip, - 0x0 ); + TARGETING::get_huid(i_target) ); break; } @@ -559,6 +775,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, // eepromGetI2CMasterTarget // ------------------------------------------------------------------ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target, + eeprom_addr_t i_i2cInfo, TARGETING::Target * &o_target ) { errlHndl_t err = NULL; @@ -574,14 +791,15 @@ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target, 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>(); + // I2C Master that talks to the DIMM EEPROM + + // The path was read from the attribute via eepromReadAttributes() + // and passed to this function in i_i2cInfo + // check that the path exists bool exists = false; - tS.exists( eepromData.i2cMasterPath, + tS.exists( i_i2cInfo.i2cMasterPath, exists ); if( !exists ) @@ -595,42 +813,43 @@ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target, * @reasoncode EEPROM_DIMM_I2C_MASTER_PATH_ERROR * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid EEPROM_GETI2CMASTERTARGET - * @userdata1 Attribute Enum - * @userdata2 <UNUSED> + * @userdata1 Attribute Chip Type Enum + * @userdata2 HUID of target * @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 ); + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + EEPROM_GETI2CMASTERTARGET, + EEPROM_DIMM_I2C_MASTER_PATH_ERROR, + i_i2cInfo.chipTypeEnum, + TARGETING::get_huid(i_target) ); break; } // Since it exists, convert to a target - o_target = tS.toTarget( eepromData.i2cMasterPath ); + o_target = tS.toTarget( i_i2cInfo.i2cMasterPath ); if( NULL == o_target ) { TRACFCOMP( g_trac_eeprom, - ERR_MRK"eepromGetI2CMasterTarget() - Parent Processor target " - "was NULL!" ); + ERR_MRK"eepromGetI2CMasterTarget() - I2C Master " + "Path 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. + * @userdata1 Attribute Chip Type Enum + * @userdata2 HUID of target + * @devdesc I2C Master Path Target is NULL. */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, EEPROM_GETI2CMASTERTARGET, EEPROM_TARGET_NULL, - 0x0, - 0x0 ); + i_i2cInfo.chipTypeEnum, + TARGETING::get_huid(i_target) ); break; } diff --git a/src/usr/i2c/eepromdd.H b/src/usr/i2c/eepromdd.H index ab47f692a..7464e1881 100755 --- a/src/usr/i2c/eepromdd.H +++ b/src/usr/i2c/eepromdd.H @@ -1,25 +1,25 @@ -// 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 +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/i2c/eepromdd.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ #ifndef __EEPROM_H #define __EEPROM_H @@ -33,6 +33,7 @@ // ---------------------------------------------- // Includes // ---------------------------------------------- +#include <i2c/eepromif.H> #include <errl/errlentry.H> namespace EEPROM @@ -57,9 +58,12 @@ typedef struct uint64_t port; uint64_t engine; uint64_t devAddr; - uint64_t addr; int64_t chip; + uint64_t offset; eeprom_device_t deviceType; + TARGETING::EntityPath i2cMasterPath; + uint64_t writePageSize; // in bytes + eeprom_chip_types_t chipTypeEnum; } eeprom_addr_t; /** @@ -85,9 +89,9 @@ typedef struct * 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. +* framework. This argument list consists of the chip number of +* the EEPROM to access from the given I2C Master target and the +* internal offset to use on the slave I2C device. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the * error log. @@ -111,7 +115,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, * * @param[in] i_buflen - Number of bytes to read from the EEPROM device. * - * @param[in] i_i2cInfo - Structure of I2C parameters neede to execute + * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute * the command to the I2C device driver. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the @@ -136,7 +140,7 @@ errlHndl_t eepromRead ( TARGETING::Target * i_target, * 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 + * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute * the command to the I2C device driver. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the @@ -157,7 +161,7 @@ errlHndl_t eepromWrite ( TARGETING::Target * i_target, * * @param[out] o_bufSize - The size of the buffer to be written. * - * @param[in] i_i2cInfo - Structure of I2C parameters neede to execute + * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute * the command to the I2C device driver. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the @@ -192,6 +196,9 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, * * @param[in] i_target - The current Target. * + * @param[in] i_i2cInfo - Structure of I2C parameters needed to execute + * the command to the I2C device driver. + * * @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 @@ -201,6 +208,7 @@ errlHndl_t eepromReadAttributes ( TARGETING::Target * i_target, * error log. */ errlHndl_t eepromGetI2CMasterTarget ( TARGETING::Target * i_target, + eeprom_addr_t i_i2cInfo, TARGETING::Target * &o_target ); }; // end EEPROM namespace diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C index 23398fbc3..0a32c1ca8 100755 --- a/src/usr/i2c/i2c.C +++ b/src/usr/i2c/i2c.C @@ -56,6 +56,7 @@ TRAC_INIT( & g_trac_i2c, "I2C", KILOBYTE ); trace_desc_t* g_trac_i2cr = NULL; TRAC_INIT( & g_trac_i2cr, "I2CR", KILOBYTE ); + // Easy macro replace for unit testing //#define TRACUCOMP(args...) TRACFCOMP(args) #define TRACUCOMP(args...) @@ -105,7 +106,15 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, args.devAddr = va_arg( i_args, uint64_t ); TRACDCOMP( g_trac_i2c, - ENTER_MRK"i2cPerformOp()" ); + ENTER_MRK"i2cPerformOp(): i_opType=%d, " + "p=%d, engine=%d, devAddr=0x%lx", + (uint64_t) i_opType, args.port, args.engine, args.devAddr ); + + TRACUCOMP( g_trac_i2c, + ENTER_MRK"i2cPerformOp(): i_opType=%d, p/e/devAddr= " + "%d/%d/0x%x, len=%d", + (uint64_t) i_opType, args.port, args.engine, args.devAddr, + io_buflen); do { @@ -135,6 +144,8 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, break; } + // @todo RTC:72715 - Check that target is an I2C master + // Get the mutex for the requested engine mutex_t * engineLock = NULL; switch( args.engine ) @@ -153,8 +164,9 @@ errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, default: TRACFCOMP( g_trac_i2c, - ERR_MRK"Invalid engine for getting Mutex!" ); - // TODO - Create an error here + ERR_MRK"Invalid engine for getting Mutex! " + "args.engine=%d", args.engine ); + // @todo RTC:69113 - Create an error here break; }; @@ -278,7 +290,7 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, uint64_t devAddr = i_args.devAddr; uint64_t port = i_args.port; - // TODO - hardcoded to 400KHz for now + // @todo RTC:72715 - Add multiple bus speed support (set to 400KHz for now) uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ ); uint64_t timeoutCount = I2C_TIMEOUT_COUNT( interval ); @@ -298,8 +310,8 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, // Do Command/Mode reg setups. err = i2cSetup( i_target, i_buflen, - true, - true, + true, // i_readNotWrite + true, // i_withStop i_args ); if( err ) @@ -324,7 +336,11 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, break; } - while( 0 == status.fifo_entry_count ) + // Wait for 1 of 2 indictators to read from FIFO: + // 1) fifo_entry_count !=0 + // 2) Data Request bit is on + while( (0 == status.fifo_entry_count) && + (0 == status.data_request) ) { nanosleep( 0, (interval * 1000) ); @@ -338,6 +354,12 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, break; } + + TRACUCOMP( g_trac_i2c, "i2cRead() Wait Loop: status=0x%016llx " + ".fifo_entry_count=%d, .data_request=%d", + status.value, status.fifo_entry_count, status.data_request); + + if( 0 == timeoutCount-- ) { TRACFCOMP( g_trac_i2c, @@ -381,6 +403,10 @@ errlHndl_t i2cRead ( TARGETING::Target * i_target, size, DEVICE_SCOM_ADDRESS( masterAddrs[engine].fifo ) ); + TRACUCOMP( g_trac_i2c, + INFO_MRK"i2cRead() - FIFO[0x%lx] = 0x%016llx", + masterAddrs[engine].fifo, fifo.value); + if( err ) { break; @@ -388,9 +414,11 @@ 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 : byte %d : %.2X", - engine, devAddr, bytesRead, fifo.byte_0 ); + TRACUCOMP( g_trac_i2cr, + "I2C READ DATA : engine %.2X : port %.2x : " + "devAddr %.2X : byte %d : %.2X (0x%lx)", + engine, port, devAddr, bytesRead, + fifo.byte_0, fifo.value ); } if( err ) @@ -449,8 +477,8 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target, // Do Command/Mode reg setups err = i2cSetup( i_target, io_buflen, - false, - true, + false, // i_readNotWrite + true, // i_withStop i_args ); if( err ) @@ -483,9 +511,11 @@ errlHndl_t i2cWrite ( TARGETING::Target * i_target, break; } - TRACSCOMP( g_trac_i2cr, - "I2C WRITE DATA : engine %.2X : devAddr %.2X : byte %d : %.2X", - engine, devAddr, bytesWritten, fifo.byte_0 ); + TRACUCOMP( g_trac_i2cr, + "I2C WRITE DATA : engine %.2X : port %.2X : " + "devAddr %.2X : byte %d : %.2X (0x%lx)", + engine, port, devAddr, bytesWritten, + fifo.byte_0, fifo.value ); } if( err ) @@ -533,7 +563,8 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, uint64_t devAddr = i_args.devAddr; TRACDCOMP( g_trac_i2c, - ENTER_MRK"i2cSetup()" ); + ENTER_MRK"i2cSetup(): buf_len=%d, r_nw=%d, w_stop=%d", + i_buflen, i_readNotWrite, i_withStop ); // Define the registers that we'll use modereg mode; @@ -541,8 +572,6 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, do { - // TODO - Validate some of the arg values passed in - // Wait for Command complete before we start err = i2cWaitForCmdComp( i_target, i_args ); @@ -557,16 +586,22 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, // - port number mode.value = 0x0ull; - // TODO - Hard code to 400KHz until we get attributes in place to get this from - // the target. + + + // @todo RTC:72715 - Add multiple bus speed support + // Hard code to 400KHz until we get attributes in place to get + // this from the target. mode.bit_rate_div = I2C_CLOCK_DIVISOR_400KHZ; mode.port_num = port; + TRACUCOMP( g_trac_i2c,"i2cSetup(): set mode = 0x%lx", mode.value); + err = deviceWrite( i_target, &mode.value, size, DEVICE_SCOM_ADDRESS( masterAddrs[engine].mode ) ); + if( err ) { break; @@ -581,10 +616,19 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, cmd.with_start = 1; cmd.with_stop = (i_withStop ? 1 : 0); cmd.with_addr = 1; - cmd.device_addr = devAddr; + + // cmd.device_addr is 7 bits + // devAddr though is a uint64_t + // -- value stored in LSB byte of uint64_t + // -- LS-bit is unused, creating the 7 bit cmd.device_addr + // So will be masking for LSB, and then shifting to push off LS-bit + cmd.device_addr = (0x000000FF & devAddr) >> 1; + cmd.read_not_write = (i_readNotWrite ? 1 : 0); cmd.length_b = i_buflen; + TRACUCOMP( g_trac_i2c,"i2cSetup(): set cmd = 0x%lx", cmd.value); + err = deviceWrite( i_target, &cmd.value, size, @@ -617,10 +661,13 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target, // Define the registers that we'll use statusreg status; - // TODO - hardcoded to 400KHz for now. + // @todo RTC:72715 - Add multiple bus speed support (set to 400KHz for now) uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ ); uint64_t timeoutCount = I2C_TIMEOUT_COUNT( interval ); + TRACUCOMP(g_trac_i2c, "i2cWaitForCmdComp(): timeoutCount=%d, interval=%d", + timeoutCount, interval); + do { // Check the Command Complete bit @@ -700,6 +747,11 @@ errlHndl_t i2cReadStatusReg ( TARGETING::Target * i_target, break; } + TRACUCOMP(g_trac_i2c,"i2cReadStatusReg(): " + INFO_MRK"status[0x%lx]: 0x%016llx", + masterAddrs[engine].status, o_statusReg.value ); + + // Check for Errors // Per the specification it is a requirement to check for errors each time // that the status register is read. @@ -783,13 +835,6 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target, i_statusVal.value ); } - if( 1 == i_statusVal.data_request ) - { - errorFound = true; - TRACFCOMP( g_trac_i2c, - ERR_MRK"I2C Data Request Error! - status reg: %016llx", - i_statusVal.value ); - } if( 1 == i_statusVal.stop_error ) { @@ -807,6 +852,8 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target, i_statusVal.value ); // Get the Interrupt Register value to add to the log + // - i2cGetInterrupts() adds intRegVal to trace, so it ill be added + // to error log below err = i2cGetInterrupts( i_target, i_args, intRegVal ); @@ -815,6 +862,7 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target, { break; } + } if( errorFound ) @@ -838,10 +886,7 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target, 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. + // @todo RTC:69113 - Add target and I2C traces to the errorlog. break; } @@ -862,7 +907,7 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target, { errlHndl_t err = NULL; - // TODO - hardcoded to 400KHz for now + // @todo RTC:72715 - support multiple bus speeds (set to 400KHz for now) uint64_t interval = I2C_TIMEOUT_INTERVAL( I2C_CLOCK_DIVISOR_400KHZ ); uint64_t timeoutCount = I2C_TIMEOUT_COUNT( interval ); @@ -885,7 +930,17 @@ errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target, break; } - while( I2C_MAX_FIFO_CAPACITY <= status.fifo_entry_count ) + TRACUCOMP( g_trac_i2c, "i2cWaitForFifoSpace(): status=0x%016llx " + "I2C_MAX_FIFO_CAPACITY=%d, status.fifo_entry_count=%d", + status.value, I2C_MAX_FIFO_CAPACITY, + status.fifo_entry_count); + + + // 2 Conditions to wait on: + // 1) FIFO is full + // 2) Data Request bit is not set + while( (I2C_MAX_FIFO_CAPACITY <= status.fifo_entry_count) && + (0 == status.data_request) ) { // FIFO is full, wait before writing any data nanosleep( 0, (interval * 1000) ); @@ -958,6 +1013,11 @@ errlHndl_t i2cReset ( TARGETING::Target * i_target, do { reset.value = 0x0; + + TRACUCOMP(g_trac_i2c,"i2cReset() " + "reset[0x%lx]: 0x%016llx", + masterAddrs[engine].reset, reset.value ); + err = deviceWrite( i_target, &reset.value, size, @@ -1009,12 +1069,18 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target, do { mode.value = 0x0ull; - // TODO - Hard code to 400KHz until we get attributes in place to get this from - // the target. + + // @todo RTC:72715 - support multiple bus speeds + // 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; + TRACUCOMP(g_trac_i2c,"i2cSendSlaveStop(): " + "mode[0x%lx]: 0x%016llx", + masterAddrs[engine].mode, mode.value ); + err = deviceWrite( i_target, &mode.value, size, @@ -1028,6 +1094,10 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target, cmd.value = 0x0ull; cmd.with_stop = 1; + TRACUCOMP(g_trac_i2c,"i2cSendSlaveStop(): " + "cmd[0x%lx]: 0x%016llx", + masterAddrs[engine].command, cmd.value ); + err = deviceWrite( i_target, &cmd.value, size, @@ -1085,6 +1155,10 @@ errlHndl_t i2cGetInterrupts ( TARGETING::Target * i_target, break; } + TRACUCOMP(g_trac_i2c,"i2cGetInterrupts(): " + "interrupt[0x%lx]: 0x%016llx", + masterAddrs[engine].interrupt, intreg.value ); + // Return the data read o_intRegValue = intreg.value; } while( 0 ); @@ -1107,7 +1181,7 @@ errlHndl_t i2cSetupMasters ( void ) modereg mode; size_t size = sizeof(uint64_t); - TRACFCOMP( g_trac_i2c, + TRACDCOMP( g_trac_i2c, ENTER_MRK"i2cSetupMasters()" ); do @@ -1151,7 +1225,7 @@ errlHndl_t i2cSetupMasters ( void ) break; } - TRACDCOMP( g_trac_i2c, + TRACUCOMP( g_trac_i2c, INFO_MRK"I2C Master Centaurs: %d", centList.size() ); @@ -1172,7 +1246,8 @@ errlHndl_t i2cSetupMasters ( void ) // Write Mode Register: mode.value = 0x0ull; - // TODO - Hard code to 400KHz until we get attributes in place + // @todo RTC:72715 - support multiple bus speeds + // Hard code to 400KHz until we get attributes in place // to get this from the target. mode.bit_rate_div = I2C_CLOCK_DIVISOR_400KHZ; err = deviceWrite( centList[centaur], @@ -1238,7 +1313,7 @@ errlHndl_t i2cSetupMasters ( void ) break; } - TRACDCOMP( g_trac_i2c, + TRACUCOMP( g_trac_i2c, INFO_MRK"I2C Master Procs: %d", procList.size() ); @@ -1259,7 +1334,8 @@ errlHndl_t i2cSetupMasters ( void ) // Write Mode Register: mode.value = 0x0ull; - // TODO - Hard code to 400KHz until we get attributes in place + // @todo RTC:72715 - support multiple bus speeds + // Hard code to 400KHz until we get attributes in place // to get this from the target. mode.bit_rate_div = I2C_CLOCK_DIVISOR_400KHZ; err = deviceWrite( procList[proc], @@ -1293,10 +1369,11 @@ errlHndl_t i2cSetupMasters ( void ) } } while( 0 ); - TRACFCOMP( g_trac_i2c, + TRACDCOMP( g_trac_i2c, EXIT_MRK"i2cSetupMasters()" ); return err; } + } // end namespace I2C diff --git a/src/usr/i2c/test/eepromddtest.H b/src/usr/i2c/test/eepromddtest.H index 5c622a7f5..71211c08a 100755 --- a/src/usr/i2c/test/eepromddtest.H +++ b/src/usr/i2c/test/eepromddtest.H @@ -1,25 +1,25 @@ -// 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 +/* 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,2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ #ifndef __EEPROMTEST_H #define __EEPROMTEST_H @@ -37,10 +37,18 @@ #include <i2c/eepromddreasoncodes.H> #include <targeting/common/commontargeting.H> #include "i2ctest.H" +#include "../eepromdd.H" extern trace_desc_t* g_trac_eeprom; +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + using namespace TARGETING; +using namespace EEPROM; + + class EEPROMTest: public CxxTest::TestSuite { @@ -57,32 +65,47 @@ class EEPROMTest: public CxxTest::TestSuite int fails = 0; int num_ops = 0; + uint8_t* testBuffer = NULL; + uint8_t* testBuffer_read = NULL; + + TRACFCOMP( g_trac_eeprom, "testEEPROMReadWrite - Start" ); struct { - uint64_t addr; // Slave Device Address to access + uint64_t offset; // Internal Slave Device Offset 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 }, + + + // MVPD of processor - chip 0 + // Write: + { 0x0000, VPD_PRIMARY, 0xfedcba9876543210, 8, false }, + // Read: + { 0x0000, VPD_PRIMARY, 0xfedcba9876543210, 8, true }, + + // SBE Primary of processor - chip 2 + // Write: + { 0x0100, SBE_PRIMARY, 0xaabb000000000000, 2, false }, + // Read: + { 0x0100, SBE_PRIMARY, 0xaabb000000000000, 2, true }, + + // SBE Backup of processor - chip 3 + // Write: + { 0x00F0, SBE_BACKUP, 0x1122334400000000, 4, false }, + // Read: + { 0x00F0, SBE_BACKUP, 0x1122334400000000, 4, true }, }; const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]); - //@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. + // Skipping EEPROM test altogether in VBU/VPO environment if( TARGETING::is_vpo() ) { return; @@ -98,13 +121,10 @@ class EEPROMTest: public CxxTest::TestSuite 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. + // Uncomment the following code when other I2C devices + // are supported // TARGETING::TargetService& tS = TARGETING::targetService(); // TARGETING::Target * sysTarget = NULL; -// TargetHandleList fullList; // // Get top level system target // tS.getTopLevelTarget( sysTarget ); @@ -159,8 +179,9 @@ class EEPROMTest: public CxxTest::TestSuite fullList[j], &data, testData[i].size, - DEVICE_EEPROM_ADDRESS( testData[i].addr, - testData[i].chip ) ); + DEVICE_EEPROM_ADDRESS( + testData[i].chip, + testData[i].offset)); if( err ) { @@ -189,8 +210,92 @@ class EEPROMTest: public CxxTest::TestSuite } } } + + // Test EEPROM Write of large size + // @todo RTC:69113 - will clean this up: + // 1) Make its own testcase function + // 2) Will use a larger data set: Plan on using 4K header of + // test_signed_container and putting it into un-used area of + // SBE_BACKUP + // 3) Will restore original data just in case + uint64_t testBufLen = 0xF1; + testBuffer = static_cast<uint8_t*>(malloc(testBufLen)); + memset(testBuffer, 0xFE, testBufLen); + + // Randomize the Data a bit + for (uint64_t i = 0; + i < ((testBufLen / 8) + 1); + i++) + testBuffer[i*8] = i; + + for (uint64_t k = 0; k < 8; k++) + testBuffer[k] = k; + + // do the Write operation + err = deviceOp( DeviceFW::WRITE, + fullList[0], + testBuffer, + testBufLen, + DEVICE_EEPROM_ADDRESS(SBE_BACKUP,0x0)); + if( err ) + { + TS_FAIL( "testEEPROMReadWrite - FAIL on large Data Write"); + errlCommit( err, + EEPROM_COMP_ID ); + delete err; + break; + } + + // Read Back and Compare + testBuffer_read = static_cast<uint8_t*>(malloc( testBufLen )); + + // clear read buffer + memset (testBuffer_read, 0, testBufLen); + + // do the Read operation + err = deviceOp( DeviceFW::READ, + fullList[0], + testBuffer_read, + testBufLen, + DEVICE_EEPROM_ADDRESS(SBE_BACKUP,0x0)); + + + if( err ) + { + TS_FAIL( "testEEPROMReadWrite - FAIL on large Data Read"); + errlCommit( err, + EEPROM_COMP_ID ); + delete err; + break; + } + + + // Compare the data + if ( memcmp( testBuffer, testBuffer_read, testBufLen) ) + { + TS_FAIL( "testEEPROMReadWrite - MISCOMPARE on large Data"); + break; + } + else + { + TRACUCOMP( g_trac_eeprom, "testEEPROMReadWrite - large " + "Data R/W Successful"); + } + } while( 0 ); + // Clean up malloc'ed buffers + if ( testBuffer != NULL) + { + free(testBuffer); + } + + if ( testBuffer_read != NULL) + { + free(testBuffer_read); + } + + TRACFCOMP( g_trac_eeprom, "testEEPROMReadWrite - %d/%d fails", fails, num_ops ); @@ -260,7 +365,6 @@ class EEPROMTest: public CxxTest::TestSuite uint64_t data = 0x0ull; size_t dataSize = 8; - const int64_t CHIP_NUM = 20; do { @@ -283,14 +387,14 @@ class EEPROMTest: public CxxTest::TestSuite testTarget, &data, dataSize, - DEVICE_EEPROM_ADDRESS( 0x0, - CHIP_NUM ) ); + DEVICE_EEPROM_ADDRESS( LAST_CHIP_TYPE, + 0x0 ) ); if( NULL == err ) { fails++; TS_FAIL( "Error should've resulted in using EEPROM chip %d!", - CHIP_NUM ); + LAST_CHIP_TYPE ); } else { diff --git a/src/usr/i2c/test/i2ctest.H b/src/usr/i2c/test/i2ctest.H index 95f1cc16d..d98858451 100755 --- a/src/usr/i2c/test/i2ctest.H +++ b/src/usr/i2c/test/i2ctest.H @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/usr/i2c/test/i2ctest.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 +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/i2c/test/i2ctest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ #ifndef __I2CTEST_H #define __I2CTEST_H @@ -42,12 +42,21 @@ extern trace_desc_t* g_trac_i2c; using namespace TARGETING; + +// Used to ignore comparing data on reads +#define I2C_TEST_IGNORE_DATA_COMPARE 0xFFFFFFFFFFFFFFFF + +// @todo RTC:72715: Re-visit the use of this function when we have full +// Attribute support bool isI2CAvailable( TARGETING::Target * i_target ) { bool avail = true; - EepromAddrInfo0 eepromData; - if( i_target->tryGetAttr<ATTR_EEPROM_ADDR_INFO0>( eepromData ) ) + + // Rudimentary Check - Every I2C Master has VPD Primary Attribute + EepromVpdPrimaryInfo eepromData; + if( i_target->tryGetAttr<ATTR_EEPROM_VPD_PRIMARY_INFO>( eepromData ) ) { + if( ( 0x80 == eepromData.port ) && ( 0x80 == eepromData.devAddr ) && ( 0x80 == eepromData.engine ) ) @@ -74,10 +83,10 @@ class I2CTest: public CxxTest::TestSuite * 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. + * Currently only Processor targets are supported in simics. + * + * Add other targets to this testcase when their support is + * added. */ void testI2CReadWrite ( void ) { @@ -99,28 +108,97 @@ class I2CTest: public CxxTest::TestSuite 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 + // if data = I2C_TEST_IGNORE_DATA_COMPARE + // than ignore data compare + size_t size; // Number of Bytes to read/write bool rnw; // Read (true), Write (false) targetType_t type; // Target Type } 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. + + // PROCESSOR TESTS + // -- For Processor SEEPROM's, ONLY USE ENGINE 0 + + // READ All 3 at address 0 for 8 bytes first + // Ignore data compare as we're not sure what's + // been writted there + + // Read SBE Primary: Murano-0, port-0 + { 0x00, 0x00, 0xAC, I2C_TEST_IGNORE_DATA_COMPARE, + 8, true, I2C_PROC_TARGET }, // Read + + // Read SBE Backup: Murano-0, port-0 + { 0x00, 0x00, 0xAE, I2C_TEST_IGNORE_DATA_COMPARE, + 8, true, I2C_PROC_TARGET }, // Read + + // Read From MVPD: Murano-0, port 1 + { 0x01, 0x00, 0xA4, I2C_TEST_IGNORE_DATA_COMPARE, + 8, true, I2C_PROC_TARGET }, // Read data back + + + // Read/Write SBE Primary: Murano-0, port-0 + // Safe to write to first 1K: 0x-0x400 + + { 0x00, 0x00, 0xAC, 0x0000ababcdcdefef, + 8, false, I2C_PROC_TARGET }, // Write data to 0x0000 + + { 0x00, 0x00, 0xAC, 0x0000000000000000, + 2, false, I2C_PROC_TARGET }, // Write addr for read + + { 0x00, 0x00, 0xAc, 0xababcdcdefef0000, + 6, true, I2C_PROC_TARGET }, // Read data back + + { 0x00, 0x00, 0xAC, 0x0003000000000000, + 2, false, I2C_PROC_TARGET }, // Write addr for read + + { 0x00, 0x00, 0xAC, 0xcdefef0000000000, + 3, true, I2C_PROC_TARGET }, // Read data back + + { 0x00, 0x00, 0xAC, 0x0005ee1200000000, + 4, false, I2C_PROC_TARGET }, // Write data to 0x0005 + + { 0x00, 0x00, 0xAC, 0x0005000000000000, + 2, false, I2C_PROC_TARGET }, // Write addr for read + + { 0x00, 0x00, 0xAC, 0xee12000000000000, + 2, true, I2C_PROC_TARGET }, // Read data back + + + + // Read/Write SBE Backup: Murano-0, port-0 + // Safe to write to first 1K: 0x-0x400 + + { 0x00, 0x00, 0xAE, 0x0000ababcdcdefef, + 8, false, I2C_PROC_TARGET }, // Write data to 0x0000 + + { 0x00, 0x00, 0xAE, 0x0000000000000000, + 2, false, I2C_PROC_TARGET }, // Write addr for read + + { 0x00, 0x00, 0xAE, 0xababcdcdefef0000, + 6, true, I2C_PROC_TARGET }, // Read data back + + { 0x00, 0x00, 0xAE, 0x0003000000000000, + 2, false, I2C_PROC_TARGET }, // Write addr for read + + { 0x00, 0x00, 0xAE, 0xcdefef0000000000, + 3, true, I2C_PROC_TARGET }, // Read data back + + { 0x00, 0x00, 0xAE, 0x0005ee1200000000, + 4, false, I2C_PROC_TARGET }, // Write data to 0x0005 + + { 0x00, 0x00, 0xAE, 0x0005000000000000, + 2, false, I2C_PROC_TARGET }, // Write addr for read + + { 0x00, 0x00, 0xAE, 0xee12000000000000, + 2, true, I2C_PROC_TARGET }, // Read data back + + + // MEMBUF TESTS + // Use the following commands when Centaur devices are + // supported in simics. No target date. // Real Centaur Devices // { 0x00, 0x00, 0x51, 0x1111000000000000, // 2, false, I2C_CENTAUR_TARGET }, // Write addr of 0x0000 @@ -134,10 +212,8 @@ class I2CTest: public CxxTest::TestSuite const uint32_t NUM_CMDS = sizeof(testData)/sizeof(testData[0]); - //@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. + + // Skipping I2C test altogether in VBU/VPO environment if( TARGETING::is_vpo() ) { return; @@ -168,7 +244,18 @@ class I2CTest: public CxxTest::TestSuite for( uint32_t i = 0; i < NUM_CMDS; i++ ) { + + // Make sure size is less than or = to 8 bytes + // to fit into data uint64_t data; + if (testData[i].size > 8) + { + TRACFCOMP( g_trac_i2c, + "testI2ReadWrite Size (%d) is greater than" + " 8 bytes. Skipping test %d", + testData[i].size, i ); + continue; + } // if a read, initialize data, else, set data to write if( testData[i].rnw ) @@ -220,7 +307,7 @@ class I2CTest: public CxxTest::TestSuite if( !isI2CAvailable( theTarget ) ) { TRACFCOMP( g_trac_i2c, - "testI2ReadWrite Operation - no i2c function" ); + "testI2CReadWrite Operation - no i2c function" ); continue; @@ -259,8 +346,10 @@ class I2CTest: public CxxTest::TestSuite continue; } - // compare data for the read - if( testData[i].rnw ) + // compare data for the read, but ignore case where + // data = I2C_TEST_IGNORE_DATA_COMPARE + if( ( testData[i].rnw ) && + ( testData[i].data != I2C_TEST_IGNORE_DATA_COMPARE )) { if( data != testData[i].data ) { |