add i2c block read support for ich5 and higher. untested.

git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2792 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
Mark D. Studebaker committed 2004-12-08 04:55:45 +00:00
1 parent ca07a1d985
commit b6e48cb30f
1 file changed
+27 -13
+27 -13
View File
@@ -29,12 +29,13 @@
82801DB 24C3 (HW PEC supported, 32 byte buffer not supported)
82801EB 24D3 (HW PEC supported, 32 byte buffer not supported)
6300ESB 25A4 ("")
ICH6 266A
ICH6 266A ("")
This driver supports several versions of Intel's I/O Controller Hubs (ICH).
For SMBus support, they are similar to the PIIX4 and are part
of Intel's '810' and other chipsets.
See the doc/busses/i2c-i801 file for details.
I2C Block Read and Process Call are not supported.
I2C Block Read supported for ICH5 and higher.
Block Process Call are not supported.
*/
/* Note: we assume there can only be one I801, with one SMBus interface */
@@ -95,11 +96,11 @@
#define I801_WORD_DATA 0x0C
#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
#define I801_BLOCK_DATA 0x14
#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
#define I801_I2C_BLOCK_DATA 0x18 /* ich4 and later */
#define I801_BLOCK_LAST 0x34
#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
#define I801_START 0x40
#define I801_PEC_EN 0x80 /* ICH4 only */
#define I801_PEC_EN 0x80 /* ich4 and later */
/* insmod parameters */
@@ -117,7 +118,8 @@ static int i801_block_transaction(union i2c_smbus_data *data,
static unsigned short i801_smba;
static struct pci_dev *I801_dev;
static int isich4;
static int isich4; /* is PEC supported? */
static int isich5; /* is i2c block read supported? */
static int i801_setup(struct pci_dev *dev)
{
@@ -136,6 +138,7 @@ static int i801_setup(struct pci_dev *dev)
isich4 = 1;
else
isich4 = 0;
isich5 = isich4 && dev->device != PCI_DEVICE_ID_INTEL_82801DB_3;
/* Determine the address of the SMBus areas */
if (force_addr) {
@@ -275,7 +278,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(I801_dev, SMBHSTCFG,
hostc | SMBHSTCFG_I2C_EN);
} else {
} else if (!isich5) {
dev_err(I801_dev,
"I2C_SMBUS_I2C_BLOCK_READ unsupported!\n");
return -1;
@@ -301,6 +304,9 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
for (i = 1; i <= len; i++) {
if (i == len && read_write == I2C_SMBUS_READ)
smbcmd = I801_BLOCK_LAST;
else if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
read_write == I2C_SMBUS_READ)
smbcmd = I801_I2C_BLOCK_DATA;
else
smbcmd = I801_BLOCK_DATA;
outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
@@ -369,12 +375,17 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
}
if (i == 1 && read_write == I2C_SMBUS_READ) {
len = inb_p(SMBHSTDAT0);
if (len < 1)
len = 1;
if (len > 32)
len = 32;
data->block[0] = len;
if (command != I2C_SMBUS_I2C_BLOCK_DATA) {
len = inb_p(SMBHSTDAT0);
if (len < 1)
len = 1;
if (len > 32)
len = 32;
data->block[0] = len;
} else {
/* if slave returns < 32 bytes transaction will fail */
data->block[0] = 32;
}
}
/* Retrieve/store value in SMBBLKDAT */
@@ -417,7 +428,8 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
#endif
result = 0;
END:
if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
read_write == I2C_SMBUS_WRITE) {
/* restore saved configuration register value */
pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
}
@@ -552,6 +564,8 @@ static u32 i801_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_HWPEC_CALC
: 0)
#endif
| (isich5 ? I2C_FUNC_SMBUS_READ_I2C_BLOCK
: 0)
;
}