summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c/i2c.C
diff options
context:
space:
mode:
authorMike Baiocchi <mbaiocch@us.ibm.com>2018-01-25 09:53:29 -0600
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2018-01-26 17:03:43 -0500
commit079068a0dd84a877e3aa9b382b4dcaebecfa5f37 (patch)
tree54aa28b9d03bd20838147ed12d88f02d4576c964 /src/usr/i2c/i2c.C
parentc9a86977d3eb0902e16c51338da83069117d4b7d (diff)
downloadtalos-hostboot-079068a0dd84a877e3aa9b382b4dcaebecfa5f37.tar.gz
talos-hostboot-079068a0dd84a877e3aa9b382b4dcaebecfa5f37.zip
I2C Reset Path: Add Poll of SCL High Before Issuing Stop Command
At the end of the I2C reset sequence, a 'stop' command is sent to each port on the master that was reset. Before sending this 'stop' command, a poll has been added such to check that SCL (clock line) is high. This addresses a known issue with current TPMs. Change-Id: I13b199f5b4d10d7224d3ccc5d1a8baaecb4f2326 CQ: SW405816 Backport: release-fips910 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/52636 Reviewed-by: Christopher J. Engel <cjengel@us.ibm.com> Reviewed-by: Timothy R. Block <block@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr/i2c/i2c.C')
-rwxr-xr-xsrc/usr/i2c/i2c.C55
1 files changed, 54 insertions, 1 deletions
diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C
index 762d66ec2..61256f3bd 100755
--- a/src/usr/i2c/i2c.C
+++ b/src/usr/i2c/i2c.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2017 */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -80,6 +80,9 @@ TRAC_INIT( & g_trac_i2cr, "I2CR", KILOBYTE );
// Defines
// ----------------------------------------------
#define I2C_RESET_DELAY_NS (5 * NS_PER_MSEC) // Sleep for 5 ms after reset
+#define I2C_RESET_POLL_DELAY_NS (500 * 1000) // Sleep for 500usec per poll
+#define I2C_RESET_POLL_DELAY_TOTAL_NS (500 * NS_PER_MSEC) // Total time to poll
+
#define P9_MASTER_PORTS 13 // Number of Ports used in P9
#define CENTAUR_MASTER_ENGINES 1 // Number of Engines in a Centaur
#define MAX_NACK_RETRIES 3
@@ -2791,6 +2794,7 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
// Master Registers
mode_reg_t mode;
command_reg_t cmd;
+ status_reg_t status_reg;
uint64_t l_speed = I2C_BUS_SPEED_FROM_MRW;
// I2C Bus Speed Array
@@ -2897,6 +2901,55 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
continue;
}
+ // Look for Clock Line (SCL) High such that 'stop' cmd will work
+ status_reg.value = 0x0ull;
+ size_t delay_ns = 0;
+ for ( ;
+ delay_ns <= I2C_RESET_POLL_DELAY_TOTAL_NS;
+ delay_ns += I2C_RESET_POLL_DELAY_NS)
+ {
+ err = i2cRegisterOp( DeviceFW::READ,
+ i_target,
+ &status_reg.value,
+ I2C_REG_STATUS,
+ i_args );
+
+ if( err )
+ {
+ TRACFCOMP( g_trac_i2c,
+ ERR_MRK"Reading I2C Status Reg Failed!!" );
+ break;
+ }
+
+ if ( status_reg.scl_input_level != 0 )
+ {
+ break;
+ }
+
+ // Sleep before polling again
+ nanosleep( 0, I2C_RESET_POLL_DELAY_NS );
+
+ }
+
+ if ( err )
+ {
+ // We still need to send the slave stop to the other ports
+ // on this I2C engine
+ errlCommit( err, I2C_COMP_ID );
+ continue;
+ }
+
+ if ( delay_ns > I2C_RESET_POLL_DELAY_TOTAL_NS )
+ {
+ // Even though we don't see the Clock Line High, just
+ // trace a warning here and continue to send the 'stop' cmd
+ TRACFCOMP( g_trac_i2c, INFO_MRK"i2cSendSlaveStop(): "
+ "Not seeing SCL High 0x%.16llX after 0x%X ns of "
+ "polling (max=0x%X)",
+ status_reg.value, delay_ns,
+ I2C_RESET_POLL_DELAY_TOTAL_NS );
+ }
+
cmd.value = 0x0ull;
cmd.with_stop = 1;
OpenPOWER on IntegriCloud