Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / i2c / busses / i2c-i801.c
index 94a30f5..bbb2fbe 100644 (file)
@@ -68,7 +68,6 @@
 /* PCI Address Constants */
 #define SMBBAR         4
 #define SMBHSTCFG      0x040
-#define SMBREV         0x008
 
 /* Host configuration bits for SMBHSTCFG */
 #define SMBHSTCFG_HST_EN       1
@@ -102,68 +101,6 @@ static struct pci_driver i801_driver;
 static struct pci_dev *I801_dev;
 static int isich4;
 
-static int __devinit i801_setup(struct pci_dev *dev)
-{
-       unsigned char temp;
-       int err;
-
-       I801_dev = dev;
-       if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
-           (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
-           (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
-               isich4 = 1;
-       else
-               isich4 = 0;
-
-       err = pci_enable_device(dev);
-       if (err) {
-               dev_err(&dev->dev, "Failed to enable SMBus device (%d)\n",
-                       err);
-               goto exit;
-       }
-
-       /* Determine the address of the SMBus area */
-       i801_smba = pci_resource_start(dev, SMBBAR);
-       if (!i801_smba) {
-               dev_err(&dev->dev, "SMBus base address uninitialized, "
-                       "upgrade BIOS\n");
-               err = -ENODEV;
-               goto exit_disable;
-       }
-
-       err = pci_request_region(dev, SMBBAR, i801_driver.name);
-       if (err) {
-               dev_err(&dev->dev, "Failed to request SMBus region "
-                       "0x%lx-0x%lx\n", i801_smba,
-                       pci_resource_end(dev, SMBBAR));
-               goto exit_disable;
-       }
-
-       pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
-       temp &= ~SMBHSTCFG_I2C_EN;      /* SMBus timing */
-       if (!(temp & SMBHSTCFG_HST_EN)) {
-               dev_warn(&dev->dev, "enabling SMBus device\n");
-               temp |= SMBHSTCFG_HST_EN;
-       }
-       pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
-
-       if (temp & SMBHSTCFG_SMB_SMI_EN)
-               dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n");
-       else
-               dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n");
-
-       pci_read_config_byte(I801_dev, SMBREV, &temp);
-       dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp);
-       dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba);
-
-       return 0;
-
-exit_disable:
-       pci_disable_device(dev);
-exit:
-       return err;
-}
-
 static int i801_transaction(void)
 {
        int temp;
@@ -497,7 +434,7 @@ static u32 i801_func(struct i2c_adapter *adapter)
             | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = i801_access,
        .functionality  = i801_func,
 };
@@ -527,24 +464,80 @@ MODULE_DEVICE_TABLE (pci, i801_ids);
 
 static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+       unsigned char temp;
        int err;
 
-       if ((err = i801_setup(dev)))
-               return err;
+       I801_dev = dev;
+       if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
+           (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
+           (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
+               isich4 = 1;
+       else
+               isich4 = 0;
+
+       err = pci_enable_device(dev);
+       if (err) {
+               dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
+                       err);
+               goto exit;
+       }
+
+       /* Determine the address of the SMBus area */
+       i801_smba = pci_resource_start(dev, SMBBAR);
+       if (!i801_smba) {
+               dev_err(&dev->dev, "SMBus base address uninitialized, "
+                       "upgrade BIOS\n");
+               err = -ENODEV;
+               goto exit;
+       }
+
+       err = pci_request_region(dev, SMBBAR, i801_driver.name);
+       if (err) {
+               dev_err(&dev->dev, "Failed to request SMBus region "
+                       "0x%lx-0x%Lx\n", i801_smba,
+                       (unsigned long long)pci_resource_end(dev, SMBBAR));
+               goto exit;
+       }
+
+       pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
+       temp &= ~SMBHSTCFG_I2C_EN;      /* SMBus timing */
+       if (!(temp & SMBHSTCFG_HST_EN)) {
+               dev_info(&dev->dev, "Enabling SMBus device\n");
+               temp |= SMBHSTCFG_HST_EN;
+       }
+       pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
+
+       if (temp & SMBHSTCFG_SMB_SMI_EN)
+               dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
+       else
+               dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
 
        /* set up the driverfs linkage to our parent device */
        i801_adapter.dev.parent = &dev->dev;
 
        snprintf(i801_adapter.name, I2C_NAME_SIZE,
                "SMBus I801 adapter at %04lx", i801_smba);
-       return i2c_add_adapter(&i801_adapter);
+       err = i2c_add_adapter(&i801_adapter);
+       if (err) {
+               dev_err(&dev->dev, "Failed to add SMBus adapter\n");
+               goto exit_release;
+       }
+       return 0;
+
+exit_release:
+       pci_release_region(dev, SMBBAR);
+exit:
+       return err;
 }
 
 static void __devexit i801_remove(struct pci_dev *dev)
 {
        i2c_del_adapter(&i801_adapter);
        pci_release_region(dev, SMBBAR);
-       pci_disable_device(dev);
+       /*
+        * do not call pci_disable_device(dev) since it can cause hard hangs on
+        * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
+        */
 }
 
 static struct pci_driver i801_driver = {