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 @@
#define SMBHSTCFG_SMB_SMI_EN 2
#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 */
#define MAX_TIMEOUT 100
#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
......@@ -91,10 +98,15 @@
#define I801_START 0x40
#define I801_PEC_EN 0x80 /* ICH4 only */
static int i801_transaction(void);
static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
int command, int hwpec);
/* I801 Hosts Status register bits */
#define SMBHSTSTS_BYTE_DONE 0x80
#define SMBHSTSTS_INUSE_STS 0x40
#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 char i801_original_hstcfg;
......@@ -133,27 +145,32 @@ static int i801_transaction(void)
do {
msleep(1);
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 (timeout >= MAX_TIMEOUT) {
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
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;
dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
}
if (temp & 0x08) {
if (temp & SMBHSTSTS_BUS_ERR) {
result = -1;
dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
"until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */
}
if (temp & 0x04) {
if (temp & SMBHSTSTS_DEV_ERR) {
result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n");
}
......@@ -172,6 +189,24 @@ static int i801_transaction(void)
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 */
static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
int command, int hwpec)
......@@ -229,11 +264,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
if (i == 1) {
/* Erronenous conditions before transaction:
* Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
errmask=0x9f;
errmask = 0x9f;
} else {
/* Erronenous conditions during transaction:
* Failed, Bus_Err, Dev_Err, Intr */
errmask=0x1e;
errmask = 0x1e;
}
if (temp & errmask) {
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,
msleep(1);
temp = inb_p(SMBHSTSTS);
}
while ((!(temp & 0x80))
while ((!(temp & SMBHSTSTS_BYTE_DONE))
&& (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
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;
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
}
if (temp & 0x10) {
if (temp & SMBHSTSTS_FAILED) {
result = -1;
dev_dbg(&I801_dev->dev,
"Error: Failed bus transaction\n");
} else if (temp & 0x08) {
} else if (temp & SMBHSTSTS_BUS_ERR) {
result = -1;
dev_err(&I801_dev->dev, "Bus collision!\n");
} else if (temp & 0x04) {
} else if (temp & SMBHSTSTS_DEV_ERR) {
result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n");
}
if (i == 1 && read_write == I2C_SMBUS_READ) {
len = inb_p(SMBHSTDAT0);
if (len < 1)
len = 1;
if (len > 32)
len = 32;
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
result = -1;
goto END;
}
data->block[0] = len;
}
......@@ -313,20 +355,9 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
goto END;
}
if (hwpec) {
/* wait for INTR bit as advised by Intel */
timeout = 0;
do {
msleep(1);
temp = inb_p(SMBHSTSTS);
} while ((!(temp & 0x02))
&& (timeout++ < MAX_TIMEOUT));
if (hwpec)
i801_wait_hwpec();
if (timeout >= MAX_TIMEOUT) {
dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
}
outb_p(temp, SMBHSTSTS);
}
result = 0;
END:
if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
......@@ -393,7 +424,10 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
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)
ret = i801_block_transaction(data, read_write, size, hwpec);
......@@ -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
time, so we forcibly disable it after every transaction. */
if (hwpec)
outb_p(0, SMBAUXCTL);
outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
if(block)
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