diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-piix4.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-piix4.c | 117 |
1 files changed, 77 insertions, 40 deletions
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 8bbd6ece7c4..a6f54ba27e2 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -22,7 +22,7 @@ Intel PIIX4, 440MX Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100 ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800 - AMD Hudson-2 + AMD Hudson-2, ML, CZ SMSC Victory66 Note: we assume there can only be one device, with one or more @@ -38,7 +38,6 @@ #include <linux/ioport.h> #include <linux/i2c.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/dmi.h> #include <linux/acpi.h> #include <linux/io.h> @@ -99,7 +98,7 @@ MODULE_PARM_DESC(force_addr, static int srvrworks_csb5_delay; static struct pci_driver piix4_driver; -static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = { +static const struct dmi_system_id piix4_dmi_blacklist[] = { { .ident = "Sapphire AM2RD790", .matches = { @@ -119,7 +118,7 @@ static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = { /* The IBM entry is in a separate table because we only check it on Intel-based systems */ -static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = { +static const struct dmi_system_id piix4_dmi_ibm[] = { { .ident = "IBM", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, @@ -131,8 +130,8 @@ struct i2c_piix4_adapdata { unsigned short smba; }; -static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) +static int piix4_setup(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id) { unsigned char temp; unsigned short piix4_smba; @@ -204,21 +203,20 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, */ pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 1); - dev_printk(KERN_NOTICE, &PIIX4_dev->dev, - "WARNING: SMBus interface has been " - "FORCEFULLY ENABLED!\n"); + dev_notice(&PIIX4_dev->dev, + "WARNING: SMBus interface has been FORCEFULLY ENABLED!\n"); } else { dev_err(&PIIX4_dev->dev, - "Host SMBus controller not enabled!\n"); + "SMBus Host Controller not enabled!\n"); release_region(piix4_smba, SMBIOSIZE); return -ENODEV; } } if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2)) - dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus\n"); else if ((temp & 0x0E) == 0) - dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus\n"); else dev_err(&PIIX4_dev->dev, "Illegal Interrupt configuration " "(or code out of date)!\n"); @@ -231,12 +229,13 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, return piix4_smba; } -static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) +static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id, u8 aux) { unsigned short piix4_smba; unsigned short smba_idx = 0xcd6; - u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c; + u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status; + u8 i2ccfg, i2ccfg_offset = 0x10; /* SB800 and later SMBus does not support forcing address */ if (force || force_addr) { @@ -246,6 +245,16 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, } /* Determine the address of the SMBus areas */ + if ((PIIX4_dev->vendor == PCI_VENDOR_ID_AMD && + PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && + PIIX4_dev->revision >= 0x41) || + (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD && + PIIX4_dev->device == 0x790b && + PIIX4_dev->revision >= 0x49)) + smb_en = 0x00; + else + smb_en = (aux) ? 0x28 : 0x2c; + if (!request_region(smba_idx, 2, "smba_idx")) { dev_err(&PIIX4_dev->dev, "SMBus base address index region " "0x%x already in use!\n", smba_idx); @@ -257,13 +266,22 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, smba_en_hi = inb_p(smba_idx + 1); release_region(smba_idx, 2); - if ((smba_en_lo & 1) == 0) { + if (!smb_en) { + smb_en_status = smba_en_lo & 0x10; + piix4_smba = smba_en_hi << 8; + if (aux) + piix4_smba |= 0x20; + } else { + smb_en_status = smba_en_lo & 0x01; + piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0; + } + + if (!smb_en_status) { dev_err(&PIIX4_dev->dev, - "Host SMBus controller not enabled!\n"); + "SMBus Host Controller not enabled!\n"); return -ENODEV; } - piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0; if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) return -ENODEV; @@ -273,6 +291,14 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, return -EBUSY; } + /* Aux SMBus does not support IRQ information */ + if (aux) { + dev_info(&PIIX4_dev->dev, + "Auxiliary SMBus Host Controller at 0x%x\n", + piix4_smba); + return piix4_smba; + } + /* Request the SMBus I2C bus config region */ if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) { dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region " @@ -284,9 +310,9 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, release_region(piix4_smba + i2ccfg_offset, 1); if (i2ccfg & 1) - dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus\n"); else - dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus\n"); dev_info(&PIIX4_dev->dev, "SMBus Host Controller at 0x%x, revision %d\n", @@ -295,9 +321,9 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, return piix4_smba; } -static int __devinit piix4_setup_aux(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id, - unsigned short base_reg_addr) +static int piix4_setup_aux(struct pci_dev *PIIX4_dev, + const struct pci_device_id *id, + unsigned short base_reg_addr) { /* Set up auxiliary SMBus controllers found on some * AMD chipsets e.g. SP5100 (SB700 derivative) */ @@ -514,7 +540,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = piix4_func, }; -static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = { +static const struct pci_device_id piix4_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) }, { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) }, @@ -523,6 +549,7 @@ static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x790b) }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4) }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, @@ -541,9 +568,8 @@ MODULE_DEVICE_TABLE (pci, piix4_ids); static struct i2c_adapter *piix4_main_adapter; static struct i2c_adapter *piix4_aux_adapter; -static int __devinit piix4_add_adapter(struct pci_dev *dev, - unsigned short smba, - struct i2c_adapter **padap) +static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, + struct i2c_adapter **padap) { struct i2c_adapter *adap; struct i2c_piix4_adapdata *adapdata; @@ -589,8 +615,7 @@ static int __devinit piix4_add_adapter(struct pci_dev *dev, return 0; } -static int __devinit piix4_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; @@ -599,7 +624,7 @@ static int __devinit piix4_probe(struct pci_dev *dev, dev->revision >= 0x40) || dev->vendor == PCI_VENDOR_ID_AMD) /* base address location etc changed in SB800 */ - retval = piix4_setup_sb800(dev, id); + retval = piix4_setup_sb800(dev, id, 0); else retval = piix4_setup(dev, id); @@ -613,21 +638,33 @@ static int __devinit piix4_probe(struct pci_dev *dev, return retval; /* Check for auxiliary SMBus on some AMD chipsets */ + retval = -ENODEV; + if (dev->vendor == PCI_VENDOR_ID_ATI && - dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && - dev->revision < 0x40) { - retval = piix4_setup_aux(dev, id, 0x58); - if (retval > 0) { - /* Try to add the aux adapter if it exists, - * piix4_add_adapter will clean up if this fails */ - piix4_add_adapter(dev, retval, &piix4_aux_adapter); + dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) { + if (dev->revision < 0x40) { + retval = piix4_setup_aux(dev, id, 0x58); + } else { + /* SB800 added aux bus too */ + retval = piix4_setup_sb800(dev, id, 1); } } + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) { + retval = piix4_setup_sb800(dev, id, 1); + } + + if (retval > 0) { + /* Try to add the aux adapter if it exists, + * piix4_add_adapter will clean up if this fails */ + piix4_add_adapter(dev, retval, &piix4_aux_adapter); + } + return 0; } -static void __devexit piix4_adap_remove(struct i2c_adapter *adap) +static void piix4_adap_remove(struct i2c_adapter *adap) { struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap); @@ -639,7 +676,7 @@ static void __devexit piix4_adap_remove(struct i2c_adapter *adap) } } -static void __devexit piix4_remove(struct pci_dev *dev) +static void piix4_remove(struct pci_dev *dev) { if (piix4_main_adapter) { piix4_adap_remove(piix4_main_adapter); @@ -656,7 +693,7 @@ static struct pci_driver piix4_driver = { .name = "piix4_smbus", .id_table = piix4_ids, .probe = piix4_probe, - .remove = __devexit_p(piix4_remove), + .remove = piix4_remove, }; module_pci_driver(piix4_driver); |
