diff options
author | Daniel Kurtz <djkurtz@chromium.org> | 2012-07-24 08:13:58 -0400 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-07-24 08:13:58 -0400 |
commit | 70a1cc1952355404a5746c88757f5a444df52b04 (patch) | |
tree | b97d76988c4ac5781faf3edd8bde4021eadc1ad1 /drivers/i2c/busses/i2c-i801.c | |
parent | 0ba8b8bfd56533f0b9af7513c6ebbc10c79ae052 (diff) |
i2c-i801: Check and return errors during byte-by-byte transfers
If an error is detected in the polling loop, abort the transaction and
return an error code.
* DEV_ERR is set if the device does not respond with an acknowledge, and
the SMBus controller times out (minimum 25ms).
* BUS_ERR is set if a bus arbitration collision is detected. In other
words, when the SMBus controller tries to generate a START condition, but
detects that the SMBDATA is being held low, usually by another SMBus/I2C
master.
* FAILED is only set if a transaction is stopped by software (using
the SMBHSTCNT KILL bit).
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-i801.c')
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 05f394938b82..40a50f780972 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -131,9 +131,11 @@ | |||
131 | #define SMBHSTSTS_INTR 0x02 | 131 | #define SMBHSTSTS_INTR 0x02 |
132 | #define SMBHSTSTS_HOST_BUSY 0x01 | 132 | #define SMBHSTSTS_HOST_BUSY 0x01 |
133 | 133 | ||
134 | #define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \ | 134 | #define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \ |
135 | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ | 135 | SMBHSTSTS_DEV_ERR) |
136 | SMBHSTSTS_INTR) | 136 | |
137 | #define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \ | ||
138 | STATUS_ERROR_FLAGS) | ||
137 | 139 | ||
138 | /* Older devices have their ID defined in <linux/pci_ids.h> */ | 140 | /* Older devices have their ID defined in <linux/pci_ids.h> */ |
139 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 | 141 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 |
@@ -384,7 +386,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, | |||
384 | do { | 386 | do { |
385 | usleep_range(250, 500); | 387 | usleep_range(250, 500); |
386 | status = inb_p(SMBHSTSTS(priv)); | 388 | status = inb_p(SMBHSTSTS(priv)); |
387 | } while ((!(status & SMBHSTSTS_BYTE_DONE)) | 389 | } while (!(status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS)) |
388 | && (timeout++ < MAX_RETRIES)); | 390 | && (timeout++ < MAX_RETRIES)); |
389 | 391 | ||
390 | result = i801_check_post(priv, status, timeout > MAX_RETRIES); | 392 | result = i801_check_post(priv, status, timeout > MAX_RETRIES); |