Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
[pandora-kernel.git] / drivers / i2c / busses / i2c-sis630.c
index dec0baf..e7c4b79 100644 (file)
@@ -1,7 +1,4 @@
 /*
-    i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
-
     Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
 
     This program is free software; you can redistribute it and/or modify
@@ -55,6 +52,7 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 /* SIS630 SMBus registers */
@@ -134,9 +132,9 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc
 
                if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
                        dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
-                       return -1;
+                       return -EBUSY;
                 } else {
-                       dev_dbg(&adap->dev, "Successfull!\n");
+                       dev_dbg(&adap->dev, "Successful!\n");
                }
         }
 
@@ -177,17 +175,17 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
                dev_dbg(&adap->dev, "SMBus Timeout!\n");
-               result = -1;
+               result = -ETIMEDOUT;
        }
 
        if (temp & 0x02) {
                dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
-               result = -1;
+               result = -ENXIO;
        }
 
        if (temp & 0x04) {
                dev_err(&adap->dev, "Bus collision!\n");
-               result = -1;
+               result = -EIO;
                /*
                  TBD: Datasheet say:
                  the software should clear this bit and restart SMBUS operation.
@@ -250,8 +248,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
                        if (i==8 || (len<8 && i==len)) {
                                dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i);
                                /* first transaction */
-                               if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock))
-                                       return -1;
+                               rc = sis630_transaction_start(adap,
+                                               SIS630_BLOCK_DATA, &oldclock);
+                               if (rc)
+                                       return rc;
                        }
                        else if ((i-1)%8 == 7 || i==len) {
                                dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
@@ -264,9 +264,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
                                        */
                                        sis630_write(SMB_STS,0x10);
                                }
-                               if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
+                               rc = sis630_transaction_wait(adap,
+                                               SIS630_BLOCK_DATA);
+                               if (rc) {
                                        dev_dbg(&adap->dev, "trans_wait failed\n");
-                                       rc = -1;
                                        break;
                                }
                        }
@@ -275,13 +276,14 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
        else {
                /* read request */
                data->block[0] = len = 0;
-               if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) {
-                       return -1;
-               }
+               rc = sis630_transaction_start(adap,
+                               SIS630_BLOCK_DATA, &oldclock);
+               if (rc)
+                       return rc;
                do {
-                       if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
+                       rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
+                       if (rc) {
                                dev_dbg(&adap->dev, "trans_wait failed\n");
-                               rc = -1;
                                break;
                        }
                        /* if this first transaction then read byte count */
@@ -311,11 +313,13 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
        return rc;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
                         unsigned short flags, char read_write,
                         u8 command, int size, union i2c_smbus_data *data)
 {
+       int status;
+
        switch (size) {
                case I2C_SMBUS_QUICK:
                        sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
@@ -350,13 +354,14 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
                        size = SIS630_BLOCK_DATA;
                        return sis630_block_data(adap, data, read_write);
                default:
-                       printk("Unsupported I2C size\n");
-                       return -1;
-                       break;
+                       dev_warn(&adap->dev, "Unsupported transaction %d\n",
+                                size);
+                       return -EOPNOTSUPP;
        }
 
-       if (sis630_transaction(adap, size))
-               return -1;
+       status = sis630_transaction(adap, size);
+       if (status)
+               return status;
 
        if ((size != SIS630_PCALL) &&
                ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
@@ -372,9 +377,6 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
                case SIS630_WORD_DATA:
                        data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
                        break;
-               default:
-                       return -1;
-                       break;
        }
 
        return 0;
@@ -433,6 +435,11 @@ static int sis630_setup(struct pci_dev *sis630_dev)
 
        dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
 
+       retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
+                                  sis630_driver.name);
+       if (retval)
+               goto exit;
+
        /* Everything is happy, let's grab the memory and set things up. */
        if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
                            sis630_driver.name)) {
@@ -457,7 +464,8 @@ static const struct i2c_algorithm smbus_algorithm = {
 
 static struct i2c_adapter sis630_adapter = {
        .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON,
+       .id             = I2C_HW_SMBUS_SIS630,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
@@ -476,7 +484,7 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i
                return -ENODEV;
        }
 
-       /* set up the driverfs linkage to our parent device */
+       /* set up the sysfs linkage to our parent device */
        sis630_adapter.dev.parent = &dev->dev;
 
        sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",