Commit ca8b9e32 authored by Oleg Ryjkov's avatar Oleg Ryjkov Committed by Jean Delvare

i2c-i801: Various cleanups

* Use defines instead of raw numbers for register bits
* Fix several wrong indentations and trailing whitespace
* Move hwpec timeout checking to a separate function
Signed-off-by: default avatarOleg Ryjkov <olegr@google.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent a92c344d
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
/* /*
SUPPORTED DEVICES PCI ID SUPPORTED DEVICES PCI ID
82801AA 2413 82801AA 2413
82801AB 2423 82801AB 2423
82801BA 2443 82801BA 2443
82801CA/CAM 2483 82801CA/CAM 2483
82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported)
82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported)
6300ESB 25A4 6300ESB 25A4
...@@ -74,6 +74,13 @@ ...@@ -74,6 +74,13 @@
#define SMBHSTCFG_SMB_SMI_EN 2 #define SMBHSTCFG_SMB_SMI_EN 2
#define SMBHSTCFG_I2C_EN 4 #define SMBHSTCFG_I2C_EN 4
/* Auxillary control register bits, ICH4+ only */
#define SMBAUXCTL_CRC 1
#define SMBAUXCTL_E32B 2
/* kill bit for SMBHSTCNT */
#define SMBHSTCNT_KILL 2
/* Other settings */ /* Other settings */
#define MAX_TIMEOUT 100 #define MAX_TIMEOUT 100
#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
...@@ -91,10 +98,15 @@ ...@@ -91,10 +98,15 @@
#define I801_START 0x40 #define I801_START 0x40
#define I801_PEC_EN 0x80 /* ICH4 only */ #define I801_PEC_EN 0x80 /* ICH4 only */
/* I801 Hosts Status register bits */
static int i801_transaction(void); #define SMBHSTSTS_BYTE_DONE 0x80
static int i801_block_transaction(union i2c_smbus_data *data, char read_write, #define SMBHSTSTS_INUSE_STS 0x40
int command, int hwpec); #define SMBHSTSTS_SMBALERT_STS 0x20
#define SMBHSTSTS_FAILED 0x10
#define SMBHSTSTS_BUS_ERR 0x08
#define SMBHSTSTS_DEV_ERR 0x04
#define SMBHSTSTS_INTR 0x02
#define SMBHSTSTS_HOST_BUSY 0x01
static unsigned long i801_smba; static unsigned long i801_smba;
static unsigned char i801_original_hstcfg; static unsigned char i801_original_hstcfg;
...@@ -133,27 +145,32 @@ static int i801_transaction(void) ...@@ -133,27 +145,32 @@ static int i801_transaction(void)
do { do {
msleep(1); msleep(1);
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
result = -1; result = -1;
/* try to stop the current command */
dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
msleep(1);
outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
} }
if (temp & 0x10) { if (temp & SMBHSTSTS_FAILED) {
result = -1; result = -1;
dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
} }
if (temp & 0x08) { if (temp & SMBHSTSTS_BUS_ERR) {
result = -1; result = -1;
dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
"until next hard reset. (sorry!)\n"); "until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */ /* Clock stops and slave is stuck in mid-transmission */
} }
if (temp & 0x04) { if (temp & SMBHSTSTS_DEV_ERR) {
result = -1; result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n"); dev_dbg(&I801_dev->dev, "Error: no response!\n");
} }
...@@ -172,6 +189,24 @@ static int i801_transaction(void) ...@@ -172,6 +189,24 @@ static int i801_transaction(void)
return result; return result;
} }
/* wait for INTR bit as advised by Intel */
static void i801_wait_hwpec(void)
{
int timeout = 0;
int temp;
do {
msleep(1);
temp = inb_p(SMBHSTSTS);
} while ((!(temp & SMBHSTSTS_INTR))
&& (timeout++ < MAX_TIMEOUT));
if (timeout >= MAX_TIMEOUT) {
dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
}
outb_p(temp, SMBHSTSTS);
}
/* All-inclusive block transaction function */ /* All-inclusive block transaction function */
static int i801_block_transaction(union i2c_smbus_data *data, char read_write, static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
int command, int hwpec) int command, int hwpec)
...@@ -227,13 +262,13 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -227,13 +262,13 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
/* Make sure the SMBus host is ready to start transmitting */ /* Make sure the SMBus host is ready to start transmitting */
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
if (i == 1) { if (i == 1) {
/* Erronenous conditions before transaction: /* Erronenous conditions before transaction:
* Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
errmask=0x9f; errmask = 0x9f;
} else { } else {
/* Erronenous conditions during transaction: /* Erronenous conditions during transaction:
* Failed, Bus_Err, Dev_Err, Intr */ * Failed, Bus_Err, Dev_Err, Intr */
errmask=0x1e; errmask = 0x1e;
} }
if (temp & errmask) { if (temp & errmask) {
dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
...@@ -243,7 +278,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -243,7 +278,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
dev_err(&I801_dev->dev, dev_err(&I801_dev->dev,
"Reset failed! (%02x)\n", temp); "Reset failed! (%02x)\n", temp);
result = -1; result = -1;
goto END; goto END;
} }
if (i != 1) { if (i != 1) {
/* if die in middle of block transaction, fail */ /* if die in middle of block transaction, fail */
...@@ -261,33 +296,40 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -261,33 +296,40 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
msleep(1); msleep(1);
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
} }
while ((!(temp & 0x80)) while ((!(temp & SMBHSTSTS_BYTE_DONE))
&& (timeout++ < MAX_TIMEOUT)); && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
/* try to stop the current command */
dev_dbg(&I801_dev->dev, "Terminating the current "
"operation\n");
outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
msleep(1);
outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
SMBHSTCNT);
result = -1; result = -1;
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
} }
if (temp & 0x10) { if (temp & SMBHSTSTS_FAILED) {
result = -1; result = -1;
dev_dbg(&I801_dev->dev, dev_dbg(&I801_dev->dev,
"Error: Failed bus transaction\n"); "Error: Failed bus transaction\n");
} else if (temp & 0x08) { } else if (temp & SMBHSTSTS_BUS_ERR) {
result = -1; result = -1;
dev_err(&I801_dev->dev, "Bus collision!\n"); dev_err(&I801_dev->dev, "Bus collision!\n");
} else if (temp & 0x04) { } else if (temp & SMBHSTSTS_DEV_ERR) {
result = -1; result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n"); dev_dbg(&I801_dev->dev, "Error: no response!\n");
} }
if (i == 1 && read_write == I2C_SMBUS_READ) { if (i == 1 && read_write == I2C_SMBUS_READ) {
len = inb_p(SMBHSTDAT0); len = inb_p(SMBHSTDAT0);
if (len < 1) if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
len = 1; result = -1;
if (len > 32) goto END;
len = 32; }
data->block[0] = len; data->block[0] = len;
} }
...@@ -313,20 +355,9 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -313,20 +355,9 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
goto END; goto END;
} }
if (hwpec) { if (hwpec)
/* wait for INTR bit as advised by Intel */ i801_wait_hwpec();
timeout = 0;
do {
msleep(1);
temp = inb_p(SMBHSTSTS);
} while ((!(temp & 0x02))
&& (timeout++ < MAX_TIMEOUT));
if (timeout >= MAX_TIMEOUT) {
dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
}
outb_p(temp, SMBHSTSTS);
}
result = 0; result = 0;
END: END:
if (command == I2C_SMBUS_I2C_BLOCK_DATA) { if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
...@@ -393,7 +424,10 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, ...@@ -393,7 +424,10 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
return -1; return -1;
} }
outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */ if (hwpec) /* enable/disable hardware PEC */
outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
else
outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
if(block) if(block)
ret = i801_block_transaction(data, read_write, size, hwpec); ret = i801_block_transaction(data, read_write, size, hwpec);
...@@ -405,7 +439,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, ...@@ -405,7 +439,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
/* Some BIOSes don't like it when PEC is enabled at reboot or resume /* Some BIOSes don't like it when PEC is enabled at reboot or resume
time, so we forcibly disable it after every transaction. */ time, so we forcibly disable it after every transaction. */
if (hwpec) if (hwpec)
outb_p(0, SMBAUXCTL); outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
if(block) if(block)
return ret; return ret;
......
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