diff options
42 files changed, 2222 insertions, 330 deletions
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 8c5698a8c2e..46bcff2849b 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -643,6 +643,60 @@ X!Idrivers/video/console/fonts.c !Edrivers/spi/spi.c </chapter> + <chapter id="i2c"> + <title>I<superscript>2</superscript>C and SMBus Subsystem</title> + + <para> + I<superscript>2</superscript>C (or without fancy typography, "I2C") + is an acronym for the "Inter-IC" bus, a simple bus protocol which is + widely used where low data rate communications suffice. + Since it's also a licensed trademark, some vendors use another + name (such as "Two-Wire Interface", TWI) for the same bus. + I2C only needs two signals (SCL for clock, SDA for data), conserving + board real estate and minimizing signal quality issues. + Most I2C devices use seven bit addresses, and bus speeds of up + to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet + found wide use. + I2C is a multi-master bus; open drain signaling is used to + arbitrate between masters, as well as to handshake and to + synchronize clocks from slower clients. + </para> + + <para> + The Linux I2C programming interfaces support only the master + side of bus interactions, not the slave side. + The programming interface is structured around two kinds of driver, + and two kinds of device. + An I2C "Adapter Driver" abstracts the controller hardware; it binds + to a physical device (perhaps a PCI device or platform_device) and + exposes a <structname>struct i2c_adapter</structname> representing + each I2C bus segment it manages. + On each I2C bus segment will be I2C devices represented by a + <structname>struct i2c_client</structname>. Those devices will + be bound to a <structname>struct i2c_driver</structname>, + which should follow the standard Linux driver model. + (At this writing, a legacy model is more widely used.) + There are functions to perform various I2C protocol operations; at + this writing all such functions are usable only from task context. + </para> + + <para> + The System Management Bus (SMBus) is a sibling protocol. Most SMBus + systems are also I2C conformant. The electrical constraints are + tighter for SMBus, and it standardizes particular protocol messages + and idioms. Controllers that support I2C can also support most + SMBus operations, but SMBus controllers don't support all the protocol + options that an I2C controller will. + There are functions to perform various SMBus protocol operations, + either using I2C primitives or by issuing SMBus commands to + i2c_adapter devices which don't support those I2C operations. + </para> + +!Iinclude/linux/i2c.h +!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info +!Edrivers/i2c/i2c-core.c + </chapter> + <chapter id="splice"> <title>splice API</title> <para>) @@ -654,4 +708,5 @@ X!Idrivers/video/console/fonts.c !Ffs/splice.c </chapter> + </book> diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 3a159dac04f..281458b47d7 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -330,3 +330,10 @@ Who: Tejun Heo <htejun@gmail.com> --------------------------- +What: Legacy RTC drivers (under drivers/i2c/chips) +When: November 2007 +Why: Obsolete. We have a RTC subsystem with better drivers. +Who: Jean Delvare <khali@linux-fr.org> + +--------------------------- + diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index c34f0db78a3..fe6406f2f9a 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -5,8 +5,8 @@ Supported adapters: '810' and '810E' chipsets) * Intel 82801BA (ICH2 - part of the '815E' chipset) * Intel 82801CA/CAM (ICH3) - * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported) - * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported) + * Intel 82801DB (ICH4) (HW PEC supported) + * Intel 82801EB/ER (ICH5) (HW PEC supported) * Intel 6300ESB * Intel 82801FB/FR/FW/FRW (ICH6) * Intel 82801G (ICH7) diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index 7cbe43fa270..fa0c786a8bf 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -6,7 +6,7 @@ Supported adapters: Datasheet: Publicly available at the Intel website * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges Datasheet: Only available via NDA from ServerWorks - * ATI IXP200, IXP300, IXP400 and SB600 southbridges + * ATI IXP200, IXP300, IXP400, SB600 and SB700 southbridges Datasheet: Not publicly available * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com diff --git a/Documentation/i2c/busses/i2c-taos-evm b/Documentation/i2c/busses/i2c-taos-evm new file mode 100644 index 00000000000..9146e33be6d --- /dev/null +++ b/Documentation/i2c/busses/i2c-taos-evm @@ -0,0 +1,46 @@ +Kernel driver i2c-taos-evm + +Author: Jean Delvare <khali@linux-fr.org> + +This is a driver for the evaluation modules for TAOS I2C/SMBus chips. +The modules include an SMBus master with limited capabilities, which can +be controlled over the serial port. Virtually all evaluation modules +are supported, but a few lines of code need to be added for each new +module to instantiate the right I2C chip on the bus. Obviously, a driver +for the chip in question is also needed. + +Currently supported devices are: + +* TAOS TSL2550 EVM + +For addtional information on TAOS products, please see + http://www.taosinc.com/ + + +Using this driver +----------------- + +In order to use this driver, you'll need the serport driver, and the +inputattach tool, which is part of the input-utils package. The following +commands will tell the kernel that you have a TAOS EVM on the first +serial port: + +# modprobe serport +# inputattach --taos-evm /dev/ttyS0 + + +Technical details +----------------- + +Only 4 SMBus transaction types are supported by the TAOS evaluation +modules: +* Receive Byte +* Send Byte +* Read Byte +* Write Byte + +The communication protocol is text-based and pretty simple. It is +described in a PDF document on the CD which comes with the evaluation +module. The communication is rather slow, because the serial port has +to operate at 1200 bps. However, I don't think this is a big concern in +practice, as these modules are meant for evaluation and testing only. diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875 index 96fec562a8e..a0cd8af2f40 100644 --- a/Documentation/i2c/chips/max6875 +++ b/Documentation/i2c/chips/max6875 @@ -99,7 +99,7 @@ And then read the data or - count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer); + count = i2c_smbus_read_i2c_block_data(fd, 0x84, 16, buffer); The block read should read 16 bytes. 0x84 is the block read command. diff --git a/Documentation/i2c/chips/x1205 b/Documentation/i2c/chips/x1205 deleted file mode 100644 index 09407c991fe..00000000000 --- a/Documentation/i2c/chips/x1205 +++ /dev/null @@ -1,38 +0,0 @@ -Kernel driver x1205 -=================== - -Supported chips: - * Xicor X1205 RTC - Prefix: 'x1205' - Addresses scanned: none - Datasheet: http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html - -Authors: - Karen Spearel <kas11@tampabay.rr.com>, - Alessandro Zummo <a.zummo@towertech.it> - -Description ------------ - -This module aims to provide complete access to the Xicor X1205 RTC. -Recently Xicor has merged with Intersil, but the chip is -still sold under the Xicor brand. - -This chip is located at address 0x6f and uses a 2-byte register addressing. -Two bytes need to be written to read a single register, while most -other chips just require one and take the second one as the data -to be written. To prevent corrupting unknown chips, the user must -explicitely set the probe parameter. - -example: - -modprobe x1205 probe=0,0x6f - -The module supports one more option, hctosys, which is used to set the -software clock from the x1205. On systems where the x1205 is the -only hardware rtc, this parameter could be used to achieve a correct -date/time earlier in the system boot sequence. - -example: - -modprobe x1205 probe=0,0x6f hctosys=1 diff --git a/Documentation/i2c/summary b/Documentation/i2c/summary index aea60bf7e8f..003c7319b8c 100644 --- a/Documentation/i2c/summary +++ b/Documentation/i2c/summary @@ -67,7 +67,6 @@ i2c-proc: The /proc/sys/dev/sensors interface for device (client) drivers Algorithm drivers ----------------- -i2c-algo-8xx: An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT) i2c-algo-bit: A bit-banging algorithm i2c-algo-pcf: A PCF 8584 style algorithm i2c-algo-ibm_ocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT) @@ -81,6 +80,5 @@ i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (NOT mkpatch i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit) i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT) i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit) -i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT) i2c-velleman: Velleman K8000 parallel port adapter (uses i2c-algo-bit) diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index 3d8d36b0ad1..2c170032bf3 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -571,7 +571,7 @@ SMBus communication u8 command, u8 length, u8 *values); extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, - u8 command, u8 *values); + u8 command, u8 length, u8 *values); These ones were removed in Linux 2.6.10 because they had no users, but could be added back later if needed: diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index 58899078810..014dfa575be 100644 --- a/drivers/i2c/algos/Kconfig +++ b/drivers/i2c/algos/Kconfig @@ -34,10 +34,6 @@ config I2C_ALGOPCA This support is also available as a module. If so, the module will be called i2c-algo-pca. -config I2C_ALGO8XX - tristate "MPC8xx CPM I2C interface" - depends on 8xx - config I2C_ALGO_SGI tristate "I2C SGI interfaces" depends on SGI_IP22 || SGI_IP32 || X86_VISWS diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 838dc1c19d6..fcde9bab5b9 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -207,6 +207,7 @@ config I2C_PIIX4 ATI IXP300 ATI IXP400 ATI SB600 + ATI SB700 Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 @@ -390,11 +391,6 @@ config I2C_PROSAVAGE This support is also available as a module. If so, the module will be called i2c-prosavage. -config I2C_RPXLITE - tristate "Embedded Planet RPX Lite/Classic support" - depends on RPXLITE || RPXCLASSIC - select I2C_ALGO8XX - config I2C_S3C2410 tristate "S3C2410 I2C Driver" depends on ARCH_S3C2410 @@ -512,6 +508,22 @@ config I2C_SIS96X This driver can also be built as a module. If so, the module will be called i2c-sis96x. +config I2C_TAOS_EVM + tristate "TAOS evaluation module" + depends on EXPERIMENTAL + select SERIO + select SERIO_SERPORT + default n + help + This supports TAOS evaluation modules on serial port. In order to + use this driver, you will need the inputattach tool, which is part + of the input-utils package. + + If unsure, say N. + + This support is also available as a module. If so, the module + will be called i2c-taos-evm. + config I2C_STUB tristate "I2C/SMBus Test Stub" depends on EXPERIMENTAL && m @@ -635,4 +647,13 @@ config I2C_PNX This driver can also be built as a module. If so, the module will be called i2c-pnx. +config I2C_PMCMSP + tristate "PMC MSP I2C TWI Controller" + depends on PMC_MSP + help + This driver supports the PMC TWI controller on MSP devices. + + This driver can also be built as module. If so, the module + will be called i2c-pmcmsp. + endmenu diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 14d1432f698..a6db4e38bda 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -32,10 +32,10 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o +obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o -obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o @@ -44,6 +44,7 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o +obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index a7dd54654a9..025f19423fa 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -63,14 +63,14 @@ static void i2c_gpio_setscl_val(void *data, int state) gpio_set_value(pdata->scl_pin, state); } -int i2c_gpio_getsda(void *data) +static int i2c_gpio_getsda(void *data) { struct i2c_gpio_platform_data *pdata = data; return gpio_get_value(pdata->sda_pin); } -int i2c_gpio_getscl(void *data) +static int i2c_gpio_getscl(void *data) { struct i2c_gpio_platform_data *pdata = data; @@ -142,7 +142,13 @@ static int __init i2c_gpio_probe(struct platform_device *pdev) adap->algo_data = bit_data; adap->dev.parent = &pdev->dev; - ret = i2c_bit_add_bus(adap); + /* + * If "dev->id" is negative we consider it as zero. + * The reason to do so is to avoid sysfs names that only make + * sense when there are multiple adapters. + */ + adap->nr = pdev->id >= 0 ? pdev->id : 0; + ret = i2c_bit_add_numbered_bus(adap); if (ret) goto err_add_bus; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 611b57192c9..8f5c686123b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -22,12 +22,12 @@ /* SUPPORTED DEVICES PCI ID - 82801AA 2413 - 82801AB 2423 - 82801BA 2443 - 82801CA/CAM 2483 - 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) - 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) + 82801AA 2413 + 82801AB 2423 + 82801BA 2443 + 82801CA/CAM 2483 + 82801DB 24C3 (HW PEC supported) + 82801EB 24D3 (HW PEC supported) 6300ESB 25A4 ICH6 266A ICH7 27DA @@ -74,6 +74,13 @@ #define SMBHSTCFG_SMB_SMI_EN 2 #define SMBHSTCFG_I2C_EN 4 +/* Auxillary control register bits, ICH4+ only */ +#define SMBAUXCTL_CRC 1 +#define SMBAUXCTL_E32B 2 + +/* kill bit for SMBHSTCNT */ +#define SMBHSTCNT_KILL 2 + /* Other settings */ #define MAX_TIMEOUT 100 #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ @@ -91,10 +98,15 @@ #define I801_START 0x40 #define I801_PEC_EN 0x80 /* ICH4 only */ - -static int i801_transaction(void); -static int i801_block_transaction(union i2c_smbus_data *data, char read_write, - int command, int hwpec); +/* I801 Hosts Status register bits */ +#define SMBHSTSTS_BYTE_DONE 0x80 +#define SMBHSTSTS_INUSE_STS 0x40 +#define SMBHSTSTS_SMBALERT_STS 0x20 +#define SMBHSTSTS_FAILED 0x10 +#define SMBHSTSTS_BUS_ERR 0x08 +#define SMBHSTSTS_DEV_ERR 0x04 +#define SMBHSTSTS_INTR 0x02 +#define SMBHSTSTS_HOST_BUSY 0x01 static unsigned long i801_smba; static unsigned char i801_original_hstcfg; @@ -102,7 +114,7 @@ static struct pci_driver i801_driver; static struct pci_dev *I801_dev; static int isich4; -static int i801_transaction(void) +static int i801_transaction(int xact) { int temp; int result = 0; @@ -127,33 +139,40 @@ static int i801_transaction(void) } } - outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + /* the current contents of SMBHSTCNT can be overwritten, since PEC, + * INTREN, SMBSCMD are passed in xact */ + outb_p(xact | I801_START, SMBHSTCNT); /* We will always wait for a fraction of a second! */ do { msleep(1); temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); + } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); result = -1; + /* try to stop the current command */ + dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); + outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); + msleep(1); + outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); } - if (temp & 0x10) { + if (temp & SMBHSTSTS_FAILED) { result = -1; dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); } - if (temp & 0x08) { + if (temp & SMBHSTSTS_BUS_ERR) { result = -1; dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " "until next hard reset. (sorry!)\n"); /* Clock stops and slave is stuck in mid-transmission */ } - if (temp & 0x04) { + if (temp & SMBHSTSTS_DEV_ERR) { result = -1; dev_dbg(&I801_dev->dev, "Error: no response!\n"); } @@ -172,44 +191,70 @@ static int i801_transaction(void) return result; } -/* All-inclusive block transaction function */ -static int i801_block_transaction(union i2c_smbus_data *data, char read_write, - int command, int hwpec) +/* wait for INTR bit as advised by Intel */ +static void i801_wait_hwpec(void) +{ + int timeout = 0; + int temp; + + do { + msleep(1); + temp = inb_p(SMBHSTSTS); + } while ((!(temp & SMBHSTSTS_INTR)) + && (timeout++ < MAX_TIMEOUT)); + + if (timeout >= MAX_TIMEOUT) { + dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); + } + outb_p(temp, SMBHSTSTS); +} + +static int i801_block_transaction_by_block(union i2c_smbus_data *data, + char read_write, int hwpec) +{ + int i, len; + + inb_p(SMBHSTCNT); /* reset the data buffer index */ + + /* Use 32-byte buffer to process this transaction */ + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + outb_p(len, SMBHSTDAT0); + for (i = 0; i < len; i++) + outb_p(data->block[i+1], SMBBLKDAT); + } + + if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 | + I801_PEC_EN * hwpec)) + return -1; + + if (read_write == I2C_SMBUS_READ) { + len = inb_p(SMBHSTDAT0); + if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) + return -1; + + data->block[0] = len; + for (i = 0; i < len; i++) + data->block[i + 1] = inb_p(SMBBLKDAT); + } + return 0; +} + +static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, + char read_write, int hwpec) { int i, len; int smbcmd; int temp; int result = 0; int timeout; - unsigned char hostc, errmask; + unsigned char errmask; - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); - pci_write_config_byte(I801_dev, SMBHSTCFG, - hostc | SMBHSTCFG_I2C_EN); - } else { - dev_err(&I801_dev->dev, - "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); - return -1; - } - } + len = data->block[0]; if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 1) - len = 1; - if (len > 32) - len = 32; outb_p(len, SMBHSTDAT0); outb_p(data->block[1], SMBBLKDAT); - } else { - len = 32; /* max for reads */ - } - - if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) { - /* set 32 byte buffer */ } for (i = 1; i <= len; i++) { @@ -227,13 +272,13 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, /* Make sure the SMBus host is ready to start transmitting */ temp = inb_p(SMBHSTSTS); if (i == 1) { - /* Erronenous conditions before transaction: + /* Erronenous conditions before transaction: * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - errmask=0x9f; + errmask = 0x9f; } else { - /* Erronenous conditions during transaction: + /* Erronenous conditions during transaction: * Failed, Bus_Err, Dev_Err, Intr */ - errmask=0x1e; + errmask = 0x1e; } if (temp & errmask) { dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " @@ -242,14 +287,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { dev_err(&I801_dev->dev, "Reset failed! (%02x)\n", temp); - result = -1; - goto END; + return -1; } - if (i != 1) { + if (i != 1) /* if die in middle of block transaction, fail */ - result = -1; - goto END; - } + return -1; } if (i == 1) @@ -261,33 +303,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, msleep(1); temp = inb_p(SMBHSTSTS); } - while ((!(temp & 0x80)) - && (timeout++ < MAX_TIMEOUT)); + while ((!(temp & SMBHSTSTS_BYTE_DONE)) + && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { + /* try to stop the current command */ + dev_dbg(&I801_dev->dev, "Terminating the current " + "operation\n"); + outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); + msleep(1); + outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), + SMBHSTCNT); result = -1; dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); } - if (temp & 0x10) { + if (temp & SMBHSTSTS_FAILED) { result = -1; dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); - } else if (temp & 0x08) { + } else if (temp & SMBHSTSTS_BUS_ERR) { result = -1; dev_err(&I801_dev->dev, "Bus collision!\n"); - } else if (temp & 0x04) { + } else if (temp & SMBHSTSTS_DEV_ERR) { result = -1; dev_dbg(&I801_dev->dev, "Error: no response!\n"); } if (i == 1 && read_write == I2C_SMBUS_READ) { len = inb_p(SMBHSTDAT0); - if (len < 1) - len = 1; - if (len > 32) - len = 32; + if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) + return -1; data->block[0] = len; } @@ -310,25 +357,58 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); if (result < 0) - goto END; + return result; } + return result; +} - if (hwpec) { - /* wait for INTR bit as advised by Intel */ - timeout = 0; - do { - msleep(1); - temp = inb_p(SMBHSTSTS); - } while ((!(temp & 0x02)) - && (timeout++ < MAX_TIMEOUT)); +static int i801_set_block_buffer_mode(void) +{ + outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL); + if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0) + return -1; + return 0; +} - if (timeout >= MAX_TIMEOUT) { - dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); +/* Block transaction function */ +static int i801_block_transaction(union i2c_smbus_data *data, char read_write, + int command, int hwpec) +{ + int result = 0; + unsigned char hostc; + + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { + /* set I2C_EN bit in configuration register */ + pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); + pci_write_config_byte(I801_dev, SMBHSTCFG, + hostc | SMBHSTCFG_I2C_EN); + } else { + dev_err(&I801_dev->dev, + "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); + return -1; } - outb_p(temp, SMBHSTSTS); } - result = 0; -END: |