summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c
diff options
context:
space:
mode:
authorAndres Lugo <aalugore@us.ibm.com>2014-11-13 11:57:02 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2014-12-09 12:03:20 -0600
commitfd5e3a64c72a176a6610631dfb248aaa5058ae93 (patch)
treeb4b3e77def3a08f86d2453922605b202ba595365 /src/usr/i2c
parentd1f7475ae5459ab567a361dd6cbb4ef1278764b3 (diff)
downloadtalos-hostboot-fd5e3a64c72a176a6610631dfb248aaa5058ae93.tar.gz
talos-hostboot-fd5e3a64c72a176a6610631dfb248aaa5058ae93.zip
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 <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/i2c')
-rwxr-xr-xsrc/usr/i2c/eepromdd.C64
-rwxr-xr-xsrc/usr/i2c/i2c.C352
-rwxr-xr-xsrc/usr/i2c/i2c.H45
3 files changed, 424 insertions, 37 deletions
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 <i2c/eepromddreasoncodes.H>
#include <i2c/eepromif.H>
#include <i2c/i2creasoncodes.H>
+#include <i2c/i2cif.H>
#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<TARGETING::ATTR_I2C_SWITCHES>
+ (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<TARGETING::ATTR_I2C_SWITCHES>
- (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<TARGETING::ATTR_I2C_ENGINE_MUTEX_0>();
- break;
-
- case 1:
- engineLock = i_target->getHbMutexAttr<TARGETING::ATTR_I2C_ENGINE_MUTEX_1>();
- break;
-
- case 2:
- engineLock = i_target->getHbMutexAttr<TARGETING::ATTR_I2C_ENGINE_MUTEX_2>();
- 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<TARGETING::ATTR_I2C_ENGINE_MUTEX_0>();
+ break;
+ case 1:
+ i_engineLock = i_target->
+ getHbMutexAttr<TARGETING::ATTR_I2C_ENGINE_MUTEX_1>();
+ break;
+ case 2:
+ i_engineLock = i_target->
+ getHbMutexAttr<TARGETING::ATTR_I2C_ENGINE_MUTEX_2>();
+ 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,
@@ -542,6 +543,19 @@ errlHndl_t fsi_i2cPerformOp( DeviceFW::OperationType i_opType,
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.
* NOTE: This function handles the MUTEX used to avoid deadlocks.
@@ -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.
@@ -712,6 +743,20 @@ 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
* slave device.
OpenPOWER on IntegriCloud