--- i2c-piix4.c	2013-12-20 14:22:26.000000000 +0100
+++ i2c-piix4.c.orig	2013-12-15 21:31:33.000000000 +0100
@@ -1,40 +1,3 @@
-/*********************  P r o g r a m  -  M o d u l e ***********************/
-/*!
- *        \file  i2c-piix4.c
- *
- *      \author  aw
- *        $Date: 2012/12/03 10:44:30 $
- *    $Revision: 1.1 $
- *
- *        \brief I2C Driver support for SC 24 SMBus. Derived from original
- *               i2c-piix4.c and enhanced to support 2nd SMBus controller
- *			     on 08SC24.
- *
- *	       Note: 1st Controller shall be IO-Mapped
- * 				 2nd Controller IO-Mapped or MEM-Mapped
- *
- *     Switches:
- */
-/*---------------------------[ Public Functions ]----------------------------
- *
- *-------------------------------[ History ]---------------------------------
- *
- *  $Log: i2c-piix4.c,v $
- *  Revision 1.1  2012/12/03 10:44:30  awerner
- *  Initial Revision
- *
- *
- *
- *---------------------------------------------------------------------------
- * (c) Copyright 2012 by MEN mikro elektronik GmbH, Nuremberg, Germany
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the  License, or (at your
- * option) any later version.
- ****************************************************************************/
-
-
 /*
  Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
  Philip Edelbrock <phil@netroedge.com>
@@ -52,18 +15,19 @@
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+*/
 
 /*
  Supports:
  Intel PIIX4, 440MX
  Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
- ATI IXP200, IXP300, IXP400, SB600, SB700, SB800
- AMD Hudson-2
+	ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800
+	AMD Hudson-2, CZ
  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/moduleparam.h>
@@ -73,40 +37,29 @@
 #include <linux/stddef.h>
 #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>
-#include <linux/mutex.h>
 
-/*
- *				DEFINES
- */
 
-/* PIIX4 SMBus adress offset Makros */
-#define SMBHSTSTS	0
-#define SMBHSLVSTS	1
-#define SMBHSTCNT	2
-#define SMBHSTCMD	3
-#define SMBHSTADD	4
-#define SMBHSTDAT0  5
-#define SMBHSTDAT1  6
-#define SMBBLKDAT   7
-#define SMBSLVCNT   8
-#define SMBSHDWCMD  9
-#define SMBSLVEVT   0xA
-#define SMBSLVDAT   0xC
+/* PIIX4 SMBus address offsets */
+#define SMBHSTSTS	(0 + piix4_smba)
+#define SMBHSLVSTS	(1 + piix4_smba)
+#define SMBHSTCNT	(2 + piix4_smba)
+#define SMBHSTCMD	(3 + piix4_smba)
+#define SMBHSTADD	(4 + piix4_smba)
+#define SMBHSTDAT0	(5 + piix4_smba)
+#define SMBHSTDAT1	(6 + piix4_smba)
+#define SMBBLKDAT	(7 + piix4_smba)
+#define SMBSLVCNT	(8 + piix4_smba)
+#define SMBSHDWCMD	(9 + piix4_smba)
+#define SMBSLVEVT	(0xA + piix4_smba)
+#define SMBSLVDAT	(0xC + piix4_smba)
 
 /* count for request_region */
-#define SMBIOSIZE	8	/* IO-mapped 1st SMBus */
-#define SMBMSIZE    8	/* Memory-mapped 2nd SMBus */
-
-#define ACPIMMIOEN_ENBL 0x00000001
-#define ACPIMMIOEN_SEL	0x00000002
-
-/* Mapping of SMBus 1 Controller */
-#define MEMMAP		0
-#define IOMAP		1
+#define SMBIOSIZE	8
 
 /* PCI Address Constants */
 #define SMBBA		0x090
@@ -116,9 +69,6 @@
 #define SMBSHDW2	0x0D5
 #define SMBREV		0x0D6
 
-/* primary controller IO mapped addresses */
-#define SMB_ADDR_INDEX	0xcd6
-
 /* Other settings */
 #define MAX_TIMEOUT	500
 #define  ENABLE_INT9	0
@@ -146,70 +96,10 @@ MODULE_PARM_DESC(force_addr,
 		"Forcibly enable the PIIX4 at the given address. "
 		"EXTREMELY DANGEROUS!");
 
-
-/*
- *				GLOBALES                     
- */
-
-/* SMBus base adress Controller 0 */
-static unsigned short piix4_smba0;
-/* SMBus base adress Controller 1 */
-static unsigned int piix4_smba1;
-
 static int srvrworks_csb5_delay;
 static struct pci_driver piix4_driver;
 
