Commit f289aa67 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 76c25284 0b4a5d51
...@@ -76,6 +76,24 @@ config I2C_I801 ...@@ -76,6 +76,24 @@ config I2C_I801
in the lm_sensors package, which you can download at in the lm_sensors package, which you can download at
http://www.lm-sensors.nu http://www.lm-sensors.nu
config I2C_ISA
tristate " ISA Bus support"
depends on I2C && I2C_PROC && ISA && EXPERIMENTAL
help
If you say yes to this option, support will be included for i2c
interfaces that are on the ISA bus.
This can also be built as a module which can be inserted and removed
while the kernel is running. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>.
The module will be called i2c-isa.
You will also need the latest user-space utilties: you can find them
in the lm_sensors package, which you can download at
http://www.lm-sensors.nu
config I2C_PIIX4 config I2C_PIIX4
tristate " Intel PIIX4" tristate " Intel PIIX4"
depends on I2C && I2C_PROC && PCI && EXPERIMENTAL depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
......
...@@ -6,4 +6,5 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o ...@@ -6,4 +6,5 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_ISA) += i2c-isa.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
...@@ -60,6 +60,8 @@ ...@@ -60,6 +60,8 @@
/* Note: we assume there can only be one ALI15X3, with one SMBus interface */ /* Note: we assume there can only be one ALI15X3, with one SMBus interface */
/* #define DEBUG 1 */
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -71,46 +73,46 @@ ...@@ -71,46 +73,46 @@
#include <asm/io.h> #include <asm/io.h>
/* ALI15X3 SMBus address offsets */ /* ALI15X3 SMBus address offsets */
#define SMBHSTSTS (0 + ali15x3_smba) #define SMBHSTSTS (0 + ali15x3_smba)
#define SMBHSTCNT (1 + ali15x3_smba) #define SMBHSTCNT (1 + ali15x3_smba)
#define SMBHSTSTART (2 + ali15x3_smba) #define SMBHSTSTART (2 + ali15x3_smba)
#define SMBHSTCMD (7 + ali15x3_smba) #define SMBHSTCMD (7 + ali15x3_smba)
#define SMBHSTADD (3 + ali15x3_smba) #define SMBHSTADD (3 + ali15x3_smba)
#define SMBHSTDAT0 (4 + ali15x3_smba) #define SMBHSTDAT0 (4 + ali15x3_smba)
#define SMBHSTDAT1 (5 + ali15x3_smba) #define SMBHSTDAT1 (5 + ali15x3_smba)
#define SMBBLKDAT (6 + ali15x3_smba) #define SMBBLKDAT (6 + ali15x3_smba)
/* PCI Address Constants */ /* PCI Address Constants */
#define SMBCOM 0x004 #define SMBCOM 0x004
#define SMBBA 0x014 #define SMBBA 0x014
#define SMBATPC 0x05B /* used to unlock xxxBA registers */ #define SMBATPC 0x05B /* used to unlock xxxBA registers */
#define SMBHSTCFG 0x0E0 #define SMBHSTCFG 0x0E0
#define SMBSLVC 0x0E1 #define SMBSLVC 0x0E1
#define SMBCLK 0x0E2 #define SMBCLK 0x0E2
#define SMBREV 0x008 #define SMBREV 0x008
/* Other settings */ /* Other settings */
#define MAX_TIMEOUT 200 /* times 1/100 sec */ #define MAX_TIMEOUT 200 /* times 1/100 sec */
#define ALI15X3_SMB_IOSIZE 32 #define ALI15X3_SMB_IOSIZE 32
/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB. /* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB.
We don't use these here. If the bases aren't set to some value we We don't use these here. If the bases aren't set to some value we
tell user to upgrade BIOS and we fail. tell user to upgrade BIOS and we fail.
*/ */
#define ALI15X3_SMB_DEFAULTBASE 0xE800 #define ALI15X3_SMB_DEFAULTBASE 0xE800
/* ALI15X3 address lock bits */ /* ALI15X3 address lock bits */
#define ALI15X3_LOCK 0x06 #define ALI15X3_LOCK 0x06
/* ALI15X3 command constants */ /* ALI15X3 command constants */
#define ALI15X3_ABORT 0x02 #define ALI15X3_ABORT 0x02
#define ALI15X3_T_OUT 0x04 #define ALI15X3_T_OUT 0x04
#define ALI15X3_QUICK 0x00 #define ALI15X3_QUICK 0x00
#define ALI15X3_BYTE 0x10 #define ALI15X3_BYTE 0x10
#define ALI15X3_BYTE_DATA 0x20 #define ALI15X3_BYTE_DATA 0x20
#define ALI15X3_WORD_DATA 0x30 #define ALI15X3_WORD_DATA 0x30
#define ALI15X3_BLOCK_DATA 0x40 #define ALI15X3_BLOCK_DATA 0x40
#define ALI15X3_BLOCK_CLR 0x80 #define ALI15X3_BLOCK_CLR 0x80
/* ALI15X3 status register bits */ /* ALI15X3 status register bits */
#define ALI15X3_STS_IDLE 0x04 #define ALI15X3_STS_IDLE 0x04
...@@ -129,55 +131,52 @@ MODULE_PARM(force_addr, "i"); ...@@ -129,55 +131,52 @@ MODULE_PARM(force_addr, "i");
MODULE_PARM_DESC(force_addr, MODULE_PARM_DESC(force_addr,
"Initialize the base address of the i2c controller"); "Initialize the base address of the i2c controller");
static void ali15x3_do_pause(unsigned int amount);
static int ali15x3_transaction(void);
static unsigned short ali15x3_smba = 0; static unsigned short ali15x3_smba = 0;
int ali15x3_setup(struct pci_dev *ALI15X3_dev) static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
{ {
u16 a; u16 a;
unsigned char temp; unsigned char temp;
/* Check the following things: /* Check the following things:
- SMB I/O address is initialized - SMB I/O address is initialized
- Device is enabled - Device is enabled
- We can use the addresses - We can use the addresses
*/ */
/* Unlock the register. /* Unlock the register.
The data sheet says that the address registers are read-only The data sheet says that the address registers are read-only
if the lock bits are 1, but in fact the address registers if the lock bits are 1, but in fact the address registers
are zero unless you clear the lock bits. are zero unless you clear the lock bits.
*/ */
pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
if (temp & ALI15X3_LOCK) { if (temp & ALI15X3_LOCK) {
temp &= ~ALI15X3_LOCK; temp &= ~ALI15X3_LOCK;
pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
} }
/* Determine the address of the SMBus area */ /* Determine the address of the SMBus area */
pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
if (ali15x3_smba == 0 && force_addr == 0) { if (ali15x3_smba == 0 && force_addr == 0) {
printk dev_err(&ALI15X3_dev->dev, "ALI15X3_smb region uninitialized "
("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); "- upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV; return -ENODEV;
} }
if(force_addr) if(force_addr)
ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) { if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) {
printk dev_err(&ALI15X3_dev->dev,
("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n", "ALI15X3_smb region 0x%x already in use!\n",
ali15x3_smba); ali15x3_smba);
return -ENODEV; return -ENODEV;
} }
if(force_addr) { if(force_addr) {
printk("i2c-ali15x3.o: forcing ISA address 0x%04X\n", ali15x3_smba); dev_info(&ALI15X3_dev->dev, "forcing ISA address 0x%04X\n",
ali15x3_smba);
if (PCIBIOS_SUCCESSFUL != if (PCIBIOS_SUCCESSFUL !=
pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba)) pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba))
return -ENODEV; return -ENODEV;
...@@ -186,68 +185,60 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) ...@@ -186,68 +185,60 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev)
return -ENODEV; return -ENODEV;
if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {
/* make sure it works */ /* make sure it works */
printk("i2c-ali15x3.o: force address failed - not supported?\n"); dev_err(&ALI15X3_dev->dev,
"force address failed - not supported?\n");
return -ENODEV; return -ENODEV;
} }
} }
/* check if whole device is enabled */ /* check if whole device is enabled */
pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
if ((temp & 1) == 0) { if ((temp & 1) == 0) {
printk("i2c-ali15x3: enabling SMBus device\n"); dev_info(&ALI15X3_dev->dev, "enabling SMBus device\n");
pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);
} }
/* Is SMB Host controller enabled? */ /* Is SMB Host controller enabled? */
pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
if ((temp & 1) == 0) { if ((temp & 1) == 0) {
printk("i2c-ali15x3: enabling SMBus controller\n"); dev_info(&ALI15X3_dev->dev, "enabling SMBus controller\n");
pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);
} }
/* set SMB clock to 74KHz as recommended in data sheet */ /* set SMB clock to 74KHz as recommended in data sheet */
pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
/* Everything is happy, let's grab the memory and set things up. */ /*
request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb"); The interrupt routing for SMB is set up in register 0x77 in the
1533 ISA Bridge device, NOT in the 7101 device.
#ifdef DEBUG Don't bother with finding the 1533 device and reading the register.
/* if ((....... & 0x0F) == 1)
The interrupt routing for SMB is set up in register 0x77 in the dev_dbg(&ALI15X3_dev->dev, "ALI15X3 using Interrupt 9 for SMBus.\n");
1533 ISA Bridge device, NOT in the 7101 device. */
Don't bother with finding the 1533 device and reading the register.
if ((....... & 0x0F) == 1)
printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n");
*/
pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp); dev_dbg(&ALI15X3_dev->dev, "SMBREV = 0x%X\n", temp);
printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba); dev_dbg(&ALI15X3_dev->dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba);
#endif /* DEBUG */
return 0; return 0;
} }
/* Internally used pause function */ /* Internally used pause function */
void ali15x3_do_pause(unsigned int amount) static void ali15x3_do_pause(unsigned int amount)
{ {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule_timeout(amount); schedule_timeout(amount);
} }
/* Another internally used function */ /* Another internally used function */
int ali15x3_transaction(void) static int ali15x3_transaction(struct i2c_adapter *adap)
{ {
int temp; int temp;
int result = 0; int result = 0;
int timeout = 0; int timeout = 0;
#ifdef DEBUG dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, "
printk "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
"DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBHSTDAT1));
#endif
/* get status */ /* get status */
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
...@@ -255,43 +246,32 @@ int ali15x3_transaction(void) ...@@ -255,43 +246,32 @@ int ali15x3_transaction(void)
/* Make sure the SMBus host is ready to start transmitting */ /* Make sure the SMBus host is ready to start transmitting */
/* Check the busy bit first */ /* Check the busy bit first */
if (temp & ALI15X3_STS_BUSY) { if (temp & ALI15X3_STS_BUSY) {
/* /*
If the host controller is still busy, it may have timed out in the previous transaction, If the host controller is still busy, it may have timed out in the
resulting in a "SMBus Timeout" printk. previous transaction, resulting in a "SMBus Timeout" Dev.
I've tried the following to reset a stuck busy bit. I've tried the following to reset a stuck busy bit.
1. Reset the controller with an ABORT command. 1. Reset the controller with an ABORT command.
(this doesn't seem to clear the controller if an external device is hung) (this doesn't seem to clear the controller if an external
2. Reset the controller and the other SMBus devices with a T_OUT command. device is hung)
(this clears the host busy bit if an external device is hung, 2. Reset the controller and the other SMBus devices with a
but it comes back upon a new access to a device) T_OUT command. (this clears the host busy bit if an
3. Disable and reenable the controller in SMBHSTCFG external device is hung, but it comes back upon a new access
Worst case, nothing seems to work except power reset. to a device)
*/ 3. Disable and reenable the controller in SMBHSTCFG
/* Abort - reset the host controller */ Worst case, nothing seems to work except power reset.
/* */
#ifdef DEBUG /* Abort - reset the host controller */
printk("i2c-ali15x3.o: Resetting host controller to clear busy condition\n",temp); /*
#endif Try resetting entire SMB bus, including other devices -
outb_p(ALI15X3_ABORT, SMBHSTCNT); This may not work either - it clears the BUSY bit but
temp = inb_p(SMBHSTSTS); then the BUSY bit may come back on when you try and use the chip again.
if (temp & ALI15X3_STS_BUSY) { If that's the case you are stuck.
*/ */
dev_info(&adap->dev, "Resetting entire SMB Bus to "
/* "clear busy condition (%02x)\n", temp);
Try resetting entire SMB bus, including other devices -
This may not work either - it clears the BUSY bit but
then the BUSY bit may come back on when you try and use the chip again.
If that's the case you are stuck.
*/
printk
("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",
temp);
outb_p(ALI15X3_T_OUT, SMBHSTCNT); outb_p(ALI15X3_T_OUT, SMBHSTCNT);
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
} }
/*
}
*/
/* now check the error bits and the busy bit */ /* now check the error bits and the busy bit */
if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
...@@ -302,9 +282,9 @@ int ali15x3_transaction(void) ...@@ -302,9 +282,9 @@ int ali15x3_transaction(void)
/* this is probably going to be correctable only by a power reset /* this is probably going to be correctable only by a power reset
as one of the bits now appears to be stuck */ as one of the bits now appears to be stuck */
/* This may be a bus or device with electrical problems. */ /* This may be a bus or device with electrical problems. */
printk dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - "
("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n", "controller or device on bus is probably hung\n",
temp); temp);
return -1; return -1;
} }
} else { } else {
...@@ -328,48 +308,41 @@ int ali15x3_transaction(void) ...@@ -328,48 +308,41 @@ int ali15x3_transaction(void)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
result = -1; result = -1;
printk("i2c-ali15x3.o: SMBus Timeout!\n"); dev_err(&adap->dev, "SMBus Timeout!\n");
} }
if (temp & ALI15X3_STS_TERM) { if (temp & ALI15X3_STS_TERM) {
result = -1; result = -1;
#ifdef DEBUG dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
printk("i2c-ali15x3.o: Error: Failed bus transaction\n");
#endif
} }
/* /*
Unfortunately the ALI SMB controller maps "no response" and "bus collision" Unfortunately the ALI SMB controller maps "no response" and "bus
into a single bit. No reponse is the usual case so don't collision" into a single bit. No reponse is the usual case so don't
do a printk. do a printk.
This means that bus collisions go unreported. This means that bus collisions go unreported.
*/ */
if (temp & ALI15X3_STS_COLL) { if (temp & ALI15X3_STS_COLL) {
result = -1; result = -1;
#ifdef DEBUG dev_dbg(&adap->dev,
printk "Error: no response or bus collision ADD=%02x\n",
("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n", inb_p(SMBHSTADD));
inb_p(SMBHSTADD));
#endif
} }
/* haven't ever seen this */ /* haven't ever seen this */
if (temp & ALI15X3_STS_DEV) { if (temp & ALI15X3_STS_DEV) {
result = -1; result = -1;
printk("i2c-ali15x3.o: Error: device error\n"); dev_err(&adap->dev, "Error: device error\n");
} }
#ifdef DEBUG dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "
printk "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, " inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBHSTDAT1));
#endif
return result; return result;
} }
/* Return -1 on error. */ /* Return -1 on error. */
s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write, u8 command, unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data * data) int size, union i2c_smbus_data * data)
{ {
...@@ -377,9 +350,9 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, ...@@ -377,9 +350,9 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
int temp; int temp;
int timeout; int timeout;
/* clear all the bits (clear-on-write) */ /* clear all the bits (clear-on-write) */
outb_p(0xFF, SMBHSTSTS); outb_p(0xFF, SMBHSTSTS);
/* make sure SMBus is idle */ /* make sure SMBus is idle */
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
for (timeout = 0; for (timeout = 0;
(timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
...@@ -388,14 +361,12 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, ...@@ -388,14 +361,12 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
} }
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n", dev_err(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp);
temp);
} }
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL: case I2C_SMBUS_PROC_CALL:
printk dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n");
return -1; return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
...@@ -442,7 +413,8 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, ...@@ -442,7 +413,8 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
data->block[0] = len; data->block[0] = len;
} }
outb_p(len, SMBHSTDAT0); outb_p(len, SMBHSTDAT0);
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ /* Reset SMBBLKDAT */
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
for (i = 1; i <= len; i++) for (i = 1; i <= len; i++)
outb_p(data->block[i], SMBBLKDAT); outb_p(data->block[i], SMBBLKDAT);
} }
...@@ -452,7 +424,7 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, ...@@ -452,7 +424,7 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
outb_p(size, SMBHSTCNT); /* output command */ outb_p(size, SMBHSTCNT); /* output command */
if (ali15x3_transaction()) /* Error in transaction */ if (ali15x3_transaction(adap)) /* Error in transaction */
return -1; return -1;
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
...@@ -474,22 +446,19 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, ...@@ -474,22 +446,19 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
if (len > 32) if (len > 32)
len = 32; len = 32;
data->block[0] = len; data->block[0] = len;
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ /* Reset SMBBLKDAT */
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
for (i = 1; i <= data->block[0]; i++) { for (i = 1; i <= data->block[0]; i++) {
data->block[i] = inb_p(SMBBLKDAT); data->block[i] = inb_p(SMBBLKDAT);
#ifdef DEBUG dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n",
printk len, i, data->block[i]);
("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n",
len, i, data->block[i]);
#endif /* DEBUG */
} }
break; break;
} }
return 0; return 0;
} }
static u32 ali15x3_func(struct i2c_adapter *adapter)
u32 ali15x3_func(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
...@@ -510,8 +479,6 @@ static struct i2c_adapter ali15x3_adapter = { ...@@ -510,8 +479,6 @@ static struct i2c_adapter ali15x3_adapter = {
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
static struct pci_device_id ali15x3_ids[] __devinitdata = { static struct pci_device_id ali15x3_ids[] __devinitdata = {
{ {
.vendor = PCI_VENDOR_ID_AL, .vendor = PCI_VENDOR_ID_AL,
...@@ -525,9 +492,8 @@ static struct pci_device_id ali15x3_ids[] __devinitdata = { ...@@ -525,9 +492,8 @@ static struct pci_device_id ali15x3_ids[] __devinitdata = {
static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
if (ali15x3_setup(dev)) { if (ali15x3_setup(dev)) {
printk dev_err(&dev->dev,
("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n"); "ALI15X3 not detected, module not inserted.\n");
return -ENODEV; return -ENODEV;
} }
...@@ -557,17 +523,15 @@ static int __init i2c_ali15x3_init(void) ...@@ -557,17 +523,15 @@ static int __init i2c_ali15x3_init(void)
return pci_module_init(&ali15x3_driver); return pci_module_init(&ali15x3_driver);
} }
static void __exit i2c_ali15x3_exit(void) static void __exit i2c_ali15x3_exit(void)
{ {
pci_unregister_driver(&ali15x3_driver); pci_unregister_driver(&ali15x3_driver);
release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
} }
MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
"Philip Edelbrock <phil@netroedge.com>, "
MODULE_AUTHOR "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("ALI15X3 SMBus driver"); MODULE_DESCRIPTION("ALI15X3 SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
Note: we assume there can only be one device, with one SMBus interface. Note: we assume there can only be one device, with one SMBus interface.
*/ */
/* #define DEBUG 1 */
#include <linux/version.h> #include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -46,44 +48,42 @@ ...@@ -46,44 +48,42 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "i2c-amd756"
/* AMD756 SMBus address offsets */ /* AMD756 SMBus address offsets */
#define SMB_ADDR_OFFSET 0xE0 #define SMB_ADDR_OFFSET 0xE0
#define SMB_IOSIZE 16 #define SMB_IOSIZE 16
#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) #define SMB_GLOBAL_STATUS (0x0 + amd756_ioport)
#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) #define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport)
#define SMB_HOST_ADDRESS (0x4 + amd756_ioport) #define SMB_HOST_ADDRESS (0x4 + amd756_ioport)
#define SMB_HOST_DATA (0x6 + amd756_ioport) #define SMB_HOST_DATA (0x6 + amd756_ioport)
#define SMB_HOST_COMMAND (0x8 + amd756_ioport) #define SMB_HOST_COMMAND (0x8 + amd756_ioport)
#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) #define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport)
#define SMB_HAS_DATA (0xA + amd756_ioport) #define SMB_HAS_DATA (0xA + amd756_ioport)
#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) #define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport)
#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) #define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport)
#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) #define SMB_SNOOP_ADDRESS (0xF + amd756_ioport)
/* PCI Address Constants */ /* PCI Address Constants */
/* address of I/O space */ /* address of I/O space */
#define SMBBA 0x058 /* mh */ #define SMBBA 0x058 /* mh */
#define SMBBANFORCE 0x014 #define SMBBANFORCE 0x014
/* general configuration */ /* general configuration */
#define SMBGCFG 0x041 /* mh */ #define SMBGCFG 0x041 /* mh */
/* silicon revision code */ /* silicon revision code */
#define SMBREV 0x008 #define SMBREV 0x008
/* Other settings */ /* Other settings */
#define MAX_TIMEOUT 500 #define MAX_TIMEOUT 500
/* AMD756 constants */ /* AMD756 constants */
#define AMD756_QUICK 0x00 #define AMD756_QUICK 0x00
#define AMD756_BYTE 0x01 #define AMD756_BYTE 0x01
#define AMD756_BYTE_DATA 0x02 #define AMD756_BYTE_DATA 0x02
#define AMD756_WORD_DATA 0x03 #define AMD756_WORD_DATA 0x03
#define AMD756_PROCESS_CALL 0x04 #define AMD756_PROCESS_CALL 0x04
#define AMD756_BLOCK_DATA 0x05 #define AMD756_BLOCK_DATA 0x05
static unsigned short amd756_ioport = 0; static unsigned short amd756_ioport = 0;
...@@ -101,36 +101,36 @@ static void amd756_do_pause(unsigned int amount) ...@@ -101,36 +101,36 @@ static void amd756_do_pause(unsigned int amount)
schedule_timeout(amount); schedule_timeout(amount);
} }
#define GS_ABRT_STS (1 << 0) #define GS_ABRT_STS (1 << 0)
#define GS_COL_STS (1 << 1) #define GS_COL_STS (1 << 1)
#define GS_PRERR_STS (1 << 2) #define GS_PRERR_STS (1 << 2)
#define GS_HST_STS (1 << 3) #define GS_HST_STS (1 << 3)
#define GS_HCYC_STS (1 << 4) #define GS_HCYC_STS (1 << 4)
#define GS_TO_STS (1 << 5) #define GS_TO_STS (1 << 5)
#define GS_SMB_STS (1 << 11) #define GS_SMB_STS (1 << 11)
#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ #define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \
GS_HCYC_STS | GS_TO_STS ) GS_HCYC_STS | GS_TO_STS )
#define GE_CYC_TYPE_MASK (7) #define GE_CYC_TYPE_MASK (7)
#define GE_HOST_STC (1 << 3) #define GE_HOST_STC (1 << 3)
#define GE_ABORT (1 << 5) #define GE_ABORT (1 << 5)
static int amd756_transaction(void) static int amd756_transaction(struct i2c_adapter *adap)
{ {
int temp; int temp;
int result = 0; int result = 0;
int timeout = 0; int timeout = 0;
pr_debug(DRV_NAME dev_dbg(&adap->dev, ": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, "
": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", "DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS),
inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS),
inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); inb_p(SMB_HOST_DATA));
/* Make sure the SMBus host is ready to start transmitting */ /* Make sure the SMBus host is ready to start transmitting */
if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) {
pr_debug(DRV_NAME ": SMBus busy (%04x). Waiting... \n", temp); dev_dbg(&adap->dev, ": SMBus busy (%04x). Waiting... \n", temp);
do { do {
amd756_do_pause(1); amd756_do_pause(1);
temp = inw_p(SMB_GLOBAL_STATUS); temp = inw_p(SMB_GLOBAL_STATUS);
...@@ -138,7 +138,7 @@ static int amd756_transaction(void) ...@@ -138,7 +138,7 @@ static int amd756_transaction(void)
(timeout++ < MAX_TIMEOUT)); (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
pr_debug(DRV_NAME ": Busy wait timeout (%04x)\n", temp); dev_dbg(&adap->dev, ": Busy wait timeout (%04x)\n", temp);
goto abort; goto abort;
} }
timeout = 0; timeout = 0;
...@@ -155,46 +155,46 @@ static int amd756_transaction(void) ...@@ -155,46 +155,46 @@ static int amd756_transaction(void)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
pr_debug(DRV_NAME ": Completion timeout!\n"); dev_dbg(&adap->dev, ": Completion timeout!\n");
goto abort; goto abort;
} }
if (temp & GS_PRERR_STS) { if (temp & GS_PRERR_STS) {
result = -1; result = -1;
pr_debug(DRV_NAME ": SMBus Protocol error (no response)!\n"); dev_dbg(&adap->dev, ": SMBus Protocol error (no response)!\n");
} }
if (temp & GS_COL_STS) { if (temp & GS_COL_STS) {
result = -1; result = -1;
printk(KERN_WARNING DRV_NAME " SMBus collision!\n"); dev_warn(&adap->dev, " SMBus collision!\n");
} }
if (temp & GS_TO_STS) { if (temp & GS_TO_STS) {
result = -1; result = -1;
pr_debug(DRV_NAME ": SMBus protocol timeout!\n"); dev_dbg(&adap->dev, ": SMBus protocol timeout!\n");
} }
if (temp & GS_HCYC_STS) if (temp & GS_HCYC_STS)
pr_debug(DRV_NAME " SMBus protocol success!\n"); dev_dbg(&adap->dev, " SMBus protocol success!\n");
outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
#ifdef DEBUG #ifdef DEBUG
if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
pr_debug(DRV_NAME dev_dbg(&adap->dev,
": Failed reset at end of transaction (%04x)\n", temp); ": Failed reset at end of transaction (%04x)\n", temp);
} }
pr_debug(DRV_NAME
": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
#endif #endif
dev_dbg(&adap->dev,
": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
return result; return result;
abort: abort:
printk(KERN_WARNING DRV_NAME ": Sending abort.\n"); dev_warn(&adap->dev, ": Sending abort.\n");
outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
amd756_do_pause(100); amd756_do_pause(100);
outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
...@@ -211,7 +211,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, ...@@ -211,7 +211,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
/** TODO: Should I supporte the 10-bit transfers? */ /** TODO: Should I supporte the 10-bit transfers? */
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL: case I2C_SMBUS_PROC_CALL:
pr_debug(DRV_NAME ": I2C_SMBUS_PROC_CALL not supported!\n"); dev_dbg(&adap->dev, ": I2C_SMBUS_PROC_CALL not supported!\n");
/* TODO: Well... It is supported, I'm just not sure what to do here... */ /* TODO: Well... It is supported, I'm just not sure what to do here... */
return -1; return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
...@@ -266,7 +266,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, ...@@ -266,7 +266,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
/* How about enabling interrupts... */ /* How about enabling interrupts... */
outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
if (amd756_transaction()) /* Error in transaction */ if (amd756_transaction(adap)) /* Error in transaction */
return -1; return -1;
if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
...@@ -334,7 +334,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev, ...@@ -334,7 +334,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
u8 temp; u8 temp;
if (amd756_ioport) { if (amd756_ioport) {
printk(KERN_ERR DRV_NAME ": Only one device supported. " dev_err(&pdev->dev, ": Only one device supported. "
"(you have a strange motherboard, btw..)\n"); "(you have a strange motherboard, btw..)\n");
return -ENODEV; return -ENODEV;
} }
...@@ -351,8 +351,8 @@ static int __devinit amd756_probe(struct pci_dev *pdev, ...@@ -351,8 +351,8 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
pci_read_config_byte(pdev, SMBGCFG, &temp); pci_read_config_byte(pdev, SMBGCFG, &temp);
if ((temp & 128) == 0) { if ((temp & 128) == 0) {
printk(KERN_ERR DRV_NAME dev_err(&pdev->dev,
": Error: SMBus controller I/O not enabled!\n"); ": Error: SMBus controller I/O not enabled!\n");
return -ENODEV; return -ENODEV;
} }
...@@ -364,16 +364,14 @@ static int __devinit amd756_probe(struct pci_dev *pdev, ...@@ -364,16 +364,14 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
} }
if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) { if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) {
printk(KERN_ERR DRV_NAME dev_err(&pdev->dev, ": SMB region 0x%x already in use!\n",
": SMB region 0x%x already in use!\n", amd756_ioport); amd756_ioport);
return -ENODEV; return -ENODEV;
} }
#ifdef DEBUG
pci_read_config_byte(pdev, SMBREV, &temp); pci_read_config_byte(pdev, SMBREV, &temp);
printk(KERN_DEBUG DRV_NAME ": SMBREV = 0x%X\n", temp); dev_dbg(&pdev->dev, ": SMBREV = 0x%X\n", temp);
printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport); dev_dbg(&pdev->dev, ": AMD756_smba = 0x%X\n", amd756_ioport);
#endif
/* set up the driverfs linkage to our parent device */ /* set up the driverfs linkage to our parent device */
amd756_adapter.dev.parent = &pdev->dev; amd756_adapter.dev.parent = &pdev->dev;
...@@ -383,8 +381,8 @@ static int __devinit amd756_probe(struct pci_dev *pdev, ...@@ -383,8 +381,8 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
error = i2c_add_adapter(&amd756_adapter); error = i2c_add_adapter(&amd756_adapter);
if (error) { if (error) {
printk(KERN_ERR DRV_NAME dev_err(&pdev->dev,
": Adapter registration failed, module not inserted.\n"); ": Adapter registration failed, module not inserted.\n");
goto out_err; goto out_err;
} }
......
...@@ -74,7 +74,7 @@ unsigned int amd_ec_wait_write(struct amd_smbus *smbus) ...@@ -74,7 +74,7 @@ unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
udelay(1); udelay(1);
if (!timeout) { if (!timeout) {
printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for IBF to clear\n"); dev_warn(&smbus->dev->dev, "Timeout while waiting for IBF to clear\n");
return -1; return -1;
} }
...@@ -89,7 +89,7 @@ unsigned int amd_ec_wait_read(struct amd_smbus *smbus) ...@@ -89,7 +89,7 @@ unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
udelay(1); udelay(1);
if (!timeout) { if (!timeout) {
printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for OBF to set\n"); dev_warn(&smbus->dev->dev, "Timeout while waiting for OBF to set\n");
return -1; return -1;
} }
...@@ -256,11 +256,11 @@ s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, ...@@ -256,11 +256,11 @@ s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BLOCK_DATA_PEC: case I2C_SMBUS_BLOCK_DATA_PEC:
case I2C_SMBUS_PROC_CALL_PEC: case I2C_SMBUS_PROC_CALL_PEC:
case I2C_SMBUS_BLOCK_PROC_CALL_PEC: case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
printk(KERN_WARNING "i2c-amd8111.c: Unexpected software PEC transaction %d\n.", size); dev_warn(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
return -1; return -1;
default: default:
printk(KERN_WARNING "i2c-amd8111.c: Unsupported transaction %d\n", size); dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
return -1; return -1;
} }
...@@ -392,7 +392,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev) ...@@ -392,7 +392,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev)
} }
static struct pci_driver amd8111_driver = { static struct pci_driver amd8111_driver = {
.name = "amd8111 smbus", .name = "amd8111 smbus 2",
.id_table = amd8111_ids, .id_table = amd8111_ids,
.probe = amd8111_probe, .probe = amd8111_probe,
.remove = __devexit_p(amd8111_remove), .remove = __devexit_p(amd8111_remove),
......
...@@ -49,65 +49,48 @@ ...@@ -49,65 +49,48 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <asm/io.h> #include <asm/io.h>
MODULE_LICENSE("GPL");
#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC #ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
#define HAVE_PEC #define HAVE_PEC
#endif #endif
#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS
#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS 0x2483
#endif
#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS
#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS 0x24C3
#endif
static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3,
PCI_DEVICE_ID_INTEL_82801AB_3,
PCI_DEVICE_ID_INTEL_82801BA_2,
PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
0 };
/* I801 SMBus address offsets */ /* I801 SMBus address offsets */
#define SMBHSTSTS (0 + i801_smba) #define SMBHSTSTS (0 + i801_smba)
#define SMBHSTCNT (2 + i801_smba) #define SMBHSTCNT (2 + i801_smba)
#define SMBHSTCMD (3 + i801_smba) #define SMBHSTCMD (3 + i801_smba)
#define SMBHSTADD (4 + i801_smba) #define SMBHSTADD (4 + i801_smba)
#define SMBHSTDAT0 (5 + i801_smba) #define SMBHSTDAT0 (5 + i801_smba)
#define SMBHSTDAT1 (6 + i801_smba) #define SMBHSTDAT1 (6 + i801_smba)
#define SMBBLKDAT (7 + i801_smba) #define SMBBLKDAT (7 + i801_smba)
#define SMBPEC (8 + i801_smba) /* ICH4 only */ #define SMBPEC (8 + i801_smba) /* ICH4 only */
#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ #define SMBAUXSTS (12 + i801_smba) /* ICH4 only */
#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ #define SMBAUXCTL (13 + i801_smba) /* ICH4 only */
/* PCI Address Constants */ /* PCI Address Constants */
#define SMBBA 0x020 #define SMBBA 0x020
#define SMBHSTCFG 0x040 #define SMBHSTCFG 0x040
#define SMBREV 0x008 #define SMBREV 0x008
/* Host configuration bits for SMBHSTCFG */ /* Host configuration bits for SMBHSTCFG */
#define SMBHSTCFG_HST_EN 1 #define SMBHSTCFG_HST_EN 1
#define SMBHSTCFG_SMB_SMI_EN 2 #define SMBHSTCFG_SMB_SMI_EN 2
#define SMBHSTCFG_I2C_EN 4 #define SMBHSTCFG_I2C_EN 4
/* Other settings */ /* Other settings */
#define MAX_TIMEOUT 100 #define MAX_TIMEOUT 100
#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
/* I801 command constants */ /* I801 command constants */
#define I801_QUICK 0x00 #define I801_QUICK 0x00
#define I801_BYTE 0x04 #define I801_BYTE 0x04
#define I801_BYTE_DATA 0x08 #define I801_BYTE_DATA 0x08
#define I801_WORD_DATA 0x0C #define I801_WORD_DATA 0x0C
#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ #define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
#define I801_BLOCK_DATA 0x14 #define I801_BLOCK_DATA 0x14
#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ #define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
#define I801_BLOCK_LAST 0x34 #define I801_BLOCK_LAST 0x34
#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ #define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
#define I801_START 0x40 #define I801_START 0x40
#define I801_PEC_EN 0x80 /* ICH4 only */ #define I801_PEC_EN 0x80 /* ICH4 only */
/* insmod parameters */ /* insmod parameters */
...@@ -119,10 +102,6 @@ MODULE_PARM_DESC(force_addr, ...@@ -119,10 +102,6 @@ MODULE_PARM_DESC(force_addr,
"Forcibly enable the I801 at the given address. " "Forcibly enable the I801 at the given address. "
"EXTREMELY DANGEROUS!"); "EXTREMELY DANGEROUS!");
static void i801_do_pause(unsigned int amount); static void i801_do_pause(unsigned int amount);
static int i801_transaction(void); static int i801_transaction(void);
static int i801_block_transaction(union i2c_smbus_data *data, static int i801_block_transaction(union i2c_smbus_data *data,
...@@ -135,7 +114,6 @@ static int isich4; ...@@ -135,7 +114,6 @@ static int isich4;
static int i801_setup(struct pci_dev *dev) static int i801_setup(struct pci_dev *dev)
{ {
int error_return = 0; int error_return = 0;
int *num = supported;
unsigned char temp; unsigned char temp;
/* Note: we keep on searching until we have found 'function 3' */ /* Note: we keep on searching until we have found 'function 3' */
...@@ -143,101 +121,90 @@ static int i801_setup(struct pci_dev *dev) ...@@ -143,101 +121,90 @@ static int i801_setup(struct pci_dev *dev)
return -ENODEV; return -ENODEV;
I801_dev = dev; I801_dev = dev;
isich4 = *num == PCI_DEVICE_ID_INTEL_82801DB_SMBUS; if (dev->device == PCI_DEVICE_ID_INTEL_82801DB_3)
isich4 = 1;
else
isich4 = 0;
/* Determine the address of the SMBus areas */ /* Determine the address of the SMBus areas */
if (force_addr) { if (force_addr) {
i801_smba = force_addr & 0xfff0; i801_smba = force_addr & 0xfff0;
} else { } else {
pci_read_config_word(I801_dev, SMBBA, &i801_smba); pci_read_config_word(I801_dev, SMBBA, &i801_smba);
i801_smba &= 0xfff0; i801_smba &= 0xfff0;
if(i801_smba == 0) { if(i801_smba == 0) {
printk(KERN_ERR "i2c-i801.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); dev_err(&dev->dev, "SMB base address uninitialized"
"- upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV; return -ENODEV;
} }
} }
if (check_region(i801_smba, (isich4 ? 16 : 8))) { if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
printk dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
(KERN_ERR "i2c-i801.o: I801_smb region 0x%x already in use!\n", i801_smba);
i801_smba); error_return = -EBUSY;
error_return = -ENODEV;
goto END; goto END;
} }
pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
pci_write_config_byte(I801_dev, SMBHSTCFG, temp); pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
/* If force_addr is set, we program the new address here. Just to make
sure, we disable the device first. */ /* If force_addr is set, we program the new address here. Just to make
sure, we disable the device first. */
if (force_addr) { if (force_addr) {
pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
pci_write_config_word(I801_dev, SMBBA, i801_smba); pci_write_config_word(I801_dev, SMBBA, i801_smba);
pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
printk dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to "
(KERN_WARNING "i2c-i801.o: WARNING: I801 SMBus interface set to new " "new address %04x!\n", i801_smba);
"address %04x!\n", i801_smba);
} else if ((temp & 1) == 0) { } else if ((temp & 1) == 0) {
pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
printk(KERN_WARNING "i2c-i801.o: enabling SMBus device\n"); dev_warn(&dev->dev, "enabling SMBus device\n");
} }
request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus");
#ifdef DEBUG
if (temp & 0x02) if (temp & 0x02)
printk dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n");
(KERN_DEBUG "i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
else else
printk dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n");
(KERN_DEBUG "i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
pci_read_config_byte(I801_dev, SMBREV, &temp); pci_read_config_byte(I801_dev, SMBREV, &temp);
printk(KERN_DEBUG "i2c-i801.o: SMBREV = 0x%X\n", temp); dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp);
printk(KERN_DEBUG "i2c-i801.o: I801_smba = 0x%X\n", i801_smba); dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba);
#endif /* DEBUG */
END: END:
return error_return; return error_return;
} }
void i801_do_pause(unsigned int amount) static void i801_do_pause(unsigned int amount)
{ {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule_timeout(amount); schedule_timeout(amount);
} }
int i801_transaction(void) static int i801_transaction(void)
{ {
int temp; int temp;
int result = 0; int result = 0;
int timeout = 0; int timeout = 0;
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x,"
printk "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
(KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
"DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTDAT1));
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
#endif
/* Make sure the SMBus host is ready to start transmitting */ /* Make sure the SMBus host is ready to start transmitting */
/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
#ifdef DEBUG dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting... \n",
printk(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n", temp);
temp);
#endif
outb_p(temp, SMBHSTSTS); outb_p(temp, SMBHSTSTS);
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
printk(KERN_DEBUG "i2c-i801.o: Failed! (%02x)\n", temp);
#endif
return -1; return -1;
} else { } else {
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Successfull!\n");
printk(KERN_DEBUG "i2c-i801.o: Successfull!\n");
#endif
} }
} }
...@@ -251,76 +218,64 @@ int i801_transaction(void) ...@@ -251,76 +218,64 @@ int i801_transaction(void)
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
#ifdef DEBUG dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
result = -1; result = -1;
#endif
} }
if (temp & 0x10) { if (temp & 0x10) {
result = -1; result = -1;
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
printk(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
#endif
} }
if (temp & 0x08) { if (temp & 0x08) {
result = -1; result = -1;
printk dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
(KERN_ERR "i2c-i801.o: Bus collision! SMBus may be locked until next hard\n" "until next hard reset. (sorry!)\n");
"reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */ /* Clock stops and slave is stuck in mid-transmission */
} }
if (temp & 0x04) { if (temp & 0x04) {
result = -1; result = -1;
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Error: no response!\n");
printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
#endif
} }
if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
outb_p(inb(SMBHSTSTS), SMBHSTSTS); outb_p(inb(SMBHSTSTS), SMBHSTSTS);
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Failed reset at end of transaction"
printk "(%02x)\n", temp);
(KERN_DEBUG "i2c-i801.o: Failed reset at end of transaction (%02x)\n",
temp);
#endif
} }
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
printk "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
(KERN_DEBUG "i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTDAT1));
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
#endif
return result; return result;
} }
/* All-inclusive block transaction function */ /* All-inclusive block transaction function */
int i801_block_transaction(union i2c_smbus_data *data, char read_write, static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
int command) int command)
{ {
int i, len; int i, len;
int smbcmd; int smbcmd;
int temp; int temp;
int result = 0; int result = 0;
int timeout; int timeout;
unsigned char hostc, errmask; unsigned char hostc, errmask;
if (command == I2C_SMBUS_I2C_BLOCK_DATA) { if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
/* set I2C_EN bit in configuration register */ /* set I2C_EN bit in configuration register */
pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(I801_dev, SMBHSTCFG, pci_write_config_byte(I801_dev, SMBHSTCFG,
hostc | SMBHSTCFG_I2C_EN); hostc | SMBHSTCFG_I2C_EN);
} else { } else {
printk("i2c-i801.o: " dev_err(&I801_dev->dev,
"I2C_SMBUS_I2C_BLOCK_READ not supported!\n"); "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
return -1; return -1;
} }
} }
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0]; len = data->block[0];
...@@ -343,60 +298,43 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -343,60 +298,43 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write,
smbcmd = I801_BLOCK_LAST; smbcmd = I801_BLOCK_LAST;
else else
smbcmd = I801_BLOCK_DATA; smbcmd = I801_BLOCK_DATA;
#if 0 /* now using HW PEC */
if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC)
smbcmd |= I801_PEC_EN;
#endif
outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
printk "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
(KERN_DEBUG "i2c-i801.o: Block (pre %d): CNT=%02x, CMD=%02x, ADD=%02x, " inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
"DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBBLKDAT));
#endif
/* Make sure the SMBus host is ready to start transmitting */ /* Make sure the SMBus host is ready to start transmitting */
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
if (i == 1) { if (i == 1) {
/* Erronenous conditions before transaction: /* Erronenous conditions before transaction:
* Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
errmask=0x9f; errmask=0x9f;
} else { } else {
/* Erronenous conditions during transaction: /* Erronenous conditions during transaction:
* Failed, Bus_Err, Dev_Err, Intr */ * Failed, Bus_Err, Dev_Err, Intr */
errmask=0x1e; errmask=0x1e;
} }
if (temp & errmask) { if (temp & errmask) {
#ifdef DEBUG dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
printk "Resetting... \n", temp);
(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n",
temp);
#endif
outb_p(temp, SMBHSTSTS); outb_p(temp, SMBHSTSTS);
if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
printk dev_err(&I801_dev->dev,
(KERN_ERR "i2c-i801.o: Reset failed! (%02x)\n", "Reset failed! (%02x)\n", temp);
temp);
result = -1; result = -1;
goto END; goto END;
} }
if (i != 1) { if (i != 1) {
result = -1; /* if die in middle of block transaction, fail */ /* if die in middle of block transaction, fail */
goto END; result = -1;
} goto END;
}
} }
if (i == 1) { if (i == 1)
#if 0 /* #ifdef HAVE_PEC (now using HW PEC) */
if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
if(read_write == I2C_SMBUS_WRITE)
outb_p(data->block[len + 1], SMBPEC);
}
#endif
outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
}
/* We will always wait for a fraction of a second! */ /* We will always wait for a fraction of a second! */
timeout = 0; timeout = 0;
...@@ -410,25 +348,19 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -410,25 +348,19 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write,
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
result = -1; result = -1;
#ifdef DEBUG dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
#endif
} }
if (temp & 0x10) { if (temp & 0x10) {
result = -1; result = -1;
#ifdef DEBUG dev_dbg(&I801_dev->dev,
printk "Error: Failed bus transaction\n");
(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
#endif
} else if (temp & 0x08) { } else if (temp & 0x08) {
result = -1; result = -1;
printk(KERN_ERR "i2c-i801.o: Bus collision!\n"); dev_err(&I801_dev->dev, "Bus collision!\n");
} else if (temp & 0x04) { } else if (temp & 0x04) {
result = -1; result = -1;
#ifdef DEBUG dev_dbg(&I801_dev->dev, "Error: no response!\n");
printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
#endif
} }
if (i == 1 && read_write == I2C_SMBUS_READ) { if (i == 1 && read_write == I2C_SMBUS_READ) {
...@@ -440,7 +372,7 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -440,7 +372,7 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write,
data->block[0] = len; data->block[0] = len;
} }
/* Retrieve/store value in SMBBLKDAT */ /* Retrieve/store value in SMBBLKDAT */
if (read_write == I2C_SMBUS_READ) if (read_write == I2C_SMBUS_READ)
data->block[i] = inb_p(SMBBLKDAT); data->block[i] = inb_p(SMBBLKDAT);
if (read_write == I2C_SMBUS_WRITE && i+1 <= len) if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
...@@ -448,18 +380,15 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -448,18 +380,15 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write,
if ((temp & 0x9e) != 0x00) if ((temp & 0x9e) != 0x00)
outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
#ifdef DEBUG
if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
printk dev_dbg(&I801_dev->dev,
(KERN_DEBUG "i2c-i801.o: Bad status (%02x) at end of transaction\n", "Bad status (%02x) at end of transaction\n",
temp); temp);
} }
printk dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
(KERN_DEBUG "i2c-i801.o: Block (post %d): CNT=%02x, CMD=%02x, ADD=%02x, " "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
"DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
inb_p(SMBBLKDAT));
#endif
if (result < 0) if (result < 0)
goto END; goto END;
...@@ -476,29 +405,24 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, ...@@ -476,29 +405,24 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write,
&& (timeout++ < MAX_TIMEOUT)); && (timeout++ < MAX_TIMEOUT));
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
printk(KERN_DEBUG "i2c-i801.o: PEC Timeout!\n"); dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
}
#if 0 /* now using HW PEC */
if(read_write == I2C_SMBUS_READ) {
data->block[len + 1] = inb_p(SMBPEC);
} }
#endif
outb_p(temp, SMBHSTSTS); outb_p(temp, SMBHSTSTS);
} }
#endif #endif
result = 0; result = 0;
END: END:
if (command == I2C_SMBUS_I2C_BLOCK_DATA) { if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
/* restore saved configuration register value */ /* restore saved configuration register value */
pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
} }
return result; return result;
} }
/* Return -1 on error. */ /* Return -1 on error. */
s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, static s32 i801_access(struct i2c_adapter * adap, u16 addr,
char read_write, u8 command, int size, unsigned short flags, char read_write, u8 command,
union i2c_smbus_data * data) int size, union i2c_smbus_data * data)
{ {
int hwpec = 0; int hwpec = 0;
int block = 0; int block = 0;
...@@ -554,7 +478,7 @@ s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, ...@@ -554,7 +478,7 @@ s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
break; break;
case I2C_SMBUS_PROC_CALL: case I2C_SMBUS_PROC_CALL:
default: default:
printk(KERN_ERR "i2c-i801.o: Unsupported transaction %d\n", size); dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
return -1; return -1;
} }
...@@ -600,7 +524,7 @@ s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, ...@@ -600,7 +524,7 @@ s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
} }
u32 i801_func(struct i2c_adapter *adapter) static u32 i801_func(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
...@@ -627,8 +551,6 @@ static struct i2c_adapter i801_adapter = { ...@@ -627,8 +551,6 @@ static struct i2c_adapter i801_adapter = {
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
static struct pci_device_id i801_ids[] __devinitdata = { static struct pci_device_id i801_ids[] __devinitdata = {
{ {
.vendor = PCI_VENDOR_ID_INTEL, .vendor = PCI_VENDOR_ID_INTEL,
...@@ -650,13 +572,13 @@ static struct pci_device_id i801_ids[] __devinitdata = { ...@@ -650,13 +572,13 @@ static struct pci_device_id i801_ids[] __devinitdata = {
}, },
{ {
.vendor = PCI_VENDOR_ID_INTEL, .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_82801CA_SMBUS, .device = PCI_DEVICE_ID_INTEL_82801CA_3,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
}, },
{ {
.vendor = PCI_VENDOR_ID_INTEL, .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_82801DB_SMBUS, .device = PCI_DEVICE_ID_INTEL_82801DB_3,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
}, },
...@@ -667,8 +589,8 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id ...@@ -667,8 +589,8 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
{ {
if (i801_setup(dev)) { if (i801_setup(dev)) {
printk dev_warn(&dev->dev,
(KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n"); "I801 not detected, module not inserted.\n");
return -ENODEV; return -ENODEV;
} }
...@@ -694,22 +616,21 @@ static struct pci_driver i801_driver = { ...@@ -694,22 +616,21 @@ static struct pci_driver i801_driver = {
static int __init i2c_i801_init(void) static int __init i2c_i801_init(void)
{ {
printk(KERN_INFO "i2c-i801.o version %s (%s)\n", I2C_VERSION, I2C_DATE); printk(KERN_INFO "i2c-i801 version %s (%s)\n", I2C_VERSION, I2C_DATE);
return pci_module_init(&i801_driver); return pci_module_init(&i801_driver);
} }
static void __exit i2c_i801_exit(void) static void __exit i2c_i801_exit(void)
{ {
pci_unregister_driver(&i801_driver); pci_unregister_driver(&i801_driver);
release_region(i801_smba, (isich4 ? 16 : 8)); release_region(i801_smba, (isich4 ? 16 : 8));
} }
MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
"Philip Edelbrock <phil@netroedge.com>, "
MODULE_AUTHOR "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("I801 SMBus driver"); MODULE_DESCRIPTION("I801 SMBus driver");
MODULE_LICENSE("GPL");
module_init(i2c_i801_init); module_init(i2c_i801_init);
module_exit(i2c_i801_exit); module_exit(i2c_i801_exit);
/*
i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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.
*/
/* This implements an i2c algorithm/adapter for ISA bus. Not that this is
on first sight very useful; almost no functionality is preserved.
Except that it makes writing drivers for chips which can be on both
the SMBus and the ISA bus very much easier. See lm78.c for an example
of this. */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/i2c.h>
/* This is the actual algorithm we define */
static struct i2c_algorithm isa_algorithm = {
.name = "ISA bus algorithm",
.id = I2C_ALGO_ISA,
};
/* There can only be one... */
static struct i2c_adapter isa_adapter = {
.owner = THIS_MODULE,
.name = "ISA main adapter",
.id = I2C_ALGO_ISA | I2C_HW_ISA,
.algo = &isa_algorithm,
};
static int __init i2c_isa_init(void)
{
return i2c_add_adapter(&isa_adapter);
}
static void __exit i2c_isa_exit(void)
{
i2c_del_adapter(&isa_adapter);
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
MODULE_DESCRIPTION("ISA bus access through i2c");
MODULE_LICENSE("GPL");
module_init(i2c_isa_init);
module_exit(i2c_isa_exit);
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
Note: we assume there can only be one device, with one SMBus interface. Note: we assume there can only be one device, with one SMBus interface.
*/ */
/* #define DEBUG 1 */
#include <linux/module.h> #include <linux/module.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -49,37 +51,37 @@ struct sd { ...@@ -49,37 +51,37 @@ struct sd {
}; };
/* PIIX4 SMBus address offsets */ /* PIIX4 SMBus address offsets */
#define SMBHSTSTS (0 + piix4_smba) #define SMBHSTSTS (0 + piix4_smba)
#define SMBHSLVSTS (1 + piix4_smba) #define SMBHSLVSTS (1 + piix4_smba)
#define SMBHSTCNT (2 + piix4_smba) #define SMBHSTCNT (2 + piix4_smba)
#define SMBHSTCMD (3 + piix4_smba) #define SMBHSTCMD (3 + piix4_smba)
#define SMBHSTADD (4 + piix4_smba) #define SMBHSTADD (4 + piix4_smba)
#define SMBHSTDAT0 (5 + piix4_smba) #define SMBHSTDAT0 (5 + piix4_smba)
#define SMBHSTDAT1 (6 + piix4_smba) #define SMBHSTDAT1 (6 + piix4_smba)
#define SMBBLKDAT (7 + piix4_smba) #define SMBBLKDAT (7 + piix4_smba)
#define SMBSLVCNT (8 + piix4_smba) #define SMBSLVCNT (8 + piix4_smba)
#define SMBSHDWCMD (9 + piix4_smba) #define SMBSHDWCMD (9 + piix4_smba)
#define SMBSLVEVT (0xA + piix4_smba) #define SMBSLVEVT (0xA + piix4_smba)
#define SMBSLVDAT (0xC + piix4_smba) #define SMBSLVDAT (0xC + piix4_smba)
/* PCI Address Constants */ /* PCI Address Constants */
#define SMBBA 0x090 #define SMBBA 0x090
#define SMBHSTCFG 0x0D2 #define SMBHSTCFG 0x0D2
#define SMBSLVC 0x0D3 #define SMBSLVC 0x0D3
#define SMBSHDW1 0x0D4 #define SMBSHDW1 0x0D4
#define SMBSHDW2 0x0D5 #define SMBSHDW2 0x0D5
#define SMBREV 0x0D6 #define SMBREV 0x0D6
/* Other settings */ /* Other settings */
#define MAX_TIMEOUT 500 #define MAX_TIMEOUT 500
#define ENABLE_INT9 0 #define ENABLE_INT9 0
/* PIIX4 constants */ /* PIIX4 constants */
#define PIIX4_QUICK 0x00 #define PIIX4_QUICK 0x00
#define PIIX4_BYTE 0x04 #define PIIX4_BYTE 0x04
#define PIIX4_BYTE_DATA 0x08 #define PIIX4_BYTE_DATA 0x08
#define PIIX4_WORD_DATA 0x0C #define PIIX4_WORD_DATA 0x0C
#define PIIX4_BLOCK_DATA 0x14 #define PIIX4_BLOCK_DATA 0x14
/* insmod parameters */ /* insmod parameters */
...@@ -102,6 +104,7 @@ static int piix4_transaction(void); ...@@ -102,6 +104,7 @@ static int piix4_transaction(void);
static unsigned short piix4_smba = 0; static unsigned short piix4_smba = 0;
static struct i2c_adapter piix4_adapter;
/* /*
* Get DMI information. * Get DMI information.
...@@ -125,18 +128,17 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id ...@@ -125,18 +128,17 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id
if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data) if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
return -ENODEV; return -ENODEV;
printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name); dev_info(&PIIX4_dev->dev, "Found %s device\n", PIIX4_dev->dev.name);
if(ibm_dmi_probe()) { if(ibm_dmi_probe()) {
printk dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module "
(KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n"); "may corrupt your serial eeprom! Refusing to load "
printk "module!\n");
(KERN_ERR " your serial eeprom! Refusing to load module!\n"); error_return = -EPERM;
error_return = -EPERM; goto END;
goto END;
} }
/* Determine the address of the SMBus areas */ /* Determine the address of the SMBus areas */
if (force_addr) { if (force_addr) {
piix4_smba = force_addr & 0xfff0; piix4_smba = force_addr & 0xfff0;
force = 0; force = 0;
...@@ -144,75 +146,68 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id ...@@ -144,75 +146,68 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id
pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
piix4_smba &= 0xfff0; piix4_smba &= 0xfff0;
if(piix4_smba == 0) { if(piix4_smba == 0) {
printk(KERN_ERR "i2c-piix4.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); dev_err(&PIIX4_dev->dev, "SMB base address "
"uninitialized - upgrade BIOS or use "
"force_addr=0xaddr\n");
return -ENODEV; return -ENODEV;
} }
} }
if (check_region(piix4_smba, 8)) { if (!request_region(piix4_smba, 8, "piix4-smbus")) {
printk dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n",
(KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n", piix4_smba);
piix4_smba);
error_return = -ENODEV; error_return = -ENODEV;
goto END; goto END;
} }
pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
/* If force_addr is set, we program the new address here. Just to make /* If force_addr is set, we program the new address here. Just to make
sure, we disable the PIIX4 first. */ sure, we disable the PIIX4 first. */
if (force_addr) { if (force_addr) {
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01); pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
printk dev_info(&PIIX4_dev->dev, "WARNING: SMBus interface set to "
(KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to new " "new address %04x!\n", piix4_smba);
"address %04x!\n", piix4_smba);
} else if ((temp & 1) == 0) { } else if ((temp & 1) == 0) {
if (force) { if (force) {
/* This should never need to be done, but has been noted that /* This should never need to be done, but has been
many Dell machines have the SMBus interface on the PIIX4 * noted that many Dell machines have the SMBus
disabled!? NOTE: This assumes I/O space and other allocations WERE * interface on the PIIX4 disabled!? NOTE: This assumes
done by the Bios! Don't complain if your hardware does weird * I/O space and other allocations WERE done by the
things after enabling this. :') Check for Bios updates before * Bios! Don't complain if your hardware does weird
resorting to this. */ * things after enabling this. :') Check for Bios
* updates before resorting to this.
*/
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
temp | 1); temp | 1);
printk dev_printk(KERN_NOTICE, &PIIX4_dev->dev,
(KERN_NOTICE "i2c-piix4.o: WARNING: SMBus interface has been FORCEFULLY " "WARNING: SMBus interface has been "
"ENABLED!\n"); "FORCEFULLY ENABLED!\n");
} else { } else {
printk dev_err(&PIIX4_dev->dev,
(KERN_ERR "i2c-piix4.o: Host SMBus controller not enabled!\n"); "Host SMBus controller not enabled!\n");
error_return = -ENODEV; error_return = -ENODEV;
goto END; goto END;
} }
} }
/* Everything is happy, let's grab the memory and set things up. */
request_region(piix4_smba, 8, "piix4-smbus");
#ifdef DEBUG
if ((temp & 0x0E) == 8) if ((temp & 0x0E) == 8)
printk dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n");
(KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for SMBus.\n");
else if ((temp & 0x0E) == 0) else if ((temp & 0x0E) == 0)
printk dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n");
(KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# for SMBus.\n");
else else
printk dev_err(&PIIX4_dev->dev, "Illegal Interrupt configuration "
(KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration (or code out " "(or code out of date)!\n");
"of date)!\n");
pci_read_config_byte(PIIX4_dev, SMBREV, &temp); pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp); dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp);
printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba); dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba);
#endif /* DEBUG */
END: END:
return error_return; return error_return;
} }
/* Internally used pause function */ /* Internally used pause function */
static void piix4_do_pause(unsigned int amount) static void piix4_do_pause(unsigned int amount)
{ {
...@@ -227,29 +222,21 @@ static int piix4_transaction(void) ...@@ -227,29 +222,21 @@ static int piix4_transaction(void)
int result = 0; int result = 0;
int timeout = 0; int timeout = 0;
#ifdef DEBUG dev_dbg(&piix4_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
printk "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
(KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
"DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTDAT1));
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
#endif
/* Make sure the SMBus host is ready to start transmitting */ /* Make sure the SMBus host is ready to start transmitting */
if ((temp = inb_p(SMBHSTSTS)) != 0x00) { if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
#ifdef DEBUG dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). "
printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n", "Resetting... \n", temp);
temp);
#endif
outb_p(temp, SMBHSTSTS); outb_p(temp, SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) != 0x00) { if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
#ifdef DEBUG dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp);
#endif
return -1; return -1;
} else { } else {
#ifdef DEBUG dev_dbg(&piix4_adapter.dev, "Successfull!\n");
printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n");
#endif
} }
} }
...@@ -262,50 +249,40 @@ static int piix4_transaction(void) ...@@ -262,50 +249,40 @@ static int piix4_transaction(void)
temp = inb_p(SMBHSTSTS); temp = inb_p(SMBHSTSTS);
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
#ifdef DEBUG
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) { if (timeout >= MAX_TIMEOUT) {
printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n"); dev_err(&piix4_adapter.dev, "SMBus Timeout!\n");
result = -1; result = -1;
} }
#endif
if (temp & 0x10) { if (temp & 0x10) {
result = -1; result = -1;
#ifdef DEBUG dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n");
printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n");
#endif
} }
if (temp & 0x08) { if (temp & 0x08) {
result = -1; result = -1;
printk dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be "
(KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n" "locked until next hard reset. (sorry!)\n");
"reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */ /* Clock stops and slave is stuck in mid-transmission */
} }
if (temp & 0x04) { if (temp & 0x04) {
result = -1; result = -1;
#ifdef DEBUG dev_err(&piix4_adapter.dev, "Error: no response!\n");
printk(KERN_ERR "i2c-piix4.o: Error: no response!\n");
#endif
} }
if (inb_p(SMBHSTSTS) != 0x00) if (inb_p(SMBHSTSTS) != 0x00)
outb_p(inb(SMBHSTSTS), SMBHSTSTS); outb_p(inb(SMBHSTSTS), SMBHSTSTS);
#ifdef DEBUG
if ((temp = inb_p(SMBHSTSTS)) != 0x00) { if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
printk dev_err(&piix4_adapter.dev, "Failed reset at end of "
(KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n", "transaction (%02x)\n", temp);
temp);
} }
printk dev_dbg(&piix4_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
(KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); inb_p(SMBHSTDAT1));
#endif
return result; return result;
} }
...@@ -318,8 +295,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, ...@@ -318,8 +295,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
switch (size) { switch (size) {
case I2C_SMBUS_PROC_CALL: case I2C_SMBUS_PROC_CALL:
printk dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
(KERN_ERR "i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n");
return -1; return -1;
case I2C_SMBUS_QUICK: case I2C_SMBUS_QUICK:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
...@@ -402,7 +378,6 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, ...@@ -402,7 +378,6 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
return 0; return 0;
} }
static u32 piix4_func(struct i2c_adapter *adapter) static u32 piix4_func(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
...@@ -424,8 +399,6 @@ static struct i2c_adapter piix4_adapter = { ...@@ -424,8 +399,6 @@ static struct i2c_adapter piix4_adapter = {
.algo = &smbus_algorithm, .algo = &smbus_algorithm,
}; };
static struct pci_device_id piix4_ids[] __devinitdata = { static struct pci_device_id piix4_ids[] __devinitdata = {
{ {
.vendor = PCI_VENDOR_ID_INTEL, .vendor = PCI_VENDOR_ID_INTEL,
...@@ -468,7 +441,7 @@ static struct pci_device_id piix4_ids[] __devinitdata = { ...@@ -468,7 +441,7 @@ static struct pci_device_id piix4_ids[] __devinitdata = {
static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
int retval; int retval;
retval = piix4_setup(dev, id); retval = piix4_setup(dev, id);
if (retval) if (retval)
return retval; return retval;
...@@ -499,7 +472,7 @@ static struct pci_driver piix4_driver = { ...@@ -499,7 +472,7 @@ static struct pci_driver piix4_driver = {
static int __init i2c_piix4_init(void) static int __init i2c_piix4_init(void)
{ {
printk("i2c-piix4.o version %s (%s)\n", I2C_VERSION, I2C_DATE); printk(KERN_INFO "i2c-piix4 version %s (%s)\n", I2C_VERSION, I2C_DATE);
return pci_module_init(&piix4_driver); return pci_module_init(&piix4_driver);
} }
...@@ -510,8 +483,6 @@ static void __exit i2c_piix4_exit(void) ...@@ -510,8 +483,6 @@ static void __exit i2c_piix4_exit(void)
release_region(piix4_smba, 8); release_region(piix4_smba, 8);
} }
MODULE_AUTHOR MODULE_AUTHOR
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>"); ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("PIIX4 SMBus driver"); MODULE_DESCRIPTION("PIIX4 SMBus driver");
......
...@@ -93,9 +93,9 @@ SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1 ...@@ -93,9 +93,9 @@ SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1
/* Initial values */ /* Initial values */
/* Note: Eventhough I left the low and high limits named os and hyst, /* Note: Even though I left the low and high limits named os and hyst,
they don't quite work like a thermostat the way the LM75 does. I.e., they don't quite work like a thermostat the way the LM75 does. I.e.,
a lower temp than THYST actuall triggers an alarm instead of a lower temp than THYST actually triggers an alarm instead of
clearing it. Weird, ey? --Phil */ clearing it. Weird, ey? --Phil */
#define adm1021_INIT_TOS 60 #define adm1021_INIT_TOS 60
#define adm1021_INIT_THYST 20 #define adm1021_INIT_THYST 20
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/i2c-proc.h> #include <linux/i2c-proc.h>
#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ #define LM75_SYSCTL_TEMP 1200 /* Degrees Celsius * 10 */
/* Addresses to scan */ /* Addresses to scan */
static unsigned short normal_i2c[] = { SENSORS_I2C_END }; static unsigned short normal_i2c[] = { SENSORS_I2C_END };
......
...@@ -152,7 +152,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) ...@@ -152,7 +152,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
/* load own address in S0, effective address is (own << 1) */ /* load own address in S0, effective address is (own << 1) */
i2c_outb(adap, get_own(adap)); i2c_outb(adap, get_own(adap));
/* check it's realy writen */ /* check it's really written */
if ((temp = i2c_inb(adap)) != get_own(adap)) { if ((temp = i2c_inb(adap)) != get_own(adap)) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp)); DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp));
return -ENXIO; return -ENXIO;
...@@ -168,7 +168,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) ...@@ -168,7 +168,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
/* load clock register S2 */ /* load clock register S2 */
i2c_outb(adap, get_clock(adap)); i2c_outb(adap, get_clock(adap));
/* check it's realy writen, the only 5 lowest bits does matter */ /* check it's really written, the only 5 lowest bits does matter */
if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) { if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp)); DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp));
return -ENXIO; return -ENXIO;
...@@ -177,7 +177,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) ...@@ -177,7 +177,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
/* Enable serial interface, idle, S0 selected */ /* Enable serial interface, idle, S0 selected */
set_pcf(adap, 1, I2C_PCF_IDLE); set_pcf(adap, 1, I2C_PCF_IDLE);
/* check to see PCF is realy idled and we can access status register */ /* check to see PCF is really idled and we can access status register */
if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) { if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp)); DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp));
return -ENXIO; return -ENXIO;
......
...@@ -53,6 +53,16 @@ static void i2cproc_remove(int bus); ...@@ -53,6 +53,16 @@ static void i2cproc_remove(int bus);
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
int i2c_device_probe(struct device *dev)
{
return -ENODEV;
}
int i2c_device_remove(struct device *dev)
{
return 0;
}
/* --------------------------------------------------- /* ---------------------------------------------------
* registering functions * registering functions
* --------------------------------------------------- * ---------------------------------------------------
...@@ -204,6 +214,16 @@ int i2c_add_driver(struct i2c_driver *driver) ...@@ -204,6 +214,16 @@ int i2c_add_driver(struct i2c_driver *driver)
drivers[i] = driver; drivers[i] = driver;
DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name));
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.name = driver->name;
driver->driver.bus = &i2c_bus_type;
driver->driver.probe = i2c_device_probe;
driver->driver.remove = i2c_device_remove;
res = driver_register(&driver->driver);
if (res)
goto out_unlock;
/* now look for instances of driver on our adapters /* now look for instances of driver on our adapters
*/ */
...@@ -236,6 +256,8 @@ int i2c_del_driver(struct i2c_driver *driver) ...@@ -236,6 +256,8 @@ int i2c_del_driver(struct i2c_driver *driver)
goto out_unlock; goto out_unlock;
} }
driver_unregister(&driver->driver);
/* Have a look at each adapter, if clients of this driver are still /* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver * attached. If so, detach them to be able to kill the driver
* afterwards. * afterwards.
......
...@@ -270,7 +270,7 @@ static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen, ...@@ -270,7 +270,7 @@ static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
} }
/* This funcion reads or writes a 'real' value (encoded by the combination /* This function reads or writes a 'real' value (encoded by the combination
of an integer and a magnitude, the last is the power of ten the value of an integer and a magnitude, the last is the power of ten the value
should be divided with) to a /proc/sys directory. To use this function, should be divided with) to a /proc/sys directory. To use this function,
you must (before registering the ctl_table) set the extra2 field to the you must (before registering the ctl_table) set the extra2 field to the
......
...@@ -143,7 +143,10 @@ struct i2c_driver { ...@@ -143,7 +143,10 @@ struct i2c_driver {
* with the device. * with the device.
*/ */
int (*command)(struct i2c_client *client,unsigned int cmd, void *arg); int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
struct device_driver driver;
}; };
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
extern struct bus_type i2c_bus_type; extern struct bus_type i2c_bus_type;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment