diff options
Diffstat (limited to 'drivers/i2c/i2c-core-base.c')
| -rw-r--r-- | drivers/i2c/i2c-core-base.c | 13 | 
1 files changed, 11 insertions, 2 deletions
| diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 31d16ada6e7d..15c95aaa484c 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -198,7 +198,16 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)  		val = !val;  		bri->set_scl(adap, val); -		ndelay(RECOVERY_NDELAY); + +		/* +		 * If we can set SDA, we will always create STOP here to ensure +		 * the additional pulses will do no harm. This is achieved by +		 * letting SDA follow SCL half a cycle later. +		 */ +		ndelay(RECOVERY_NDELAY / 2); +		if (bri->set_sda) +			bri->set_sda(adap, val); +		ndelay(RECOVERY_NDELAY / 2);  	}  	/* check if recovery actually succeeded */ @@ -615,7 +624,7 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)  static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,  				 unsigned int flags)  { -	rt_mutex_lock(&adapter->bus_lock); +	rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter));  }  /** |