[PATCH] i2c-i801: I2C patch for Intel ESB2
[linux-2.6-block.git] / drivers / i2c / busses / i2c-i801.c
CommitLineData
1da177e4
LT
1/*
2 i801.c - Part of lm_sensors, Linux kernel modules for hardware
3 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
b0a70b57 34 ESB2 269B
1da177e4
LT
35 This driver supports several versions of Intel's I/O Controller Hubs (ICH).
36 For SMBus support, they are similar to the PIIX4 and are part
37 of Intel's '810' and other chipsets.
38 See the doc/busses/i2c-i801 file for details.
39 I2C Block Read and Process Call are not supported.
40*/
41
42/* Note: we assume there can only be one I801, with one SMBus interface */
43
44#include <linux/config.h>
45#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
56#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
57#define HAVE_PEC
58#endif
59
60/* I801 SMBus address offsets */
61#define SMBHSTSTS (0 + i801_smba)
62#define SMBHSTCNT (2 + i801_smba)
63#define SMBHSTCMD (3 + i801_smba)
64#define SMBHSTADD (4 + i801_smba)
65#define SMBHSTDAT0 (5 + i801_smba)
66#define SMBHSTDAT1 (6 + i801_smba)
67#define SMBBLKDAT (7 + i801_smba)
68#define SMBPEC (8 + i801_smba) /* ICH4 only */
69#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */
70#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */
71
72/* PCI Address Constants */
73#define SMBBA 0x020
74#define SMBHSTCFG 0x040
75#define SMBREV 0x008
76
77/* Host configuration bits for SMBHSTCFG */
78#define SMBHSTCFG_HST_EN 1
79#define SMBHSTCFG_SMB_SMI_EN 2
80#define SMBHSTCFG_I2C_EN 4
81
82/* Other settings */
83#define MAX_TIMEOUT 100
84#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
85
86/* I801 command constants */
87#define I801_QUICK 0x00
88#define I801_BYTE 0x04
89#define I801_BYTE_DATA 0x08
90#define I801_WORD_DATA 0x0C
91#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
92#define I801_BLOCK_DATA 0x14
93#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
94#define I801_BLOCK_LAST 0x34
95#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
96#define I801_START 0x40
97#define I801_PEC_EN 0x80 /* ICH4 only */
98
99/* insmod parameters */
100
101/* If force_addr is set to anything different from 0, we forcibly enable
102 the I801 at the given address. VERY DANGEROUS! */
103static u16 force_addr;
104module_param(force_addr, ushort, 0);
105MODULE_PARM_DESC(force_addr,
106 "Forcibly enable the I801 at the given address. "
107 "EXTREMELY DANGEROUS!");
108
109static int i801_transaction(void);
110static int i801_block_transaction(union i2c_smbus_data *data,
111 char read_write, int command);
112
113static unsigned short i801_smba;
114static struct pci_dev *I801_dev;
115static int isich4;
116
117static int i801_setup(struct pci_dev *dev)
118{
119 int error_return = 0;
120 unsigned char temp;
121
122 /* Note: we keep on searching until we have found 'function 3' */
123 if(PCI_FUNC(dev->devfn) != 3)
124 return -ENODEV;
125
126 I801_dev = dev;
127 if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
128 (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
129 (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
130 isich4 = 1;
131 else
132 isich4 = 0;
133
134 /* Determine the address of the SMBus areas */
135 if (force_addr) {
136 i801_smba = force_addr & 0xfff0;
137 } else {
138 pci_read_config_word(I801_dev, SMBBA, &i801_smba);
139 i801_smba &= 0xfff0;
140 if(i801_smba == 0) {
141 dev_err(&dev->dev, "SMB base address uninitialized"
142 "- upgrade BIOS or use force_addr=0xaddr\n");
143 return -ENODEV;
144 }
145 }
146
147 if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
148 dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
149 i801_smba);
150 error_return = -EBUSY;
151 goto END;
152 }
153
154 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
155 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
156 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
157
158 /* If force_addr is set, we program the new address here. Just to make
159 sure, we disable the device first. */
160 if (force_addr) {
161 pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
162 pci_write_config_word(I801_dev, SMBBA, i801_smba);
163 pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
164 dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to "
165 "new address %04x!\n", i801_smba);
166 } else if ((temp & 1) == 0) {
167 pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
168 dev_warn(&dev->dev, "enabling SMBus device\n");
169 }
170
171 if (temp & 0x02)
172 dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n");
173 else
174 dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n");
175
176 pci_read_config_byte(I801_dev, SMBREV, &temp);
177 dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp);
178 dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba);
179
180END:
181 return error_return;
182}
183
184static int i801_transaction(void)
185{
186 int temp;
187 int result = 0;
188 int timeout = 0;
189
190 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x,"
191 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
192 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
193 inb_p(SMBHSTDAT1));
194
195 /* Make sure the SMBus host is ready to start transmitting */
196 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
197 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
198 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting... \n",
199 temp);
200 outb_p(temp, SMBHSTSTS);
201 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
202 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
203 return -1;
204 } else {
205 dev_dbg(&I801_dev->dev, "Successfull!\n");
206 }
207 }
208
209 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
210
211 /* We will always wait for a fraction of a second! */
212 do {
213 msleep(1);
214 temp = inb_p(SMBHSTSTS);
215 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
216
217 /* If the SMBus is still busy, we give up */
218 if (timeout >= MAX_TIMEOUT) {
219 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
220 result = -1;
221 }
222
223 if (temp & 0x10) {
224 result = -1;
225 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
226 }
227
228 if (temp & 0x08) {
229 result = -1;
230 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
231 "until next hard reset. (sorry!)\n");
232 /* Clock stops and slave is stuck in mid-transmission */
233 }
234
235 if (temp & 0x04) {
236 result = -1;
237 dev_dbg(&I801_dev->dev, "Error: no response!\n");
238 }
239
240 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
241 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
242
243 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
244 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction"
245 "(%02x)\n", temp);
246 }
247 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
248 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
249 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
250 inb_p(SMBHSTDAT1));
251 return result;
252}
253
254/* All-inclusive block transaction function */
255static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
256 int command)
257{
258 int i, len;
259 int smbcmd;
260 int temp;
261 int result = 0;
262 int timeout;
263 unsigned char hostc, errmask;
264
265 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
266 if (read_write == I2C_SMBUS_WRITE) {
267 /* set I2C_EN bit in configuration register */
268 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
269 pci_write_config_byte(I801_dev, SMBHSTCFG,
270 hostc | SMBHSTCFG_I2C_EN);
271 } else {
272 dev_err(&I801_dev->dev,
273 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
274 return -1;
275 }
276 }
277
278 if (read_write == I2C_SMBUS_WRITE) {
279 len = data->block[0];
280 if (len < 1)
281 len = 1;
282 if (len > 32)
283 len = 32;
284 outb_p(len, SMBHSTDAT0);
285 outb_p(data->block[1], SMBBLKDAT);
286 } else {
287 len = 32; /* max for reads */
288 }
289
290 if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
291 /* set 32 byte buffer */
292 }
293
294 for (i = 1; i <= len; i++) {
295 if (i == len && read_write == I2C_SMBUS_READ)
296 smbcmd = I801_BLOCK_LAST;
297 else
298 smbcmd = I801_BLOCK_DATA;
299 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
300
301 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
302 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
303 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
304 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
305
306 /* Make sure the SMBus host is ready to start transmitting */
307 temp = inb_p(SMBHSTSTS);
308 if (i == 1) {
309 /* Erronenous conditions before transaction:
310 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
311 errmask=0x9f;
312 } else {
313 /* Erronenous conditions during transaction:
314 * Failed, Bus_Err, Dev_Err, Intr */
315 errmask=0x1e;
316 }
317 if (temp & errmask) {
318 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
319 "Resetting... \n", temp);
320 outb_p(temp, SMBHSTSTS);
321 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
322 dev_err(&I801_dev->dev,
323 "Reset failed! (%02x)\n", temp);
324 result = -1;
325 goto END;
326 }
327 if (i != 1) {
328 /* if die in middle of block transaction, fail */
329 result = -1;
330 goto END;
331 }
332 }
333
334 if (i == 1)
335 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
336
337 /* We will always wait for a fraction of a second! */
338 timeout = 0;
339 do {
340 temp = inb_p(SMBHSTSTS);
341 msleep(1);
342 }
343 while ((!(temp & 0x80))
344 && (timeout++ < MAX_TIMEOUT));
345
346 /* If the SMBus is still busy, we give up */
347 if (timeout >= MAX_TIMEOUT) {
348 result = -1;
349 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
350 }
351
352 if (temp & 0x10) {
353 result = -1;
354 dev_dbg(&I801_dev->dev,
355 "Error: Failed bus transaction\n");
356 } else if (temp & 0x08) {
357 result = -1;
358 dev_err(&I801_dev->dev, "Bus collision!\n");
359 } else if (temp & 0x04) {
360 result = -1;
361 dev_dbg(&I801_dev->dev, "Error: no response!\n");
362 }
363
364 if (i == 1 && read_write == I2C_SMBUS_READ) {
365 len = inb_p(SMBHSTDAT0);
366 if (len < 1)
367 len = 1;
368 if (len > 32)
369 len = 32;
370 data->block[0] = len;
371 }
372
373 /* Retrieve/store value in SMBBLKDAT */
374 if (read_write == I2C_SMBUS_READ)
375 data->block[i] = inb_p(SMBBLKDAT);
376 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
377 outb_p(data->block[i+1], SMBBLKDAT);
378 if ((temp & 0x9e) != 0x00)
379 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
380
381 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
382 dev_dbg(&I801_dev->dev,
383 "Bad status (%02x) at end of transaction\n",
384 temp);
385 }
386 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
387 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
388 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
389 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
390
391 if (result < 0)
392 goto END;
393 }
394
395#ifdef HAVE_PEC
396 if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
397 /* wait for INTR bit as advised by Intel */
398 timeout = 0;
399 do {
400 temp = inb_p(SMBHSTSTS);
401 msleep(1);
402 } while ((!(temp & 0x02))
403 && (timeout++ < MAX_TIMEOUT));
404
405 if (timeout >= MAX_TIMEOUT) {
406 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
407 }
408 outb_p(temp, SMBHSTSTS);
409 }
410#endif
411 result = 0;
412END:
413 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
414 /* restore saved configuration register value */
415 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
416 }
417 return result;
418}
419
420/* Return -1 on error. */
421static s32 i801_access(struct i2c_adapter * adap, u16 addr,
422 unsigned short flags, char read_write, u8 command,
423 int size, union i2c_smbus_data * data)
424{
425 int hwpec = 0;
426 int block = 0;
427 int ret, xact = 0;
428
429#ifdef HAVE_PEC
430 if(isich4)
431 hwpec = (flags & I2C_CLIENT_PEC) != 0;
432#endif
433
434 switch (size) {
435 case I2C_SMBUS_QUICK:
436 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
437 SMBHSTADD);
438 xact = I801_QUICK;
439 break;
440 case I2C_SMBUS_BYTE:
441 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
442 SMBHSTADD);
443 if (read_write == I2C_SMBUS_WRITE)
444 outb_p(command, SMBHSTCMD);
445 xact = I801_BYTE;
446 break;
447 case I2C_SMBUS_BYTE_DATA:
448 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
449 SMBHSTADD);
450 outb_p(command, SMBHSTCMD);
451 if (read_write == I2C_SMBUS_WRITE)
452 outb_p(data->byte, SMBHSTDAT0);
453 xact = I801_BYTE_DATA;
454 break;
455 case I2C_SMBUS_WORD_DATA:
456 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
457 SMBHSTADD);
458 outb_p(command, SMBHSTCMD);
459 if (read_write == I2C_SMBUS_WRITE) {
460 outb_p(data->word & 0xff, SMBHSTDAT0);
461 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
462 }
463 xact = I801_WORD_DATA;
464 break;
465 case I2C_SMBUS_BLOCK_DATA:
466 case I2C_SMBUS_I2C_BLOCK_DATA:
467#ifdef HAVE_PEC
468 case I2C_SMBUS_BLOCK_DATA_PEC:
469 if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
470 size = I2C_SMBUS_BLOCK_DATA_PEC;
471#endif
472 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
473 SMBHSTADD);
474 outb_p(command, SMBHSTCMD);
475 block = 1;
476 break;
477 case I2C_SMBUS_PROC_CALL:
478 default:
479 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
480 return -1;
481 }
482
483#ifdef HAVE_PEC
484 if(isich4 && hwpec) {
485 if(size != I2C_SMBUS_QUICK &&
486 size != I2C_SMBUS_I2C_BLOCK_DATA)
487 outb_p(1, SMBAUXCTL); /* enable HW PEC */
488 }
489#endif
490 if(block)
491 ret = i801_block_transaction(data, read_write, size);
492 else {
493 outb_p(xact | ENABLE_INT9, SMBHSTCNT);
494 ret = i801_transaction();
495 }
496
497#ifdef HAVE_PEC
498 if(isich4 && hwpec) {
499 if(size != I2C_SMBUS_QUICK &&
500 size != I2C_SMBUS_I2C_BLOCK_DATA)
501 outb_p(0, SMBAUXCTL);
502 }
503#endif
504
505 if(block)
506 return ret;
507 if(ret)
508 return -1;
509 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
510 return 0;
511
512 switch (xact & 0x7f) {
513 case I801_BYTE: /* Result put in SMBHSTDAT0 */
514 case I801_BYTE_DATA:
515 data->byte = inb_p(SMBHSTDAT0);
516 break;
517 case I801_WORD_DATA:
518 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
519 break;
520 }
521 return 0;
522}
523
524
525static u32 i801_func(struct i2c_adapter *adapter)
526{
527 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
528 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
529 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
530#ifdef HAVE_PEC
531 | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
532 I2C_FUNC_SMBUS_HWPEC_CALC
533 : 0)
534#endif
535 ;
536}
537
538static struct i2c_algorithm smbus_algorithm = {
539 .name = "Non-I2C SMBus adapter",
540 .id = I2C_ALGO_SMBUS,
541 .smbus_xfer = i801_access,
542 .functionality = i801_func,
543};
544
545static struct i2c_adapter i801_adapter = {
546 .owner = THIS_MODULE,
547 .class = I2C_CLASS_HWMON,
548 .algo = &smbus_algorithm,
549 .name = "unset",
550};
551
552static struct pci_device_id i801_ids[] = {
553 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
554 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
555 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
556 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
557 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
558 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
559 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
560 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
561 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
b0a70b57 562 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
1da177e4
LT
563 { 0, }
564};
565
566MODULE_DEVICE_TABLE (pci, i801_ids);
567
568static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
569{
570
571 if (i801_setup(dev)) {
572 dev_warn(&dev->dev,
573 "I801 not detected, module not inserted.\n");
574 return -ENODEV;
575 }
576
577 /* set up the driverfs linkage to our parent device */
578 i801_adapter.dev.parent = &dev->dev;
579
580 snprintf(i801_adapter.name, I2C_NAME_SIZE,
581 "SMBus I801 adapter at %04x", i801_smba);
582 return i2c_add_adapter(&i801_adapter);
583}
584
585static void __devexit i801_remove(struct pci_dev *dev)
586{
587 i2c_del_adapter(&i801_adapter);
588 release_region(i801_smba, (isich4 ? 16 : 8));
589}
590
591static struct pci_driver i801_driver = {
592 .name = "i801_smbus",
593 .id_table = i801_ids,
594 .probe = i801_probe,
595 .remove = __devexit_p(i801_remove),
596};
597
598static int __init i2c_i801_init(void)
599{
600 return pci_register_driver(&i801_driver);
601}
602
603static void __exit i2c_i801_exit(void)
604{
605 pci_unregister_driver(&i801_driver);
606}
607
608MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
609 "Philip Edelbrock <phil@netroedge.com>, "
610 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
611MODULE_DESCRIPTION("I801 SMBus driver");
612MODULE_LICENSE("GPL");
613
614module_init(i2c_i801_init);
615module_exit(i2c_i801_exit);