diff for duplicates of <43CAB1B7.6020903@sh.cvut.cz> diff --git a/a/1.txt b/N1/1.txt index a1a0554..4591c89 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -8,21 +8,21 @@ yes I think you are right. (ADD/2 is the address of chip, that it tries to acces > Second block are errors from lm90 for different registers: > -> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS\x04, -> TYP\x10, CMD\x01, ADD™, DAT0 , DAT1\x10 -> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS\x14, -> TYP\x10, CMD\x01, ADD™, DAT0), DAT1\x10 -> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS\x04, -> TYP\x10, CMD\b, ADD˜, DAT0), DAT1\x10 +> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS=04, +> TYP=10, CMD=01, ADD=99, DAT0=a0, DAT1=10 +> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS=14, +> TYP=10, CMD=01, ADD=99, DAT0=29, DAT1=10 +> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS=04, +> TYP=10, CMD=08, ADD=98, DAT0=29, DAT1=10 > Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Error: command never > completed -> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS\x04, -> TYP\x10, CMD\b, ADD˜, DAT0), DAT1\x10 +> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS=04, +> TYP=10, CMD=08, ADD=98, DAT0=29, DAT1=10 > Jan 15 22:24:02 cooker kernel: lm90 0-004c: Register 0x8 read failed (-1) -> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS\x04, -> TYP\x10, CMD\a, ADD˜, DAT0), DAT1\x10 -> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS\x14, -> TYP\x10, CMD\a, ADD˜, DAT0), DAT1\x10 +> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS=04, +> TYP=10, CMD=07, ADD=98, DAT0=29, DAT1=10 +> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS=14, +> TYP=10, CMD=07, ADD=98, DAT0=29, DAT1=10 > > Here I do not see SMBus errors - it appears really that i2c device did not > respond. OTOH interesting is that there is no timeout. Apparently command @@ -33,7 +33,7 @@ yes I think you are right. (ADD/2 is the address of chip, that it tries to acces > the controller if an external device is hung") Well it seems this ali 15x3 has maybe same hardware bug? It was mentioned already here: -http://www2.lm-sensors.nu/~lm78/readticket.cgi?ticket 30 +http://www2.lm-sensors.nu/~lm78/readticket.cgi?ticket=2030 > In the log below you can see that the ALI15X3 chip seems to keep in idle-state > without reporting "done", but it does not turn in "busy" state. I patched the @@ -69,10 +69,3 @@ I hope it can help now. Regards Rudolf --------------- next part -------------- -A non-text attachment was scrubbed... -Name: i2c-ali15x3.c -Type: text/x-csrc -Size: 16990 bytes -Desc: not available -Url : http://lists.lm-sensors.org/pipermail/lm-sensors/attachments/20060115/0b2bfd6b/i2c-ali15x3-0001.bin diff --git a/N1/2.hdr b/N1/2.hdr new file mode 100644 index 0000000..eda7e20 --- /dev/null +++ b/N1/2.hdr @@ -0,0 +1,5 @@ +Content-Type: text/x-csrc; + name="i2c-ali15x3.c" +Content-Transfer-Encoding: 7bit +Content-Disposition: inline; + filename="i2c-ali15x3.c" diff --git a/N1/2.txt b/N1/2.txt new file mode 100644 index 0000000..b5e683d --- /dev/null +++ b/N1/2.txt @@ -0,0 +1,592 @@ +/* + ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and + Philip Edelbrock <phil@netroedge.com> and + Mark D. Studebaker <mdsxyz123@yahoo.com> + + 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 is the driver for the SMB Host controller on + Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. + + The M1543C is a South bridge for desktop systems. + The M1533 is a South bridge for portable systems. + They are part of the following ALI chipsets: + "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge + with AGP and 100MHz CPU Front Side bus + "Aladdin V": Includes the M1541 Socket 7 North bridge + with AGP and 100MHz CPU Front Side bus + "Aladdin IV": Includes the M1541 Socket 7 North bridge + with host bus up to 83.3 MHz. + For an overview of these chips see http://www.acerlabs.com + + The M1533/M1543C devices appear as FOUR separate devices + on the PCI bus. An output of lspci will show something similar + to the following: + + 00:02.0 USB Controller: Acer Laboratories Inc. M5237 + 00:03.0 Bridge: Acer Laboratories Inc. M7101 + 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 + 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 + + The SMB controller is part of the 7101 device, which is an + ACPI-compliant Power Management Unit (PMU). + + The whole 7101 device has to be enabled for the SMB to work. + You can't just enable the SMB alone. + The SMB and the ACPI have separate I/O spaces. + We make sure that the SMB is enabled. We leave the ACPI alone. + + This driver controls the SMB Host only. + The SMB Slave controller on the M15X3 is not enabled. + + This driver does not use interrupts. +*/ + +/* Note: we assume there can only be one ALI15X3, with one SMBus interface */ + +/* #define DEBUG 1 */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <asm/io.h> +#include "version.h" +#include "sensors_compat.h" + +/* ALI15X3 SMBus address offsets */ +#define SMBHSTSTS (0 + ali15x3_smba) +#define SMBHSTCNT (1 + ali15x3_smba) +#define SMBHSTSTART (2 + ali15x3_smba) +#define SMBHSTCMD (7 + ali15x3_smba) +#define SMBHSTADD (3 + ali15x3_smba) +#define SMBHSTDAT0 (4 + ali15x3_smba) +#define SMBHSTDAT1 (5 + ali15x3_smba) +#define SMBBLKDAT (6 + ali15x3_smba) + +/* PCI Address Constants */ +#define SMBCOM 0x004 +#define SMBBA 0x014 +#define SMBATPC 0x05B /* used to unlock xxxBA registers */ +#define SMBHSTCFG 0x0E0 +#define SMBSLVC 0x0E1 +#define SMBCLK 0x0E2 +#define SMBREV 0x008 + +/* Other settings */ +#define MAX_TIMEOUT 50 /* times 1/100 sec */ +#define MAX_RETRIES 3 /* maximum reset retries */ +#define ALI15X3_SMB_IOSIZE 32 + +/* 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 + tell user to upgrade BIOS and we fail. +*/ +#define ALI15X3_SMB_DEFAULTBASE 0xE800 + +/* ALI15X3 address lock bits */ +#define ALI15X3_LOCK 0x06 + +/* ALI15X3 command constants */ +#define ALI15X3_ABORT 0x02 +#define ALI15X3_T_OUT 0x04 +#define ALI15X3_QUICK 0x00 +#define ALI15X3_BYTE 0x10 +#define ALI15X3_BYTE_DATA 0x20 +#define ALI15X3_WORD_DATA 0x30 +#define ALI15X3_BLOCK_DATA 0x40 +#define ALI15X3_BLOCK_CLR 0x80 + +/* ALI15X3 status register bits */ +#define ALI15X3_STS_IDLE 0x04 +#define ALI15X3_STS_BUSY 0x08 +#define ALI15X3_STS_DONE 0x10 +#define ALI15X3_STS_DEV 0x20 /* device error */ +#define ALI15X3_STS_COLL 0x40 /* collision or no response */ +#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ +#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ + + +#define E_TIMEOUT -2 + +#define PRINTK(fmt, arg...) {;} + + +/* If force_addr is set to anything different from 0, we forcibly enable + the device at the given address. */ +static int force_addr = 0; +MODULE_PARM(force_addr, "i"); +MODULE_PARM_DESC(force_addr, + "Initialize the base address of the i2c controller"); + +static unsigned short ali15x3_smba = 0; + +static int ali15x3_setup(struct pci_dev *ALI15X3_dev) +{ + u16 a; + unsigned char temp; + + /* Check the following things: + - SMB I/O address is initialized + - Device is enabled + - We can use the addresses + */ + + /* Unlock the register. + The data sheet says that the address registers are read-only + if the lock bits are 1, but in fact the address registers + are zero unless you clear the lock bits. + */ + pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); + if (temp & ALI15X3_LOCK) { + temp &= ~ALI15X3_LOCK; + pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); + } + + /* Determine the address of the SMBus area */ + pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); + ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); + if (ali15x3_smba == 0 && force_addr == 0) { + dev_err(ALI15X3_dev, "ALI15X3_smb region uninitialized " + "- upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + + if(force_addr) + ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); + + if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) { + dev_err(ALI15X3_dev, + "ALI15X3_smb region 0x%x already in use!\n", + ali15x3_smba); + return -ENODEV; + } + + if(force_addr) { + dev_info(ALI15X3_dev, "forcing ISA address 0x%04X\n", + ali15x3_smba); + if (PCIBIOS_SUCCESSFUL != + pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba)) + return -ENODEV; + if (PCIBIOS_SUCCESSFUL != + pci_read_config_word(ALI15X3_dev, SMBBA, &a)) + return -ENODEV; + if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { + /* make sure it works */ + dev_err(ALI15X3_dev, + "force address failed - not supported?\n"); + return -ENODEV; + } + } + /* check if whole device is enabled */ + pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); + if ((temp & 1) == 0) { + dev_info(ALI15X3_dev, "enabling SMBus device\n"); + pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); + } + + /* Is SMB Host controller enabled? */ + pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); + if ((temp & 1) == 0) { + dev_info(ALI15X3_dev, "enabling SMBus controller\n"); + pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); + } + + /* set SMB clock to 74KHz as recommended in data sheet */ + /* ??CK Evtl. verursacht das die Bus timeouts, deshalb*/ + /* belassen wir es mal bei den Default-Einstellungen */ + pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); + + /* + The interrupt routing for SMB is set up in register 0x77 in the + 1533 ISA Bridge device, NOT in the 7101 device. + Don't bother with finding the 1533 device and reading the register. + if ((....... & 0x0F) == 1) + dev_dbg(ALI15X3_dev, "ALI15X3 using Interrupt 9 for SMBus.\n"); + */ + pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); + dev_dbg(ALI15X3_dev, "SMBREV = 0x%X\n", temp); + dev_dbg(ALI15X3_dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba); + + return 0; +} + +static int ali15x3_wait_for_idle (struct i2c_adapter *adap) +{ + int temp; + int timeout; + + /* make sure SMBus is idle */ + temp = inb_p(SMBHSTSTS); + for (timeout = 0; + (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); + timeout++) { + i2c_delay(1); + temp = inb_p(SMBHSTSTS); + } + if (timeout >= MAX_TIMEOUT) { + dev_err(adap, "Idle wait Timeout! STS=0x%02x\n", temp); + return -1; + } + + return 0; +} + +static int ali15x3_do_reset (struct i2c_adapter *adap) +{ + int temp; + + /* + If the host controller is still busy, it may have timed out in the + previous transaction, resulting in a "SMBus Timeout" Dev. + I've tried the following to reset a stuck busy bit. + 1. Reset the controller with an ABORT command. + (this doesn't seem to clear the controller if an external + device is hung) + 2. Reset the controller and the other SMBus devices with a + T_OUT command. (this clears the host busy bit if an + external device is hung, but it comes back upon a new access + to a device) + 3. Disable and reenable the controller in SMBHSTCFG + Worst case, nothing seems to work except power reset. + */ + /* Abort - reset the host controller */ + /* + 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. + */ + dev_dbg(adap, "Resetting entire SMB Bus (abort) to " + "clear busy condition (%02x)\n", temp); + outb_p(ALI15X3_T_OUT, SMBHSTCNT); + i2c_delay(1); + temp = inb_p(SMBHSTSTS); + dev_dbg(adap, "Status after reset: %02x\n", temp); + + /* now check the error bits and the busy bit */ + if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { + /* do a clear-on-write */ + dev_dbg(adap, "Doing a clear on write\n"); + outb_p(0xFF, SMBHSTSTS); + if ((temp = inb_p(SMBHSTSTS)) & + (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { + /* this is probably going to be correctable only by a power reset + as one of the bits now appears to be stuck */ + /* This may be a bus or device with electrical problems. */ + dev_err(adap, "SMBus reset failed! (0x%02x) - " + "controller or device on bus is probably hung\n", + temp); + return -1; + } + } else { + /* check and clear done bit */ + if (temp & ALI15X3_STS_DONE) { + dev_info(adap, "Resetting done flag\n"); + outb_p(temp, SMBHSTSTS); + } + } + + return 0; +} + +/* Another internally used function */ +static int ali15x3_transaction(struct i2c_adapter *adap) +{ + int temp; + int result = 0; + int timeout = 0; + + /*dev_dbg(adap, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); */ + + /* start the transaction by writing anything to the start register */ + outb_p(0xFF, SMBHSTSTART); + + /* We will always wait for a fraction of a second! */ + timeout = 0; + do { + i2c_delay(1); + temp = inb_p(SMBHSTSTS); + } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE))) + && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + //dev_warn(adap, "SMBus Timeout, doing a reset\n"); + ali15x3_do_reset(adap); + return E_TIMEOUT; + } + + if (temp & ALI15X3_STS_TERM) { + result = -1; + //dev_dbg(adap, "Error: Failed bus transaction\n"); + } + + /* + Unfortunately the ALI SMB controller maps "no response" and "bus + collision" into a single bit. No reponse is the usual case so don't + do a PRINTK. + This means that bus collisions go unreported. + */ + if (temp & ALI15X3_STS_COLL) { + result = -1; + /*dev_dbg(adap, + "Error: no response or bus collision ADD=%02x\n", + inb_p(SMBHSTADD)); */ + } + + /* haven't ever seen this */ + if (temp & ALI15X3_STS_DEV) { + result = -1; + dev_err(adap, "Error: device error\n"); + } + dev_dbg(adap, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); + return result; +} + +/* Return -1 on error. */ +static s32 ali15x3_access(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 retries; + int tsize; + + for (retries = 0; retries < MAX_RETRIES; retries++) + { + /* clear all the bits (clear-on-write) */ + outb_p(0xFF, SMBHSTSTS); + + /* ali15x3_do_reset(adap); */ + ali15x3_wait_for_idle(adap); + + switch (size) { + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + tsize = ALI15X3_QUICK; + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + tsize = ALI15X3_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + tsize = ALI15X3_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + tsize = ALI15X3_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 0) { + len = 0; + data->block[0] = len; + } + if (len > 32) { + len = 32; + data->block[0] = len; + } + outb_p(len, SMBHSTDAT0); + /* Reset SMBBLKDAT */ + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); + for (i = 1; i <= len; i++) + outb_p(data->block[i], SMBBLKDAT); + } + tsize = ALI15X3_BLOCK_DATA; + break; + default: + PRINTK + (KERN_WARNING "i2c-ali15x3.o: Unsupported transaction %d\n", size); + return -1; + } + + outb_p(tsize, SMBHSTCNT); /* output command */ + + switch (ali15x3_transaction(adap)) + { + case 0: + break; /* no error, continue */ + case E_TIMEOUT: + PRINTK(KERN_INFO "i2c-ali15x3.o: timeout, doing a retry (%d)\n", retries); + continue; + default: + return -1; + } + + break; + } + + if (retries == MAX_RETRIES) + { + PRINTK(KERN_WARNING "i2c-ali15x3.o: transaction failed, maximum retries reached\n"); + return -1; + } + + if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) + return 0; + + + switch (tsize) { + case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */ + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI15X3_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI15X3_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + case ALI15X3_BLOCK_DATA: + len = inb_p(SMBHSTDAT0); + if (len > 32) + len = 32; + data->block[0] = len; + /* Reset SMBBLKDAT */ + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); + for (i = 1; i <= data->block[0]; i++) { + data->block[i] = inb_p(SMBBLKDAT); + dev_dbg(adap, "Blk: len=%d, i=%d, data=%02x\n", + len, i, data->block[i]); + } + break; + } + return 0; +} + +static void ali15x3_inc(struct i2c_adapter *adapter) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + +static void ali15x3_dec(struct i2c_adapter *adapter) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + +static u32 ali15x3_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 struct i2c_algorithm smbus_algorithm = { + .name = "Non-I2C SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = ali15x3_access, + .functionality = ali15x3_func, +}; + +static struct i2c_adapter ali15x3_adapter = { + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, + .algo = &smbus_algorithm, + .name = "unset", + .inc_use = ali15x3_inc, + .dec_use = ali15x3_dec, +}; + +static struct pci_device_id ali15x3_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_AL, + .device = PCI_DEVICE_ID_AL_M7101, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, } +}; + +static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + if (ali15x3_setup(dev)) { + dev_err(dev, + "ALI15X3 not detected, module not inserted.\n"); + return -ENODEV; + } + + snprintf(ali15x3_adapter.name, 32, + "SMBus ALI15X3 adapter at %04x", ali15x3_smba); + return i2c_add_adapter(&ali15x3_adapter); +} + +static void __devexit ali15x3_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&ali15x3_adapter); + release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); +} + +static struct pci_driver ali15x3_driver = { + .name = "ali15x3 smbus", + .id_table = ali15x3_ids, + .probe = ali15x3_probe, + .remove = __devexit_p(ali15x3_remove), +}; + +static int __init i2c_ali15x3_init(void) +{ + PRINTK("i2c-ali15x3.o version %s (%s)\n", LM_VERSION, LM_DATE); + return pci_module_init(&ali15x3_driver); +} + +static void __exit i2c_ali15x3_exit(void) +{ + pci_unregister_driver(&ali15x3_driver); +} + +MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, " + "Philip Edelbrock <phil@netroedge.com>, " + "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); +MODULE_DESCRIPTION("ALI15X3 SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_ali15x3_init); +module_exit(i2c_ali15x3_exit); diff --git a/a/content_digest b/N1/content_digest index e8de0bf..c5519b8 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -2,14 +2,14 @@ "ref\0200601150045.30942.arvidjaar@newmail.ru\0" "ref\0200601152212.31491.arvidjaar@newmail.ru\0" "ref\0200601152248.07800.arvidjaar@newmail.ru\0" - "From\0r.marek@sh.cvut.cz (Rudolf Marek)\0" - "Subject\0[lm-sensors] 2.6.15: lm90 0-004c: Register 0x13 read failed (-1)\0" - "Date\0Sun, 15 Jan 2006 20:33:59 +0000\0" + "From\0Rudolf Marek <r.marek@sh.cvut.cz>\0" + "Subject\0Re: [lm-sensors] 2.6.15: lm90 0-004c: Register 0x13 read failed (-1)\0" + "Date\0Sun, 15 Jan 2006 21:33:59 +0100\0" "To\0Andrey Borzenkov <arvidjaar@newmail.ru>\0" "Cc\0Jean Delvare <khali@linux-fr.org>" linux-kernel@vger.kernel.org " lm-sensors@lm-sensors.org\0" - "\00:1\0" + "\01:1\0" "b\0" "Hello all,\n" "\n" @@ -21,21 +21,21 @@ "\n" "> Second block are errors from lm90 for different registers:\n" "> \n" - "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS\004, \n" - "> TYP\020, CMD\001, ADD\342\204\242, DAT0\302\240, DAT1\020\n" - "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS\024, \n" - "> TYP\020, CMD\001, ADD\342\204\242, DAT0), DAT1\020\n" - "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS\004, \n" - "> TYP\020, CMD\b, ADD\313\234, DAT0), DAT1\020\n" + "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS=04, \n" + "> TYP=10, CMD=01, ADD=99, DAT0=a0, DAT1=10\n" + "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS=14, \n" + "> TYP=10, CMD=01, ADD=99, DAT0=29, DAT1=10\n" + "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS=04, \n" + "> TYP=10, CMD=08, ADD=98, DAT0=29, DAT1=10\n" "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Error: command never \n" "> completed\n" - "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS\004, \n" - "> TYP\020, CMD\b, ADD\313\234, DAT0), DAT1\020\n" + "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS=04, \n" + "> TYP=10, CMD=08, ADD=98, DAT0=29, DAT1=10\n" "> Jan 15 22:24:02 cooker kernel: lm90 0-004c: Register 0x8 read failed (-1)\n" - "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS\004, \n" - "> TYP\020, CMD\a, ADD\313\234, DAT0), DAT1\020\n" - "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS\024, \n" - "> TYP\020, CMD\a, ADD\313\234, DAT0), DAT1\020\n" + "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (pre): STS=04, \n" + "> TYP=10, CMD=07, ADD=98, DAT0=29, DAT1=10\n" + "> Jan 15 22:24:02 cooker kernel: i2c_adapter i2c-0: Transaction (post): STS=14, \n" + "> TYP=10, CMD=07, ADD=98, DAT0=29, DAT1=10\n" "> \n" "> Here I do not see SMBus errors - it appears really that i2c device did not \n" "> respond. OTOH interesting is that there is no timeout. Apparently command \n" @@ -46,7 +46,7 @@ "> the controller if an external device is hung\")\n" "\n" "Well it seems this ali 15x3 has maybe same hardware bug? It was mentioned already here:\n" - "http://www2.lm-sensors.nu/~lm78/readticket.cgi?ticket 30\n" + "http://www2.lm-sensors.nu/~lm78/readticket.cgi?ticket=2030\n" "\n" "> In the log below you can see that the ALI15X3 chip seems to keep in idle-state\n" "> without reporting \"done\", but it does not turn in \"busy\" state. I patched the\n" @@ -81,13 +81,601 @@ "I hope it can help now.\n" "\n" "Regards\n" - "Rudolf\n" - "-------------- next part --------------\n" - "A non-text attachment was scrubbed...\n" - "Name: i2c-ali15x3.c\n" - "Type: text/x-csrc\n" - "Size: 16990 bytes\n" - "Desc: not available\n" - Url : http://lists.lm-sensors.org/pipermail/lm-sensors/attachments/20060115/0b2bfd6b/i2c-ali15x3-0001.bin + Rudolf + "\01:2\0" + "fn\0i2c-ali15x3.c\0" + "b\0" + "/*\n" + " ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware\n" + " monitoring\n" + " Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and\n" + " Philip Edelbrock <phil@netroedge.com> and\n" + " Mark D. Studebaker <mdsxyz123@yahoo.com>\n" + "\n" + " This program is free software; you can redistribute it and/or modify\n" + " it under the terms of the GNU General Public License as published by\n" + " the Free Software Foundation; either version 2 of the License, or\n" + " (at your option) any later version.\n" + "\n" + " This program is distributed in the hope that it will be useful,\n" + " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + " GNU General Public License for more details.\n" + "\n" + " You should have received a copy of the GNU General Public License\n" + " along with this program; if not, write to the Free Software\n" + " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" + "*/\n" + "\n" + "/*\n" + " This is the driver for the SMB Host controller on\n" + " Acer Labs Inc. (ALI) M1541 and M1543C South Bridges.\n" + "\n" + " The M1543C is a South bridge for desktop systems.\n" + " The M1533 is a South bridge for portable systems.\n" + " They are part of the following ALI chipsets:\n" + " \"Aladdin Pro 2\": Includes the M1621 Slot 1 North bridge\n" + " with AGP and 100MHz CPU Front Side bus\n" + " \"Aladdin V\": Includes the M1541 Socket 7 North bridge\n" + " with AGP and 100MHz CPU Front Side bus\n" + " \"Aladdin IV\": Includes the M1541 Socket 7 North bridge\n" + " with host bus up to 83.3 MHz.\n" + " For an overview of these chips see http://www.acerlabs.com\n" + "\n" + " The M1533/M1543C devices appear as FOUR separate devices\n" + " on the PCI bus. An output of lspci will show something similar\n" + " to the following:\n" + "\n" + "\t00:02.0 USB Controller: Acer Laboratories Inc. M5237\n" + "\t00:03.0 Bridge: Acer Laboratories Inc. M7101\n" + "\t00:07.0 ISA bridge: Acer Laboratories Inc. M1533\n" + "\t00:0f.0 IDE interface: Acer Laboratories Inc. M5229\n" + "\n" + " The SMB controller is part of the 7101 device, which is an\n" + " ACPI-compliant Power Management Unit (PMU).\n" + "\n" + " The whole 7101 device has to be enabled for the SMB to work.\n" + " You can't just enable the SMB alone.\n" + " The SMB and the ACPI have separate I/O spaces.\n" + " We make sure that the SMB is enabled. We leave the ACPI alone.\n" + "\n" + " This driver controls the SMB Host only.\n" + " The SMB Slave controller on the M15X3 is not enabled.\n" + "\n" + " This driver does not use interrupts.\n" + "*/\n" + "\n" + "/* Note: we assume there can only be one ALI15X3, with one SMBus interface */\n" + "\n" + "/* #define DEBUG 1 */\n" + "\n" + "#include <linux/module.h>\n" + "#include <linux/pci.h>\n" + "#include <linux/kernel.h>\n" + "#include <linux/stddef.h>\n" + "#include <linux/sched.h>\n" + "#include <linux/ioport.h>\n" + "#include <linux/i2c.h>\n" + "#include <linux/init.h>\n" + "#include <asm/io.h>\n" + "#include \"version.h\"\n" + "#include \"sensors_compat.h\"\n" + "\n" + "/* ALI15X3 SMBus address offsets */\n" + "#define SMBHSTSTS\t(0 + ali15x3_smba)\n" + "#define SMBHSTCNT\t(1 + ali15x3_smba)\n" + "#define SMBHSTSTART\t(2 + ali15x3_smba)\n" + "#define SMBHSTCMD\t(7 + ali15x3_smba)\n" + "#define SMBHSTADD\t(3 + ali15x3_smba)\n" + "#define SMBHSTDAT0\t(4 + ali15x3_smba)\n" + "#define SMBHSTDAT1\t(5 + ali15x3_smba)\n" + "#define SMBBLKDAT\t(6 + ali15x3_smba)\n" + "\n" + "/* PCI Address Constants */\n" + "#define SMBCOM\t\t0x004\n" + "#define SMBBA\t\t0x014\n" + "#define SMBATPC\t\t0x05B\t/* used to unlock xxxBA registers */\n" + "#define SMBHSTCFG\t0x0E0\n" + "#define SMBSLVC\t\t0x0E1\n" + "#define SMBCLK\t\t0x0E2\n" + "#define SMBREV\t\t0x008\n" + "\n" + "/* Other settings */\n" + "#define MAX_TIMEOUT\t\t50\t/* times 1/100 sec */\n" + "#define MAX_RETRIES\t\t3\t/* maximum reset retries */\n" + "#define ALI15X3_SMB_IOSIZE\t32\n" + "\n" + "/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB.\n" + " We don't use these here. If the bases aren't set to some value we\n" + " tell user to upgrade BIOS and we fail.\n" + "*/\n" + "#define ALI15X3_SMB_DEFAULTBASE\t0xE800\n" + "\n" + "/* ALI15X3 address lock bits */\n" + "#define ALI15X3_LOCK\t\t0x06\n" + "\n" + "/* ALI15X3 command constants */\n" + "#define ALI15X3_ABORT\t\t0x02\n" + "#define ALI15X3_T_OUT\t\t0x04\n" + "#define ALI15X3_QUICK\t\t0x00\n" + "#define ALI15X3_BYTE\t\t0x10\n" + "#define ALI15X3_BYTE_DATA\t0x20\n" + "#define ALI15X3_WORD_DATA\t0x30\n" + "#define ALI15X3_BLOCK_DATA\t0x40\n" + "#define ALI15X3_BLOCK_CLR\t0x80\n" + "\n" + "/* ALI15X3 status register bits */\n" + "#define ALI15X3_STS_IDLE\t0x04\n" + "#define ALI15X3_STS_BUSY\t0x08\n" + "#define ALI15X3_STS_DONE\t0x10\n" + "#define ALI15X3_STS_DEV\t\t0x20\t/* device error */\n" + "#define ALI15X3_STS_COLL\t0x40\t/* collision or no response */\n" + "#define ALI15X3_STS_TERM\t0x80\t/* terminated by abort */\n" + "#define ALI15X3_STS_ERR\t\t0xE0\t/* all the bad error bits */\n" + "\n" + "\n" + "#define E_TIMEOUT\t-2\n" + "\n" + "#define\tPRINTK(fmt, arg...) {;}\n" + "\n" + "\n" + "/* If force_addr is set to anything different from 0, we forcibly enable\n" + " the device at the given address. */\n" + "static int force_addr = 0;\n" + "MODULE_PARM(force_addr, \"i\");\n" + "MODULE_PARM_DESC(force_addr,\n" + "\t\t \"Initialize the base address of the i2c controller\");\n" + "\n" + "static unsigned short ali15x3_smba = 0;\n" + "\n" + "static int ali15x3_setup(struct pci_dev *ALI15X3_dev)\n" + "{\n" + "\tu16 a;\n" + "\tunsigned char temp;\n" + "\n" + "\t/* Check the following things:\n" + "\t\t- SMB I/O address is initialized\n" + "\t\t- Device is enabled\n" + "\t\t- We can use the addresses\n" + "\t*/\n" + "\n" + "\t/* Unlock the register.\n" + "\t The data sheet says that the address registers are read-only\n" + "\t if the lock bits are 1, but in fact the address registers\n" + "\t are zero unless you clear the lock bits.\n" + "\t*/\n" + "\tpci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);\n" + "\tif (temp & ALI15X3_LOCK) {\n" + "\t\ttemp &= ~ALI15X3_LOCK;\n" + "\t\tpci_write_config_byte(ALI15X3_dev, SMBATPC, temp);\n" + "\t}\n" + "\n" + "\t/* Determine the address of the SMBus area */\n" + "\tpci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);\n" + "\tali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));\n" + "\tif (ali15x3_smba == 0 && force_addr == 0) {\n" + "\t\tdev_err(ALI15X3_dev, \"ALI15X3_smb region uninitialized \"\n" + "\t\t\t\"- upgrade BIOS or use force_addr=0xaddr\\n\");\n" + "\t\treturn -ENODEV;\n" + "\t}\n" + "\n" + "\tif(force_addr)\n" + "\t\tali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);\n" + "\n" + "\tif (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, \"ali15x3-smb\")) {\n" + "\t\tdev_err(ALI15X3_dev,\n" + "\t\t\t\"ALI15X3_smb region 0x%x already in use!\\n\",\n" + "\t\t\tali15x3_smba);\n" + "\t\treturn -ENODEV;\n" + "\t}\n" + "\n" + "\tif(force_addr) {\n" + "\t\tdev_info(ALI15X3_dev, \"forcing ISA address 0x%04X\\n\",\n" + "\t\t\tali15x3_smba);\n" + "\t\tif (PCIBIOS_SUCCESSFUL !=\n" + "\t\t pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba))\n" + "\t\t\treturn -ENODEV;\n" + "\t\tif (PCIBIOS_SUCCESSFUL !=\n" + "\t\t pci_read_config_word(ALI15X3_dev, SMBBA, &a))\n" + "\t\t\treturn -ENODEV;\n" + "\t\tif ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {\n" + "\t\t\t/* make sure it works */\n" + "\t\t\tdev_err(ALI15X3_dev,\n" + "\t\t\t\t\"force address failed - not supported?\\n\");\n" + "\t\t\treturn -ENODEV;\n" + "\t\t}\n" + "\t}\n" + "\t/* check if whole device is enabled */\n" + "\tpci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);\n" + "\tif ((temp & 1) == 0) {\n" + "\t\tdev_info(ALI15X3_dev, \"enabling SMBus device\\n\");\n" + "\t\tpci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);\n" + "\t}\n" + "\n" + "\t/* Is SMB Host controller enabled? */\n" + "\tpci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);\n" + "\tif ((temp & 1) == 0) {\n" + "\t\tdev_info(ALI15X3_dev, \"enabling SMBus controller\\n\");\n" + "\t\tpci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);\n" + "\t}\n" + "\n" + "\t/* set SMB clock to 74KHz as recommended in data sheet */\n" + "\t/* ??CK Evtl. verursacht das die Bus timeouts, deshalb*/\n" + "\t/* belassen wir es mal bei den Default-Einstellungen */\n" + "\tpci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);\n" + "\n" + "\t/*\n" + "\t The interrupt routing for SMB is set up in register 0x77 in the\n" + "\t 1533 ISA Bridge device, NOT in the 7101 device.\n" + "\t Don't bother with finding the 1533 device and reading the register.\n" + "\tif ((....... & 0x0F) == 1)\n" + "\t\tdev_dbg(ALI15X3_dev, \"ALI15X3 using Interrupt 9 for SMBus.\\n\");\n" + "\t*/\n" + "\tpci_read_config_byte(ALI15X3_dev, SMBREV, &temp);\n" + "\tdev_dbg(ALI15X3_dev, \"SMBREV = 0x%X\\n\", temp);\n" + "\tdev_dbg(ALI15X3_dev, \"iALI15X3_smba = 0x%X\\n\", ali15x3_smba);\n" + "\n" + "\treturn 0;\n" + "}\n" + "\n" + "static int ali15x3_wait_for_idle (struct i2c_adapter *adap)\n" + "{\n" + "\tint temp;\n" + "\tint timeout;\n" + "\n" + "\t/* make sure SMBus is idle */\n" + "\ttemp = inb_p(SMBHSTSTS);\n" + "\tfor (timeout = 0;\n" + "\t (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);\n" + "\t timeout++) {\n" + "\t\ti2c_delay(1);\n" + "\t\ttemp = inb_p(SMBHSTSTS);\n" + "\t}\n" + "\tif (timeout >= MAX_TIMEOUT) {\n" + "\t\tdev_err(adap, \"Idle wait Timeout! STS=0x%02x\\n\", temp);\n" + "\t\treturn -1;\n" + "\t}\n" + "\n" + "\treturn 0;\n" + "}\n" + "\n" + "static int ali15x3_do_reset (struct i2c_adapter *adap)\n" + "{\n" + "\tint temp;\n" + "\t\n" + "\t/*\n" + "\t If the host controller is still busy, it may have timed out in the\n" + "\t previous transaction, resulting in a \"SMBus Timeout\" Dev.\n" + "\t I've tried the following to reset a stuck busy bit.\n" + "\t\t1. Reset the controller with an ABORT command.\n" + "\t\t (this doesn't seem to clear the controller if an external\n" + "\t\t device is hung)\n" + "\t\t2. Reset the controller and the other SMBus devices with a\n" + "\t\t T_OUT command. (this clears the host busy bit if an\n" + "\t\t external device is hung, but it comes back upon a new access\n" + "\t\t to a device)\n" + "\t\t3. Disable and reenable the controller in SMBHSTCFG\n" + "\t Worst case, nothing seems to work except power reset.\n" + "\t*/\n" + "\t/* Abort - reset the host controller */\n" + "\t/*\n" + "\t Try resetting entire SMB bus, including other devices -\n" + "\t This may not work either - it clears the BUSY bit but\n" + "\t then the BUSY bit may come back on when you try and use the chip again.\n" + "\t If that's the case you are stuck.\n" + "\t*/\n" + "\tdev_dbg(adap, \"Resetting entire SMB Bus (abort) to \"\n" + "\t\t\"clear busy condition (%02x)\\n\", temp);\n" + "\toutb_p(ALI15X3_T_OUT, SMBHSTCNT);\n" + "\ti2c_delay(1);\n" + "\ttemp = inb_p(SMBHSTSTS);\n" + "\tdev_dbg(adap, \"Status after reset: %02x\\n\", temp);\n" + "\n" + "\t/* now check the error bits and the busy bit */\n" + "\tif (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {\n" + "\t\t/* do a clear-on-write */\n" + "\t\tdev_dbg(adap, \"Doing a clear on write\\n\");\n" + "\t\toutb_p(0xFF, SMBHSTSTS);\n" + "\t\tif ((temp = inb_p(SMBHSTSTS)) &\n" + "\t\t (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {\n" + "\t\t\t/* this is probably going to be correctable only by a power reset\n" + "\t\t\t as one of the bits now appears to be stuck */\n" + "\t\t\t/* This may be a bus or device with electrical problems. */\n" + "\t\t\tdev_err(adap, \"SMBus reset failed! (0x%02x) - \"\n" + "\t\t\t\t\"controller or device on bus is probably hung\\n\",\n" + "\t\t\t\ttemp);\n" + "\t\t\treturn -1;\n" + "\t\t}\n" + "\t} else {\n" + "\t\t/* check and clear done bit */\n" + "\t\tif (temp & ALI15X3_STS_DONE) {\n" + "\t\t\tdev_info(adap, \"Resetting done flag\\n\");\n" + "\t\t\toutb_p(temp, SMBHSTSTS);\n" + "\t\t}\n" + "\t}\n" + "\t\n" + "\treturn 0;\n" + "}\n" + "\n" + "/* Another internally used function */\n" + "static int ali15x3_transaction(struct i2c_adapter *adap)\n" + "{\n" + "\tint temp;\n" + "\tint result = 0;\n" + "\tint timeout = 0;\n" + "\n" + "\t/*dev_dbg(adap, \"Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, \"\n" + "\t\t\"ADD=%02x, DAT0=%02x, DAT1=%02x\\n\", inb_p(SMBHSTSTS),\n" + "\t\tinb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),\n" + "\t\tinb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); */\n" + "\n" + "\t/* start the transaction by writing anything to the start register */\n" + "\toutb_p(0xFF, SMBHSTSTART);\n" + "\n" + "\t/* We will always wait for a fraction of a second! */\n" + "\ttimeout = 0;\n" + "\tdo {\n" + "\t\ti2c_delay(1);\n" + "\t\ttemp = inb_p(SMBHSTSTS);\n" + "\t} while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))\n" + "\t\t && (timeout++ < MAX_TIMEOUT));\n" + "\n" + "\t/* If the SMBus is still busy, we give up */\n" + "\tif (timeout >= MAX_TIMEOUT) {\n" + "\t\t//dev_warn(adap, \"SMBus Timeout, doing a reset\\n\");\n" + "\t\tali15x3_do_reset(adap);\n" + "\t\treturn E_TIMEOUT;\n" + "\t}\n" + "\n" + "\tif (temp & ALI15X3_STS_TERM) {\n" + "\t\tresult = -1;\n" + "\t\t//dev_dbg(adap, \"Error: Failed bus transaction\\n\");\n" + "\t}\n" + "\n" + "\t/*\n" + "\t Unfortunately the ALI SMB controller maps \"no response\" and \"bus\n" + "\t collision\" into a single bit. No reponse is the usual case so don't\n" + "\t do a PRINTK.\n" + "\t This means that bus collisions go unreported.\n" + "\t*/\n" + "\tif (temp & ALI15X3_STS_COLL) {\n" + "\t\tresult = -1;\n" + "\t\t/*dev_dbg(adap,\n" + "\t\t\t\"Error: no response or bus collision ADD=%02x\\n\",\n" + "\t\t\tinb_p(SMBHSTADD)); */\n" + "\t}\n" + "\n" + "\t/* haven't ever seen this */\n" + "\tif (temp & ALI15X3_STS_DEV) {\n" + "\t\tresult = -1;\n" + "\t\tdev_err(adap, \"Error: device error\\n\");\n" + "\t}\n" + "\tdev_dbg(adap, \"Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, \"\n" + "\t\t\"ADD=%02x, DAT0=%02x, DAT1=%02x\\n\", inb_p(SMBHSTSTS),\n" + "\t\tinb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),\n" + "\t\tinb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));\n" + "\treturn result;\n" + "}\n" + "\n" + "/* Return -1 on error. */\n" + "static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,\n" + "\t\t unsigned short flags, char read_write, u8 command,\n" + "\t\t int size, union i2c_smbus_data * data)\n" + "{\n" + "\tint i, len;\n" + "\tint retries;\n" + "\tint tsize;\n" + "\t\n" + "\tfor (retries = 0; retries < MAX_RETRIES; retries++)\n" + "\t{\t\n" + "\t\t/* clear all the bits (clear-on-write) */\n" + "\t\toutb_p(0xFF, SMBHSTSTS);\n" + "\t\n" + "\t\t/* ali15x3_do_reset(adap); */\n" + "\t\tali15x3_wait_for_idle(adap);\n" + "\t\n" + "\t\tswitch (size) {\n" + "\t\tcase I2C_SMBUS_QUICK:\n" + "\t\t\toutb_p(((addr & 0x7f) << 1) | (read_write & 0x01),\n" + "\t\t\tSMBHSTADD);\n" + "\t\t\ttsize = ALI15X3_QUICK;\n" + "\t\t\tbreak;\n" + "\t\tcase I2C_SMBUS_BYTE:\n" + "\t\t\toutb_p(((addr & 0x7f) << 1) | (read_write & 0x01),\n" + "\t\t\tSMBHSTADD);\n" + "\t\t\tif (read_write == I2C_SMBUS_WRITE)\n" + "\t\t\t\toutb_p(command, SMBHSTCMD);\n" + "\t\t\ttsize = ALI15X3_BYTE;\n" + "\t\t\tbreak;\n" + "\t\tcase I2C_SMBUS_BYTE_DATA:\n" + "\t\t\toutb_p(((addr & 0x7f) << 1) | (read_write & 0x01),\n" + "\t\t\tSMBHSTADD);\n" + "\t\t\toutb_p(command, SMBHSTCMD);\n" + "\t\t\tif (read_write == I2C_SMBUS_WRITE)\n" + "\t\t\t\toutb_p(data->byte, SMBHSTDAT0);\n" + "\t\t\ttsize = ALI15X3_BYTE_DATA;\n" + "\t\t\tbreak;\n" + "\t\tcase I2C_SMBUS_WORD_DATA:\n" + "\t\t\toutb_p(((addr & 0x7f) << 1) | (read_write & 0x01),\n" + "\t\t\tSMBHSTADD);\n" + "\t\t\toutb_p(command, SMBHSTCMD);\n" + "\t\t\tif (read_write == I2C_SMBUS_WRITE) {\n" + "\t\t\t\toutb_p(data->word & 0xff, SMBHSTDAT0);\n" + "\t\t\t\toutb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);\n" + "\t\t\t}\n" + "\t\t\ttsize = ALI15X3_WORD_DATA;\n" + "\t\t\tbreak;\n" + "\t\tcase I2C_SMBUS_BLOCK_DATA:\n" + "\t\t\toutb_p(((addr & 0x7f) << 1) | (read_write & 0x01),\n" + "\t\t\tSMBHSTADD);\n" + "\t\t\toutb_p(command, SMBHSTCMD);\n" + "\t\t\tif (read_write == I2C_SMBUS_WRITE) {\n" + "\t\t\t\tlen = data->block[0];\n" + "\t\t\t\tif (len < 0) {\n" + "\t\t\t\t\tlen = 0;\n" + "\t\t\t\t\tdata->block[0] = len;\n" + "\t\t\t\t}\n" + "\t\t\t\tif (len > 32) {\n" + "\t\t\t\t\tlen = 32;\n" + "\t\t\t\t\tdata->block[0] = len;\n" + "\t\t\t\t}\n" + "\t\t\t\toutb_p(len, SMBHSTDAT0);\n" + "\t\t\t\t/* Reset SMBBLKDAT */\n" + "\t\t\t\toutb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);\n" + "\t\t\t\tfor (i = 1; i <= len; i++)\n" + "\t\t\t\t\toutb_p(data->block[i], SMBBLKDAT);\n" + "\t\t\t}\n" + "\t\t\ttsize = ALI15X3_BLOCK_DATA;\n" + "\t\t\tbreak;\n" + "\t\tdefault:\n" + "\t\t\tPRINTK\n" + "\t\t\t(KERN_WARNING \"i2c-ali15x3.o: Unsupported transaction %d\\n\", size);\n" + "\t\t\treturn -1;\n" + "\t\t}\n" + "\t\n" + "\t\toutb_p(tsize, SMBHSTCNT);\t/* output command */\n" + "\t\n" + "\t\tswitch (ali15x3_transaction(adap))\n" + "\t\t{\n" + "\t\t\tcase 0:\n" + "\t\t\t\tbreak;\t/* no error, continue */\n" + "\t\t\tcase E_TIMEOUT:\t\n" + "\t\t\t\tPRINTK(KERN_INFO \"i2c-ali15x3.o: timeout, doing a retry (%d)\\n\", retries);\n" + "\t\t\t\tcontinue;\n" + "\t\t\tdefault:\n" + "\t\t\t\treturn -1;\n" + "\t\t}\n" + "\t\t\n" + "\t\tbreak;\n" + "\t}\n" + "\t\n" + "\tif (retries == MAX_RETRIES)\n" + "\t{\n" + "\t\tPRINTK(KERN_WARNING \"i2c-ali15x3.o: transaction failed, maximum retries reached\\n\");\t\n" + "\t\treturn -1;\n" + "\t}\n" + "\t\t\n" + "\tif ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))\n" + "\t\treturn 0;\n" + "\n" + "\n" + "\tswitch (tsize) {\n" + "\tcase ALI15X3_BYTE:\t/* Result put in SMBHSTDAT0 */\n" + "\t\tdata->byte = inb_p(SMBHSTDAT0);\n" + "\t\tbreak;\n" + "\tcase ALI15X3_BYTE_DATA:\n" + "\t\tdata->byte = inb_p(SMBHSTDAT0);\n" + "\t\tbreak;\n" + "\tcase ALI15X3_WORD_DATA:\n" + "\t\tdata->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);\n" + "\t\tbreak;\n" + "\tcase ALI15X3_BLOCK_DATA:\n" + "\t\tlen = inb_p(SMBHSTDAT0);\n" + "\t\tif (len > 32)\n" + "\t\t\tlen = 32;\n" + "\t\tdata->block[0] = len;\n" + "\t\t/* Reset SMBBLKDAT */\n" + "\t\toutb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);\n" + "\t\tfor (i = 1; i <= data->block[0]; i++) {\n" + "\t\t\tdata->block[i] = inb_p(SMBBLKDAT);\n" + "\t\t\tdev_dbg(adap, \"Blk: len=%d, i=%d, data=%02x\\n\",\n" + "\t\t\t\tlen, i, data->block[i]);\n" + "\t\t}\n" + "\t\tbreak;\n" + "\t}\n" + "\treturn 0;\n" + "}\n" + "\n" + "static void ali15x3_inc(struct i2c_adapter *adapter)\n" + "{\n" + "#ifdef MODULE\n" + "\tMOD_INC_USE_COUNT;\n" + "#endif\n" + "}\n" + "\n" + "static void ali15x3_dec(struct i2c_adapter *adapter)\n" + "{\n" + "#ifdef MODULE\n" + "\tMOD_DEC_USE_COUNT;\n" + "#endif\n" + "}\n" + "\n" + "static u32 ali15x3_func(struct i2c_adapter *adapter)\n" + "{\n" + "\treturn I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |\n" + "\t I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |\n" + "\t I2C_FUNC_SMBUS_BLOCK_DATA;\n" + "}\n" + "\n" + "static struct i2c_algorithm smbus_algorithm = {\n" + "\t.name\t\t= \"Non-I2C SMBus adapter\",\n" + "\t.id\t\t= I2C_ALGO_SMBUS,\n" + "\t.smbus_xfer\t= ali15x3_access,\n" + "\t.functionality\t= ali15x3_func,\n" + "};\n" + "\n" + "static struct i2c_adapter ali15x3_adapter = {\n" + "\t.id\t\t= I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,\n" + "\t.algo\t\t= &smbus_algorithm,\n" + "\t.name\t\t= \"unset\",\n" + "\t.inc_use\t= ali15x3_inc,\n" + "\t.dec_use\t= ali15x3_dec,\n" + "};\n" + "\n" + "static struct pci_device_id ali15x3_ids[] __devinitdata = {\n" + "\t{\n" + "\t.vendor =\tPCI_VENDOR_ID_AL,\n" + "\t.device =\tPCI_DEVICE_ID_AL_M7101,\n" + "\t.subvendor =\tPCI_ANY_ID,\n" + "\t.subdevice =\tPCI_ANY_ID,\n" + "\t},\n" + "\t{ 0, }\n" + "};\n" + "\n" + "static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)\n" + "{\n" + "\tif (ali15x3_setup(dev)) {\n" + "\t\tdev_err(dev,\n" + "\t\t\t\"ALI15X3 not detected, module not inserted.\\n\");\n" + "\t\treturn -ENODEV;\n" + "\t}\n" + "\n" + "\tsnprintf(ali15x3_adapter.name, 32,\n" + "\t\t\"SMBus ALI15X3 adapter at %04x\", ali15x3_smba);\n" + "\treturn i2c_add_adapter(&ali15x3_adapter);\n" + "}\n" + "\n" + "static void __devexit ali15x3_remove(struct pci_dev *dev)\n" + "{\n" + "\ti2c_del_adapter(&ali15x3_adapter);\n" + "\trelease_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);\n" + "}\n" + "\n" + "static struct pci_driver ali15x3_driver = {\n" + "\t.name\t\t= \"ali15x3 smbus\",\n" + "\t.id_table\t= ali15x3_ids,\n" + "\t.probe\t\t= ali15x3_probe,\n" + "\t.remove\t\t= __devexit_p(ali15x3_remove),\n" + "};\n" + "\n" + "static int __init i2c_ali15x3_init(void)\n" + "{\n" + "\tPRINTK(\"i2c-ali15x3.o version %s (%s)\\n\", LM_VERSION, LM_DATE);\n" + "\treturn pci_module_init(&ali15x3_driver);\n" + "}\n" + "\n" + "static void __exit i2c_ali15x3_exit(void)\n" + "{\n" + "\tpci_unregister_driver(&ali15x3_driver);\n" + "}\n" + "\n" + "MODULE_AUTHOR (\"Frodo Looijaard <frodol@dds.nl>, \"\n" + "\t\t\"Philip Edelbrock <phil@netroedge.com>, \"\n" + "\t\t\"and Mark D. Studebaker <mdsxyz123@yahoo.com>\");\n" + "MODULE_DESCRIPTION(\"ALI15X3 SMBus driver\");\n" + "MODULE_LICENSE(\"GPL\");\n" + "\n" + "module_init(i2c_ali15x3_init);\n" + module_exit(i2c_ali15x3_exit); -37f71d07b1cc3964af34f9fe777220a386dd04fcc01ed81d59680b7620a7e41d +70c9d739d61c014f4d506508d64f2a2690b2e5dcdcc686818fc63025b2b3882a
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.