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
...@@ -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)
...@@ -229,11 +264,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -229,11 +264,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
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). "
...@@ -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