Patchwork [lm-sensors] I2C support for AMD Hudson-1

login
register
mail settings
Submitter Christian Herzog
Date Dec. 20, 2013, 1:43 p.m.
Message ID <20131220134349.GV25105@phys.ethz.ch>
Download mbox | patch
Permalink /patch/304081/
State Not Applicable
Headers show

Comments

Christian Herzog - Dec. 20, 2013, 1:43 p.m.
Dear list,

thanks for your instructions. I slightly modified the driver so that it builds
on 3.13-rc4. I can confirm that it works well. I also talked to the company
(www.men.de) that released the original patch and they would love to get it
into the kernel. Please find attached the patch to i2c-piix4.c of 3.13-rc4.
I also prepared a .tgz that contains
- the original archive from men.de
- my modified driver
- the patch itself

The .tgz can be obtained from http://daduke.org/junk/piix4.tgz

thanks again and Happy Holidays,
-Christian


On Tue, Dec 17, 2013 at 07:10:53PM +0100, Wolfram Sang wrote:
> 
> > > I'm currently beta testing a pretty cool embedded board for router
> > > applications etc. (http://www.pcengines.ch/apu.htm) that sports a Hudson-1 FCH
> > > which is pretty similar to the Hudson-2 your module supports but sufficiently
> > > different so that i2c-piix4 doesn't work.
> > > I found a patched i2c-piix4 source that adds support for the Hudson-1 and it
> > > works beautifully: http://www.men.de/products/13SC24-90.html#t=overview
> > > Now I'm wondering if you would be willing to get this patch into lm-sensors
> > > and also the kernel.
> > > If there's anything I can do to help, please let me know.
> 
> Can't say anything about the patch since it requires registration to get
> it :(
> 
> What you/someone can do:
> 
> * get the patch
> * port it to a recent kernel and verify it still works
> * read Documentation/SubmittingPatches
> * send the patch
> 
> Regards,
> 
>    Wolfram
> 

#------------------------------------- PATCH ------------#
Wolfram Sang - Jan. 13, 2014, 1:04 p.m.
On Fri, Dec 20, 2013 at 02:43:49PM +0100, Christian Herzog wrote:
> Dear list,
> 
> thanks for your instructions. I slightly modified the driver so that it builds
> on 3.13-rc4. I can confirm that it works well. I also talked to the company
> (www.men.de) that released the original patch and they would love to get it
> into the kernel. Please find attached the patch to i2c-piix4.c of 3.13-rc4.
> I also prepared a .tgz that contains
> - the original archive from men.de
> - my modified driver
> - the patch itself

Thanks for posting a patch known to work with a recent kernel. Yet, this
is way too intrusive. We need minimal changes in logical steps to get a
new feature supported. Ping to Jean for the details, x86 drivers are his
expertise.
Christian Herzog - Jan. 13, 2014, 1:12 p.m.
Dear all,

thanks for the feedback. I was already in contact with Jean because I noticed
the following:

I recently compiled 3.13.0-rc7 on my PC Engines apu beta box, and I2C works
out of the box, without the need for my patch. I'm still looking for somebody
who could shed some light on this situation - chances are we don't need the
patch any longer.
So: is anybody aware of any Hudson-1 related changes to the i2c-piix4 code?

thanks,
-Christian


On Mon, Jan 13, 2014 at 02:04:26PM +0100, Wolfram Sang wrote:
> On Fri, Dec 20, 2013 at 02:43:49PM +0100, Christian Herzog wrote:
> > Dear list,
> > 
> > thanks for your instructions. I slightly modified the driver so that it builds
> > on 3.13-rc4. I can confirm that it works well. I also talked to the company
> > (www.men.de) that released the original patch and they would love to get it
> > into the kernel. Please find attached the patch to i2c-piix4.c of 3.13-rc4.
> > I also prepared a .tgz that contains
> > - the original archive from men.de
> > - my modified driver
> > - the patch itself
> 
> Thanks for posting a patch known to work with a recent kernel. Yet, this
> is way too intrusive. We need minimal changes in logical steps to get a
> new feature supported. Ping to Jean for the details, x86 drivers are his
> expertise.
>
Jean Delvare - Jan. 13, 2014, 1:13 p.m.
On Mon, 13 Jan 2014 14:04:26 +0100, Wolfram Sang wrote:
> On Fri, Dec 20, 2013 at 02:43:49PM +0100, Christian Herzog wrote:
> > Dear list,
> > 
> > thanks for your instructions. I slightly modified the driver so that it builds
> > on 3.13-rc4. I can confirm that it works well. I also talked to the company
> > (www.men.de) that released the original patch and they would love to get it
> > into the kernel. Please find attached the patch to i2c-piix4.c of 3.13-rc4.
> > I also prepared a .tgz that contains
> > - the original archive from men.de
> > - my modified driver
> > - the patch itself
> 
> Thanks for posting a patch known to work with a recent kernel. Yet, this
> is way too intrusive. We need minimal changes in logical steps to get a
> new feature supported. Ping to Jean for the details, x86 drivers are his
> expertise.

On my to-do list, but swamped by more urgent matters at the moment :(

Patch

--- 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);