-static struct i2c_adapter piix4_adapter0;
-static struct i2c_adapter piix4_adapter1;
-static struct i2c_adapter piix4_adapter2;
-
-static u8 SMBusMap;
-
-/* virtual adress 2nd SMBus Controller */
-static void *virt_addr;
-
-
-/* mutex to lock the transaction functions,
- * because it could be that both Controller/adapter access 
- * the function at the same time.*/
-static struct mutex funcLock;
-
-/************************************************************************/
-/** request IO or mem mapped memory
- *					
- *  \param  from 		\IN start address to release
- *	\param  length		\IN length of data to release
- *	\param  spacetype	\IN 0 = memory  1 = IO. Type of requested memory
- *
- *  \return				\c 0 On success or error code
- */
-struct resource *reqAdressSpace(unsigned long from, unsigned long length,
-		const char* name, u8 spacetype) {
-	if (spacetype == MEMMAP)
-		return request_mem_region(from, length, name);
-
-	else
-		return request_region(from, length, name);
-}
-
-
-/************************************************************************/
-/** free requested memory, IO or mem mapped
- *					
- *  \param  from 		\IN start address to release
- *	\param  length		\IN length of data to release
- *	\param  spacetype	\IN 0 = memory  1 = IO. Type of requested memory
- *
- *  \return				\c 0 On success or error code
- */
-void relAdressSpace(unsigned long from, unsigned long length, u8 spacetype) {
-	if (spacetype == MEMMAP)
-		release_mem_region(from, length);
-	else
-		release_region(from, length);
-}
-
-static struct dmi_system_id piix4_dmi_blacklist[] = {
+static const struct dmi_system_id piix4_dmi_blacklist[] = {
 	{
 		.ident = "Sapphire AM2RD790",
 		.matches = {
@@ -224,32 +114,28 @@ static struct dmi_system_id piix4_dmi_bl
 			DMI_MATCH(DMI_BOARD_NAME, "LP UT 790FX"),
 		},
 	},
-	{}
+	{ }
 };
 
 /* The IBM entry is in a separate table because we only check it
  on Intel-based systems */
-static struct dmi_system_id  piix4_dmi_ibm[] = {
+static const struct dmi_system_id piix4_dmi_ibm[] = {
 	{
 		.ident = "IBM",
-		.matches = {DMI_MATCH(DMI_SYS_VENDOR, "IBM"),},
+		.matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
 	},
-	{},
+	{ },
 };
 
+struct i2c_piix4_adapdata {
+	unsigned short smba;
+};
 
-/************************************************************************/
-/** SMB controller setup function called upon module init
- *					
- *  \param  *PIIX4_dev 	\IN PCI device struct
- *	\param  *id			\IN PCI device ID
- *
- *  \return				\c 0 On success or error code
- */
 static int piix4_setup(struct pci_dev *PIIX4_dev,
 		const struct pci_device_id *id)
 {
 	unsigned char temp;
+	unsigned short piix4_smba;
 
 	if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
 			(PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5))
@@ -274,12 +160,12 @@ static int piix4_setup(struct pci_dev *P
 
 	/* Determine the address of the SMBus areas */
 	if (force_addr) {
-		piix4_smba0 = force_addr & 0xfff0;
+		piix4_smba = force_addr & 0xfff0;
 		force = 0;
 	} else {
-		pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba0);
-		piix4_smba0 &= 0xfff0;
-		if(piix4_smba0 == 0) {
+		pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
+		piix4_smba &= 0xfff0;
+		if(piix4_smba == 0) {
 			dev_err(&PIIX4_dev->dev, "SMBus base address "
 					"uninitialized - upgrade BIOS or use "
 					"force_addr=0xaddr\n");
@@ -287,12 +173,12 @@ static int piix4_setup(struct pci_dev *P
 		}
 	}
 
-	if (acpi_check_region(piix4_smba0, SMBIOSIZE, piix4_driver.name))
+	if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
 	return -ENODEV;
 
-	if (!request_region(piix4_smba0, SMBIOSIZE, piix4_driver.name)) {
+	if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
 		dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
-				piix4_smba0);
+			piix4_smba);
 		return -EBUSY;
 	}
 
@@ -302,10 +188,10 @@ static int piix4_setup(struct pci_dev *P
 	 sure, we disable the PIIX4 first. */
 	if (force_addr) {
 		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
-		pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba0);
+		pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
 		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
 		dev_info(&PIIX4_dev->dev, "WARNING: SMBus interface set to "
-				"new address %04x!\n", piix4_smba0);
+			"new address %04x!\n", piix4_smba);
 	} else if ((temp & 1) == 0) {
 		if (force) {
 			/* This should never need to be done, but has been
@@ -318,14 +204,12 @@ static int piix4_setup(struct pci_dev *P
 			 */
 			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");
-			release_region(piix4_smba0, SMBIOSIZE);
-			piix4_smba0 = 0;
+			release_region(piix4_smba, SMBIOSIZE);
 			return -ENODEV;
 		}
 	}
@@ -341,30 +225,17 @@ static int piix4_setup(struct pci_dev *P
 	pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
 	dev_info(&PIIX4_dev->dev,
 			"SMBus Host Controller at 0x%x, revision %d\n",
-			piix4_smba0, temp);
+		 piix4_smba, temp);
 
-	return 0;
+	return piix4_smba;
 }
 
-/************************************************************************/
-/** setup primary sb800 SMB controller
- *
- * This Function determine the base adress of the 2nd Controller [SMBus 1]. 
- * There is also a query if the controller is enabled, and a query if		
- * if the Controller is IO or Memory mapped.								
- * If the controller is memory mapped, the function will get a virtuell	    
- * adress to work with.														
- *
- *  \param *PIIX4_dev	\IN i2c pci main device Handle
- *  \param *id			\IN i2c pci main device ID	
- *
- *  \return         \c 0 On success or error code
- */
 static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
-		const struct pci_device_id *id)
+			     const struct pci_device_id *id, u8 aux)
 {
-	unsigned short smba_idx = SMB_ADDR_INDEX;
-	u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c;
+	unsigned short piix4_smba;
+	unsigned short smba_idx = 0xcd6;
+	u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en;
 
 	/* SB800 and later SMBus does not support forcing address */
 	if (force || force_addr) {
@@ -374,6 +245,8 @@ static int piix4_setup_sb800(struct pci_
 	}
 
 	/* Determine the address of the SMBus areas */
+	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);
@@ -385,34 +258,38 @@ static int piix4_setup_sb800(struct pci_
 	smba_en_hi = inb_p(smba_idx + 1);
 	release_region(smba_idx, 2);
 
-	/* check if the SMBus is enabled */
 	if ((smba_en_lo & 1) == 0) {
 		dev_err(&PIIX4_dev->dev,
 				"Host SMBus controller not enabled!\n");
 		return -ENODEV;
 	}
 
-	piix4_smba0 = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
-	if (acpi_check_region(piix4_smba0, SMBIOSIZE, piix4_driver.name))
+	piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
+	if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
 	return -ENODEV;
 
-	if (!request_region(piix4_smba0, SMBIOSIZE, piix4_driver.name)) {
+	if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
 		dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
-				piix4_smba0);
+			piix4_smba);
 		return -EBUSY;
 	}
 
+	/* Aux SMBus does not support IRQ information */
+	if (aux) {
+		dev_info(&PIIX4_dev->dev,
+			 "SMBus Host Controller at 0x%x\n", piix4_smba);
+		return piix4_smba;
+	}
+
 	/* Request the SMBus I2C bus config region */
-	if (!request_region(piix4_smba0 + i2ccfg_offset, 1, "i2ccfg")) {
+	if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) {
 		dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region "
-				"0x%x already in use!\n", piix4_smba0 + i2ccfg_offset);
-		release_region(piix4_smba0, SMBIOSIZE);
-		piix4_smba0 = 0;
+			"0x%x already in use!\n", piix4_smba + i2ccfg_offset);
+		release_region(piix4_smba, SMBIOSIZE);
 		return -EBUSY;
 	}
