1 From 6342064cad7a28d10504128d028bc4ba379d489d Mon Sep 17 00:00:00 2001
2 From: Jean Delvare <khali@linux-fr.org>
3 Date: Sun, 27 Jan 2008 18:14:50 +0100
4 Subject: [PATCH] i2c-i801: Implement I2C block read support
6 I2C block read is supported since the ICH5. I couldn't get it to work
7 using the block buffer, so it's using the old-style byte-by-byte mode
10 Note: I'm also updating the driver author... The i2c-i801 driver was
11 really written by Mark Studebaker, even though he based his work on
12 the i2c-piix4 driver which was written by Philip Edelbrock.
14 Signed-off-by: Jean Delvare <khali@linux-fr.org>
16 diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
17 index fde4420..3bd9583 100644
18 --- a/Documentation/i2c/busses/i2c-i801
19 +++ b/Documentation/i2c/busses/i2c-i801
20 @@ -17,9 +17,8 @@ Supported adapters:
21 Datasheets: Publicly available at the Intel website
24 - Frodo Looijaard <frodol@dds.nl>,
25 - Philip Edelbrock <phil@netroedge.com>,
26 Mark Studebaker <mdsxyz123@yahoo.com>
27 + Jean Delvare <khali@linux-fr.org>
31 @@ -62,7 +61,7 @@ Not supported.
32 I2C Block Read Support
33 ----------------------
35 -Not supported at the moment.
36 +I2C block read is supported on the 82801EB (ICH5) and later chips.
40 diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
41 index 0b1b1ae..aa91579 100644
42 --- a/drivers/i2c/busses/i2c-i801.c
43 +++ b/drivers/i2c/busses/i2c-i801.c
45 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
46 Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
48 + Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
50 This program is free software; you can redistribute it and/or modify
51 it under the terms of the GNU General Public License as published by
55 Block process call transaction no
56 - I2C block read transaction no
57 + I2C block read transaction yes (doesn't use the block buffer)
59 See the file Documentation/i2c/busses/i2c-i801 for details.
62 #define I801_WORD_DATA 0x0C
63 #define I801_PROC_CALL 0x10 /* unimplemented */
64 #define I801_BLOCK_DATA 0x14
65 -#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
66 +#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
67 #define I801_BLOCK_LAST 0x34
68 -#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
69 +#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
70 #define I801_START 0x40
71 #define I801_PEC_EN 0x80 /* ICH3 and later */
73 @@ -256,7 +257,8 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data,
76 static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
77 - char read_write, int hwpec)
78 + char read_write, int command,
83 @@ -273,16 +275,24 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
86 for (i = 1; i <= len; i++) {
87 - if (i == len && read_write == I2C_SMBUS_READ)
88 - smbcmd = I801_BLOCK_LAST;
90 - smbcmd = I801_BLOCK_DATA;
91 + if (i == len && read_write == I2C_SMBUS_READ) {
92 + if (command == I2C_SMBUS_I2C_BLOCK_DATA)
93 + smbcmd = I801_I2C_BLOCK_LAST;
95 + smbcmd = I801_BLOCK_LAST;
97 + if (command == I2C_SMBUS_I2C_BLOCK_DATA
98 + && read_write == I2C_SMBUS_READ)
99 + smbcmd = I801_I2C_BLOCK_DATA;
101 + smbcmd = I801_BLOCK_DATA;
103 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
105 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
106 - "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
107 + "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
108 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
109 - inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
110 + inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
112 /* Make sure the SMBus host is ready to start transmitting */
113 temp = inb_p(SMBHSTSTS);
114 @@ -346,7 +356,8 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
115 dev_dbg(&I801_dev->dev, "Error: no response!\n");
118 - if (i == 1 && read_write == I2C_SMBUS_READ) {
119 + if (i == 1 && read_write == I2C_SMBUS_READ
120 + && command != I2C_SMBUS_I2C_BLOCK_DATA) {
121 len = inb_p(SMBHSTDAT0);
122 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
124 @@ -367,9 +378,9 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
127 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
128 - "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
129 + "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
130 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
131 - inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
132 + inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
136 @@ -398,34 +409,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
137 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
138 pci_write_config_byte(I801_dev, SMBHSTCFG,
139 hostc | SMBHSTCFG_I2C_EN);
141 + } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
142 dev_err(&I801_dev->dev,
143 - "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
144 + "I2C block read is unsupported!\n");
149 - if (read_write == I2C_SMBUS_WRITE) {
150 + if (read_write == I2C_SMBUS_WRITE
151 + || command == I2C_SMBUS_I2C_BLOCK_DATA) {
152 if (data->block[0] < 1)
154 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
155 data->block[0] = I2C_SMBUS_BLOCK_MAX;
157 - data->block[0] = 32; /* max for reads */
158 + data->block[0] = 32; /* max for SMBus block reads */
161 if ((i801_features & FEATURE_BLOCK_BUFFER)
162 + && !(command == I2C_SMBUS_I2C_BLOCK_DATA
163 + && read_write == I2C_SMBUS_READ)
164 && i801_set_block_buffer_mode() == 0)
165 result = i801_block_transaction_by_block(data, read_write,
168 result = i801_block_transaction_byte_by_byte(data, read_write,
172 if (result == 0 && hwpec)
175 - if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
176 + if (command == I2C_SMBUS_I2C_BLOCK_DATA
177 + && read_write == I2C_SMBUS_WRITE) {
178 /* restore saved configuration register value */
179 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
181 @@ -477,12 +492,23 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
182 xact = I801_WORD_DATA;
184 case I2C_SMBUS_BLOCK_DATA:
185 - case I2C_SMBUS_I2C_BLOCK_DATA:
186 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
188 outb_p(command, SMBHSTCMD);
191 + case I2C_SMBUS_I2C_BLOCK_DATA:
192 + /* NB: page 240 of ICH5 datasheet shows that the R/#W
193 + * bit should be cleared here, even when reading */
194 + outb_p((addr & 0x7f) << 1, SMBHSTADD);
195 + if (read_write == I2C_SMBUS_READ) {
196 + /* NB: page 240 of ICH5 datasheet also shows
197 + * that DATA1 is the cmd field when reading */
198 + outb_p(command, SMBHSTDAT1);
200 + outb_p(command, SMBHSTCMD);
203 case I2C_SMBUS_PROC_CALL:
205 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
206 @@ -531,7 +557,9 @@ static u32 i801_func(struct i2c_adapter *adapter)
207 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
208 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
209 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
210 - ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0);
211 + ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
212 + ((i801_features & FEATURE_I2C_BLOCK_READ) ?
213 + I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
216 static const struct i2c_algorithm smbus_algorithm = {
217 @@ -573,7 +601,6 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
220 switch (dev->device) {
221 - case PCI_DEVICE_ID_INTEL_82801DB_3:
222 case PCI_DEVICE_ID_INTEL_82801EB_3:
223 case PCI_DEVICE_ID_INTEL_ESB_4:
224 case PCI_DEVICE_ID_INTEL_ICH6_16:
225 @@ -581,6 +608,9 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
226 case PCI_DEVICE_ID_INTEL_ESB2_17:
227 case PCI_DEVICE_ID_INTEL_ICH8_5:
228 case PCI_DEVICE_ID_INTEL_ICH9_6:
229 + i801_features |= FEATURE_I2C_BLOCK_READ;
231 + case PCI_DEVICE_ID_INTEL_82801DB_3:
232 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
233 i801_features |= FEATURE_SMBUS_PEC;
234 i801_features |= FEATURE_BLOCK_BUFFER;
235 @@ -698,9 +728,8 @@ static void __exit i2c_i801_exit(void)
236 pci_unregister_driver(&i801_driver);
239 -MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
240 - "Philip Edelbrock <phil@netroedge.com>, "
241 - "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
242 +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
243 + "Jean Delvare <khali@linux-fr.org>");
244 MODULE_DESCRIPTION("I801 SMBus driver");
245 MODULE_LICENSE("GPL");