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