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 ------------#

--- 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 <fro...@dds.nl> and
  Philip Edelbrock <p...@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 <fro...@dds.nl> and "
                "Philip Edelbrock <p...@netroedge.com>");
 MODULE_DESCRIPTION("PIIX4 SMBus driver");
 MODULE_LICENSE("GPL");
-
-module_init(i2c_piix4_init);
-module_exit(i2c_piix4_exit);




-- 
Dr. Christian Herzog <her...@phys.ethz.ch>  support: +41 44 633 26 68
IT Services Group, HPT H 8                    voice: +41 44 633 39 50
Department of Physics, ETH Zurich           
8093 Zurich, Switzerland                     http://nic.phys.ethz.ch/
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to