blob: 3e0d04d5a800b574579bbd2cecf06c6b24fc66a5 [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 */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020069#define SMBBAR 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
72/* Host configuration bits for SMBHSTCFG */
73#define SMBHSTCFG_HST_EN 1
74#define SMBHSTCFG_SMB_SMI_EN 2
75#define SMBHSTCFG_I2C_EN 4
76
77/* Other settings */
78#define MAX_TIMEOUT 100
79#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
80
81/* I801 command constants */
82#define I801_QUICK 0x00
83#define I801_BYTE 0x04
84#define I801_BYTE_DATA 0x08
85#define I801_WORD_DATA 0x0C
86#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
87#define I801_BLOCK_DATA 0x14
88#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
89#define I801_BLOCK_LAST 0x34
90#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
91#define I801_START 0x40
92#define I801_PEC_EN 0x80 /* ICH4 only */
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95static int i801_transaction(void);
Jean Delvare585b3162005-10-26 21:31:15 +020096static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
97 int command, int hwpec);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Jean Delvare6dcc19d2006-06-12 21:53:02 +020099static unsigned long i801_smba;
Jean Delvared6072f82005-09-25 16:37:04 +0200100static struct pci_driver i801_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101static struct pci_dev *I801_dev;
102static int isich4;
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104static int i801_transaction(void)
105{
106 int temp;
107 int result = 0;
108 int timeout = 0;
109
Jean Delvare368609c2005-07-29 12:15:07 -0700110 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
112 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
113 inb_p(SMBHSTDAT1));
114
115 /* Make sure the SMBus host is ready to start transmitting */
116 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
117 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200118 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 temp);
120 outb_p(temp, SMBHSTSTS);
121 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
122 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
123 return -1;
124 } else {
125 dev_dbg(&I801_dev->dev, "Successfull!\n");
126 }
127 }
128
129 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
130
131 /* We will always wait for a fraction of a second! */
132 do {
133 msleep(1);
134 temp = inb_p(SMBHSTSTS);
135 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
136
137 /* If the SMBus is still busy, we give up */
138 if (timeout >= MAX_TIMEOUT) {
139 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
140 result = -1;
141 }
142
143 if (temp & 0x10) {
144 result = -1;
145 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
146 }
147
148 if (temp & 0x08) {
149 result = -1;
150 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
151 "until next hard reset. (sorry!)\n");
152 /* Clock stops and slave is stuck in mid-transmission */
153 }
154
155 if (temp & 0x04) {
156 result = -1;
157 dev_dbg(&I801_dev->dev, "Error: no response!\n");
158 }
159
160 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
161 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
162
163 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700164 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 "(%02x)\n", temp);
166 }
167 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
168 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
169 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
170 inb_p(SMBHSTDAT1));
171 return result;
172}
173
174/* All-inclusive block transaction function */
175static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
Jean Delvare585b3162005-10-26 21:31:15 +0200176 int command, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177{
178 int i, len;
179 int smbcmd;
180 int temp;
181 int result = 0;
182 int timeout;
183 unsigned char hostc, errmask;
184
185 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
186 if (read_write == I2C_SMBUS_WRITE) {
187 /* set I2C_EN bit in configuration register */
188 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
189 pci_write_config_byte(I801_dev, SMBHSTCFG,
190 hostc | SMBHSTCFG_I2C_EN);
191 } else {
192 dev_err(&I801_dev->dev,
193 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
194 return -1;
195 }
196 }
197
198 if (read_write == I2C_SMBUS_WRITE) {
199 len = data->block[0];
200 if (len < 1)
201 len = 1;
202 if (len > 32)
203 len = 32;
204 outb_p(len, SMBHSTDAT0);
205 outb_p(data->block[1], SMBBLKDAT);
206 } else {
207 len = 32; /* max for reads */
208 }
209
210 if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
211 /* set 32 byte buffer */
212 }
213
214 for (i = 1; i <= len; i++) {
215 if (i == len && read_write == I2C_SMBUS_READ)
216 smbcmd = I801_BLOCK_LAST;
217 else
218 smbcmd = I801_BLOCK_DATA;
219 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
220
221 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
222 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
223 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
224 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
225
226 /* Make sure the SMBus host is ready to start transmitting */
227 temp = inb_p(SMBHSTSTS);
228 if (i == 1) {
229 /* Erronenous conditions before transaction:
230 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
231 errmask=0x9f;
232 } else {
233 /* Erronenous conditions during transaction:
234 * Failed, Bus_Err, Dev_Err, Intr */
235 errmask=0x1e;
236 }
237 if (temp & errmask) {
238 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200239 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 outb_p(temp, SMBHSTSTS);
241 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
242 dev_err(&I801_dev->dev,
243 "Reset failed! (%02x)\n", temp);
244 result = -1;
245 goto END;
246 }
247 if (i != 1) {
248 /* if die in middle of block transaction, fail */
249 result = -1;
250 goto END;
251 }
252 }
253
254 if (i == 1)
255 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
256
257 /* We will always wait for a fraction of a second! */
258 timeout = 0;
259 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200261 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 }
263 while ((!(temp & 0x80))
264 && (timeout++ < MAX_TIMEOUT));
265
266 /* If the SMBus is still busy, we give up */
267 if (timeout >= MAX_TIMEOUT) {
268 result = -1;
269 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
270 }
271
272 if (temp & 0x10) {
273 result = -1;
274 dev_dbg(&I801_dev->dev,
275 "Error: Failed bus transaction\n");
276 } else if (temp & 0x08) {
277 result = -1;
278 dev_err(&I801_dev->dev, "Bus collision!\n");
279 } else if (temp & 0x04) {
280 result = -1;
281 dev_dbg(&I801_dev->dev, "Error: no response!\n");
282 }
283
284 if (i == 1 && read_write == I2C_SMBUS_READ) {
285 len = inb_p(SMBHSTDAT0);
286 if (len < 1)
287 len = 1;
288 if (len > 32)
289 len = 32;
290 data->block[0] = len;
291 }
292
293 /* Retrieve/store value in SMBBLKDAT */
294 if (read_write == I2C_SMBUS_READ)
295 data->block[i] = inb_p(SMBBLKDAT);
296 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
297 outb_p(data->block[i+1], SMBBLKDAT);
298 if ((temp & 0x9e) != 0x00)
299 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
300
301 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
302 dev_dbg(&I801_dev->dev,
303 "Bad status (%02x) at end of transaction\n",
304 temp);
305 }
306 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
307 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
308 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
309 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
310
311 if (result < 0)
312 goto END;
313 }
314
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200315 if (hwpec) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 /* wait for INTR bit as advised by Intel */
317 timeout = 0;
318 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200320 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 } while ((!(temp & 0x02))
322 && (timeout++ < MAX_TIMEOUT));
323
324 if (timeout >= MAX_TIMEOUT) {
325 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
326 }
327 outb_p(temp, SMBHSTSTS);
328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 result = 0;
330END:
331 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
332 /* restore saved configuration register value */
333 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
334 }
335 return result;
336}
337
338/* Return -1 on error. */
339static s32 i801_access(struct i2c_adapter * adap, u16 addr,
340 unsigned short flags, char read_write, u8 command,
341 int size, union i2c_smbus_data * data)
342{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200343 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 int block = 0;
345 int ret, xact = 0;
346
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200347 hwpec = isich4 && (flags & I2C_CLIENT_PEC)
348 && size != I2C_SMBUS_QUICK
349 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351 switch (size) {
352 case I2C_SMBUS_QUICK:
353 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
354 SMBHSTADD);
355 xact = I801_QUICK;
356 break;
357 case I2C_SMBUS_BYTE:
358 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
359 SMBHSTADD);
360 if (read_write == I2C_SMBUS_WRITE)
361 outb_p(command, SMBHSTCMD);
362 xact = I801_BYTE;
363 break;
364 case I2C_SMBUS_BYTE_DATA:
365 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
366 SMBHSTADD);
367 outb_p(command, SMBHSTCMD);
368 if (read_write == I2C_SMBUS_WRITE)
369 outb_p(data->byte, SMBHSTDAT0);
370 xact = I801_BYTE_DATA;
371 break;
372 case I2C_SMBUS_WORD_DATA:
373 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
374 SMBHSTADD);
375 outb_p(command, SMBHSTCMD);
376 if (read_write == I2C_SMBUS_WRITE) {
377 outb_p(data->word & 0xff, SMBHSTDAT0);
378 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
379 }
380 xact = I801_WORD_DATA;
381 break;
382 case I2C_SMBUS_BLOCK_DATA:
383 case I2C_SMBUS_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
385 SMBHSTADD);
386 outb_p(command, SMBHSTCMD);
387 block = 1;
388 break;
389 case I2C_SMBUS_PROC_CALL:
390 default:
391 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
392 return -1;
393 }
394
Mark M. Hoffman2e3e13f2005-11-06 23:04:51 +0100395 outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200396
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200398 ret = i801_block_transaction(data, read_write, size, hwpec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 else {
400 outb_p(xact | ENABLE_INT9, SMBHSTCNT);
401 ret = i801_transaction();
402 }
403
Jean Delvarec79cfba2006-04-20 02:43:18 -0700404 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
405 time, so we forcibly disable it after every transaction. */
406 if (hwpec)
407 outb_p(0, SMBAUXCTL);
408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 if(block)
410 return ret;
411 if(ret)
412 return -1;
413 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
414 return 0;
415
416 switch (xact & 0x7f) {
417 case I801_BYTE: /* Result put in SMBHSTDAT0 */
418 case I801_BYTE_DATA:
419 data->byte = inb_p(SMBHSTDAT0);
420 break;
421 case I801_WORD_DATA:
422 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
423 break;
424 }
425 return 0;
426}
427
428
429static u32 i801_func(struct i2c_adapter *adapter)
430{
431 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
432 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
433 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
Jean Delvareb8095542005-10-26 21:25:04 +0200434 | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435}
436
437static struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 .smbus_xfer = i801_access,
439 .functionality = i801_func,
440};
441
442static struct i2c_adapter i801_adapter = {
443 .owner = THIS_MODULE,
444 .class = I2C_CLASS_HWMON,
445 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446};
447
448static struct pci_device_id i801_ids[] = {
449 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
450 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
451 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
452 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
453 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
454 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
455 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
456 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
457 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700458 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800459 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 { 0, }
461};
462
463MODULE_DEVICE_TABLE (pci, i801_ids);
464
465static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
466{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200467 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200468 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200470 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 }
501
502 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
503 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
504 if (!(temp & SMBHSTCFG_HST_EN)) {
505 dev_info(&dev->dev, "Enabling SMBus device\n");
506 temp |= SMBHSTCFG_HST_EN;
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");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515 /* set up the driverfs linkage to our parent device */
516 i801_adapter.dev.parent = &dev->dev;
517
518 snprintf(i801_adapter.name, I2C_NAME_SIZE,
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200519 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200520 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
526exit_disable:
527 pci_disable_device(dev);
528exit:
529 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530}
531
532static void __devexit i801_remove(struct pci_dev *dev)
533{
534 i2c_del_adapter(&i801_adapter);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200535 pci_release_region(dev, SMBBAR);
536 pci_disable_device(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537}
538
539static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 .name = "i801_smbus",
541 .id_table = i801_ids,
542 .probe = i801_probe,
543 .remove = __devexit_p(i801_remove),
544};
545
546static int __init i2c_i801_init(void)
547{
548 return pci_register_driver(&i801_driver);
549}
550
551static void __exit i2c_i801_exit(void)
552{
553 pci_unregister_driver(&i801_driver);
554}
555
556MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
557 "Philip Edelbrock <phil@netroedge.com>, "
558 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
559MODULE_DESCRIPTION("I801 SMBus driver");
560MODULE_LICENSE("GPL");
561
562module_init(i2c_i801_init);
563module_exit(i2c_i801_exit);