linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / i2c / busses / i2c-piix4.c
index 8f2f65b..692f473 100644 (file)
@@ -22,7 +22,7 @@
 /*
    Supports:
        Intel PIIX4, 440MX
-       Serverworks OSB4, CSB5, CSB6, HT-1000
+       Serverworks OSB4, CSB5, CSB6
        SMSC Victory66
 
    Note: we assume there can only be one device, with one SMBus interface.
@@ -102,6 +102,13 @@ MODULE_PARM_DESC(force_addr,
                 "Forcibly enable the PIIX4 at the given address. "
                 "EXTREMELY DANGEROUS!");
 
+/* If fix_hstcfg is set to anything different from 0, we reset one of the
+   registers to be a valid value. */
+static int fix_hstcfg;
+module_param (fix_hstcfg, int, 0);
+MODULE_PARM_DESC(fix_hstcfg,
+               "Fix config register. Needed on some boards (Force CPCI735).");
+
 static int piix4_transaction(void);
 
 static unsigned short piix4_smba;
@@ -130,7 +137,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
        /* Don't access SMBus on IBM systems which get corrupted eeproms */
        if (dmi_check_system(piix4_dmi_table) &&
                        PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
-               dev_err(&PIIX4_dev->dev, "IBM system detected; this module "
+               dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module "
                        "may corrupt your serial eeprom! Refusing to load "
                        "module!\n");
                return -EPERM;
@@ -159,6 +166,22 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
 
        pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
 
+       /* Some BIOS will set up the chipset incorrectly and leave a register
+          in an undefined state (causing I2C to act very strangely). */
+       if (temp & 0x02) {
+               if (fix_hstcfg) {
+                       dev_info(&PIIX4_dev->dev, "Working around buggy BIOS "
+                                       "(I2C)\n");
+                       temp &= 0xfd;
+                       pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp);
+               } else {
+                       dev_info(&PIIX4_dev->dev, "Unusual config register "
+                                       "value\n");
+                       dev_info(&PIIX4_dev->dev, "Try using fix_hstcfg=1 if "
+                                       "you experience problems\n");
+               }
+       }
        /* If force_addr is set, we program the new address here. Just to make
           sure, we disable the PIIX4 first. */
        if (force_addr) {
@@ -191,7 +214,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
                }
        }
 
-       if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2))
+       if ((temp & 0x0E) == 8)
                dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n");
        else if ((temp & 0x0E) == 0)
                dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n");
@@ -390,20 +413,12 @@ static struct i2c_adapter piix4_adapter = {
 static struct pci_device_id piix4_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3),
          .driver_data = 3 },
-       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS),
-         .driver_data = 0 },
-       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS),
-         .driver_data = 0 },
-       { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS),
-         .driver_data = 0 },
        { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
          .driver_data = 0 },
        { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
          .driver_data = 0 },
        { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6),
          .driver_data = 0 },
-       { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB),
-         .driver_data = 0 },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3),
          .driver_data = 3 },
        { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3),