aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-01-27 12:14:50 -0500
committerJean Delvare <khali@hyperion.delvare>2008-01-27 12:14:50 -0500
commit6342064cad7a28d10504128d028bc4ba379d489d (patch)
treec8a8b21672b5a09f0f357eb65ad4be08bfdde4ca /drivers
parenta0921b6c07dfbb59ac2d497e96438adaf4940f16 (diff)
i2c-i801: Implement I2C block read support
I2C block read is supported since the ICH5. I couldn't get it to work using the block buffer, so it's using the old-style byte-by-byte mode for now. Note: I'm also updating the driver author... The i2c-i801 driver was really written by Mark Studebaker, even though he based his work on the i2c-piix4 driver which was written by Philip Edelbrock. Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-i801.c79
1 files changed, 54 insertions, 25 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 0b1b1ae5e228..aa9157913b9a 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -4,6 +4,7 @@
4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, 4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
5 Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker 5 Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
6 <mdsxyz123@yahoo.com> 6 <mdsxyz123@yahoo.com>
7 Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
7 8
8 This program is free software; you can redistribute it and/or modify 9 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
@@ -46,7 +47,7 @@
46 Hardware PEC yes 47 Hardware PEC yes
47 Block buffer yes 48 Block buffer yes
48 Block process call transaction no 49 Block process call transaction no
49 I2C block read transaction no 50 I2C block read transaction yes (doesn't use the block buffer)
50 51
51 See the file Documentation/i2c/busses/i2c-i801 for details. 52 See the file Documentation/i2c/busses/i2c-i801 for details.
52*/ 53*/
@@ -102,9 +103,9 @@
102#define I801_WORD_DATA 0x0C 103#define I801_WORD_DATA 0x0C
103#define I801_PROC_CALL 0x10 /* unimplemented */ 104#define I801_PROC_CALL 0x10 /* unimplemented */
104#define I801_BLOCK_DATA 0x14 105#define I801_BLOCK_DATA 0x14
105#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ 106#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
106#define I801_BLOCK_LAST 0x34 107#define I801_BLOCK_LAST 0x34
107#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ 108#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
108#define I801_START 0x40 109#define I801_START 0x40
109#define I801_PEC_EN 0x80 /* ICH3 and later */ 110#define I801_PEC_EN 0x80 /* ICH3 and later */
110 111
@@ -256,7 +257,8 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data,
256} 257}
257 258
258static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, 259static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
259 char read_write, int hwpec) 260 char read_write, int command,
261 int hwpec)
260{ 262{
261 int i, len; 263 int i, len;
262 int smbcmd; 264 int smbcmd;
@@ -273,16 +275,24 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
273 } 275 }
274 276
275 for (i = 1; i <= len; i++) { 277 for (i = 1; i <= len; i++) {
276 if (i == len && read_write == I2C_SMBUS_READ) 278 if (i == len && read_write == I2C_SMBUS_READ) {
277 smbcmd = I801_BLOCK_LAST; 279 if (command == I2C_SMBUS_I2C_BLOCK_DATA)
278 else 280 smbcmd = I801_I2C_BLOCK_LAST;
279 smbcmd = I801_BLOCK_DATA; 281 else
282 smbcmd = I801_BLOCK_LAST;
283 } else {
284 if (command == I2C_SMBUS_I2C_BLOCK_DATA
285 && read_write == I2C_SMBUS_READ)
286 smbcmd = I801_I2C_BLOCK_DATA;
287 else
288 smbcmd = I801_BLOCK_DATA;
289 }
280 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); 290 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
281 291
282 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " 292 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
283 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, 293 "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
284 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), 294 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
285 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); 295 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
286 296
287 /* Make sure the SMBus host is ready to start transmitting */ 297 /* Make sure the SMBus host is ready to start transmitting */
288 temp = inb_p(SMBHSTSTS); 298 temp = inb_p(SMBHSTSTS);
@@ -346,7 +356,8 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
346 dev_dbg(&I801_dev->dev, "Error: no response!\n"); 356 dev_dbg(&I801_dev->dev, "Error: no response!\n");
347 } 357 }
348 358
349 if (i == 1 && read_write == I2C_SMBUS_READ) { 359 if (i == 1 && read_write == I2C_SMBUS_READ
360 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
350 len = inb_p(SMBHSTDAT0); 361 len = inb_p(SMBHSTDAT0);
351 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) 362 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
352 return -1; 363 return -1;
@@ -367,9 +378,9 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
367 temp); 378 temp);
368 } 379 }
369 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, " 380 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
370 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, 381 "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
371 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), 382 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
372 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); 383 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
373 384
374 if (result < 0) 385 if (result < 0)
375 return result; 386 return result;
@@ -398,34 +409,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
398 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); 409 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
399 pci_write_config_byte(I801_dev, SMBHSTCFG, 410 pci_write_config_byte(I801_dev, SMBHSTCFG,
400 hostc | SMBHSTCFG_I2C_EN); 411 hostc | SMBHSTCFG_I2C_EN);
401 } else { 412 } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
402 dev_err(&I801_dev->dev, 413 dev_err(&I801_dev->dev,
403 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); 414 "I2C block read is unsupported!\n");
404 return -1; 415 return -1;
405 } 416 }
406 } 417 }
407 418
408 if (read_write == I2C_SMBUS_WRITE) { 419 if (read_write == I2C_SMBUS_WRITE
420 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
409 if (data->block[0] < 1) 421 if (data->block[0] < 1)
410 data->block[0] = 1; 422 data->block[0] = 1;
411 if (data->block[0] > I2C_SMBUS_BLOCK_MAX) 423 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
412 data->block[0] = I2C_SMBUS_BLOCK_MAX; 424 data->block[0] = I2C_SMBUS_BLOCK_MAX;
413 } else { 425 } else {
414 data->block[0] = 32; /* max for reads */ 426 data->block[0] = 32; /* max for SMBus block reads */
415 } 427 }
416 428
417 if ((i801_features & FEATURE_BLOCK_BUFFER) 429 if ((i801_features & FEATURE_BLOCK_BUFFER)
430 && !(command == I2C_SMBUS_I2C_BLOCK_DATA
431 && read_write == I2C_SMBUS_READ)
418 && i801_set_block_buffer_mode() == 0) 432 && i801_set_block_buffer_mode() == 0)
419 result = i801_block_transaction_by_block(data, read_write, 433 result = i801_block_transaction_by_block(data, read_write,
420 hwpec); 434 hwpec);
421 else 435 else
422 result = i801_block_transaction_byte_by_byte(data, read_write, 436 result = i801_block_transaction_byte_by_byte(data, read_write,
423 hwpec); 437 command, hwpec);
424 438
425 if (result == 0 && hwpec) 439 if (result == 0 && hwpec)
426 i801_wait_hwpec(); 440 i801_wait_hwpec();
427 441
428 if (command == I2C_SMBUS_I2C_BLOCK_DATA) { 442 if (command == I2C_SMBUS_I2C_BLOCK_DATA
443 && read_write == I2C_SMBUS_WRITE) {
429 /* restore saved configuration register value */ 444 /* restore saved configuration register value */
430 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); 445 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
431 } 446 }
@@ -477,12 +492,23 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
477 xact = I801_WORD_DATA; 492 xact = I801_WORD_DATA;
478 break; 493 break;
479 case I2C_SMBUS_BLOCK_DATA: 494 case I2C_SMBUS_BLOCK_DATA:
480 case I2C_SMBUS_I2C_BLOCK_DATA:
481 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), 495 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
482 SMBHSTADD); 496 SMBHSTADD);
483 outb_p(command, SMBHSTCMD); 497 outb_p(command, SMBHSTCMD);
484 block = 1; 498 block = 1;
485 break; 499 break;
500 case I2C_SMBUS_I2C_BLOCK_DATA:
501 /* NB: page 240 of ICH5 datasheet shows that the R/#W
502 * bit should be cleared here, even when reading */
503 outb_p((addr & 0x7f) << 1, SMBHSTADD);
504 if (read_write == I2C_SMBUS_READ) {
505 /* NB: page 240 of ICH5 datasheet also shows
506 * that DATA1 is the cmd field when reading */
507 outb_p(command, SMBHSTDAT1);
508 } else
509 outb_p(command, SMBHSTCMD);
510 block = 1;
511 break;
486 case I2C_SMBUS_PROC_CALL: 512 case I2C_SMBUS_PROC_CALL:
487 default: 513 default:
488 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); 514 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
@@ -531,7 +557,9 @@ static u32 i801_func(struct i2c_adapter *adapter)
531 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 557 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
532 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 558 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
533 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | 559 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
534 ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0); 560 ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
561 ((i801_features & FEATURE_I2C_BLOCK_READ) ?
562 I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
535} 563}
536 564
537static const struct i2c_algorithm smbus_algorithm = { 565static const struct i2c_algorithm smbus_algorithm = {
@@ -573,7 +601,6 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
573 I801_dev = dev; 601 I801_dev = dev;
574 i801_features = 0; 602 i801_features = 0;
575 switch (dev->device) { 603 switch (dev->device) {
576 case PCI_DEVICE_ID_INTEL_82801DB_3:
577 case PCI_DEVICE_ID_INTEL_82801EB_3: 604 case PCI_DEVICE_ID_INTEL_82801EB_3:
578 case PCI_DEVICE_ID_INTEL_ESB_4: 605 case PCI_DEVICE_ID_INTEL_ESB_4:
579 case PCI_DEVICE_ID_INTEL_ICH6_16: 606 case PCI_DEVICE_ID_INTEL_ICH6_16:
@@ -581,6 +608,9 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
581 case PCI_DEVICE_ID_INTEL_ESB2_17: 608 case PCI_DEVICE_ID_INTEL_ESB2_17:
582 case PCI_DEVICE_ID_INTEL_ICH8_5: 609 case PCI_DEVICE_ID_INTEL_ICH8_5:
583 case PCI_DEVICE_ID_INTEL_ICH9_6: 610 case PCI_DEVICE_ID_INTEL_ICH9_6:
611 i801_features |= FEATURE_I2C_BLOCK_READ;
612 /* fall through */
613 case PCI_DEVICE_ID_INTEL_82801DB_3:
584 case PCI_DEVICE_ID_INTEL_TOLAPAI_1: 614 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
585 i801_features |= FEATURE_SMBUS_PEC; 615 i801_features |= FEATURE_SMBUS_PEC;
586 i801_features |= FEATURE_BLOCK_BUFFER; 616 i801_features |= FEATURE_BLOCK_BUFFER;
@@ -698,9 +728,8 @@ static void __exit i2c_i801_exit(void)
698 pci_unregister_driver(&i801_driver); 728 pci_unregister_driver(&i801_driver);
699} 729}
700 730
701MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, " 731MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
702 "Philip Edelbrock <phil@netroedge.com>, " 732 "Jean Delvare <khali@linux-fr.org>");
703 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
704MODULE_DESCRIPTION("I801 SMBus driver"); 733MODULE_DESCRIPTION("I801 SMBus driver");
705MODULE_LICENSE("GPL"); 734MODULE_LICENSE("GPL");
706 735