]> err.no Git - linux-2.6/commitdiff
i2c-i801: Various cleanups
authorOleg Ryjkov <olegr@google.com>
Thu, 12 Jul 2007 12:12:31 +0000 (14:12 +0200)
committerJean Delvare <khali@hyperion.delvare>
Thu, 12 Jul 2007 12:12:31 +0000 (14:12 +0200)
* 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>
drivers/i2c/busses/i2c-i801.c

index 611b57192c9618ac6159267b4371f89835efd75c..d5e12a4f01b01bcceabb1a1765c896aaf4c1cec4 100644 (file)
 
 /*
     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
 #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 */
 #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;