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