-
-	i2ccfg = inb_p(piix4_smba0 + i2ccfg_offset);
-	release_region(piix4_smba0 + i2ccfg_offset, 1);
+	i2ccfg = inb_p(piix4_smba + i2ccfg_offset);
+	release_region(piix4_smba + i2ccfg_offset, 1);
 
 	if (i2ccfg & 1)
 	dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n");
@@ -421,117 +298,70 @@ static int piix4_setup_sb800(struct pci_
 
 	dev_info(&PIIX4_dev->dev,
 			"SMBus Host Controller at 0x%x, revision %d\n",
-			piix4_smba0, i2ccfg >> 4);
+		 piix4_smba, i2ccfg >> 4);
 
-	return 0;
+	return piix4_smba;
 }
 
-
-/************************************************************************/
-/** setup secondary sb800 SMB controller
- *
- * This Function determine the base adress of the 2nd Controller [SMBus 1]. 
- * There is also a query if the controller is enabled, and a query if		
- * if the Controller is IO or Memory mapped.								
- * If the controller is memory mapped, the function will get a virtuell	    
- * adress to work with.														
- *
- *  \param *PIIX4_dev	\IN i2c pci main device Handle  
- *  \param *id			\IN i2c pci main device ID	
- *
- *  \return         \c 0 On success or error code
- */
-static int sec_piix4_setup_sb800(struct pci_dev *PIIX4_dev,
-		const struct pci_device_id *id)
+static int piix4_setup_aux(struct pci_dev *PIIX4_dev,
+			   const struct pci_device_id *id,
+			   unsigned short base_reg_addr)
 {
-	unsigned short smba_idx = SMB_ADDR_INDEX;
-	unsigned int i;
-	u8 smb_en = 0x24;
+	/* Set up auxiliary SMBus controllers found on some
+	 * AMD chipsets e.g. SP5100 (SB700 derivative) */
 
-	/* SB800 and later SMBus does not support forcing address */
-	if (force || force_addr) {
-		dev_err(&PIIX4_dev->dev, "SMBus does not support "
-				"forcing address!\n");
-		return -EINVAL;
-	}
-
-	/* Determine the address of the 2nd SMBus Controller */
-	if (!request_region(smba_idx, 4, "smba_idx")) {
-		dev_err(&PIIX4_dev->dev, "SMBus base address index region "
-				"0x%x already in use!\n", smba_idx);
-		return -EBUSY;
-	}
+	unsigned short piix4_smba;
 
-	/* retrieve mem mapped address of 2nd controller */
-	for (i=0; i<4; i++) {
-		/* write indirect index of Address...*/
-		outb_p(smb_en+i, smba_idx);
-		/* and read address bytes, 4 times */
-		piix4_smba1 |=(inb_p(smba_idx+1)) << (i*8);
+	/* 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;
 	}
 
-	release_region(smba_idx, 4);
-
-	/* check if 2nd controller is ENABLED */
-	if( !(piix4_smba1 & ACPIMMIOEN_ENBL) ) {
-		dev_err(&PIIX4_dev->dev,
-				"Host SMBus1 2nd controller not enabled!\n");
+	piix4_smba &= 0xfff0;
+	if (piix4_smba == 0) {
+		dev_dbg(&PIIX4_dev->dev,
+			"Auxiliary SMBus base address uninitialized\n");
 		return -ENODEV;
 	}
 
-	/* Check if the 2nd Controller is MEM-mapped or IO-mapped        						    */
-	/* New Functions to Request and Release Space Areas "reqAdressSpace() and relAdressSpace()" */
-	/* to differ between request_mem_region and request_region        						    */
-	if( piix4_smba1 & ACPIMMIOEN_SEL )
-	SMBusMap = IOMAP;
-	else
-	SMBusMap = MEMMAP;
-
-	/* adress mask + 0x900 Offset for the ASF-Registers */
-	piix4_smba1 = ( piix4_smba1 & 0xFFFFF000 ) + 0x900;
+	if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
+		return -ENODEV;
 
-	/* Request space region of 2nd Controller SMBus 1 */
-	if ( !reqAdressSpace(piix4_smba1, SMBMSIZE, "piix4_I2C_2nd_Controller",SMBusMap) ) {
-		dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
-				piix4_smba1);
+	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;
 	}
 
-	/* printk("MEN: Address of 2nd I2C controller = 0x%08x\n", piix4_smba1); */
-
-	/* memory mapping 2nd SMBus Controller */
-	if(SMBusMap == MEMMAP)
-		virt_addr = ioremap(piix4_smba1,SMBMSIZE);
+	dev_info(&PIIX4_dev->dev,
+		 "Auxiliary SMBus Host Controller at 0x%x\n",
+		 piix4_smba);
 
-	return 0;
+	return piix4_smba;
 }
 
-
-/************************************************************************/
-/** Transaction function for both Controllers, IO-mapped
- *					
- *  \param SMBusaddr    \IN adress of SMBus Controller
- *  \param i2c_adapter  \IN adapter which comes from the i2c_access function
- *
- *  \return				\c 0 On success or error code
- */
-
-static int piix4_transaction_io(unsigned int SMBusddr,struct i2c_adapter *piix4_adapter) 
+static int piix4_transaction(struct i2c_adapter *piix4_adapter)
 {
+	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(piix4_adapter);
+	unsigned short piix4_smba = adapdata->smba;
 	int temp;
 	int result = 0;
 	int timeout = 0;
 
 	dev_dbg(&piix4_adapter->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
-			"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBusddr + SMBHSTCNT),
-			inb_p(SMBusddr + SMBHSTCMD), inb_p(SMBusddr + SMBHSTADD),
-			inb_p(SMBusddr + SMBHSTDAT0), inb_p(SMBusddr + SMBHSTDAT1));
+		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
+		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		inb_p(SMBHSTDAT1));
 
 	/* Make sure the SMBus host is ready to start transmitting */
-	if ((temp = inb_p(SMBusddr + SMBHSTSTS)) != 0x00) {
-		dev_dbg(&piix4_adapter->dev, "SMBus busy (%02x). Resetting...\n", temp);
-		outb_p(temp, SMBusddr + SMBHSTSTS);
-		if ((temp = inb_p(SMBusddr + SMBHSTSTS)) != 0x00) {
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+		dev_dbg(&piix4_adapter->dev, "SMBus busy (%02x). "
+			"Resetting...\n", temp);
+		outb_p(temp, SMBHSTSTS);
+		if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
 			dev_err(&piix4_adapter->dev, "Failed! (%02x)\n", temp);
 			return -EBUSY;
 		} else {
@@ -540,7 +370,7 @@ static int piix4_transaction_io(unsigned
 	}
 
 	/* start the transaction by setting bit 6 */
-	outb_p(inb(SMBusddr + SMBHSTCNT) | 0x040, SMBusddr + SMBHSTCNT);
+	outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
 
 	/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
 	if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */
@@ -548,8 +378,8 @@ static int piix4_transaction_io(unsigned
 	else
 		msleep(1);
 
-	while ((++timeout < MAX_TIMEOUT)
-			&& ((temp = inb_p(SMBusddr + SMBHSTSTS)) & 0x01))
+	while ((++timeout < MAX_TIMEOUT) &&
+	       ((temp = inb_p(SMBHSTSTS)) & 0x01))
 		msleep(1);
 
 	/* If the SMBus is still busy, we give up */
@@ -575,187 +405,73 @@ static int piix4_transaction_io(unsigned
 		dev_dbg(&piix4_adapter->dev, "Error: no response!\n");
 	}
 
-	if (inb_p(SMBusddr+ SMBHSTSTS) != 0x00)
-		outb_p(inb(SMBusddr + SMBHSTSTS), SMBusddr + SMBHSTSTS);
+	if (inb_p(SMBHSTSTS) != 0x00)
+		outb_p(inb(SMBHSTSTS), SMBHSTSTS);
 
-	if ((temp = inb_p(SMBusddr + SMBHSTSTS)) != 0x00) {
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
 		dev_err(&piix4_adapter->dev, "Failed reset at end of "
 				"transaction (%02x)\n", temp);
 	}
 	dev_dbg(&piix4_adapter->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
-			"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBusddr + SMBHSTCNT),
-			inb_p(SMBusddr + SMBHSTCMD), inb_p(SMBusddr + SMBHSTADD),
-			inb_p(SMBusddr + SMBHSTDAT0), inb_p(SMBusddr + SMBHSTDAT1));
+		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
+		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		inb_p(SMBHSTDAT1));
 	return result;
 }
 
-
-
-/************************************************************************/
-/** Transaction function for primary Controller, IO-mapped
- *					
- * This function access the 1st Controller [SMBus 0] via the i2c_adapter 	
- * if the Controller is IO-mapped										    
- * and call the transaction function to transmit or receive data	        
- *
- *  \param  *adap	 	\IN i2c adapter				      				
- *	\param  addr	    \IN adress of a Controller Register			
- *  \param  flags		\IN unused											
- *	\param  read_write	\IN read or write operation							
- *  \param	command		\IN ommand to send									
- *	\param	size															
- *	\param  *data		data to send		
- *
- *  \return				\c 0 On success or error code
- */
-static s32 piix4_access_io(struct i2c_adapter * adap, u16 addr,
-		unsigned short flags, char read_write, u8 command, int size,
-		union i2c_smbus_data * data) {
-	int i, len;
-	int status;
-
-	switch (size) {
-	case I2C_SMBUS_QUICK:
-		outb_p((addr << 1) * read_write, piix4_smba0 + SMBHSTADD);
-		size = PIIX4_QUICK;
-		break;
-	case I2C_SMBUS_BYTE:
-		outb_p((addr << 1) * read_write, piix4_smba0 + SMBHSTADD);
-		if (read_write == I2C_SMBUS_WRITE)
-			outb_p(command, piix4_smba0 + SMBHSTCMD);
-		size = PIIX4_BYTE;
-		break;
-	case I2C_SMBUS_BYTE_DATA:
-		outb_p((addr << 1) | read_write, piix4_smba0 + SMBHSTADD);
-		outb_p(command, piix4_smba0 + SMBHSTCMD);
-		if (read_write == I2C_SMBUS_WRITE)
-			outb_p(data->byte, piix4_smba0 + SMBHSTDAT0);
-		size = PIIX4_BYTE_DATA;
-		break;
-	case I2C_SMBUS_WORD_DATA:
-		outb_p((addr << 1) | read_write, piix4_smba0 + SMBHSTADD);
-		outb_p(command, piix4_smba0 + SMBHSTCMD);
-		if (read_write == I2C_SMBUS_WRITE) {
-			outb_p(data->word & 0xff, piix4_smba0 + SMBHSTDAT0);
-			outb_p((data->word & 0xff00) >> 8, piix4_smba0 + SMBHSTDAT1);
-		}
-		size = PIIX4_WORD_DATA;
-		break;
-	case I2C_SMBUS_BLOCK_DATA:
-		outb_p((addr << 1) | read_write, piix4_smba0 + SMBHSTADD);
-		outb_p(command, piix4_smba0 + SMBHSTCMD);
-		if (read_write == I2C_SMBUS_WRITE) {
-			len = data->block[0];
-			if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
-				return -EINVAL;
-			outb_p(len, piix4_smba0 + SMBHSTDAT0);
-			i = inb_p(piix4_smba0 + SMBHSTCNT); /* Reset SMBBLKDAT */
-			for (i = 1; i <= len; i++)
-				outb_p(data->block[i], piix4_smba0 + SMBBLKDAT);
-		}
-		size = PIIX4_BLOCK_DATA;
-		break;
-	default:
-		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
-		return -EOPNOTSUPP;
-	}
-
-	outb_p((size & 0x1C) + (ENABLE_INT9 & 1), piix4_smba0 + SMBHSTCNT);
-
-	mutex_lock(&funcLock);
-
-	status = piix4_transaction_io(piix4_smba0, adap);
-
-	mutex_unlock(&funcLock);
-
-	if (status)
-		return status;
-
-	if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
-		return 0;
-
-	switch (size) {
-	case PIIX4_BYTE:
-	case PIIX4_BYTE_DATA:
-		data->byte = inb_p(piix4_smba0 + SMBHSTDAT0);
-		break;
-	case PIIX4_WORD_DATA:
-		data->word = inb_p(piix4_smba0 + SMBHSTDAT0)
-				+ (inb_p(piix4_smba0 + SMBHSTDAT1) << 8);
-		break;
-	case PIIX4_BLOCK_DATA:
-		data->block[0] = inb_p(piix4_smba0 + SMBHSTDAT0);
-		if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
-			return -EPROTO;
-		i = inb_p(piix4_smba0 + SMBHSTCNT); /* Reset SMBBLKDAT */
-		for (i = 1; i <= data->block[0]; i++)
-			data->block[i] = inb_p(piix4_smba0 + SMBBLKDAT);
-		break;
-	}
-	return 0;
-
-}
-
-/************************************************************************/
-/** Transaction function for secondary Controller, IO-mapped
- *					
- * This function access the 2nd Controller [SMBus 1] via the i2c_adapter
- * if the Controller is IO-mapped,										
- * and call the transaction function to transmit or receive data	       
- *  \param  *adap	 	\IN i2c adapter				      				
- *	\param  addr	    \IN adress of a Controller Register			
- *  \param  flags		\IN unused											
- *	\param  read_write	\IN read or write operation							
- *  \param	command		\IN ommand to send									
- *	\param	size															
- *	\param  *data		data to send		
- *
- *  \return				\c 0 On success or error code
- */
-static s32 sec_piix4_access_io(struct i2c_adapter * adap, u16 addr,
-		unsigned short flags, char read_write, u8 command, int size,
-		union i2c_smbus_data * data) {
+/* Return negative errno on error. */
+static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
+		 unsigned short flags, char read_write,
+		 u8 command, int size, union i2c_smbus_data * data)
+{
+	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
+	unsigned short piix4_smba = adapdata->smba;
 	int i, len;
 	int status;
 
 	switch (size) {
 	case I2C_SMBUS_QUICK:
-		outb_p((addr << 1) | read_write, piix4_smba1 + SMBHSTADD);
+		outb_p((addr << 1) | read_write,
+		       SMBHSTADD);
 		size = PIIX4_QUICK;
 		break;
 	case I2C_SMBUS_BYTE:
-		outb_p((addr << 1) | read_write, piix4_smba1 + SMBHSTADD);
+		outb_p((addr << 1) | read_write,
+		       SMBHSTADD);
 		if (read_write == I2C_SMBUS_WRITE)
-			outb_p(command, piix4_smba1 + SMBHSTCMD);
+			outb_p(command, SMBHSTCMD);
 		size = PIIX4_BYTE;
 		break;
 	case I2C_SMBUS_BYTE_DATA:
-		outb_p((addr << 1) | read_write, piix4_smba1 + SMBHSTADD);
-		outb_p(command, piix4_smba1 + SMBHSTCMD);
+		outb_p((addr << 1) | read_write,
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
 		if (read_write == I2C_SMBUS_WRITE)
-			outb_p(data->byte, piix4_smba1 + SMBHSTDAT0);
+			outb_p(data->byte, SMBHSTDAT0);
 		size = PIIX4_BYTE_DATA;
 		break;
 	case I2C_SMBUS_WORD_DATA:
-		outb_p((addr << 1) | read_write, piix4_smba1 + SMBHSTADD);
-		outb_p(command, piix4_smba1 + SMBHSTCMD);
+		outb_p((addr << 1) | read_write,
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
 		if (read_write == I2C_SMBUS_WRITE) {
-			outb_p(data->word & 0xff, piix4_smba1 + SMBHSTDAT0);
-			outb_p((data->word & 0xff00) >> 8, piix4_smba1 + SMBHSTDAT1);
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
 		}
 		size = PIIX4_WORD_DATA;
 		break;
 	case I2C_SMBUS_BLOCK_DATA:
-		outb_p((addr << 1) | read_write, piix4_smba1 + SMBHSTADD);
-		outb_p(command, piix4_smba1 + SMBHSTCMD);
+		outb_p((addr << 1) | read_write,
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
 		if (read_write == I2C_SMBUS_WRITE) {
 			len = data->block[0];
 			if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
 				return -EINVAL;
-			outb_p(len, piix4_smba1 + SMBHSTDAT0);
-			i = inb_p(piix4_smba1 + SMBHSTCNT); /* Reset SMBBLKDAT */
+			outb_p(len, SMBHSTDAT0);
+			i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
 			for (i = 1; i <= len; i++)
-				outb_p(data->block[i], piix4_smba1 + SMBBLKDAT);
+				outb_p(data->block[i], SMBBLKDAT);
 		}
 		size = PIIX4_BLOCK_DATA;
 		break;
@@ -764,281 +480,49 @@ static s32 sec_piix4_access_io(struct i2
 		return -EOPNOTSUPP;
 	}
 
-	outb_p((size & 0x1C) + (ENABLE_INT9 & 1), piix4_smba1 + SMBHSTCNT);
-
-	mutex_lock(&funcLock);
-
-	status = piix4_transaction_io(piix4_smba1,adap);
-
-	mutex_unlock(&funcLock);
+	outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
 
+	status = piix4_transaction(adap);
 	if (status)
 		return status;
 
 	if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
 		return 0;
 
-	switch (size) {
-	case PIIX4_BYTE:
-	case PIIX4_BYTE_DATA:
-		data->byte = inb_p(piix4_smba1 + SMBHSTDAT0);
-		break;
-	case PIIX4_WORD_DATA:
-		data->word = inb_p(piix4_smba1 + SMBHSTDAT0)
-				+ (inb_p(piix4_smba1 + SMBHSTDAT1) << 8);
-		break;
-	case PIIX4_BLOCK_DATA:
-		data->block[0] = inb_p(piix4_smba1 + SMBHSTDAT0);
-		if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
-			return -EPROTO;
-		i = inb_p(piix4_smba1 + SMBHSTCNT); /* Reset SMBBLKDAT */
-		for (i = 1; i <= data->block[0]; i++)
-			data->block[i] = inb_p(piix4_smba1 + SMBBLKDAT);
-		break;
-	}
-	return 0;
-
-}
-
-
-/************************************************************************/
-/** separate transaction function for secondary Controller, mem-mapped
- *					
- *  \return				\c 0 On success or error code
- */
-
-static int piix4_transaction_mem(void) {
-	int temp;
-	int result = 0;
-	int timeout = 0;
-
-	dev_dbg(&piix4_adapter1.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
-			"ADD=%02x, DAT0=%02x, DAT1=%02x\n", readb(virt_addr + SMBHSTCNT),
-			readb(virt_addr + SMBHSTCMD), readb(virt_addr + SMBHSTADD),
-			readb(virt_addr + SMBHSTDAT0), readb(virt_addr + SMBHSTDAT1));
-
-	/* Make sure the SMBus host is ready to start transmitting */
-	if ((temp = readb(virt_addr + SMBHSTSTS)) != 0x00) {
-		dev_dbg(&piix4_adapter1.dev, "SMBus busy (%02x). "
-				"Resetting...\n", temp);
-		writeb(temp, virt_addr + SMBHSTSTS);
-		if ((temp = readb(virt_addr + SMBHSTSTS)) != 0x00) {
-			dev_err(&piix4_adapter1.dev, "Failed! (%02x)\n", temp);
-			return -EBUSY;
-		} else {
-			dev_dbg(&piix4_adapter1.dev, "Successful!\n");
-		}
-	}
-
-	/* start the transaction by setting bit 6 */
-	writeb(readb(virt_addr + SMBHSTCNT) | 0x040, virt_addr + SMBHSTCNT);
-
-	/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
-	if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */
-		msleep(2);
-	else
-		msleep(1);
-
-	while ((++timeout < MAX_TIMEOUT)
-			&& ((temp = readb(virt_addr + SMBHSTSTS)) & 0x01))
-		msleep(1);
-
-	/* If the SMBus is still busy, we give up */
-	if (timeout == MAX_TIMEOUT) {
-		dev_err(&piix4_adapter1.dev, "SMBus Timeout!\n");
-		result = -ETIMEDOUT;
-	}
-
-	if (temp & 0x10) {
-		result = -EIO;
-		dev_err(&piix4_adapter1.dev, "Error: Failed bus transaction\n");
-	}
-
-	if (temp & 0x08) {
-		result = -EIO;
-		dev_dbg(&piix4_adapter1.dev, "Bus collision! SMBus may be "
-				"locked until next hard reset. (sorry!)\n");
-		/* Clock stops and slave is stuck in mid-transmission */
-	}
-
-	if (temp & 0x04) {
-		result = -ENXIO;
-		dev_dbg(&piix4_adapter1.dev, "Error: no response!\n");
-	}
-
-	if (readb(virt_addr + SMBHSTSTS) != 0x00)
-		writeb(readb(virt_addr + SMBHSTSTS), virt_addr + SMBHSTSTS);
-
-	if ((temp = readb(virt_addr + SMBHSTSTS)) != 0x00) {
-		dev_err(&piix4_adapter1.dev, "Failed reset at end of "
-				"transaction (%02x)\n", temp);
-	}
-	dev_dbg(&piix4_adapter1.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
-			"ADD=%02x, DAT0=%02x, DAT1=%02x\n", readb(virt_addr + SMBHSTCNT),
-			readb(virt_addr + SMBHSTCMD), readb(virt_addr + SMBHSTADD),
-			readb(virt_addr + SMBHSTDAT0), readb(virt_addr + SMBHSTDAT1));
-
-	return result;
-}
-
-
-/************************************************************************/
-/** Transaction function for both Controllers, mem-mapped
- *					
- * This function accesses the given Controller via the i2c_adapter 	
- * if the Controller is IO-mapped										    
- * and call the transaction function to transmit or receive data	        
- *
- *  \param  *adap	 	\IN i2c adapter				      				
- *	\param  addr	    \IN adress of a Controller Register			
- *  \param  flags		\IN unused											
- *	\param  read_write	\IN read or write operation							
- *  \param	command		\IN ommand to send									
- *	\param	size															
- *	\param  *data		data to send		
- *
- *  \return				\c 0 On success or error code
- */
-
-static s32 piix4_access_mem(struct i2c_adapter * adap, u16 addr,
-		unsigned short flags, char read_write, u8 command, int size,
-		union i2c_smbus_data * data) {
-	int i, len;
-	int status;
-
-	switch (size) {
-	case I2C_SMBUS_QUICK:
-		writeb((addr << 1) | read_write, virt_addr + SMBHSTADD);
-		size = PIIX4_QUICK;
-		break;
-	case I2C_SMBUS_BYTE:
-		writeb((addr << 1) | read_write, virt_addr + SMBHSTADD);
-		if (read_write == I2C_SMBUS_WRITE)
-			writeb(command, virt_addr + SMBHSTCMD);
-		size = PIIX4_BYTE;
-		break;
-	case I2C_SMBUS_BYTE_DATA:
-		writeb((addr << 1) | read_write, virt_addr + SMBHSTADD);
-		writeb(command, virt_addr + SMBHSTCMD);
-		if (read_write == I2C_SMBUS_WRITE)
-			writeb(data->byte, virt_addr + SMBHSTDAT0);
-		size = PIIX4_BYTE_DATA;
-		break;
-	case I2C_SMBUS_WORD_DATA:
-		writeb((addr << 1) | read_write, virt_addr + SMBHSTADD);
-		writeb(command, virt_addr + SMBHSTCMD);
-		if (read_write == I2C_SMBUS_WRITE) {
-			writeb(data->word & 0xff, virt_addr + SMBHSTDAT0);
-			writeb((data->word & 0xff00) >> 8, virt_addr + SMBHSTDAT1);
-		}
-		size = PIIX4_WORD_DATA;
-		break;
-	case I2C_SMBUS_BLOCK_DATA:
-		writeb((addr << 1) | read_write, virt_addr + SMBHSTADD);
-		writeb(command, virt_addr + SMBHSTCMD);
-		if (read_write == I2C_SMBUS_WRITE) {
-			len = data->block[0];
-			if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
-				return -EINVAL;
-			writeb(len, virt_addr + SMBHSTDAT0);
-			i = readb(virt_addr + SMBHSTCNT); /* Reset SMBBLKDAT */
-			for (i = 1; i <= len; i++)
-				writeb(data->block[i], virt_addr + SMBBLKDAT);
-		}
-		size = PIIX4_BLOCK_DATA;
-		break;
-	default:
-		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
-		return -EOPNOTSUPP;
-	}
-
-	writeb((size & 0x1C) + (ENABLE_INT9 & 1), virt_addr + SMBHSTCNT);
-
-	status = piix4_transaction_mem();
-	if (status)
-		return status;
-
-	if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
-		return 0;
 
 	switch (size) {
 	case PIIX4_BYTE:
 	case PIIX4_BYTE_DATA:
-		data->byte = readb(virt_addr + SMBHSTDAT0);
+		data->byte = inb_p(SMBHSTDAT0);
 		break;
 	case PIIX4_WORD_DATA:
-		data->word = readb(virt_addr + SMBHSTDAT0)
-				+ (readb(virt_addr + SMBHSTDAT1) << 8);
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
 		break;
 	case PIIX4_BLOCK_DATA:
-		data->block[0] = readb(virt_addr + SMBHSTDAT0);
+		data->block[0] = inb_p(SMBHSTDAT0);
 		if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
 			return -EPROTO;
-		i = readb(virt_addr + SMBHSTCNT); /* Reset SMBBLKDAT */
+		i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
 		for (i = 1; i <= data->block[0]; i++)
-			data->block[i] = readb(virt_addr + SMBBLKDAT);
+			data->block[i] = inb_p(SMBBLKDAT);
 		break;
 	}
 	return 0;
 }
 
-
-/************************************************************************/
-/** return capabilities of this Hardware
- *
- *  \return			capabilities flags
- */
-static u32 piix4_func(struct i2c_adapter *adapter) {
-	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA
-			| I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA;
+static u32 piix4_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-/*---------------- 1st Controller [SMBus0]----------------*/
-
-/* algorithm IO-mapped [SMBus0] */
-static const struct i2c_algorithm smbus_algorithm0 = {
-	.smbus_xfer = piix4_access_io,
-	.functionality = piix4_func,
-};
-
-/* i2c_adapter IO-mapped [SMBus0] */
-static struct i2c_adapter piix4_adapter0 = {
-	.owner = THIS_MODULE,
-	.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-	.algo = &smbus_algorithm0,
-};
-
-/*---------------- 2nd Controller [SMBus1]----------------*/
-
-/* algorithm MEM-mapped [SMBus1] */
-static const struct i2c_algorithm smbus_algorithm1 = {
-	.smbus_xfer = piix4_access_mem,
+static const struct i2c_algorithm smbus_algorithm = {
+	.smbus_xfer	= piix4_access,
 	.functionality = piix4_func,
 };
 
-/* algorithm IO-mapped [SMBus1] */
-static const struct i2c_algorithm smbus_algorithm2 = {
-	.smbus_xfer = sec_piix4_access_io,
-	.functionality = piix4_func,
-};
-
-/* i2c_adapter MEM-mapped [SMBus1] */
-static struct i2c_adapter piix4_adapter1 = {
-	.owner = THIS_MODULE,
-	.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-	.algo = &smbus_algorithm1,
-};
-
-/* i2c_adapter IO-mapped [SMBus1] */
-static struct i2c_adapter piix4_adapter2 = {
-	.owner = THIS_MODULE,
-	.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-	.algo = &smbus_algorithm2,
-};
-
-
-static const struct pci_device_id piix4_ids[] =
-		{
+static DEFINE_PCI_DEVICE_TABLE(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) },
@@ -1047,150 +531,143 @@ static const struct pci_device_id piix4_
 				{ 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,
+		     PCI_DEVICE_ID_SERVERWORKS_CSB5) },
 				{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
-						PCI_DEVICE_ID_SERVERWORKS_OSB4) }, { PCI_DEVICE(
-						PCI_VENDOR_ID_SERVERWORKS,
-						PCI_DEVICE_ID_SERVERWORKS_CSB5) }, { PCI_DEVICE(
-						PCI_VENDOR_ID_SERVERWORKS,
-						PCI_DEVICE_ID_SERVERWORKS_CSB6) }, { PCI_DEVICE(
-						PCI_VENDOR_ID_SERVERWORKS,
-						PCI_DEVICE_ID_SERVERWORKS_HT1000SB) }, { PCI_DEVICE(
-						PCI_VENDOR_ID_SERVERWORKS,
-						PCI_DEVICE_ID_SERVERWORKS_HT1100LD) }, { 0, } };
+		     PCI_DEVICE_ID_SERVERWORKS_CSB6) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+		     PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+		     PCI_DEVICE_ID_SERVERWORKS_HT1100LD) },
+	{ 0, }
+};
+
 MODULE_DEVICE_TABLE (pci, piix4_ids);
 
-/************************************************************************/
-/** Probing function for SMB Controller
- *					
- *  \param  *dev 	\IN PCI device struct
- *	\param  *id		\IN PCI device ID
- *
- *  \return				\c 0 On success or error code
- */
+static struct i2c_adapter *piix4_main_adapter;
+static struct i2c_adapter *piix4_aux_adapter;
 
-static int piix4_probe(struct pci_dev *dev,
-		const struct pci_device_id *id)
+static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
+			     struct i2c_adapter **padap)
 {
-	/* 1 = Controller not in use */
-	int ctr1_retval = 1;
-	int ctr2_retval = 1;
-
-	mutex_init(&funcLock);
-	mutex_unlock(&funcLock);
+	struct i2c_adapter *adap;
+	struct i2c_piix4_adapdata *adapdata;
+	int retval;
 
-	if ((dev->vendor == PCI_VENDOR_ID_ATI &&
-					dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
-					dev->revision >= 0x40) ||
-			dev->vendor == PCI_VENDOR_ID_AMD) {
-		/* base address location etc changed in SB800 */
-		ctr1_retval = piix4_setup_sb800(dev, id);
-		ctr2_retval = sec_piix4_setup_sb800(dev,id);
+	adap = kzalloc(sizeof(*adap), GFP_KERNEL);
+	if (adap == NULL) {
+		release_region(smba, SMBIOSIZE);
+		return -ENOMEM;
 	}
-	else
-	ctr1_retval = piix4_setup(dev, id);
-
-	/* Is just the controller 1 in use, an has a fault? */
-	if (ctr1_retval != 0 && ctr2_retval == 1)
-	return ctr1_retval;
-
 	
-	if( ctr1_retval == 0 ) {
-		/* set up the sysfs linkage to our parent device */
-		piix4_adapter0.dev.parent = &dev->dev;
-
-		snprintf(piix4_adapter0.name, sizeof(piix4_adapter0.name),
-				"SMBus PIIX4 adapter at 0x%04x", piix4_smba0);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	adap->algo = &smbus_algorithm;
 
-		/* Add 1st I2C adapter */
-		if ((ctr1_retval = i2c_add_adapter(&piix4_adapter0))) {
-			dev_err(&dev->dev, "Couldn't register adapter 0!\n");
-			release_region(piix4_smba0, SMBIOSIZE);
-			piix4_smba0 = 0;
+	adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL);
+	if (adapdata == NULL) {
+		kfree(adap);
+		release_region(smba, SMBIOSIZE);
+		return -ENOMEM;
 		}
 
-		/* if the 2nd controller is not in use, probe is ready */
-		if(ctr2_retval == 1)
-			return ctr1_retval;
-	}
+	adapdata->smba = smba;
 
-	if( ctr2_retval == 0 ) {
-		/* add adapter 1 if the [SMBus1] is MEM-mapped */
-		if(SMBusMap == MEMMAP) {
-			piix4_adapter1.dev.parent = &dev->dev;
+	/* set up the sysfs linkage to our parent device */
+	adap->dev.parent = &dev->dev;
 
-			snprintf(piix4_adapter1.name, sizeof(piix4_adapter1.name),
-					"SMBus PIIX4 2nd adapter at 0x%08x", piix4_smba1);
+	snprintf(adap->name, sizeof(adap->name),
+		"SMBus PIIX4 adapter at %04x", smba);
 
-			ctr2_retval = i2c_add_adapter(&piix4_adapter1);
+	i2c_set_adapdata(adap, adapdata);
 
+	retval = i2c_add_adapter(adap);
+	if (retval) {
+		dev_err(&dev->dev, "Couldn't register adapter!\n");
+		kfree(adapdata);
+		kfree(adap);
+		release_region(smba, SMBIOSIZE);
+		return retval;
 		}
-		/* add adapter 2 if the [SMBus1] is IO-mapped */
-		else {
-			piix4_adapter2.dev.parent = &dev->dev;
 
-			snprintf(piix4_adapter2.name, sizeof(piix4_adapter2.name),
-					"SMBus PIIX4 2nd adapter at 0x%08x", piix4_smba1);
+	*padap = adap;
+	return 0;
+}
 
-			ctr2_retval = i2c_add_adapter(&piix4_adapter2);
+static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int retval;
 
-		}
+	if ((dev->vendor == PCI_VENDOR_ID_ATI &&
+	     dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
+	     dev->revision >= 0x40) ||
+	    dev->vendor == PCI_VENDOR_ID_AMD)
+		/* base address location etc changed in SB800 */
+		retval = piix4_setup_sb800(dev, id, 0);
+	else
+		retval = piix4_setup(dev, id);
 
-		/* Could the adapter of the [SMBus1] be added? */
-		if( ctr2_retval ) {
-			dev_err(&dev->dev, "Couldn't register SMBus adapter 1!\n");
-			printk("Couldn´t register SMBus adapter 1\n");
-			relAdressSpace(piix4_smba1, SMBMSIZE,SMBusMap);
-			piix4_smba1 = 0;
+	/* If no main SMBus found, give up */
+	if (retval < 0)
+		return retval;
+
+	/* 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 */
+	retval = -ENODEV;
+
+	if (dev->vendor == PCI_VENDOR_ID_ATI &&
+	    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 both I2C Controller couldn´t initialize => there is no Controller */
-	if( ctr1_retval && ctr2_retval )
-		return -ENODEV;
-
-	/* if Controller 1 couldn´t initialize */
-	if( ctr1_retval )
-		printk("SMBus0 could not be initialize\n");
-
-	/* if Controller 2 couldn´t initialize */
-	if( ctr2_retval )
-		printk("SBus1 could not be intitialize\n");
+	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;
 }
 
-
-/************************************************************************/
-/** Removing function for SMB Controller
- *					
- *  \param  *dev 	\IN PCI device struct
- *
- *  \return			-
- */
-static void piix4_remove(struct pci_dev *dev)
+static void piix4_adap_remove(struct i2c_adapter *adap)
 {
-	if (piix4_smba0) {
-		i2c_del_adapter(&piix4_adapter0);
-		release_region(piix4_smba0, SMBIOSIZE);
-		piix4_smba0 = 0;
-	}
+	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
 
-	/* release mem region of 2nd Controller  [SMBus1] */
-	if (piix4_smba1) {
-		if(SMBusMap == MEMMAP) {
-			i2c_del_adapter(&piix4_adapter1);
-			release_mem_region(piix4_smba1, SMBMSIZE);
-
-			/* unmap the virtual adress */
-			iounmap(virt_addr);
+	if (adapdata->smba) {
+		i2c_del_adapter(adap);
+		release_region(adapdata->smba, SMBIOSIZE);
+		kfree(adapdata);
+		kfree(adap);
 		}
-		else if(SMBusMap == IOMAP) {
-			i2c_del_adapter(&piix4_adapter2);
-			release_region(piix4_smba1, SMBMSIZE);
+}
+
+static void piix4_remove(struct pci_dev *dev)
+{
+	if (piix4_main_adapter) {
+		piix4_adap_remove(piix4_main_adapter);
+		piix4_main_adapter = NULL;
 		}
 
-		piix4_smba1 = 0;
+	if (piix4_aux_adapter) {
+		piix4_adap_remove(piix4_aux_adapter);
+		piix4_aux_adapter = NULL;
 	}
 }
 
@@ -1198,23 +675,12 @@ static struct pci_driver piix4_driver =
 	.name = "piix4_smbus",
 	.id_table = piix4_ids,
 	.probe = piix4_probe,
-//	.remove = __devexit_p(piix4_remove),
+	.remove		= piix4_remove,
 };
 
-static int __init i2c_piix4_init(void)
-{
-	return pci_register_driver(&piix4_driver);
-}
-
-static void __exit i2c_piix4_exit(void)
-{
-	pci_unregister_driver(&piix4_driver);
-}
+module_pci_driver(piix4_driver);
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
 		"Philip Edelbrock <phil@netroedge.com>");
 MODULE_DESCRIPTION("PIIX4 SMBus driver");
 MODULE_LICENSE("GPL");
-
-module_init(i2c_piix4_init);
-module_exit(i2c_piix4_exit);
