aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorOleg Ryjkov <olegr@google.com>2007-07-12 08:12:31 -0400
committerJean Delvare <khali@hyperion.delvare>2007-07-12 08:12:31 -0400
commit7edcb9abb594a8f3b4ca756e03d01c870aeae127 (patch)
tree1a58c21abdb71a2ec146225e0d226103926dbbd7 /drivers/i2c
parentca8b9e32a11a7cbfecbef00c8451a79fe1af392e (diff)
i2c-i801: Use the internal 32-byte buffer on ICH4+
Add an ability to utilize the internal SRAM buffer on ICH4 and newer host controllers to speed up execution of block operations. I've split the code so that it is more clear which block transaction is performed. First of all the host controller's type is identified. isich4 is set when we think that the controller has the internal buffer. Then, before every block transaction, if isich4 is set, we attempt to enable the E32B bit in SMBAUXCTL register. Signed-off-by: Oleg Ryjkov <olegr@google.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-i801.c151
1 files changed, 100 insertions, 51 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index d5e12a4f01b0..8f5c686123b8 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -26,8 +26,8 @@
26 82801AB 2423 26 82801AB 2423
27 82801BA 2443 27 82801BA 2443
28 82801CA/CAM 2483 28 82801CA/CAM 2483
29 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) 29 82801DB 24C3 (HW PEC supported)
30 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) 30 82801EB 24D3 (HW PEC supported)
31 6300ESB 25A4 31 6300ESB 25A4
32 ICH6 266A 32 ICH6 266A
33 ICH7 27DA 33 ICH7 27DA
@@ -114,7 +114,7 @@ static struct pci_driver i801_driver;
114static struct pci_dev *I801_dev; 114static struct pci_dev *I801_dev;
115static int isich4; 115static int isich4;
116 116
117static int i801_transaction(void) 117static int i801_transaction(int xact)
118{ 118{
119 int temp; 119 int temp;
120 int result = 0; 120 int result = 0;
@@ -139,7 +139,9 @@ static int i801_transaction(void)
139 } 139 }
140 } 140 }
141 141
142 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); 142 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
143 * INTREN, SMBSCMD are passed in xact */
144 outb_p(xact | I801_START, SMBHSTCNT);
143 145
144 /* We will always wait for a fraction of a second! */ 146 /* We will always wait for a fraction of a second! */
145 do { 147 do {
@@ -207,44 +209,52 @@ static void i801_wait_hwpec(void)
207 outb_p(temp, SMBHSTSTS); 209 outb_p(temp, SMBHSTSTS);
208} 210}
209 211
210/* All-inclusive block transaction function */ 212static int i801_block_transaction_by_block(union i2c_smbus_data *data,
211static int i801_block_transaction(union i2c_smbus_data *data, char read_write, 213 char read_write, int hwpec)
212 int command, int hwpec) 214{
215 int i, len;
216
217 inb_p(SMBHSTCNT); /* reset the data buffer index */
218
219 /* Use 32-byte buffer to process this transaction */
220 if (read_write == I2C_SMBUS_WRITE) {
221 len = data->block[0];
222 outb_p(len, SMBHSTDAT0);
223 for (i = 0; i < len; i++)
224 outb_p(data->block[i+1], SMBBLKDAT);
225 }
226
227 if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
228 I801_PEC_EN * hwpec))
229 return -1;
230
231 if (read_write == I2C_SMBUS_READ) {
232 len = inb_p(SMBHSTDAT0);
233 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
234 return -1;
235
236 data->block[0] = len;
237 for (i = 0; i < len; i++)
238 data->block[i + 1] = inb_p(SMBBLKDAT);
239 }
240 return 0;
241}
242
243static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
244 char read_write, int hwpec)
213{ 245{
214 int i, len; 246 int i, len;
215 int smbcmd; 247 int smbcmd;
216 int temp; 248 int temp;
217 int result = 0; 249 int result = 0;
218 int timeout; 250 int timeout;
219 unsigned char hostc, errmask; 251 unsigned char errmask;
220 252
221 if (command == I2C_SMBUS_I2C_BLOCK_DATA) { 253 len = data->block[0];
222 if (read_write == I2C_SMBUS_WRITE) {
223 /* set I2C_EN bit in configuration register */
224 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
225 pci_write_config_byte(I801_dev, SMBHSTCFG,
226 hostc | SMBHSTCFG_I2C_EN);
227 } else {
228 dev_err(&I801_dev->dev,
229 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
230 return -1;
231 }
232 }
233 254
234 if (read_write == I2C_SMBUS_WRITE) { 255 if (read_write == I2C_SMBUS_WRITE) {
235 len = data->block[0];
236 if (len < 1)
237 len = 1;
238 if (len > 32)
239 len = 32;
240 outb_p(len, SMBHSTDAT0); 256 outb_p(len, SMBHSTDAT0);
241 outb_p(data->block[1], SMBBLKDAT); 257 outb_p(data->block[1], SMBBLKDAT);
242 } else {
243 len = 32; /* max for reads */
244 }
245
246 if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
247 /* set 32 byte buffer */
248 } 258 }
249 259
250 for (i = 1; i <= len; i++) { 260 for (i = 1; i <= len; i++) {
@@ -277,14 +287,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
277 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { 287 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
278 dev_err(&I801_dev->dev, 288 dev_err(&I801_dev->dev,
279 "Reset failed! (%02x)\n", temp); 289 "Reset failed! (%02x)\n", temp);
280 result = -1; 290 return -1;
281 goto END;
282 } 291 }
283 if (i != 1) { 292 if (i != 1)
284 /* if die in middle of block transaction, fail */ 293 /* if die in middle of block transaction, fail */
285 result = -1; 294 return -1;
286 goto END;
287 }
288 } 295 }
289 296
290 if (i == 1) 297 if (i == 1)
@@ -326,10 +333,8 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
326 333
327 if (i == 1 && read_write == I2C_SMBUS_READ) { 334 if (i == 1 && read_write == I2C_SMBUS_READ) {
328 len = inb_p(SMBHSTDAT0); 335 len = inb_p(SMBHSTDAT0);
329 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { 336 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
330 result = -1; 337 return -1;
331 goto END;
332 }
333 data->block[0] = len; 338 data->block[0] = len;
334 } 339 }
335 340
@@ -352,14 +357,58 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
352 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); 357 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
353 358
354 if (result < 0) 359 if (result < 0)
355 goto END; 360 return result;
356 } 361 }
362 return result;
363}
357 364
358 if (hwpec) 365static int i801_set_block_buffer_mode(void)
366{
367 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
368 if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
369 return -1;
370 return 0;
371}
372
373/* Block transaction function */
374static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
375 int command, int hwpec)
376{
377 int result = 0;
378 unsigned char hostc;
379
380 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
381 if (read_write == I2C_SMBUS_WRITE) {
382 /* set I2C_EN bit in configuration register */
383 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
384 pci_write_config_byte(I801_dev, SMBHSTCFG,
385 hostc | SMBHSTCFG_I2C_EN);
386 } else {
387 dev_err(&I801_dev->dev,
388 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
389 return -1;
390 }
391 }
392
393 if (read_write == I2C_SMBUS_WRITE) {
394 if (data->block[0] < 1)
395 data->block[0] = 1;
396 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
397 data->block[0] = I2C_SMBUS_BLOCK_MAX;
398 } else {
399 data->block[0] = 32; /* max for reads */
400 }
401
402 if (isich4 && i801_set_block_buffer_mode() == 0 )
403 result = i801_block_transaction_by_block(data, read_write,
404 hwpec);
405 else
406 result = i801_block_transaction_byte_by_byte(data, read_write,
407 hwpec);
408
409 if (result == 0 && hwpec)
359 i801_wait_hwpec(); 410 i801_wait_hwpec();
360 411
361 result = 0;
362END:
363 if (command == I2C_SMBUS_I2C_BLOCK_DATA) { 412 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
364 /* restore saved configuration register value */ 413 /* restore saved configuration register value */
365 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); 414 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
@@ -431,15 +480,15 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
431 480
432 if(block) 481 if(block)
433 ret = i801_block_transaction(data, read_write, size, hwpec); 482 ret = i801_block_transaction(data, read_write, size, hwpec);
434 else { 483 else
435 outb_p(xact | ENABLE_INT9, SMBHSTCNT); 484 ret = i801_transaction(xact | ENABLE_INT9);
436 ret = i801_transaction();
437 }
438 485
439 /* Some BIOSes don't like it when PEC is enabled at reboot or resume 486 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
440 time, so we forcibly disable it after every transaction. */ 487 time, so we forcibly disable it after every transaction. Turn off
488 E32B for the same reason. */
441 if (hwpec) 489 if (hwpec)
442 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); 490 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
491 SMBAUXCTL);
443 492
444 if(block) 493 if(block)
445 return ret; 494 return ret;