diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-piix4.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-piix4.c | 22 | 
1 files changed, 22 insertions, 0 deletions
| diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index c2268cdf38e8..e34d82e79b98 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -585,10 +585,29 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,  		 u8 command, int size, union i2c_smbus_data *data)  {  	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap); +	unsigned short piix4_smba = adapdata->smba; +	int retries = MAX_TIMEOUT; +	int smbslvcnt;  	u8 smba_en_lo;  	u8 port;  	int retval; +	/* Request the SMBUS semaphore, avoid conflicts with the IMC */ +	smbslvcnt  = inb_p(SMBSLVCNT); +	do { +		outb_p(smbslvcnt | 0x10, SMBSLVCNT); + +		/* Check the semaphore status */ +		smbslvcnt  = inb_p(SMBSLVCNT); +		if (smbslvcnt & 0x10) +			break; + +		usleep_range(1000, 2000); +	} while (--retries); +	/* SMBus is still owned by the IMC, we give up */ +	if (!retries) +		return -EBUSY; +  	mutex_lock(&piix4_mutex_sb800);  	outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX); @@ -606,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,  	mutex_unlock(&piix4_mutex_sb800); +	/* Release the semaphore */ +	outb_p(smbslvcnt | 0x20, SMBSLVCNT); +  	return retval;  } |