blob: c7be2fdbd86b617560faa019d65b9f8b1b399053 [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
Jason Gastonadbc2a12006-11-22 15:19:12 -080036 ICH9 2930
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 This driver supports several versions of Intel's I/O Controller Hubs (ICH).
38 For SMBus support, they are similar to the PIIX4 and are part
39 of Intel's '810' and other chipsets.
Jean Delvare455f3322006-06-12 21:52:02 +020040 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 I2C Block Read and Process Call are not supported.
42*/
43
44/* Note: we assume there can only be one I801, with one SMBus interface */
45
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/module.h>
47#include <linux/pci.h>
48#include <linux/kernel.h>
49#include <linux/stddef.h>
50#include <linux/delay.h>
51#include <linux/sched.h>
52#include <linux/ioport.h>
53#include <linux/init.h>
54#include <linux/i2c.h>
55#include <asm/io.h>
56
Linus Torvalds1da177e2005-04-16 15:20:36 -070057/* I801 SMBus address offsets */
58#define SMBHSTSTS (0 + i801_smba)
59#define SMBHSTCNT (2 + i801_smba)
60#define SMBHSTCMD (3 + i801_smba)
61#define SMBHSTADD (4 + i801_smba)
62#define SMBHSTDAT0 (5 + i801_smba)
63#define SMBHSTDAT1 (6 + i801_smba)
64#define SMBBLKDAT (7 + i801_smba)
65#define SMBPEC (8 + i801_smba) /* ICH4 only */
66#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */
67#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */
68
69/* PCI Address Constants */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020070#define SMBBAR 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070071#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
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
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200100static unsigned long 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105static int i801_transaction(void)
106{
107 int temp;
108 int result = 0;
109 int timeout = 0;
110
Jean Delvare368609c2005-07-29 12:15:07 -0700111 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
113 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
114 inb_p(SMBHSTDAT1));
115
116 /* Make sure the SMBus host is ready to start transmitting */
117 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
118 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200119 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 temp);
121 outb_p(temp, SMBHSTSTS);
122 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
123 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
124 return -1;
125 } else {
126 dev_dbg(&I801_dev->dev, "Successfull!\n");
127 }
128 }
129
130 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
131
132 /* We will always wait for a fraction of a second! */
133 do {
134 msleep(1);
135 temp = inb_p(SMBHSTSTS);
136 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
137
138 /* If the SMBus is still busy, we give up */
139 if (timeout >= MAX_TIMEOUT) {
140 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
141 result = -1;
142 }
143
144 if (temp & 0x10) {
145 result = -1;
146 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
147 }
148
149 if (temp & 0x08) {
150 result = -1;
151 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
152 "until next hard reset. (sorry!)\n");
153 /* Clock stops and slave is stuck in mid-transmission */
154 }
155
156 if (temp & 0x04) {
157 result = -1;
158 dev_dbg(&I801_dev->dev, "Error: no response!\n");
159 }
160
161 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
162 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
163
164 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700165 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 "(%02x)\n", temp);
167 }
168 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
169 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
170 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
171 inb_p(SMBHSTDAT1));
172 return result;
173}
174
175/* All-inclusive block transaction function */
176static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
Jean Delvare585b3162005-10-26 21:31:15 +0200177 int command, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178{
179 int i, len;
180 int smbcmd;
181 int temp;
182 int result = 0;
183 int timeout;
184 unsigned char hostc, errmask;
185
186 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
187 if (read_write == I2C_SMBUS_WRITE) {
188 /* set I2C_EN bit in configuration register */
189 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
190 pci_write_config_byte(I801_dev, SMBHSTCFG,
191 hostc | SMBHSTCFG_I2C_EN);
192 } else {
193 dev_err(&I801_dev->dev,
194 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
195 return -1;
196 }
197 }
198
199 if (read_write == I2C_SMBUS_WRITE) {
200 len = data->block[0];
201 if (len < 1)
202 len = 1;
203 if (len > 32)
204 len = 32;
205 outb_p(len, SMBHSTDAT0);
206 outb_p(data->block[1], SMBBLKDAT);
207 } else {
208 len = 32; /* max for reads */
209 }
210
211 if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
212 /* set 32 byte buffer */
213 }
214
215 for (i = 1; i <= len; i++) {
216 if (i == len && read_write == I2C_SMBUS_READ)
217 smbcmd = I801_BLOCK_LAST;
218 else
219 smbcmd = I801_BLOCK_DATA;
220 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
221
222 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
223 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
224 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
225 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
226
227 /* Make sure the SMBus host is ready to start transmitting */
228 temp = inb_p(SMBHSTSTS);
229 if (i == 1) {
230 /* Erronenous conditions before transaction:
231 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
232 errmask=0x9f;
233 } else {
234 /* Erronenous conditions during transaction:
235 * Failed, Bus_Err, Dev_Err, Intr */
236 errmask=0x1e;
237 }
238 if (temp & errmask) {
239 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200240 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 outb_p(temp, SMBHSTSTS);
242 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
243 dev_err(&I801_dev->dev,
244 "Reset failed! (%02x)\n", temp);
245 result = -1;
246 goto END;
247 }
248 if (i != 1) {
249 /* if die in middle of block transaction, fail */
250 result = -1;
251 goto END;
252 }
253 }
254
255 if (i == 1)
256 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
257
258 /* We will always wait for a fraction of a second! */
259 timeout = 0;
260 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200262 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 }
264 while ((!(temp & 0x80))
265 && (timeout++ < MAX_TIMEOUT));
266
267 /* If the SMBus is still busy, we give up */
268 if (timeout >= MAX_TIMEOUT) {
269 result = -1;
270 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
271 }
272
273 if (temp & 0x10) {
274 result = -1;
275 dev_dbg(&I801_dev->dev,
276 "Error: Failed bus transaction\n");
277 } else if (temp & 0x08) {
278 result = -1;
279 dev_err(&I801_dev->dev, "Bus collision!\n");
280 } else if (temp & 0x04) {
281 result = -1;
282 dev_dbg(&I801_dev->dev, "Error: no response!\n");
283 }
284
285 if (i == 1 && read_write == I2C_SMBUS_READ) {
286 len = inb_p(SMBHSTDAT0);
287 if (len < 1)
288 len = 1;
289 if (len > 32)
290 len = 32;
291 data->block[0] = len;
292 }
293
294 /* Retrieve/store value in SMBBLKDAT */
295 if (read_write == I2C_SMBUS_READ)
296 data->block[i] = inb_p(SMBBLKDAT);
297 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
298 outb_p(data->block[i+1], SMBBLKDAT);
299 if ((temp & 0x9e) != 0x00)
300 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
301
302 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
303 dev_dbg(&I801_dev->dev,
304 "Bad status (%02x) at end of transaction\n",
305 temp);
306 }
307 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
308 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
309 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
310 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
311
312 if (result < 0)
313 goto END;
314 }
315
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200316 if (hwpec) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 /* wait for INTR bit as advised by Intel */
318 timeout = 0;
319 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200321 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 } while ((!(temp & 0x02))
323 && (timeout++ < MAX_TIMEOUT));
324
325 if (timeout >= MAX_TIMEOUT) {
326 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
327 }
328 outb_p(temp, SMBHSTSTS);
329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 result = 0;
331END:
332 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
333 /* restore saved configuration register value */
334 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
335 }
336 return result;
337}
338
339/* Return -1 on error. */
340static s32 i801_access(struct i2c_adapter * adap, u16 addr,
341 unsigned short flags, char read_write, u8 command,
342 int size, union i2c_smbus_data * data)
343{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200344 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 int block = 0;
346 int ret, xact = 0;
347
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200348 hwpec = isich4 && (flags & I2C_CLIENT_PEC)
349 && size != I2C_SMBUS_QUICK
350 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
352 switch (size) {
353 case I2C_SMBUS_QUICK:
354 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
355 SMBHSTADD);
356 xact = I801_QUICK;
357 break;
358 case I2C_SMBUS_BYTE:
359 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
360 SMBHSTADD);
361 if (read_write == I2C_SMBUS_WRITE)
362 outb_p(command, SMBHSTCMD);
363 xact = I801_BYTE;
364 break;
365 case I2C_SMBUS_BYTE_DATA:
366 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
367 SMBHSTADD);
368 outb_p(command, SMBHSTCMD);
369 if (read_write == I2C_SMBUS_WRITE)
370 outb_p(data->byte, SMBHSTDAT0);
371 xact = I801_BYTE_DATA;
372 break;
373 case I2C_SMBUS_WORD_DATA:
374 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
375 SMBHSTADD);
376 outb_p(command, SMBHSTCMD);
377 if (read_write == I2C_SMBUS_WRITE) {
378 outb_p(data->word & 0xff, SMBHSTDAT0);
379 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
380 }
381 xact = I801_WORD_DATA;
382 break;
383 case I2C_SMBUS_BLOCK_DATA:
384 case I2C_SMBUS_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
386 SMBHSTADD);
387 outb_p(command, SMBHSTCMD);
388 block = 1;
389 break;
390 case I2C_SMBUS_PROC_CALL:
391 default:
392 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
393 return -1;
394 }
395
Mark M. Hoffman2e3e13f2005-11-06 23:04:51 +0100396 outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200397
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200399 ret = i801_block_transaction(data, read_write, size, hwpec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 else {
401 outb_p(xact | ENABLE_INT9, SMBHSTCNT);
402 ret = i801_transaction();
403 }
404
Jean Delvarec79cfba2006-04-20 02:43:18 -0700405 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
406 time, so we forcibly disable it after every transaction. */
407 if (hwpec)
408 outb_p(0, SMBAUXCTL);
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 if(block)
411 return ret;
412 if(ret)
413 return -1;
414 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
415 return 0;
416
417 switch (xact & 0x7f) {
418 case I801_BYTE: /* Result put in SMBHSTDAT0 */
419 case I801_BYTE_DATA:
420 data->byte = inb_p(SMBHSTDAT0);
421 break;
422 case I801_WORD_DATA:
423 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
424 break;
425 }
426 return 0;
427}
428
429
430static u32 i801_func(struct i2c_adapter *adapter)
431{
432 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
433 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
434 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
Jean Delvareb8095542005-10-26 21:25:04 +0200435 | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
Jean Delvare8f9082c2006-09-03 22:39:46 +0200438static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 .smbus_xfer = i801_access,
440 .functionality = i801_func,
441};
442
443static struct i2c_adapter i801_adapter = {
444 .owner = THIS_MODULE,
445 .class = I2C_CLASS_HWMON,
446 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447};
448
449static struct pci_device_id i801_ids[] = {
450 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
451 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
452 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
453 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
454 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
455 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
456 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
457 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
458 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700459 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800460 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800461 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 { 0, }
463};
464
465MODULE_DEVICE_TABLE (pci, i801_ids);
466
467static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
468{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200469 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200470 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200472 I801_dev = dev;
473 if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
474 (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
475 (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
476 isich4 = 1;
477 else
478 isich4 = 0;
479
480 err = pci_enable_device(dev);
481 if (err) {
482 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
483 err);
484 goto exit;
485 }
486
487 /* Determine the address of the SMBus area */
488 i801_smba = pci_resource_start(dev, SMBBAR);
489 if (!i801_smba) {
490 dev_err(&dev->dev, "SMBus base address uninitialized, "
491 "upgrade BIOS\n");
492 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200493 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200494 }
495
496 err = pci_request_region(dev, SMBBAR, i801_driver.name);
497 if (err) {
498 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700499 "0x%lx-0x%Lx\n", i801_smba,
500 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200501 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200502 }
503
504 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
505 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
506 if (!(temp & SMBHSTCFG_HST_EN)) {
507 dev_info(&dev->dev, "Enabling SMBus device\n");
508 temp |= SMBHSTCFG_HST_EN;
509 }
510 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
511
512 if (temp & SMBHSTCFG_SMB_SMI_EN)
513 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
514 else
515 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
517 /* set up the driverfs linkage to our parent device */
518 i801_adapter.dev.parent = &dev->dev;
519
520 snprintf(i801_adapter.name, I2C_NAME_SIZE,
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200521 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200522 err = i2c_add_adapter(&i801_adapter);
523 if (err) {
524 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200525 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200526 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200527 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200528
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200529exit_release:
530 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200531exit:
532 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533}
534
535static void __devexit i801_remove(struct pci_dev *dev)
536{
537 i2c_del_adapter(&i801_adapter);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200538 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200539 /*
540 * do not call pci_disable_device(dev) since it can cause hard hangs on
541 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
542 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543}
544
545static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 .name = "i801_smbus",
547 .id_table = i801_ids,
548 .probe = i801_probe,
549 .remove = __devexit_p(i801_remove),
550};
551
552static int __init i2c_i801_init(void)
553{
554 return pci_register_driver(&i801_driver);
555}
556
557static void __exit i2c_i801_exit(void)
558{
559 pci_unregister_driver(&i801_driver);
560}
561
562MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
563 "Philip Edelbrock <phil@netroedge.com>, "
564 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
565MODULE_DESCRIPTION("I801 SMBus driver");
566MODULE_LICENSE("GPL");
567
568module_init(i2c_i801_init);
569module_exit(i2c_i801_exit);