blob: b9e6fac8142d05cce7b015b5db71aacf22eb7fde [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Jean Delvare455f3322006-06-12 21:52:02 +02002 i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 monitoring
4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
5 Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
6 <mdsxyz123@yahoo.com>
7
8 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 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23/*
24 SUPPORTED DEVICES PCI ID
25 82801AA 2413
26 82801AB 2423
27 82801BA 2443
28 82801CA/CAM 2483
29 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported)
30 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported)
31 6300ESB 25A4
32 ICH6 266A
33 ICH7 27DA
Jason Gastonb0a70b52005-04-16 15:24:45 -070034 ESB2 269B
Jason Gaston8254fc42006-01-09 10:58:08 -080035 ICH8 283E
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 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
38 of Intel's '810' and other chipsets.
Jean Delvare455f3322006-06-12 21:52:02 +020039 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 I2C Block Read and Process Call are not supported.
41*/
42
43/* Note: we assume there can only be one I801, with one SMBus interface */
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/module.h>
46#include <linux/pci.h>
47#include <linux/kernel.h>
48#include <linux/stddef.h>
49#include <linux/delay.h>
50#include <linux/sched.h>
51#include <linux/ioport.h>
52#include <linux/init.h>
53#include <linux/i2c.h>
54#include <asm/io.h>
55
Linus Torvalds1da177e2005-04-16 15:20:36 -070056/* I801 SMBus address offsets */
57#define SMBHSTSTS (0 + i801_smba)
58#define SMBHSTCNT (2 + i801_smba)
59#define SMBHSTCMD (3 + i801_smba)
60#define SMBHSTADD (4 + i801_smba)
61#define SMBHSTDAT0 (5 + i801_smba)
62#define SMBHSTDAT1 (6 + i801_smba)
63#define SMBBLKDAT (7 + i801_smba)
64#define SMBPEC (8 + i801_smba) /* ICH4 only */
65#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */
66#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */
67
68/* PCI Address Constants */
69#define SMBBA 0x020
70#define SMBHSTCFG 0x040
71#define SMBREV 0x008
72
73/* Host configuration bits for SMBHSTCFG */
74#define SMBHSTCFG_HST_EN 1
75#define SMBHSTCFG_SMB_SMI_EN 2
76#define SMBHSTCFG_I2C_EN 4
77
78/* Other settings */
79#define MAX_TIMEOUT 100
80#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
81
82/* I801 command constants */
83#define I801_QUICK 0x00
84#define I801_BYTE 0x04
85#define I801_BYTE_DATA 0x08
86#define I801_WORD_DATA 0x0C
87#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
88#define I801_BLOCK_DATA 0x14
89#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
90#define I801_BLOCK_LAST 0x34
91#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
92#define I801_START 0x40
93#define I801_PEC_EN 0x80 /* ICH4 only */
94
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
96static int i801_transaction(void);
Jean Delvare585b3162005-10-26 21:31:15 +020097static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
98 int command, int hwpec);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100static unsigned short i801_smba;
Jean Delvared6072f82005-09-25 16:37:04 +0200101static struct pci_driver i801_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102static struct pci_dev *I801_dev;
103static int isich4;
104
Jean Delvare455f3322006-06-12 21:52:02 +0200105static int __devinit i801_setup(struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 unsigned char temp;
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 I801_dev = dev;
110 if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
111 (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
112 (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
113 isich4 = 1;
114 else
115 isich4 = 0;
116
Jean Delvare455f3322006-06-12 21:52:02 +0200117 /* Determine the address of the SMBus area */
Jean Delvared8db8f92006-06-12 21:50:11 +0200118 pci_read_config_word(I801_dev, SMBBA, &i801_smba);
119 i801_smba &= 0xfff0;
120 if (!i801_smba) {
121 dev_err(&dev->dev, "SMBus base address uninitialized, "
122 "upgrade BIOS\n");
123 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 }
125
Jean Delvared6072f82005-09-25 16:37:04 +0200126 if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
128 i801_smba);
Jean Delvare455f3322006-06-12 21:52:02 +0200129 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 }
131
132 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
133 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
Jean Delvare455f3322006-06-12 21:52:02 +0200134 if (!(temp & SMBHSTCFG_HST_EN)) {
135 dev_warn(&dev->dev, "enabling SMBus device\n");
136 temp |= SMBHSTCFG_HST_EN;
137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
139
Jean Delvare455f3322006-06-12 21:52:02 +0200140 if (temp & SMBHSTCFG_SMB_SMI_EN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n");
142 else
143 dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n");
144
145 pci_read_config_byte(I801_dev, SMBREV, &temp);
146 dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp);
147 dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba);
148
Jean Delvare455f3322006-06-12 21:52:02 +0200149 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150}
151
152static int i801_transaction(void)
153{
154 int temp;
155 int result = 0;
156 int timeout = 0;
157
Jean Delvare368609c2005-07-29 12:15:07 -0700158 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
160 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
161 inb_p(SMBHSTDAT1));
162
163 /* Make sure the SMBus host is ready to start transmitting */
164 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
165 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200166 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 temp);
168 outb_p(temp, SMBHSTSTS);
169 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
170 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
171 return -1;
172 } else {
173 dev_dbg(&I801_dev->dev, "Successfull!\n");
174 }
175 }
176
177 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
178
179 /* We will always wait for a fraction of a second! */
180 do {
181 msleep(1);
182 temp = inb_p(SMBHSTSTS);
183 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
184
185 /* If the SMBus is still busy, we give up */
186 if (timeout >= MAX_TIMEOUT) {
187 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
188 result = -1;
189 }
190
191 if (temp & 0x10) {
192 result = -1;
193 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
194 }
195
196 if (temp & 0x08) {
197 result = -1;
198 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
199 "until next hard reset. (sorry!)\n");
200 /* Clock stops and slave is stuck in mid-transmission */
201 }
202
203 if (temp & 0x04) {
204 result = -1;
205 dev_dbg(&I801_dev->dev, "Error: no response!\n");
206 }
207
208 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
209 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
210
211 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700212 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 "(%02x)\n", temp);
214 }
215 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
216 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
217 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
218 inb_p(SMBHSTDAT1));
219 return result;
220}
221
222/* All-inclusive block transaction function */
223static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
Jean Delvare585b3162005-10-26 21:31:15 +0200224 int command, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225{
226 int i, len;
227 int smbcmd;
228 int temp;
229 int result = 0;
230 int timeout;
231 unsigned char hostc, errmask;
232
233 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
234 if (read_write == I2C_SMBUS_WRITE) {
235 /* set I2C_EN bit in configuration register */
236 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
237 pci_write_config_byte(I801_dev, SMBHSTCFG,
238 hostc | SMBHSTCFG_I2C_EN);
239 } else {
240 dev_err(&I801_dev->dev,
241 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
242 return -1;
243 }
244 }
245
246 if (read_write == I2C_SMBUS_WRITE) {
247 len = data->block[0];
248 if (len < 1)
249 len = 1;
250 if (len > 32)
251 len = 32;
252 outb_p(len, SMBHSTDAT0);
253 outb_p(data->block[1], SMBBLKDAT);
254 } else {
255 len = 32; /* max for reads */
256 }
257
258 if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
259 /* set 32 byte buffer */
260 }
261
262 for (i = 1; i <= len; i++) {
263 if (i == len && read_write == I2C_SMBUS_READ)
264 smbcmd = I801_BLOCK_LAST;
265 else
266 smbcmd = I801_BLOCK_DATA;
267 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
268
269 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
270 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
271 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
272 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
273
274 /* Make sure the SMBus host is ready to start transmitting */
275 temp = inb_p(SMBHSTSTS);
276 if (i == 1) {
277 /* Erronenous conditions before transaction:
278 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
279 errmask=0x9f;
280 } else {
281 /* Erronenous conditions during transaction:
282 * Failed, Bus_Err, Dev_Err, Intr */
283 errmask=0x1e;
284 }
285 if (temp & errmask) {
286 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200287 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 outb_p(temp, SMBHSTSTS);
289 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
290 dev_err(&I801_dev->dev,
291 "Reset failed! (%02x)\n", temp);
292 result = -1;
293 goto END;
294 }
295 if (i != 1) {
296 /* if die in middle of block transaction, fail */
297 result = -1;
298 goto END;
299 }
300 }
301
302 if (i == 1)
303 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
304
305 /* We will always wait for a fraction of a second! */
306 timeout = 0;
307 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200309 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 }
311 while ((!(temp & 0x80))
312 && (timeout++ < MAX_TIMEOUT));
313
314 /* If the SMBus is still busy, we give up */
315 if (timeout >= MAX_TIMEOUT) {
316 result = -1;
317 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
318 }
319
320 if (temp & 0x10) {
321 result = -1;
322 dev_dbg(&I801_dev->dev,
323 "Error: Failed bus transaction\n");
324 } else if (temp & 0x08) {
325 result = -1;
326 dev_err(&I801_dev->dev, "Bus collision!\n");
327 } else if (temp & 0x04) {
328 result = -1;
329 dev_dbg(&I801_dev->dev, "Error: no response!\n");
330 }
331
332 if (i == 1 && read_write == I2C_SMBUS_READ) {
333 len = inb_p(SMBHSTDAT0);
334 if (len < 1)
335 len = 1;
336 if (len > 32)
337 len = 32;
338 data->block[0] = len;
339 }
340
341 /* Retrieve/store value in SMBBLKDAT */
342 if (read_write == I2C_SMBUS_READ)
343 data->block[i] = inb_p(SMBBLKDAT);
344 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
345 outb_p(data->block[i+1], SMBBLKDAT);
346 if ((temp & 0x9e) != 0x00)
347 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
348
349 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
350 dev_dbg(&I801_dev->dev,
351 "Bad status (%02x) at end of transaction\n",
352 temp);
353 }
354 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
355 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
356 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
357 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
358
359 if (result < 0)
360 goto END;
361 }
362
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200363 if (hwpec) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 /* wait for INTR bit as advised by Intel */
365 timeout = 0;
366 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200368 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 } while ((!(temp & 0x02))
370 && (timeout++ < MAX_TIMEOUT));
371
372 if (timeout >= MAX_TIMEOUT) {
373 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
374 }
375 outb_p(temp, SMBHSTSTS);
376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 result = 0;
378END:
379 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
380 /* restore saved configuration register value */
381 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
382 }
383 return result;
384}
385
386/* Return -1 on error. */
387static s32 i801_access(struct i2c_adapter * adap, u16 addr,
388 unsigned short flags, char read_write, u8 command,
389 int size, union i2c_smbus_data * data)
390{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200391 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 int block = 0;
393 int ret, xact = 0;
394
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200395 hwpec = isich4 && (flags & I2C_CLIENT_PEC)
396 && size != I2C_SMBUS_QUICK
397 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
399 switch (size) {
400 case I2C_SMBUS_QUICK:
401 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
402 SMBHSTADD);
403 xact = I801_QUICK;
404 break;
405 case I2C_SMBUS_BYTE:
406 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
407 SMBHSTADD);
408 if (read_write == I2C_SMBUS_WRITE)
409 outb_p(command, SMBHSTCMD);
410 xact = I801_BYTE;
411 break;
412 case I2C_SMBUS_BYTE_DATA:
413 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
414 SMBHSTADD);
415 outb_p(command, SMBHSTCMD);
416 if (read_write == I2C_SMBUS_WRITE)
417 outb_p(data->byte, SMBHSTDAT0);
418 xact = I801_BYTE_DATA;
419 break;
420 case I2C_SMBUS_WORD_DATA:
421 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
422 SMBHSTADD);
423 outb_p(command, SMBHSTCMD);
424 if (read_write == I2C_SMBUS_WRITE) {
425 outb_p(data->word & 0xff, SMBHSTDAT0);
426 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
427 }
428 xact = I801_WORD_DATA;
429 break;
430 case I2C_SMBUS_BLOCK_DATA:
431 case I2C_SMBUS_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
433 SMBHSTADD);
434 outb_p(command, SMBHSTCMD);
435 block = 1;
436 break;
437 case I2C_SMBUS_PROC_CALL:
438 default:
439 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
440 return -1;
441 }
442
Mark M. Hoffman2e3e13f2005-11-06 23:04:51 +0100443 outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200444
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200446 ret = i801_block_transaction(data, read_write, size, hwpec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 else {
448 outb_p(xact | ENABLE_INT9, SMBHSTCNT);
449 ret = i801_transaction();
450 }
451
Jean Delvarec79cfba2006-04-20 02:43:18 -0700452 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
453 time, so we forcibly disable it after every transaction. */
454 if (hwpec)
455 outb_p(0, SMBAUXCTL);
456
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 if(block)
458 return ret;
459 if(ret)
460 return -1;
461 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
462 return 0;
463
464 switch (xact & 0x7f) {
465 case I801_BYTE: /* Result put in SMBHSTDAT0 */
466 case I801_BYTE_DATA:
467 data->byte = inb_p(SMBHSTDAT0);
468 break;
469 case I801_WORD_DATA:
470 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
471 break;
472 }
473 return 0;
474}
475
476
477static u32 i801_func(struct i2c_adapter *adapter)
478{
479 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
480 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
481 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
Jean Delvareb8095542005-10-26 21:25:04 +0200482 | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483}
484
485static struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 .smbus_xfer = i801_access,
487 .functionality = i801_func,
488};
489
490static struct i2c_adapter i801_adapter = {
491 .owner = THIS_MODULE,
492 .class = I2C_CLASS_HWMON,
493 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494};
495
496static struct pci_device_id i801_ids[] = {
497 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
498 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
499 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
500 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
501 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
502 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
503 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
504 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
505 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700506 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800507 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 { 0, }
509};
510
511MODULE_DEVICE_TABLE (pci, i801_ids);
512
513static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
514{
Jean Delvare455f3322006-06-12 21:52:02 +0200515 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Jean Delvare455f3322006-06-12 21:52:02 +0200517 if ((err = i801_setup(dev)))
518 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
520 /* set up the driverfs linkage to our parent device */
521 i801_adapter.dev.parent = &dev->dev;
522
523 snprintf(i801_adapter.name, I2C_NAME_SIZE,
524 "SMBus I801 adapter at %04x", i801_smba);
525 return i2c_add_adapter(&i801_adapter);
526}
527
528static void __devexit i801_remove(struct pci_dev *dev)
529{
530 i2c_del_adapter(&i801_adapter);
531 release_region(i801_smba, (isich4 ? 16 : 8));
532}
533
534static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 .name = "i801_smbus",
536 .id_table = i801_ids,
537 .probe = i801_probe,
538 .remove = __devexit_p(i801_remove),
539};
540
541static int __init i2c_i801_init(void)
542{
543 return pci_register_driver(&i801_driver);
544}
545
546static void __exit i2c_i801_exit(void)
547{
548 pci_unregister_driver(&i801_driver);
549}
550
551MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
552 "Philip Edelbrock <phil@netroedge.com>, "
553 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
554MODULE_DESCRIPTION("I801 SMBus driver");
555MODULE_LICENSE("GPL");
556
557module_init(i2c_i801_init);
558module_exit(i2c_i801_exit);