Commit 70a1cc19 authored by Daniel Kurtz's avatar Daniel Kurtz Committed by Jean Delvare

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: default avatarDaniel Kurtz <djkurtz@chromium.org>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 0ba8b8bf
......@@ -131,9 +131,11 @@
#define SMBHSTSTS_INTR 0x02
#define SMBHSTSTS_HOST_BUSY 0x01
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
SMBHSTSTS_INTR)
#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
SMBHSTSTS_DEV_ERR)
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \
STATUS_ERROR_FLAGS)
/* Older devices have their ID defined in <linux/pci_ids.h> */
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
......@@ -384,7 +386,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
do {
usleep_range(250, 500);
status = inb_p(SMBHSTSTS(priv));
} while ((!(status & SMBHSTSTS_BYTE_DONE))
} while (!(status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS))
&& (timeout++ < MAX_RETRIES));
result = i801_check_post(priv, status, timeout > MAX_RETRIES);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment