summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c/i2c.C
diff options
context:
space:
mode:
authorNick Bofferding <bofferdn@us.ibm.com>2018-07-13 15:11:28 -0500
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2018-07-17 17:32:02 -0400
commitea3d3a6c4f987575e6b5354072003e9b3d8522fc (patch)
tree57173aceb9c9dcdf987ee7b56522c4fcfc1c088f /src/usr/i2c/i2c.C
parent85367d8e40ddd620dbe80a38e792ef04d49933aa (diff)
downloadtalos-hostboot-ea3d3a6c4f987575e6b5354072003e9b3d8522fc.tar.gz
talos-hostboot-ea3d3a6c4f987575e6b5354072003e9b3d8522fc.zip
I2C: Inhibit sending slave stop command when SDA and SCL are not both asserted
In I2C reset sequence, code previously only waited until SCL line asserted and, on timeout, sent a slave stop command anyway. This caused situations where the I2C master could get locked up for long periods when misbehaving I2C devices were holding down the clock line. This change waits for both SCL and SDA to go high before invoking the slave stop command, and if that wait times out, skips sending the slave stop. Change-Id: I9cbb783dbaecb3df2cf1171f969e79749f3cd157 CQ: SW437713 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/62436 Tested-by: Jenkins Server <pfd-jenkins+hostboot@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.C34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/usr/i2c/i2c.C b/src/usr/i2c/i2c.C
index eb8bb2a17..3b1510fed 100755
--- a/src/usr/i2c/i2c.C
+++ b/src/usr/i2c/i2c.C
@@ -2864,7 +2864,8 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
continue;
}
- // Look for Clock Line (SCL) High such that 'stop' cmd will work
+ // Look for clock line (SCL) and data line (SDA) to be high
+ // such that the 'stop' command will work
status_reg.value = 0x0ull;
size_t delay_ns = 0;
for ( ;
@@ -2884,7 +2885,8 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
break;
}
- if ( status_reg.scl_input_level != 0 )
+ if ( (status_reg.scl_input_level != 0)
+ && (status_reg.sda_input_level != 0) )
{
break;
}
@@ -2904,13 +2906,27 @@ errlHndl_t i2cSendSlaveStop ( TARGETING::Target * i_target,
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 %d ns of "
- "polling (max=%d)",
- status_reg.value, delay_ns,
- I2C_RESET_POLL_DELAY_TOTAL_NS );
+ // We don't see both clock and data lines high; in this case
+ // it's not likely for a slave stop command to work. One
+ // possible nasty side-effect of attempting slave stop is the
+ // I2C master can become indefinitely busy and prevent writes
+ // to the mode register from completing. Just continue to the
+ // next port.
+ TRACFCOMP( g_trac_i2c, ERR_MRK"i2cSendSlaveStop(): "
+ "Not seeing both SCL (%d) and SDA (%d) high "
+ "after %d ns of polling (max=%d). "
+ "Full status register = 0x%.16llX. "
+ "Inhibiting sending slave stop to e%/p% for "
+ "HUID 0x%08X.",
+ status_reg.scl_input_level,
+ status_reg.sda_input_level,
+ delay_ns,
+ I2C_RESET_POLL_DELAY_TOTAL_NS,
+ status_reg.value,
+ i_args.engine,
+ port,
+ TARGETING::get_huid(i_target));
+ continue;
}
cmd.value = 0x0ull;
OpenPOWER on IntegriCloud