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: Oleg Ryjkov <olegr@google.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
parent
a92c344d8c
commit
ca8b9e32a1
1 changed files with 75 additions and 41 deletions
|
@ -22,10 +22,10 @@
|
|||
|
||||
/*
|
||||
SUPPORTED DEVICES PCI ID
|
||||
82801AA 2413
|
||||
82801AB 2423
|
||||
82801BA 2443
|
||||
82801CA/CAM 2483
|
||||
82801AA 2413
|
||||
82801AB 2423
|
||||
82801BA 2443
|
||||
82801CA/CAM 2483
|
||||
82801DB 24C3 (HW PEC supported, 32 byte buffer not supported)
|
||||
82801EB 24D3 (HW PEC supported, 32 byte buffer not supported)
|
||||
6300ESB 25A4
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
if (i == 1) {
|
||||
/* Erronenous conditions before transaction:
|
||||
/* Erronenous conditions before transaction:
|
||||
* Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
|
||||
errmask=0x9f;
|
||||
errmask = 0x9f;
|
||||
} else {
|
||||
/* Erronenous conditions during transaction:
|
||||
/* 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). "
|
||||
|
@ -243,7 +278,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
|
|||
dev_err(&I801_dev->dev,
|
||||
"Reset failed! (%02x)\n", temp);
|
||||
result = -1;
|
||||
goto END;
|
||||
goto END;
|
||||
}
|
||||
if (i != 1) {
|
||||
/* 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,
|
|||
msleep(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
}
|
||||
while ((!(temp & 0x80))
|
||||
&& (timeout++ < MAX_TIMEOUT));
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue