diff options
author | Andrew Armenia <andrew@asquaredlabs.com> | 2012-07-24 08:13:57 -0400 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-07-24 08:13:57 -0400 |
commit | 2a2f7404a1946be62290292ca5d6438c4b50567f (patch) | |
tree | 79c458c163f378de8704bb7ea7529d3957f39c56 /drivers/i2c/busses/i2c-piix4.c | |
parent | e154bf6fbfc167426ee938111a5ffa36bd8541a1 (diff) |
i2c-piix4: Support AMD auxiliary SMBus controller
Some AMD chipsets, such as the SP5100, have an auxiliary SMBus
controller with a second set of registers. This patch adds
support for this auxiliary controller.
Tested on ASUS KCMA-D8 motherboard.
Signed-off-by: Andrew Armenia <andrew@asquaredlabs.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-piix4.c')
-rw-r--r-- | drivers/i2c/busses/i2c-piix4.c | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 42ed0af10efd..ef511df2c965 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c | |||
@@ -21,11 +21,12 @@ | |||
21 | Supports: | 21 | Supports: |
22 | Intel PIIX4, 440MX | 22 | Intel PIIX4, 440MX |
23 | Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100 | 23 | Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100 |
24 | ATI IXP200, IXP300, IXP400, SB600, SB700, SB800 | 24 | ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800 |
25 | AMD Hudson-2 | 25 | AMD Hudson-2 |
26 | SMSC Victory66 | 26 | SMSC Victory66 |
27 | 27 | ||
28 | Note: we assume there can only be one device, with one SMBus interface. | 28 | Note: we assume there can only be one device, with one or more |
29 | SMBus interfaces. | ||
29 | */ | 30 | */ |
30 | 31 | ||
31 | #include <linux/module.h> | 32 | #include <linux/module.h> |
@@ -293,6 +294,46 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, | |||
293 | return piix4_smba; | 294 | return piix4_smba; |
294 | } | 295 | } |
295 | 296 | ||
297 | static int __devinit piix4_setup_aux(struct pci_dev *PIIX4_dev, | ||
298 | const struct pci_device_id *id, | ||
299 | unsigned short base_reg_addr) | ||
300 | { | ||
301 | /* Set up auxiliary SMBus controllers found on some | ||
302 | * AMD chipsets e.g. SP5100 (SB700 derivative) */ | ||
303 | |||
304 | unsigned short piix4_smba; | ||
305 | |||
306 | /* Read address of auxiliary SMBus controller */ | ||
307 | pci_read_config_word(PIIX4_dev, base_reg_addr, &piix4_smba); | ||
308 | if ((piix4_smba & 1) == 0) { | ||
309 | dev_dbg(&PIIX4_dev->dev, | ||
310 | "Auxiliary SMBus controller not enabled\n"); | ||
311 | return -ENODEV; | ||
312 | } | ||
313 | |||
314 | piix4_smba &= 0xfff0; | ||
315 | if (piix4_smba == 0) { | ||
316 | dev_dbg(&PIIX4_dev->dev, | ||
317 | "Auxiliary SMBus base address uninitialized\n"); | ||
318 | return -ENODEV; | ||
319 | } | ||
320 | |||
321 | if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) | ||
322 | return -ENODEV; | ||
323 | |||
324 | if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { | ||
325 | dev_err(&PIIX4_dev->dev, "Auxiliary SMBus region 0x%x " | ||
326 | "already in use!\n", piix4_smba); | ||
327 | return -EBUSY; | ||
328 | } | ||
329 | |||
330 | dev_info(&PIIX4_dev->dev, | ||
331 | "Auxiliary SMBus Host Controller at 0x%x\n", | ||
332 | piix4_smba); | ||
333 | |||
334 | return piix4_smba; | ||
335 | } | ||
336 | |||
296 | static int piix4_transaction(struct i2c_adapter *piix4_adapter) | 337 | static int piix4_transaction(struct i2c_adapter *piix4_adapter) |
297 | { | 338 | { |
298 | struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter); | 339 | struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter); |
@@ -497,6 +538,7 @@ static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = { | |||
497 | MODULE_DEVICE_TABLE (pci, piix4_ids); | 538 | MODULE_DEVICE_TABLE (pci, piix4_ids); |
498 | 539 | ||
499 | static struct i2c_adapter *piix4_main_adapter; | 540 | static struct i2c_adapter *piix4_main_adapter; |
541 | static struct i2c_adapter *piix4_aux_adapter; | ||
500 | 542 | ||
501 | static int __devinit piix4_add_adapter(struct pci_dev *dev, | 543 | static int __devinit piix4_add_adapter(struct pci_dev *dev, |
502 | unsigned short smba, | 544 | unsigned short smba, |
@@ -560,10 +602,28 @@ static int __devinit piix4_probe(struct pci_dev *dev, | |||
560 | else | 602 | else |
561 | retval = piix4_setup(dev, id); | 603 | retval = piix4_setup(dev, id); |
562 | 604 | ||
605 | /* If no main SMBus found, give up */ | ||
563 | if (retval < 0) | 606 | if (retval < 0) |
564 | return retval; | 607 | return retval; |
565 | 608 | ||
566 | return piix4_add_adapter(dev, retval, &piix4_main_adapter); | 609 | /* Try to register main SMBus adapter, give up if we can't */ |
610 | retval = piix4_add_adapter(dev, retval, &piix4_main_adapter); | ||
611 | if (retval < 0) | ||
612 | return retval; | ||
613 | |||
614 | /* Check for auxiliary SMBus on some AMD chipsets */ | ||
615 | if (dev->vendor == PCI_VENDOR_ID_ATI && | ||
616 | dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && | ||
617 | dev->revision < 0x40) { | ||
618 | retval = piix4_setup_aux(dev, id, 0x58); | ||
619 | if (retval > 0) { | ||
620 | /* Try to add the aux adapter if it exists, | ||
621 | * piix4_add_adapter will clean up if this fails */ | ||
622 | piix4_add_adapter(dev, retval, &piix4_aux_adapter); | ||
623 | } | ||
624 | } | ||
625 | |||
626 | return 0; | ||
567 | } | 627 | } |
568 | 628 | ||
569 | static void __devexit piix4_adap_remove(struct i2c_adapter *adap) | 629 | static void __devexit piix4_adap_remove(struct i2c_adapter *adap) |
@@ -584,6 +644,11 @@ static void __devexit piix4_remove(struct pci_dev *dev) | |||
584 | piix4_adap_remove(piix4_main_adapter); | 644 | piix4_adap_remove(piix4_main_adapter); |
585 | piix4_main_adapter = NULL; | 645 | piix4_main_adapter = NULL; |
586 | } | 646 | } |
647 | |||
648 | if (piix4_aux_adapter) { | ||
649 | piix4_adap_remove(piix4_aux_adapter); | ||
650 | piix4_aux_adapter = NULL; | ||
651 | } | ||
587 | } | 652 | } |
588 | 653 | ||
589 | static struct pci_driver piix4_driver = { | 654 | static struct pci_driver piix4_driver = { |