diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-i801.c')
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index df6ab553f975..c60081169cc3 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -41,7 +41,8 @@ Tolapai 0x5032 32 hard yes yes yes ICH10 0x3a30 32 hard yes yes yes ICH10 0x3a60 32 hard yes yes yes - PCH 0x3b30 32 hard yes yes yes + 3400/5 Series (PCH) 0x3b30 32 hard yes yes yes + Cougar Point (PCH) 0x1c22 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -137,6 +138,17 @@ static struct pci_dev *I801_dev; #define FEATURE_I2C_BLOCK_READ (1 << 3) static unsigned int i801_features; +static const char *i801_feature_names[] = { + "SMBus PEC", + "Block buffer", + "Block process call", + "I2C block read", +}; + +static unsigned int disable_features; +module_param(disable_features, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(disable_features, "Disable selected driver features"); + /* Make sure the SMBus host is ready to start transmitting. Return 0 if it is, -EBUSY if it is not. */ static int i801_check_pre(void) @@ -340,9 +352,8 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, do { msleep(1); status = inb_p(SMBHSTSTS); - } - while ((!(status & SMBHSTSTS_BYTE_DONE)) - && (timeout++ < MAX_TIMEOUT)); + } while ((!(status & SMBHSTSTS_BYTE_DONE)) + && (timeout++ < MAX_TIMEOUT)); result = i801_check_post(status, timeout > MAX_TIMEOUT); if (result < 0) @@ -415,9 +426,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, data->block[0] = 32; /* max for SMBus block reads */ } + /* Experience has shown that the block buffer can only be used for + SMBus (not I2C) block transactions, even though the datasheet + doesn't mention this limitation. */ if ((i801_features & FEATURE_BLOCK_BUFFER) - && !(command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) + && command != I2C_SMBUS_I2C_BLOCK_DATA && i801_set_block_buffer_mode() == 0) result = i801_block_transaction_by_block(data, read_write, hwpec); @@ -437,9 +450,9 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, } /* Return negative errno on error. */ -static s32 i801_access(struct i2c_adapter * adap, u16 addr, +static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data * data) + int size, union i2c_smbus_data *data) { int hwpec; int block = 0; @@ -508,7 +521,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, else outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); - if(block) + if (block) ret = i801_block_transaction(data, read_write, size, hwpec); else ret = i801_transaction(xact | ENABLE_INT9); @@ -520,9 +533,9 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL); - if(block) + if (block) return ret; - if(ret) + if (ret) return ret; if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) return 0; @@ -561,7 +574,7 @@ static struct i2c_adapter i801_adapter = { .algo = &smbus_algorithm, }; -static struct pci_device_id i801_ids[] = { +static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) }, @@ -578,10 +591,11 @@ static struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CPT_SMBUS) }, { 0, } }; -MODULE_DEVICE_TABLE (pci, i801_ids); +MODULE_DEVICE_TABLE(pci, i801_ids); #if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE static unsigned char apanel_addr; @@ -641,7 +655,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name, /* & ~0x80, ignore enabled/disabled bit */ if ((type & ~0x80) != dmi_devices[i].type) continue; - if (strcmp(name, dmi_devices[i].name)) + if (strcasecmp(name, dmi_devices[i].name)) continue; memset(&info, 0, sizeof(struct i2c_board_info)); @@ -685,36 +699,37 @@ static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, } #endif -static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit i801_probe(struct pci_dev *dev, + const struct pci_device_id *id) { unsigned char temp; - int err; -#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE - const char *vendor; -#endif + int err, i; I801_dev = dev; i801_features = 0; switch (dev->device) { - case PCI_DEVICE_ID_INTEL_82801EB_3: - case PCI_DEVICE_ID_INTEL_ESB_4: - case PCI_DEVICE_ID_INTEL_ICH6_16: - case PCI_DEVICE_ID_INTEL_ICH7_17: - case PCI_DEVICE_ID_INTEL_ESB2_17: - case PCI_DEVICE_ID_INTEL_ICH8_5: - case PCI_DEVICE_ID_INTEL_ICH9_6: - case PCI_DEVICE_ID_INTEL_TOLAPAI_1: - case PCI_DEVICE_ID_INTEL_ICH10_4: - case PCI_DEVICE_ID_INTEL_ICH10_5: - case PCI_DEVICE_ID_INTEL_PCH_SMBUS: + default: i801_features |= FEATURE_I2C_BLOCK_READ; /* fall through */ case PCI_DEVICE_ID_INTEL_82801DB_3: i801_features |= FEATURE_SMBUS_PEC; i801_features |= FEATURE_BLOCK_BUFFER; + /* fall through */ + case PCI_DEVICE_ID_INTEL_82801CA_3: + case PCI_DEVICE_ID_INTEL_82801BA_2: + case PCI_DEVICE_ID_INTEL_82801AB_3: + case PCI_DEVICE_ID_INTEL_82801AA_3: break; } + /* Disable features on user request */ + for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { + if (i801_features & disable_features & (1 << i)) + dev_notice(&dev->dev, "%s disabled by user\n", + i801_feature_names[i]); + } + i801_features &= ~disable_features; + err = pci_enable_device(dev); if (err) { dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", @@ -790,8 +805,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id } #endif #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE - vendor = dmi_get_system_info(DMI_BOARD_VENDOR); - if (vendor && !strcmp(vendor, "FUJITSU SIEMENS")) + if (dmi_name_in_vendors("FUJITSU")) dmi_walk(dmi_check_onboard_devices, &i801_adapter); #endif |