Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a2f7404 authored by Andrew Armenia's avatar Andrew Armenia Committed by Jean Delvare
Browse files

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: default avatarAndrew Armenia <andrew@asquaredlabs.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent e154bf6f
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -8,6 +8,11 @@ Supported adapters:
    Datasheet: Only available via NDA from ServerWorks
    Datasheet: Only available via NDA from ServerWorks
  * ATI IXP200, IXP300, IXP400, SB600, SB700 and SB800 southbridges
  * ATI IXP200, IXP300, IXP400, SB600, SB700 and SB800 southbridges
    Datasheet: Not publicly available
    Datasheet: Not publicly available
    SB700 register reference available at:
    http://support.amd.com/us/Embedded_TechDocs/43009_sb7xx_rrg_pub_1.00.pdf
  * AMD SP5100 (SB700 derivative found on some server mainboards)
    Datasheet: Publicly available at the AMD website
    http://support.amd.com/us/Embedded_TechDocs/44413.pdf
  * AMD Hudson-2
  * AMD Hudson-2
    Datasheet: Not publicly available
    Datasheet: Not publicly available
  * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
  * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
@@ -68,6 +73,10 @@ this driver on those mainboards.
The ServerWorks Southbridges, the Intel 440MX, and the Victory66 are
The ServerWorks Southbridges, the Intel 440MX, and the Victory66 are
identical to the PIIX4 in I2C/SMBus support.
identical to the PIIX4 in I2C/SMBus support.


The AMD SB700 and SP5100 chipsets implement two PIIX4-compatible SMBus
controllers. If your BIOS initializes the secondary controller, it will
be detected by this driver as an "Auxiliary SMBus Host Controller".

If you own Force CPCI735 motherboard or other OSB4 based systems you may need
If you own Force CPCI735 motherboard or other OSB4 based systems you may need
to change the SMBus Interrupt Select register so the SMBus controller uses
to change the SMBus Interrupt Select register so the SMBus controller uses
the SMI mode.
the SMI mode.
+5 −1
Original line number Original line Diff line number Diff line
@@ -133,7 +133,7 @@ config I2C_PIIX4
	    ATI IXP300
	    ATI IXP300
	    ATI IXP400
	    ATI IXP400
	    ATI SB600
	    ATI SB600
	    ATI SB700
	    ATI SB700/SP5100
	    ATI SB800
	    ATI SB800
	    AMD Hudson-2
	    AMD Hudson-2
	    Serverworks OSB4
	    Serverworks OSB4
@@ -143,6 +143,10 @@ config I2C_PIIX4
	    Serverworks HT-1100
	    Serverworks HT-1100
	    SMSC Victory66
	    SMSC Victory66


	  Some AMD chipsets contain two PIIX4-compatible SMBus
	  controllers. This driver will attempt to use both controllers
	  on the SB700/SP5100, if they have been initialized by the BIOS.

	  This driver can also be built as a module.  If so, the module
	  This driver can also be built as a module.  If so, the module
	  will be called i2c-piix4.
	  will be called i2c-piix4.


+68 −3
Original line number Original line Diff line number Diff line
@@ -21,11 +21,12 @@
   Supports:
   Supports:
	Intel PIIX4, 440MX
	Intel PIIX4, 440MX
	Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
	Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
	ATI IXP200, IXP300, IXP400, SB600, SB700, SB800
	ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800
	AMD Hudson-2
	AMD Hudson-2
	SMSC Victory66
	SMSC Victory66


   Note: we assume there can only be one device, with one SMBus interface.
   Note: we assume there can only be one device, with one or more
   SMBus interfaces.
*/
*/


#include <linux/module.h>
#include <linux/module.h>
@@ -293,6 +294,46 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
	return piix4_smba;
	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)
{
	/* Set up auxiliary SMBus controllers found on some
	 * AMD chipsets e.g. SP5100 (SB700 derivative) */

	unsigned short piix4_smba;

	/* Read address of auxiliary SMBus controller */
	pci_read_config_word(PIIX4_dev, base_reg_addr, &piix4_smba);
	if ((piix4_smba & 1) == 0) {
		dev_dbg(&PIIX4_dev->dev,
			"Auxiliary SMBus controller not enabled\n");
		return -ENODEV;
	}

	piix4_smba &= 0xfff0;
	if (piix4_smba == 0) {
		dev_dbg(&PIIX4_dev->dev,
			"Auxiliary SMBus base address uninitialized\n");
		return -ENODEV;
	}

	if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
		return -ENODEV;

	if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
		dev_err(&PIIX4_dev->dev, "Auxiliary SMBus region 0x%x "
			"already in use!\n", piix4_smba);
		return -EBUSY;
	}

	dev_info(&PIIX4_dev->dev,
		 "Auxiliary SMBus Host Controller at 0x%x\n",
		 piix4_smba);

	return piix4_smba;
}

static int piix4_transaction(struct i2c_adapter *piix4_adapter)
static int piix4_transaction(struct i2c_adapter *piix4_adapter)
{
{
	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter);
	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter);
@@ -497,6 +538,7 @@ static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = {
MODULE_DEVICE_TABLE (pci, piix4_ids);
MODULE_DEVICE_TABLE (pci, piix4_ids);


static struct i2c_adapter *piix4_main_adapter;
static struct i2c_adapter *piix4_main_adapter;
static struct i2c_adapter *piix4_aux_adapter;


static int __devinit piix4_add_adapter(struct pci_dev *dev,
static int __devinit piix4_add_adapter(struct pci_dev *dev,
					unsigned short smba,
					unsigned short smba,
@@ -560,10 +602,28 @@ static int __devinit piix4_probe(struct pci_dev *dev,
	else
	else
		retval = piix4_setup(dev, id);
		retval = piix4_setup(dev, id);


	/* If no main SMBus found, give up */
	if (retval < 0)
	if (retval < 0)
		return retval;
		return retval;


	return piix4_add_adapter(dev, retval, &piix4_main_adapter);
	/* Try to register main SMBus adapter, give up if we can't */
	retval = piix4_add_adapter(dev, retval, &piix4_main_adapter);
	if (retval < 0)
		return retval;

	/* Check for auxiliary SMBus on some AMD chipsets */
	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);
		}
	}

	return 0;
}
}


static void __devexit piix4_adap_remove(struct i2c_adapter *adap)
static void __devexit piix4_adap_remove(struct i2c_adapter *adap)
@@ -584,6 +644,11 @@ static void __devexit piix4_remove(struct pci_dev *dev)
		piix4_adap_remove(piix4_main_adapter);
		piix4_adap_remove(piix4_main_adapter);
		piix4_main_adapter = NULL;
		piix4_main_adapter = NULL;
	}
	}

	if (piix4_aux_adapter) {
		piix4_adap_remove(piix4_aux_adapter);
		piix4_aux_adapter = NULL;
	}
}
}


static struct pci_driver piix4_driver = {
static struct pci_driver piix4_driver = {