blob: ac27e5f84ebe2ef60aef3fb40427ec7232ef744a [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
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +020029 82801DB 24C3 (HW PEC supported)
30 82801EB 24D3 (HW PEC supported)
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 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
Jason Gastone07bc672007-10-13 23:56:31 +020037 Tolapai 5032
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 This driver supports several versions of Intel's I/O Controller Hubs (ICH).
39 For SMBus support, they are similar to the PIIX4 and are part
40 of Intel's '810' and other chipsets.
Jean Delvare455f3322006-06-12 21:52:02 +020041 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 I2C Block Read and Process Call are not supported.
43*/
44
45/* Note: we assume there can only be one I801, with one SMBus interface */
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/module.h>
48#include <linux/pci.h>
49#include <linux/kernel.h>
50#include <linux/stddef.h>
51#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#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
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +020078/* Auxillary control register bits, ICH4+ only */
79#define SMBAUXCTL_CRC 1
80#define SMBAUXCTL_E32B 2
81
82/* kill bit for SMBHSTCNT */
83#define SMBHSTCNT_KILL 2
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085/* Other settings */
86#define MAX_TIMEOUT 100
87#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
88
89/* I801 command constants */
90#define I801_QUICK 0x00
91#define I801_BYTE 0x04
92#define I801_BYTE_DATA 0x08
93#define I801_WORD_DATA 0x0C
94#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
95#define I801_BLOCK_DATA 0x14
96#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
97#define I801_BLOCK_LAST 0x34
98#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
99#define I801_START 0x40
100#define I801_PEC_EN 0x80 /* ICH4 only */
101
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200102/* I801 Hosts Status register bits */
103#define SMBHSTSTS_BYTE_DONE 0x80
104#define SMBHSTSTS_INUSE_STS 0x40
105#define SMBHSTSTS_SMBALERT_STS 0x20
106#define SMBHSTSTS_FAILED 0x10
107#define SMBHSTSTS_BUS_ERR 0x08
108#define SMBHSTSTS_DEV_ERR 0x04
109#define SMBHSTSTS_INTR 0x02
110#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200112static unsigned long i801_smba;
Jean Delvarea5aaea32007-03-22 19:49:01 +0100113static unsigned char i801_original_hstcfg;
Jean Delvared6072f82005-09-25 16:37:04 +0200114static struct pci_driver i801_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115static struct pci_dev *I801_dev;
116static int isich4;
117
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200118static int i801_transaction(int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119{
120 int temp;
121 int result = 0;
122 int timeout = 0;
123
Jean Delvare368609c2005-07-29 12:15:07 -0700124 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
126 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
127 inb_p(SMBHSTDAT1));
128
129 /* Make sure the SMBus host is ready to start transmitting */
130 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
131 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200132 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 temp);
134 outb_p(temp, SMBHSTSTS);
135 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
136 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
137 return -1;
138 } else {
Jean Delvarefcdd96e2007-02-13 22:08:59 +0100139 dev_dbg(&I801_dev->dev, "Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 }
141 }
142
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200143 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
144 * INTREN, SMBSCMD are passed in xact */
145 outb_p(xact | I801_START, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
147 /* We will always wait for a fraction of a second! */
148 do {
149 msleep(1);
150 temp = inb_p(SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200151 } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
153 /* If the SMBus is still busy, we give up */
154 if (timeout >= MAX_TIMEOUT) {
155 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
156 result = -1;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200157 /* try to stop the current command */
158 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
159 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
160 msleep(1);
161 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 }
163
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200164 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 result = -1;
166 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
167 }
168
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200169 if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 result = -1;
171 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
172 "until next hard reset. (sorry!)\n");
173 /* Clock stops and slave is stuck in mid-transmission */
174 }
175
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200176 if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 result = -1;
178 dev_dbg(&I801_dev->dev, "Error: no response!\n");
179 }
180
181 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
182 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
183
184 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700185 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 "(%02x)\n", temp);
187 }
188 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
189 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
190 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
191 inb_p(SMBHSTDAT1));
192 return result;
193}
194
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200195/* wait for INTR bit as advised by Intel */
196static void i801_wait_hwpec(void)
197{
198 int timeout = 0;
199 int temp;
200
201 do {
202 msleep(1);
203 temp = inb_p(SMBHSTSTS);
204 } while ((!(temp & SMBHSTSTS_INTR))
205 && (timeout++ < MAX_TIMEOUT));
206
207 if (timeout >= MAX_TIMEOUT) {
208 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
209 }
210 outb_p(temp, SMBHSTSTS);
211}
212
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200213static int i801_block_transaction_by_block(union i2c_smbus_data *data,
214 char read_write, int hwpec)
215{
216 int i, len;
217
218 inb_p(SMBHSTCNT); /* reset the data buffer index */
219
220 /* Use 32-byte buffer to process this transaction */
221 if (read_write == I2C_SMBUS_WRITE) {
222 len = data->block[0];
223 outb_p(len, SMBHSTDAT0);
224 for (i = 0; i < len; i++)
225 outb_p(data->block[i+1], SMBBLKDAT);
226 }
227
228 if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
229 I801_PEC_EN * hwpec))
230 return -1;
231
232 if (read_write == I2C_SMBUS_READ) {
233 len = inb_p(SMBHSTDAT0);
234 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
235 return -1;
236
237 data->block[0] = len;
238 for (i = 0; i < len; i++)
239 data->block[i + 1] = inb_p(SMBBLKDAT);
240 }
241 return 0;
242}
243
244static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
245 char read_write, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
247 int i, len;
248 int smbcmd;
249 int temp;
250 int result = 0;
251 int timeout;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200252 unsigned char errmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200254 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
256 if (read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 outb_p(len, SMBHSTDAT0);
258 outb_p(data->block[1], SMBBLKDAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 }
260
261 for (i = 1; i <= len; i++) {
262 if (i == len && read_write == I2C_SMBUS_READ)
263 smbcmd = I801_BLOCK_LAST;
264 else
265 smbcmd = I801_BLOCK_DATA;
266 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
267
268 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
269 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
270 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
271 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
272
273 /* Make sure the SMBus host is ready to start transmitting */
274 temp = inb_p(SMBHSTSTS);
275 if (i == 1) {
Jean Delvare002cf632007-08-14 18:37:13 +0200276 /* Erroneous conditions before transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200278 errmask = 0x9f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 } else {
Jean Delvare002cf632007-08-14 18:37:13 +0200280 /* Erroneous conditions during transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 * Failed, Bus_Err, Dev_Err, Intr */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200282 errmask = 0x1e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 }
284 if (temp & errmask) {
285 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200286 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 outb_p(temp, SMBHSTSTS);
288 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
289 dev_err(&I801_dev->dev,
290 "Reset failed! (%02x)\n", temp);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200291 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 }
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200293 if (i != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 /* if die in middle of block transaction, fail */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200295 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 }
297
298 if (i == 1)
299 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
300
301 /* We will always wait for a fraction of a second! */
302 timeout = 0;
303 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200305 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 }
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200307 while ((!(temp & SMBHSTSTS_BYTE_DONE))
308 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
310 /* If the SMBus is still busy, we give up */
311 if (timeout >= MAX_TIMEOUT) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200312 /* try to stop the current command */
313 dev_dbg(&I801_dev->dev, "Terminating the current "
314 "operation\n");
315 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
316 msleep(1);
317 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
318 SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 result = -1;
320 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
321 }
322
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200323 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 result = -1;
325 dev_dbg(&I801_dev->dev,
326 "Error: Failed bus transaction\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200327 } else if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 result = -1;
329 dev_err(&I801_dev->dev, "Bus collision!\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200330 } else if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 result = -1;
332 dev_dbg(&I801_dev->dev, "Error: no response!\n");
333 }
334
335 if (i == 1 && read_write == I2C_SMBUS_READ) {
336 len = inb_p(SMBHSTDAT0);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200337 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
338 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 data->block[0] = len;
340 }
341
342 /* Retrieve/store value in SMBBLKDAT */
343 if (read_write == I2C_SMBUS_READ)
344 data->block[i] = inb_p(SMBBLKDAT);
345 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
346 outb_p(data->block[i+1], SMBBLKDAT);
347 if ((temp & 0x9e) != 0x00)
348 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
349
350 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
351 dev_dbg(&I801_dev->dev,
352 "Bad status (%02x) at end of transaction\n",
353 temp);
354 }
355 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
356 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
357 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
358 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
359
360 if (result < 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200361 return result;
362 }
363 return result;
364}
365
366static int i801_set_block_buffer_mode(void)
367{
368 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
369 if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
370 return -1;
371 return 0;
372}
373
374/* Block transaction function */
375static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
376 int command, int hwpec)
377{
378 int result = 0;
379 unsigned char hostc;
380
381 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
382 if (read_write == I2C_SMBUS_WRITE) {
383 /* set I2C_EN bit in configuration register */
384 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
385 pci_write_config_byte(I801_dev, SMBHSTCFG,
386 hostc | SMBHSTCFG_I2C_EN);
387 } else {
388 dev_err(&I801_dev->dev,
389 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
390 return -1;
391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 }
393
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200394 if (read_write == I2C_SMBUS_WRITE) {
395 if (data->block[0] < 1)
396 data->block[0] = 1;
397 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
398 data->block[0] = I2C_SMBUS_BLOCK_MAX;
399 } else {
400 data->block[0] = 32; /* max for reads */
401 }
402
403 if (isich4 && i801_set_block_buffer_mode() == 0 )
404 result = i801_block_transaction_by_block(data, read_write,
405 hwpec);
406 else
407 result = i801_block_transaction_byte_by_byte(data, read_write,
408 hwpec);
409
410 if (result == 0 && hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200411 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 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{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200425 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 int block = 0;
427 int ret, xact = 0;
428
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200429 hwpec = isich4 && (flags & I2C_CLIENT_PEC)
430 && size != I2C_SMBUS_QUICK
431 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
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:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
467 SMBHSTADD);
468 outb_p(command, SMBHSTCMD);
469 block = 1;
470 break;
471 case I2C_SMBUS_PROC_CALL:
472 default:
473 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
474 return -1;
475 }
476
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200477 if (hwpec) /* enable/disable hardware PEC */
478 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
479 else
480 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200483 ret = i801_block_transaction(data, read_write, size, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200484 else
485 ret = i801_transaction(xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
Jean Delvarec79cfba2006-04-20 02:43:18 -0700487 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200488 time, so we forcibly disable it after every transaction. Turn off
489 E32B for the same reason. */
Jean Delvarec79cfba2006-04-20 02:43:18 -0700490 if (hwpec)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200491 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
492 SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if(block)
495 return ret;
496 if(ret)
497 return -1;
498 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
499 return 0;
500
501 switch (xact & 0x7f) {
502 case I801_BYTE: /* Result put in SMBHSTDAT0 */
503 case I801_BYTE_DATA:
504 data->byte = inb_p(SMBHSTDAT0);
505 break;
506 case I801_WORD_DATA:
507 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
508 break;
509 }
510 return 0;
511}
512
513
514static u32 i801_func(struct i2c_adapter *adapter)
515{
516 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
517 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
518 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
David Brownell6662cbb2007-10-13 23:56:33 +0200519 | (isich4 ? I2C_FUNC_SMBUS_PEC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520}
521
Jean Delvare8f9082c2006-09-03 22:39:46 +0200522static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 .smbus_xfer = i801_access,
524 .functionality = i801_func,
525};
526
527static struct i2c_adapter i801_adapter = {
528 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100529 .id = I2C_HW_SMBUS_I801,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 .class = I2C_CLASS_HWMON,
531 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532};
533
534static struct pci_device_id i801_ids[] = {
535 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
536 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
537 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
538 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
539 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
540 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
541 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
542 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
543 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700544 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800545 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800546 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Jason Gastone07bc672007-10-13 23:56:31 +0200547 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 { 0, }
549};
550
551MODULE_DEVICE_TABLE (pci, i801_ids);
552
553static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
554{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200555 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200556 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200558 I801_dev = dev;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100559 switch (dev->device) {
560 case PCI_DEVICE_ID_INTEL_82801DB_3:
561 case PCI_DEVICE_ID_INTEL_82801EB_3:
562 case PCI_DEVICE_ID_INTEL_ESB_4:
563 case PCI_DEVICE_ID_INTEL_ICH6_16:
564 case PCI_DEVICE_ID_INTEL_ICH7_17:
565 case PCI_DEVICE_ID_INTEL_ESB2_17:
566 case PCI_DEVICE_ID_INTEL_ICH8_5:
567 case PCI_DEVICE_ID_INTEL_ICH9_6:
Jason Gastone07bc672007-10-13 23:56:31 +0200568 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200569 isich4 = 1;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100570 break;
571 default:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200572 isich4 = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100573 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200574
575 err = pci_enable_device(dev);
576 if (err) {
577 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
578 err);
579 goto exit;
580 }
581
582 /* Determine the address of the SMBus area */
583 i801_smba = pci_resource_start(dev, SMBBAR);
584 if (!i801_smba) {
585 dev_err(&dev->dev, "SMBus base address uninitialized, "
586 "upgrade BIOS\n");
587 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200588 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200589 }
590
591 err = pci_request_region(dev, SMBBAR, i801_driver.name);
592 if (err) {
593 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700594 "0x%lx-0x%Lx\n", i801_smba,
595 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200596 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200597 }
598
599 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100600 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200601 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
602 if (!(temp & SMBHSTCFG_HST_EN)) {
603 dev_info(&dev->dev, "Enabling SMBus device\n");
604 temp |= SMBHSTCFG_HST_EN;
605 }
606 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
607
608 if (temp & SMBHSTCFG_SMB_SMI_EN)
609 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
610 else
611 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100613 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 i801_adapter.dev.parent = &dev->dev;
615
David Brownell2096b952007-05-01 23:26:28 +0200616 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200617 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200618 err = i2c_add_adapter(&i801_adapter);
619 if (err) {
620 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200621 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200622 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200623 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200624
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200625exit_release:
626 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200627exit:
628 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629}
630
631static void __devexit i801_remove(struct pci_dev *dev)
632{
633 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100634 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200635 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200636 /*
637 * do not call pci_disable_device(dev) since it can cause hard hangs on
638 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
639 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640}
641
Jean Delvarea5aaea32007-03-22 19:49:01 +0100642#ifdef CONFIG_PM
643static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
644{
645 pci_save_state(dev);
646 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
647 pci_set_power_state(dev, pci_choose_state(dev, mesg));
648 return 0;
649}
650
651static int i801_resume(struct pci_dev *dev)
652{
653 pci_set_power_state(dev, PCI_D0);
654 pci_restore_state(dev);
655 return pci_enable_device(dev);
656}
657#else
658#define i801_suspend NULL
659#define i801_resume NULL
660#endif
661
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 .name = "i801_smbus",
664 .id_table = i801_ids,
665 .probe = i801_probe,
666 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100667 .suspend = i801_suspend,
668 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669};
670
671static int __init i2c_i801_init(void)
672{
673 return pci_register_driver(&i801_driver);
674}
675
676static void __exit i2c_i801_exit(void)
677{
678 pci_unregister_driver(&i801_driver);
679}
680
681MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
682 "Philip Edelbrock <phil@netroedge.com>, "
683 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
684MODULE_DESCRIPTION("I801 SMBus driver");
685MODULE_LICENSE("GPL");
686
687module_init(i2c_i801_init);
688module_exit(i2c_i801_exit);