blob: d5e12a4f01b01bcceabb1a1765c896aaf4c1cec4 [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
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +020025 82801AA 2413
26 82801AB 2423
27 82801BA 2443
28 82801CA/CAM 2483
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#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
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +020077/* Auxillary control register bits, ICH4+ only */
78#define SMBAUXCTL_CRC 1
79#define SMBAUXCTL_E32B 2
80
81/* kill bit for SMBHSTCNT */
82#define SMBHSTCNT_KILL 2
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084/* Other settings */
85#define MAX_TIMEOUT 100
86#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
87
88/* I801 command constants */
89#define I801_QUICK 0x00
90#define I801_BYTE 0x04
91#define I801_BYTE_DATA 0x08
92#define I801_WORD_DATA 0x0C
93#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
94#define I801_BLOCK_DATA 0x14
95#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
96#define I801_BLOCK_LAST 0x34
97#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
98#define I801_START 0x40
99#define I801_PEC_EN 0x80 /* ICH4 only */
100
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200101/* I801 Hosts Status register bits */
102#define SMBHSTSTS_BYTE_DONE 0x80
103#define SMBHSTSTS_INUSE_STS 0x40
104#define SMBHSTSTS_SMBALERT_STS 0x20
105#define SMBHSTSTS_FAILED 0x10
106#define SMBHSTSTS_BUS_ERR 0x08
107#define SMBHSTSTS_DEV_ERR 0x04
108#define SMBHSTSTS_INTR 0x02
109#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200111static unsigned long i801_smba;
Jean Delvarea5aaea32007-03-22 19:49:01 +0100112static unsigned char i801_original_hstcfg;
Jean Delvared6072f82005-09-25 16:37:04 +0200113static struct pci_driver i801_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114static struct pci_dev *I801_dev;
115static int isich4;
116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117static int i801_transaction(void)
118{
119 int temp;
120 int result = 0;
121 int timeout = 0;
122
Jean Delvare368609c2005-07-29 12:15:07 -0700123 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
125 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
126 inb_p(SMBHSTDAT1));
127
128 /* Make sure the SMBus host is ready to start transmitting */
129 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
130 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200131 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 temp);
133 outb_p(temp, SMBHSTSTS);
134 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
135 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
136 return -1;
137 } else {
Jean Delvarefcdd96e2007-02-13 22:08:59 +0100138 dev_dbg(&I801_dev->dev, "Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 }
140 }
141
142 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
143
144 /* We will always wait for a fraction of a second! */
145 do {
146 msleep(1);
147 temp = inb_p(SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200148 } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 /* If the SMBus is still busy, we give up */
151 if (timeout >= MAX_TIMEOUT) {
152 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
153 result = -1;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200154 /* try to stop the current command */
155 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
156 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
157 msleep(1);
158 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 }
160
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200161 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 result = -1;
163 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
164 }
165
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200166 if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 result = -1;
168 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
169 "until next hard reset. (sorry!)\n");
170 /* Clock stops and slave is stuck in mid-transmission */
171 }
172
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200173 if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 result = -1;
175 dev_dbg(&I801_dev->dev, "Error: no response!\n");
176 }
177
178 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
179 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
180
181 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700182 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 "(%02x)\n", temp);
184 }
185 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
186 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
187 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
188 inb_p(SMBHSTDAT1));
189 return result;
190}
191
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200192/* wait for INTR bit as advised by Intel */
193static void i801_wait_hwpec(void)
194{
195 int timeout = 0;
196 int temp;
197
198 do {
199 msleep(1);
200 temp = inb_p(SMBHSTSTS);
201 } while ((!(temp & SMBHSTSTS_INTR))
202 && (timeout++ < MAX_TIMEOUT));
203
204 if (timeout >= MAX_TIMEOUT) {
205 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
206 }
207 outb_p(temp, SMBHSTSTS);
208}
209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210/* All-inclusive block transaction function */
211static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
Jean Delvare585b3162005-10-26 21:31:15 +0200212 int command, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213{
214 int i, len;
215 int smbcmd;
216 int temp;
217 int result = 0;
218 int timeout;
219 unsigned char hostc, errmask;
220
221 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
222 if (read_write == I2C_SMBUS_WRITE) {
223 /* set I2C_EN bit in configuration register */
224 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
225 pci_write_config_byte(I801_dev, SMBHSTCFG,
226 hostc | SMBHSTCFG_I2C_EN);
227 } else {
228 dev_err(&I801_dev->dev,
229 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
230 return -1;
231 }
232 }
233
234 if (read_write == I2C_SMBUS_WRITE) {
235 len = data->block[0];
236 if (len < 1)
237 len = 1;
238 if (len > 32)
239 len = 32;
240 outb_p(len, SMBHSTDAT0);
241 outb_p(data->block[1], SMBBLKDAT);
242 } else {
243 len = 32; /* max for reads */
244 }
245
246 if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
247 /* set 32 byte buffer */
248 }
249
250 for (i = 1; i <= len; i++) {
251 if (i == len && read_write == I2C_SMBUS_READ)
252 smbcmd = I801_BLOCK_LAST;
253 else
254 smbcmd = I801_BLOCK_DATA;
255 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
256
257 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
258 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
259 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
260 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
261
262 /* Make sure the SMBus host is ready to start transmitting */
263 temp = inb_p(SMBHSTSTS);
264 if (i == 1) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200265 /* Erronenous conditions before transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200267 errmask = 0x9f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 } else {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200269 /* Erronenous conditions during transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 * Failed, Bus_Err, Dev_Err, Intr */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200271 errmask = 0x1e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 }
273 if (temp & errmask) {
274 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200275 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 outb_p(temp, SMBHSTSTS);
277 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
278 dev_err(&I801_dev->dev,
279 "Reset failed! (%02x)\n", temp);
280 result = -1;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200281 goto END;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
283 if (i != 1) {
284 /* if die in middle of block transaction, fail */
285 result = -1;
286 goto END;
287 }
288 }
289
290 if (i == 1)
291 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
292
293 /* We will always wait for a fraction of a second! */
294 timeout = 0;
295 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200297 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 }
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200299 while ((!(temp & SMBHSTSTS_BYTE_DONE))
300 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
302 /* If the SMBus is still busy, we give up */
303 if (timeout >= MAX_TIMEOUT) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200304 /* try to stop the current command */
305 dev_dbg(&I801_dev->dev, "Terminating the current "
306 "operation\n");
307 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
308 msleep(1);
309 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
310 SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 result = -1;
312 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
313 }
314
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200315 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 result = -1;
317 dev_dbg(&I801_dev->dev,
318 "Error: Failed bus transaction\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200319 } else if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 result = -1;
321 dev_err(&I801_dev->dev, "Bus collision!\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200322 } else if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 result = -1;
324 dev_dbg(&I801_dev->dev, "Error: no response!\n");
325 }
326
327 if (i == 1 && read_write == I2C_SMBUS_READ) {
328 len = inb_p(SMBHSTDAT0);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200329 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
330 result = -1;
331 goto END;
332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 data->block[0] = len;
334 }
335
336 /* Retrieve/store value in SMBBLKDAT */
337 if (read_write == I2C_SMBUS_READ)
338 data->block[i] = inb_p(SMBBLKDAT);
339 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
340 outb_p(data->block[i+1], SMBBLKDAT);
341 if ((temp & 0x9e) != 0x00)
342 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
343
344 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
345 dev_dbg(&I801_dev->dev,
346 "Bad status (%02x) at end of transaction\n",
347 temp);
348 }
349 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
350 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
351 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
352 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
353
354 if (result < 0)
355 goto END;
356 }
357
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200358 if (hwpec)
359 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 result = 0;
362END:
363 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
364 /* restore saved configuration register value */
365 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
366 }
367 return result;
368}
369
370/* Return -1 on error. */
371static s32 i801_access(struct i2c_adapter * adap, u16 addr,
372 unsigned short flags, char read_write, u8 command,
373 int size, union i2c_smbus_data * data)
374{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200375 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 int block = 0;
377 int ret, xact = 0;
378
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200379 hwpec = isich4 && (flags & I2C_CLIENT_PEC)
380 && size != I2C_SMBUS_QUICK
381 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383 switch (size) {
384 case I2C_SMBUS_QUICK:
385 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
386 SMBHSTADD);
387 xact = I801_QUICK;
388 break;
389 case I2C_SMBUS_BYTE:
390 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
391 SMBHSTADD);
392 if (read_write == I2C_SMBUS_WRITE)
393 outb_p(command, SMBHSTCMD);
394 xact = I801_BYTE;
395 break;
396 case I2C_SMBUS_BYTE_DATA:
397 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
398 SMBHSTADD);
399 outb_p(command, SMBHSTCMD);
400 if (read_write == I2C_SMBUS_WRITE)
401 outb_p(data->byte, SMBHSTDAT0);
402 xact = I801_BYTE_DATA;
403 break;
404 case I2C_SMBUS_WORD_DATA:
405 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
406 SMBHSTADD);
407 outb_p(command, SMBHSTCMD);
408 if (read_write == I2C_SMBUS_WRITE) {
409 outb_p(data->word & 0xff, SMBHSTDAT0);
410 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
411 }
412 xact = I801_WORD_DATA;
413 break;
414 case I2C_SMBUS_BLOCK_DATA:
415 case I2C_SMBUS_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
417 SMBHSTADD);
418 outb_p(command, SMBHSTCMD);
419 block = 1;
420 break;
421 case I2C_SMBUS_PROC_CALL:
422 default:
423 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
424 return -1;
425 }
426
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200427 if (hwpec) /* enable/disable hardware PEC */
428 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
429 else
430 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200431
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200433 ret = i801_block_transaction(data, read_write, size, hwpec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 else {
435 outb_p(xact | ENABLE_INT9, SMBHSTCNT);
436 ret = i801_transaction();
437 }
438
Jean Delvarec79cfba2006-04-20 02:43:18 -0700439 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
440 time, so we forcibly disable it after every transaction. */
441 if (hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200442 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700443
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 if(block)
445 return ret;
446 if(ret)
447 return -1;
448 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
449 return 0;
450
451 switch (xact & 0x7f) {
452 case I801_BYTE: /* Result put in SMBHSTDAT0 */
453 case I801_BYTE_DATA:
454 data->byte = inb_p(SMBHSTDAT0);
455 break;
456 case I801_WORD_DATA:
457 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
458 break;
459 }
460 return 0;
461}
462
463
464static u32 i801_func(struct i2c_adapter *adapter)
465{
466 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
467 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
468 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
Jean Delvareb8095542005-10-26 21:25:04 +0200469 | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470}
471
Jean Delvare8f9082c2006-09-03 22:39:46 +0200472static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 .smbus_xfer = i801_access,
474 .functionality = i801_func,
475};
476
477static struct i2c_adapter i801_adapter = {
478 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100479 .id = I2C_HW_SMBUS_I801,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 .class = I2C_CLASS_HWMON,
481 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482};
483
484static struct pci_device_id i801_ids[] = {
485 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
486 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
487 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
488 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
489 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
490 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
491 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
492 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
493 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700494 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800495 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800496 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 { 0, }
498};
499
500MODULE_DEVICE_TABLE (pci, i801_ids);
501
502static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
503{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200504 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200505 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200507 I801_dev = dev;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100508 switch (dev->device) {
509 case PCI_DEVICE_ID_INTEL_82801DB_3:
510 case PCI_DEVICE_ID_INTEL_82801EB_3:
511 case PCI_DEVICE_ID_INTEL_ESB_4:
512 case PCI_DEVICE_ID_INTEL_ICH6_16:
513 case PCI_DEVICE_ID_INTEL_ICH7_17:
514 case PCI_DEVICE_ID_INTEL_ESB2_17:
515 case PCI_DEVICE_ID_INTEL_ICH8_5:
516 case PCI_DEVICE_ID_INTEL_ICH9_6:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200517 isich4 = 1;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100518 break;
519 default:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200520 isich4 = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100521 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200522
523 err = pci_enable_device(dev);
524 if (err) {
525 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
526 err);
527 goto exit;
528 }
529
530 /* Determine the address of the SMBus area */
531 i801_smba = pci_resource_start(dev, SMBBAR);
532 if (!i801_smba) {
533 dev_err(&dev->dev, "SMBus base address uninitialized, "
534 "upgrade BIOS\n");
535 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200536 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200537 }
538
539 err = pci_request_region(dev, SMBBAR, i801_driver.name);
540 if (err) {
541 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700542 "0x%lx-0x%Lx\n", i801_smba,
543 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200544 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200545 }
546
547 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100548 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200549 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
550 if (!(temp & SMBHSTCFG_HST_EN)) {
551 dev_info(&dev->dev, "Enabling SMBus device\n");
552 temp |= SMBHSTCFG_HST_EN;
553 }
554 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
555
556 if (temp & SMBHSTCFG_SMB_SMI_EN)
557 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
558 else
559 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100561 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 i801_adapter.dev.parent = &dev->dev;
563
David Brownell2096b952007-05-01 23:26:28 +0200564 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200565 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200566 err = i2c_add_adapter(&i801_adapter);
567 if (err) {
568 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200569 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200570 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200571 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200572
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200573exit_release:
574 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200575exit:
576 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577}
578
579static void __devexit i801_remove(struct pci_dev *dev)
580{
581 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100582 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200583 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200584 /*
585 * do not call pci_disable_device(dev) since it can cause hard hangs on
586 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
587 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588}
589
Jean Delvarea5aaea32007-03-22 19:49:01 +0100590#ifdef CONFIG_PM
591static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
592{
593 pci_save_state(dev);
594 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
595 pci_set_power_state(dev, pci_choose_state(dev, mesg));
596 return 0;
597}
598
599static int i801_resume(struct pci_dev *dev)
600{
601 pci_set_power_state(dev, PCI_D0);
602 pci_restore_state(dev);
603 return pci_enable_device(dev);
604}
605#else
606#define i801_suspend NULL
607#define i801_resume NULL
608#endif
609
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 .name = "i801_smbus",
612 .id_table = i801_ids,
613 .probe = i801_probe,
614 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100615 .suspend = i801_suspend,
616 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617};
618
619static int __init i2c_i801_init(void)
620{
621 return pci_register_driver(&i801_driver);
622}
623
624static void __exit i2c_i801_exit(void)
625{
626 pci_unregister_driver(&i801_driver);
627}
628
629MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
630 "Philip Edelbrock <phil@netroedge.com>, "
631 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
632MODULE_DESCRIPTION("I801 SMBus driver");
633MODULE_LICENSE("GPL");
634
635module_init(i2c_i801_init);
636module_exit(i2c_i801_exit);