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 8e1e3f8..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);
@@ -314,35 +326,11 @@ static u32 ali1563_func(struct i2c_adapter * a)
 }
 
 
-static void ali1563_enable(struct pci_dev * dev)
-{
-       u16 ctrl;
-
-       pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
-       ctrl |= 0x7;
-       pci_write_config_word(dev,ALI1563_SMBBA,ctrl);
-}
-
 static int __devinit ali1563_setup(struct pci_dev * dev)
 {
        u16 ctrl;
 
        pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
-       printk("ali1563: SMBus control = %04x\n",ctrl);
-
-       /* Check if device is even enabled first */
-       if (!(ctrl & ALI1563_SMB_IOEN)) {
-               dev_warn(&dev->dev,"I/O space not enabled, trying manually\n");
-               ali1563_enable(dev);
-       }
-       if (!(ctrl & ALI1563_SMB_IOEN)) {
-               dev_warn(&dev->dev,"I/O space still not enabled, giving up\n");
-               goto Err;
-       }
-       if (!(ctrl & ALI1563_SMB_HOSTEN)) {
-               dev_warn(&dev->dev,"Host Controller not enabled\n");
-               goto Err;
-       }
 
        /* SMB I/O Base in high 12 bits and must be aligned with the
         * size of the I/O space. */
@@ -351,11 +339,35 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
                dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
                goto Err;
        }
+
+       /* Check if device is enabled */
+       if (!(ctrl & ALI1563_SMB_HOSTEN)) {
+               dev_warn(&dev->dev, "Host Controller not enabled\n");
+               goto Err;
+       }
+       if (!(ctrl & ALI1563_SMB_IOEN)) {
+               dev_warn(&dev->dev, "I/O space not enabled, trying manually\n");
+               pci_write_config_word(dev, ALI1563_SMBBA,
+                                     ctrl | ALI1563_SMB_IOEN);
+               pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
+               if (!(ctrl & ALI1563_SMB_IOEN)) {
+                       dev_err(&dev->dev, "I/O space still not enabled, "
+                               "giving up\n");
+                       goto Err;
+               }
+       }
+
+       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_warn(&dev->dev,"Could not allocate I/O space");
+               dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
+                       ali1563_smba);
                goto Err;
        }
+       dev_info(&dev->dev, "Found ALi1563 SMBus at 0x%04x\n", ali1563_smba);
 
        return 0;
 Err:
@@ -374,7 +386,8 @@ static const struct i2c_algorithm ali1563_algorithm = {
 
 static struct i2c_adapter ali1563_adapter = {
        .owner  = THIS_MODULE,
-       .class  = I2C_CLASS_HWMON,
+       .id     = I2C_HW_SMBUS_ALI1563,
+       .class  = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo   = &ali1563_algorithm,
 };
 
@@ -384,13 +397,18 @@ static int __devinit ali1563_probe(struct pci_dev * dev,
        int error;
 
        if ((error = ali1563_setup(dev)))
-               return error;
+               goto exit;
        ali1563_adapter.dev.parent = &dev->dev;
        sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x",
                ali1563_smba);
        if ((error = i2c_add_adapter(&ali1563_adapter)))
-               ali1563_shutdown(dev);
-       printk("%s: Returning %d\n",__FUNCTION__,error);
+               goto exit_shutdown;
+       return 0;
+
+exit_shutdown:
+       ali1563_shutdown(dev);
+exit:
+       dev_warn(&dev->dev, "ALi1563 SMBus probe failed (%d)\n", error);
        return error;
 }