From fd5e3a64c72a176a6610631dfb248aaa5058ae93 Mon Sep 17 00:00:00 2001 From: Andres Lugo Date: Thu, 13 Nov 2014 11:57:02 -0600 Subject: Remove errors in VPD presence detect for eeprom RTC:117048 Change-Id: Ie63fb413cb9efb9d1ea450467efa500613939af2 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14494 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- src/usr/i2c/eepromdd.C | 64 +++++++++ src/usr/i2c/i2c.C | 352 +++++++++++++++++++++++++++++++++++++++++++------ src/usr/i2c/i2c.H | 45 +++++++ 3 files changed, 424 insertions(+), 37 deletions(-) (limited to 'src/usr/i2c') diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index d8c244af6..4fddd2d22 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -46,6 +46,7 @@ #include #include #include +#include #include "eepromdd.H" #include "errlud_i2c.H" @@ -253,6 +254,69 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, return err; } // end eepromPerformOp +//------------------------------------------------------------------- +//eepromPresence +//------------------------------------------------------------------- +bool eepromPresence ( TARGETING::Target * i_target ) +{ + + TRACDCOMP(g_trac_eeprom, ENTER_MRK"eepromPresence()"); + + errlHndl_t err = NULL; + bool l_present = false; + TARGETING::Target * theTarget = NULL; + + eeprom_addr_t i2cInfo; + + i2cInfo.chip = EEPROM::VPD_PRIMARY; + i2cInfo.offset = 0; + do + { + + // Read Attributes needed to complete the operation + err = eepromReadAttributes( i_target, + i2cInfo ); + + if( err ) + { + TRACFCOMP(g_trac_eeprom, + ERR_MRK"Error in eepromPresence::eepromReadAttributes()"); + break; + } + + // Check to see if we need to find a new target for + // the I2C Master + err = eepromGetI2CMasterTarget( i_target, + i2cInfo, + theTarget ); + + if( err ) + { + TRACFCOMP(g_trac_eeprom, + ERR_MRK"Error in eepromPresence::eepromGetI2Cmaster()"); + break; + } + + //Check for the target at the I2C level + l_present = I2C::i2cPresence(theTarget, + i2cInfo.port, + i2cInfo.engine, + i2cInfo.devAddr ); + + if( !l_present ) + { + TRACDCOMP(g_trac_eeprom, + ERR_MRK"i2cPresence returned false! chip NOT present!"); + break; + } + + } while( 0 ); + + TRACDCOMP(g_trac_eeprom, EXIT_MRK"eepromPresence()"); + return l_present; +} + + // ------------------------------------------------------------------ // eepromRead diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C index 50aef65e2..f44993fbe 100755 --- a/src/usr/i2c/i2c.C +++ b/src/usr/i2c/i2c.C @@ -282,7 +282,27 @@ errlHndl_t fsi_i2cPerformOp( DeviceFW::OperationType i_opType, return err; } // end fsi_i2cPerformOp - +// ------------------------------------------------------------------ +// i2cSetSwitches +// ------------------------------------------------------------------ +void i2cSetSwitches( TARGETING::Target * i_target, + misc_args_t & io_args ) +{ + // Set Host vs FSI switches if both values are zero; + // Otherwise, caller should have already set them + if ( ( io_args.switches.useHostI2C == 0 ) && + ( io_args.switches.useFsiI2C == 0 ) ) + { + if ( !( i_target->tryGetAttr + (io_args.switches) ) ) + { + // Default to Host + io_args.switches.useHostI2C = 1; + io_args.switches.useFsiI2C = 0; + } + } + return; +} // ------------------------------------------------------------------ // i2cCommonOp @@ -296,6 +316,7 @@ errlHndl_t i2cCommonOp( DeviceFW::OperationType i_opType, { errlHndl_t err = NULL; errlHndl_t err_reset = NULL; + bool mutex_success = false; mutex_t * engineLock = NULL; bool mutex_needs_unlock = false; @@ -345,42 +366,20 @@ errlHndl_t i2cCommonOp( DeviceFW::OperationType i_opType, break; } - // Set Host vs FSI switches if both values are zero; - // Otherwise, caller should have already set them - if ( ( i_args.switches.useHostI2C == 0 ) && - ( i_args.switches.useFsiI2C == 0 ) ) - { - if ( !( i_target->tryGetAttr - (i_args.switches) ) ) - { - // Default to Host - i_args.switches.useHostI2C = 1; - i_args.switches.useFsiI2C = 0; - } - } + //Set Host vs Fsi switches if not done already + i2cSetSwitches(i_target, i_args); // Get the mutex for the requested engine - switch( i_args.engine ) - { - case 0: - engineLock = i_target->getHbMutexAttr(); - break; - - case 1: - engineLock = i_target->getHbMutexAttr(); - break; - - case 2: - engineLock = i_target->getHbMutexAttr(); - break; + mutex_success = i2cGetEngineMutex( i_target, + i_args, + engineLock ); - default: - TRACFCOMP( g_trac_i2c, - ERR_MRK"Invalid engine for getting Mutex! " - "i_args.engine=%d", i_args.engine ); - // @todo RTC:69113 - Create an error here - break; - }; + if( !mutex_success ) + { + TRACUCOMP( g_trac_i2c, + ERR_MRK"Error in i2cCommonOp::i2cGetEngineMutex()"); + break; + } // Lock on this engine TRACUCOMP( g_trac_i2c, @@ -617,6 +616,241 @@ errlHndl_t i2cCommonOp( DeviceFW::OperationType i_opType, return err; } // end i2cCommonOp + + +// ------------------------------------------------------------------ +// i2cPresence +// ------------------------------------------------------------------ +bool i2cPresence( TARGETING::Target * i_target, + uint64_t i_port, + uint64_t i_engine, + uint64_t i_devAddr ) +{ + TRACUCOMP(g_trac_i2c, ENTER_MRK"i2cPresence()"); + + errlHndl_t err = NULL; + bool l_mutex_success = false; + bool l_present = false; + size_t buflen = 1; + uint64_t reset_error = 0; + misc_args_t args; + + args.port = i_port; + args.engine = i_engine; + args.devAddr = i_devAddr; + args.read_not_write = true; + args.with_stop = true; + args.skip_mode_setup = false; + + //Registers + status_reg_t status; + fifo_reg_t fifo; + + + // Synchronization + mutex_t * engineLock = NULL; + bool mutex_needs_unlock = false; + + // Use Local Variables (timeoutCount gets decremented); + uint64_t l_interval_ns; + uint64_t l_timeoutCount; + + + do + { + + // Get the mutex for the requested engine + l_mutex_success = i2cGetEngineMutex( i_target, + args, + engineLock ); + + if( !l_mutex_success ) + { + TRACUCOMP( g_trac_i2c, + ERR_MRK"Error in i2cPresence::i2cGetEngineMutex()"); + break; + } + + // Lock on this engine + TRACUCOMP( g_trac_i2c, + INFO_MRK"Obtaining lock for engine: %d", + args.engine ); + + (void)mutex_lock( engineLock ); + mutex_needs_unlock = true; + + TRACUCOMP( g_trac_i2c, + INFO_MRK"Locked on engine: %d", + args.engine ); + + + + //Set Host vs FSI switches + i2cSetSwitches( i_target, args ); + + err = i2cSetBusVariables(i_target, + I2C_BUS_SPEED_400KHZ, + args); + + if( err ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"error in i2cPresence::i2cSetBusVariables()"); + break; + } + + err = i2cSetup( i_target, + buflen, + args ); + + if( err ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"error in i2cPresence::i2cSetup()"); + break; + } + + l_interval_ns = args.polling_interval_ns; + l_timeoutCount = args.timeout_count; + + //Check the Command Complete bit + do + { + nanosleep( 0, l_interval_ns ); + + status.value = 0x0ull; + err = i2cRegisterOp( DeviceFW::READ, + i_target, + &status.value, + I2C_REG_STATUS, + args ); + + if( err ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"i2cPresence::error in i2cRegisterOp()"); + break; + } + + if( 0 == l_timeoutCount-- ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"i2cPresence() - Timed out waiting for " + "Command Complete!"); + break; + } + + }while( 0 == status.command_complete && + 0 == status.fifo_entry_count && + 0 == status.nack_received && + 0 == status.data_request ); /* Command has completed + or fifo has data */ + + if( err ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"Error when waiting for Command Complete"); + break; + } + + + if( status.nack_received == 0 ) + { + //The chip was present. + TRACUCOMP(g_trac_i2c, + ERR_MRK"chip found! i2cPresence returning true!"); + + // No nack received so we check the FIFO register + if( status.fifo_entry_count != 0 || status.data_request != 0 ) + { + + //Read data from FIFO register to complete operation. + fifo.value = 0x0ull; + err = i2cRegisterOp( DeviceFW::READ, + i_target, + &fifo.value, + I2C_REG_FIFO, + args ); + + TRACUCOMP(g_trac_i2c, + "i2cPresence() - FIFO = 0x%016llx", + fifo.value); + + if( err ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"Error in i2cPresence::i2cRegisterOp()" + " - FIFO register"); + break; + } + + // -check for command complete + err = i2cWaitForCmdComp(i_target, + args ); + if( err ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"Error in i2cPresence::i2cWaitForCmdComp()"); + break; + } + + } + + l_present = true; + break; + } + else + { + //The chip was not present. + TRACUCOMP(g_trac_i2c, + ERR_MRK"The chip was not present!"); + + // reset error register + err = i2cRegisterOp( DeviceFW::WRITE, + i_target, + &reset_error, + I2C_REG_RESET_ERRORS, + args ); + + if( err ) + { + TRACUCOMP(g_trac_i2c, + ERR_MRK"Error in i2cPresence::i2cRegisterOp()" + " - Error register"); + } + break; + } + + } while ( 0 ); + + if( err ) + { + TRACFCOMP( g_trac_i2c, + ERR_MRK"i2cPresence() Error!" + "tgt=0x%X", + TARGETING::get_huid(i_target)); + errlCommit(err, + I2C_COMP_ID); + + } + + // Check if we need to unlock the mutex + if ( mutex_needs_unlock == true ) + { + // Unlock + (void) mutex_unlock( engineLock ); + TRACUCOMP( g_trac_i2c, + INFO_MRK"Unlocked engine: %d", + args.engine ); + } + + TRACUCOMP(g_trac_i2c, EXIT_MRK"i2cPresence()"); + + return l_present; + +} + + // ------------------------------------------------------------------ // i2cRead // ------------------------------------------------------------------ @@ -998,6 +1232,50 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, return err; } // end i2cSetup + +// ------------------------------------------------------------------ +// i2cGetEngineMutex +// ------------------------------------------------------------------ +bool i2cGetEngineMutex( TARGETING::Target * i_target, + misc_args_t & i_args, + mutex_t *& i_engineLock ) +{ + bool success = true; + + do + { + switch( i_args.engine ) + { + case 0: + i_engineLock = i_target-> + getHbMutexAttr(); + break; + case 1: + i_engineLock = i_target-> + getHbMutexAttr(); + break; + case 2: + i_engineLock = i_target-> + getHbMutexAttr(); + break; + + default: + TRACFCOMP( g_trac_i2c, + ERR_MRK"Invalid engine for getting Mutex! " + "i_args.engine=%d", i_args.engine ); + success = false; + assert(false, "i2c.C: Invalid engine for getting Mutex!" + "i_args.engine=%d", i_args.engine ); + + break; + }; + + }while( 0 ); + + return success; +} + + // ------------------------------------------------------------------ // i2cWaitForCmdComp // ------------------------------------------------------------------ @@ -1013,7 +1291,7 @@ errlHndl_t i2cWaitForCmdComp ( TARGETING::Target * i_target, // Define the registers that we'll use status_reg_t status; - // Use Local Variables (timeoutCount gets derecmented) + // Use Local Variables (timeoutCount gets decremented) uint64_t interval_ns = i_args.polling_interval_ns; uint64_t timeoutCount = i_args.timeout_count; @@ -2176,7 +2454,7 @@ errlHndl_t i2cSetBusVariables ( TARGETING::Target * i_target, { errlHndl_t err = NULL; - TRACDCOMP( g_trac_i2c, + TRACUCOMP( g_trac_i2c, ENTER_MRK"i2cSetBusVariables(): i_speed=%d", i_speed ); @@ -2250,7 +2528,7 @@ errlHndl_t i2cSetBusVariables ( TARGETING::Target * i_target, i_speed, io_args.bus_speed, io_args.bit_rate_divisor, io_args.polling_interval_ns, io_args.timeout_count); - TRACDCOMP( g_trac_i2c, + TRACUCOMP( g_trac_i2c, EXIT_MRK"i2cSetBusVariables()" ); return err; diff --git a/src/usr/i2c/i2c.H b/src/usr/i2c/i2c.H index 8413ef9b0..e400e2756 100755 --- a/src/usr/i2c/i2c.H +++ b/src/usr/i2c/i2c.H @@ -154,6 +154,7 @@ enum i2c_reg_offset_t I2C_REG_INTERRUPT = 6, I2C_REG_STATUS = 7, I2C_REG_RESET = 7, + I2C_REG_RESET_ERRORS= 8, I2C_REG_SET_SCL = 9, I2C_REG_RESET_SCL = 11, I2C_REG_SET_SDA = 12, @@ -541,6 +542,19 @@ errlHndl_t fsi_i2cPerformOp( DeviceFW::OperationType i_opType, int64_t i_accessType, va_list i_args ); +/** + * @brief This function sets the Host vs FSI switches if the user has not + * already. + * + * param[in] i_target - The target device + * + * @param[in/out] io_args - The argument object to set the switches for + * + * @return void + */ +void i2cSetSwitches( TARGETING::Target * i_target, + misc_args_t & io_args); + /** * * @brief Performs the actual I2C operation. @@ -643,6 +657,23 @@ errlHndl_t i2cSetup ( TARGETING::Target * i_target, size_t & i_buflen, misc_args_t & i_args); + +/** + * @brief This function gets the appropriate engine mutex for a given target. + * + * @param[in] i_target - The target to get the mutex for. + * + * @param[in] i_args - Structure containing arguments needed to determine + * the correct engine mutex. + * + * @param[in/out] i_engineLock - The mutex. + * + * @return bool - True if valid mutex is found, False otherwise. + */ +bool i2cGetEngineMutex( TARGETING::Target * i_target, + misc_args_t & i_args, + mutex_t *& i_engineLock ); + /** * @brief This function will wait for the command to be complete or * timeout waiting before returning. @@ -711,6 +742,20 @@ errlHndl_t i2cCheckForErrors ( TARGETING::Target * i_target, errlHndl_t i2cWaitForFifoSpace ( TARGETING::Target * i_target, misc_args_t & i_args); +/** + * @brief This function manually sends a stop signal + * + * @param[in] i_target - The i2c Target + * + * @param[in] i_args - Structure containing argumets needed for a command + * transaction + * + * @return errHndl_t - NULL if successful, otherwise a pointer to the error + * log. + */ +errlHndl_t i2cSendStopSignal(TARGETING::Target * i_target, + misc_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 -- cgit v1.2.1