diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-i801.c')
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 154 |
1 files changed, 64 insertions, 90 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index dfca7493362..3e0d04d5a80 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | i801.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | monitoring | 3 | monitoring |
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 |
@@ -36,7 +36,7 @@ | |||
36 | This driver supports several versions of Intel's I/O Controller Hubs (ICH). | 36 | This driver supports several versions of Intel's I/O Controller Hubs (ICH). |
37 | For SMBus support, they are similar to the PIIX4 and are part | 37 | For SMBus support, they are similar to the PIIX4 and are part |
38 | of Intel's '810' and other chipsets. | 38 | of Intel's '810' and other chipsets. |
39 | See the doc/busses/i2c-i801 file for details. | 39 | See the file Documentation/i2c/busses/i2c-i801 for details. |
40 | I2C Block Read and Process Call are not supported. | 40 | I2C Block Read and Process Call are not supported. |
41 | */ | 41 | */ |
42 | 42 | ||
@@ -66,9 +66,8 @@ | |||
66 | #define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ | 66 | #define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ |
67 | 67 | ||
68 | /* PCI Address Constants */ | 68 | /* PCI Address Constants */ |
69 | #define SMBBA 0x020 | 69 | #define SMBBAR 4 |
70 | #define SMBHSTCFG 0x040 | 70 | #define SMBHSTCFG 0x040 |
71 | #define SMBREV 0x008 | ||
72 | 71 | ||
73 | /* Host configuration bits for SMBHSTCFG */ | 72 | /* Host configuration bits for SMBHSTCFG */ |
74 | #define SMBHSTCFG_HST_EN 1 | 73 | #define SMBHSTCFG_HST_EN 1 |
@@ -92,92 +91,16 @@ | |||
92 | #define I801_START 0x40 | 91 | #define I801_START 0x40 |
93 | #define I801_PEC_EN 0x80 /* ICH4 only */ | 92 | #define I801_PEC_EN 0x80 /* ICH4 only */ |
94 | 93 | ||
95 | /* insmod parameters */ | ||
96 | |||
97 | /* If force_addr is set to anything different from 0, we forcibly enable | ||
98 | the I801 at the given address. VERY DANGEROUS! */ | ||
99 | static u16 force_addr; | ||
100 | module_param(force_addr, ushort, 0); | ||
101 | MODULE_PARM_DESC(force_addr, | ||
102 | "Forcibly enable the I801 at the given address. " | ||
103 | "EXTREMELY DANGEROUS!"); | ||
104 | 94 | ||
105 | static int i801_transaction(void); | 95 | static int i801_transaction(void); |
106 | static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | 96 | static int i801_block_transaction(union i2c_smbus_data *data, char read_write, |
107 | int command, int hwpec); | 97 | int command, int hwpec); |
108 | 98 | ||
109 | static unsigned short i801_smba; | 99 | static unsigned long i801_smba; |
110 | static struct pci_driver i801_driver; | 100 | static struct pci_driver i801_driver; |
111 | static struct pci_dev *I801_dev; | 101 | static struct pci_dev *I801_dev; |
112 | static int isich4; | 102 | static int isich4; |
113 | 103 | ||
114 | static int i801_setup(struct pci_dev *dev) | ||
115 | { | ||
116 | int error_return = 0; | ||
117 | unsigned char temp; | ||
118 | |||
119 | /* Note: we keep on searching until we have found 'function 3' */ | ||
120 | if(PCI_FUNC(dev->devfn) != 3) | ||
121 | return -ENODEV; | ||
122 | |||
123 | I801_dev = dev; | ||
124 | if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || | ||
125 | (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || | ||
126 | (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) | ||
127 | isich4 = 1; | ||
128 | else | ||
129 | isich4 = 0; | ||
130 | |||
131 | /* Determine the address of the SMBus areas */ | ||
132 | if (force_addr) { | ||
133 | i801_smba = force_addr & 0xfff0; | ||
134 | } else { | ||
135 | pci_read_config_word(I801_dev, SMBBA, &i801_smba); | ||
136 | i801_smba &= 0xfff0; | ||
137 | if(i801_smba == 0) { | ||
138 | dev_err(&dev->dev, "SMB base address uninitialized " | ||
139 | "- upgrade BIOS or use force_addr=0xaddr\n"); | ||
140 | return -ENODEV; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) { | ||
145 | dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n", | ||
146 | i801_smba); | ||
147 | error_return = -EBUSY; | ||
148 | goto END; | ||
149 | } | ||
150 | |||
151 | pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); | ||
152 | temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ | ||
153 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp); | ||
154 | |||
155 | /* If force_addr is set, we program the new address here. Just to make | ||
156 | sure, we disable the device first. */ | ||
157 | if (force_addr) { | ||
158 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); | ||
159 | pci_write_config_word(I801_dev, SMBBA, i801_smba); | ||
160 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); | ||
161 | dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to " | ||
162 | "new address %04x!\n", i801_smba); | ||
163 | } else if ((temp & 1) == 0) { | ||
164 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); | ||
165 | dev_warn(&dev->dev, "enabling SMBus device\n"); | ||
166 | } | ||
167 | |||
168 | if (temp & 0x02) | ||
169 | dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); | ||
170 | else | ||
171 | dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n"); | ||
172 | |||
173 | pci_read_config_byte(I801_dev, SMBREV, &temp); | ||
174 | dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); | ||
175 | dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); | ||
176 | |||
177 | END: | ||
178 | return error_return; | ||
179 | } | ||
180 | |||
181 | static int i801_transaction(void) | 104 | static int i801_transaction(void) |
182 | { | 105 | { |
183 | int temp; | 106 | int temp; |
@@ -334,8 +257,8 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | |||
334 | /* We will always wait for a fraction of a second! */ | 257 | /* We will always wait for a fraction of a second! */ |
335 | timeout = 0; | 258 | timeout = 0; |
336 | do { | 259 | do { |
337 | temp = inb_p(SMBHSTSTS); | ||
338 | msleep(1); | 260 | msleep(1); |
261 | temp = inb_p(SMBHSTSTS); | ||
339 | } | 262 | } |
340 | while ((!(temp & 0x80)) | 263 | while ((!(temp & 0x80)) |
341 | && (timeout++ < MAX_TIMEOUT)); | 264 | && (timeout++ < MAX_TIMEOUT)); |
@@ -393,8 +316,8 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | |||
393 | /* wait for INTR bit as advised by Intel */ | 316 | /* wait for INTR bit as advised by Intel */ |
394 | timeout = 0; | 317 | timeout = 0; |
395 | do { | 318 | do { |
396 | temp = inb_p(SMBHSTSTS); | ||
397 | msleep(1); | 319 | msleep(1); |
320 | temp = inb_p(SMBHSTSTS); | ||
398 | } while ((!(temp & 0x02)) | 321 | } while ((!(temp & 0x02)) |
399 | && (timeout++ < MAX_TIMEOUT)); | 322 | && (timeout++ < MAX_TIMEOUT)); |
400 | 323 | ||
@@ -541,25 +464,76 @@ MODULE_DEVICE_TABLE (pci, i801_ids); | |||
541 | 464 | ||
542 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) | 465 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) |
543 | { | 466 | { |
467 | unsigned char temp; | ||
468 | int err; | ||
469 | |||
470 | I801_dev = dev; | ||
471 | if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || | ||
472 | (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || | ||
473 | (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) | ||
474 | isich4 = 1; | ||
475 | else | ||
476 | isich4 = 0; | ||
477 | |||
478 | err = pci_enable_device(dev); | ||
479 | if (err) { | ||
480 | dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", | ||
481 | err); | ||
482 | goto exit; | ||
483 | } | ||
484 | |||
485 | /* Determine the address of the SMBus area */ | ||
486 | i801_smba = pci_resource_start(dev, SMBBAR); | ||
487 | if (!i801_smba) { | ||
488 | dev_err(&dev->dev, "SMBus base address uninitialized, " | ||
489 | "upgrade BIOS\n"); | ||
490 | err = -ENODEV; | ||
491 | goto exit_disable; | ||
492 | } | ||
493 | |||
494 | err = pci_request_region(dev, SMBBAR, i801_driver.name); | ||
495 | if (err) { | ||
496 | dev_err(&dev->dev, "Failed to request SMBus region " | ||
497 | "0x%lx-0x%lx\n", i801_smba, | ||
498 | pci_resource_end(dev, SMBBAR)); | ||
499 | goto exit_disable; | ||
500 | } | ||
544 | 501 | ||
545 | if (i801_setup(dev)) { | 502 | pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); |
546 | dev_warn(&dev->dev, | 503 | temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ |
547 | "I801 not detected, module not inserted.\n"); | 504 | if (!(temp & SMBHSTCFG_HST_EN)) { |
548 | return -ENODEV; | 505 | dev_info(&dev->dev, "Enabling SMBus device\n"); |
506 | temp |= SMBHSTCFG_HST_EN; | ||
549 | } | 507 | } |
508 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp); | ||
509 | |||
510 | if (temp & SMBHSTCFG_SMB_SMI_EN) | ||
511 | dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); | ||
512 | else | ||
513 | dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); | ||
550 | 514 | ||
551 | /* set up the driverfs linkage to our parent device */ | 515 | /* set up the driverfs linkage to our parent device */ |
552 | i801_adapter.dev.parent = &dev->dev; | 516 | i801_adapter.dev.parent = &dev->dev; |
553 | 517 | ||
554 | snprintf(i801_adapter.name, I2C_NAME_SIZE, | 518 | snprintf(i801_adapter.name, I2C_NAME_SIZE, |
555 | "SMBus I801 adapter at %04x", i801_smba); | 519 | "SMBus I801 adapter at %04lx", i801_smba); |
556 | return i2c_add_adapter(&i801_adapter); | 520 | err = i2c_add_adapter(&i801_adapter); |
521 | if (err) { | ||
522 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); | ||
523 | goto exit_disable; | ||
524 | } | ||
525 | |||
526 | exit_disable: | ||
527 | pci_disable_device(dev); | ||
528 | exit: | ||
529 | return err; | ||
557 | } | 530 | } |
558 | 531 | ||
559 | static void __devexit i801_remove(struct pci_dev *dev) | 532 | static void __devexit i801_remove(struct pci_dev *dev) |
560 | { | 533 | { |
561 | i2c_del_adapter(&i801_adapter); | 534 | i2c_del_adapter(&i801_adapter); |
562 | release_region(i801_smba, (isich4 ? 16 : 8)); | 535 | pci_release_region(dev, SMBBAR); |
536 | pci_disable_device(dev); | ||
563 | } | 537 | } |
564 | 538 | ||
565 | static struct pci_driver i801_driver = { | 539 | static struct pci_driver i801_driver = { |