Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / drivers / i2c / busses / i2c-ali1563.c
index 6b68074..fc3e5b0 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/i2c.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 
 #define ALI1563_MAX_TIMEOUT    500
 #define        ALI1563_SMBBA           0x80
@@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
 {
        u32 data;
        int timeout;
+       int status = -EIO;
 
        dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "
                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
@@ -103,13 +105,15 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
                /* Issue 'kill' to host controller */
                outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
                data = inb_p(SMB_HST_STS);
+               status = -ETIMEDOUT;
        }
 
        /* device error - no response, ignore the autodetection case */
-       if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) {
-               dev_err(&a->dev, "Device error!\n");
+       if (data & HST_STS_DEVERR) {
+               if (size != HST_CNTL2_QUICK)
+                       dev_err(&a->dev, "Device error!\n");
+               status = -ENXIO;
        }
-
        /* bus collision */
        if (data & HST_STS_BUSERR) {
                dev_err(&a->dev, "Bus collision!\n");
@@ -122,13 +126,14 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
                outb_p(0x0,SMB_HST_CNTL2);
        }
 
-       return -1;
+       return status;
 }
 
 static int ali1563_block_start(struct i2c_adapter * a)
 {
        u32 data;
        int timeout;
+       int status = -EIO;
 
        dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "
                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
@@ -164,13 +169,20 @@ static int ali1563_block_start(struct i2c_adapter * a)
 
        if (timeout && !(data & HST_STS_BAD))
                return 0;
+
+       if (timeout == 0)
+               status = -ETIMEDOUT;
+
+       if (data & HST_STS_DEVERR)
+               status = -ENXIO;
+
        dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
-               timeout ? "Timeout " : "",
+               timeout ? "" : "Timeout ",
                data & HST_STS_FAIL ? "Transaction Failed " : "",
                data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
                data & HST_STS_DEVERR ? "Device Error " : "",
                !(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
-       return -1;
+       return status;
 }
 
 static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
@@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
 
        /* Map the size to what the chip understands */
        switch (size) {
-       case I2C_SMBUS_PROC_CALL:
-               dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
-               error = -EINVAL;
-               break;
        case I2C_SMBUS_QUICK:
                size = HST_CNTL2_QUICK;
                break;
@@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
        case I2C_SMBUS_BLOCK_DATA:
                size = HST_CNTL2_BLOCK;
                break;
+       default:
+               dev_warn(&a->dev, "Unsupported transaction %d\n", size);
+               error = -EOPNOTSUPP;
+               goto Done;
        }
 
        outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
@@ -345,6 +357,10 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
                }
        }
 
+       if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE,
+                             ali1563_pci_driver.name))
+               goto Err;
+
        if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
                            ali1563_pci_driver.name)) {
                dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
@@ -371,7 +387,7 @@ static const struct i2c_algorithm ali1563_algorithm = {
 static struct i2c_adapter ali1563_adapter = {
        .owner  = THIS_MODULE,
        .id     = I2C_HW_SMBUS_ALI1563,
-       .class  = I2C_CLASS_HWMON,
+       .class  = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo   = &ali1563_algorithm,
 };