blob: c31699d8df3a6d3f97c0e4085f93987af934ea56 [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/*
Jean Delvareae7b0492008-01-27 18:14:49 +010024 Supports the following Intel I/O Controller Hubs (ICH):
25
26 I/O Block I2C
27 region SMBus Block proc. block
28 Chip name PCI ID size PEC buffer call read
29 ----------------------------------------------------------------------
30 82801AA (ICH) 0x2413 16 no no no no
31 82801AB (ICH0) 0x2423 16 no no no no
32 82801BA (ICH2) 0x2443 16 no no no no
33 82801CA (ICH3) 0x2483 32 soft no no no
34 82801DB (ICH4) 0x24c3 32 hard yes no no
35 82801E (ICH5) 0x24d3 32 hard yes yes yes
36 6300ESB 0x25a4 32 hard yes yes yes
37 82801F (ICH6) 0x266a 32 hard yes yes yes
38 6310ESB/6320ESB 0x269b 32 hard yes yes yes
39 82801G (ICH7) 0x27da 32 hard yes yes yes
40 82801H (ICH8) 0x283e 32 hard yes yes yes
41 82801I (ICH9) 0x2930 32 hard yes yes yes
42 Tolapai 0x5032 32 hard yes ? ?
43
44 Features supported by this driver:
45 Software PEC no
46 Hardware PEC yes
47 Block buffer yes
48 Block process call transaction no
49 I2C block read transaction no
50
51 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070052*/
53
54/* Note: we assume there can only be one I801, with one SMBus interface */
55
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#include <linux/module.h>
57#include <linux/pci.h>
58#include <linux/kernel.h>
59#include <linux/stddef.h>
60#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/ioport.h>
62#include <linux/init.h>
63#include <linux/i2c.h>
64#include <asm/io.h>
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066/* I801 SMBus address offsets */
67#define SMBHSTSTS (0 + i801_smba)
68#define SMBHSTCNT (2 + i801_smba)
69#define SMBHSTCMD (3 + i801_smba)
70#define SMBHSTADD (4 + i801_smba)
71#define SMBHSTDAT0 (5 + i801_smba)
72#define SMBHSTDAT1 (6 + i801_smba)
73#define SMBBLKDAT (7 + i801_smba)
Jean Delvareae7b0492008-01-27 18:14:49 +010074#define SMBPEC (8 + i801_smba) /* ICH3 and later */
75#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */
76#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78/* PCI Address Constants */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020079#define SMBBAR 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
82/* Host configuration bits for SMBHSTCFG */
83#define SMBHSTCFG_HST_EN 1
84#define SMBHSTCFG_SMB_SMI_EN 2
85#define SMBHSTCFG_I2C_EN 4
86
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +020087/* Auxillary control register bits, ICH4+ only */
88#define SMBAUXCTL_CRC 1
89#define SMBAUXCTL_E32B 2
90
91/* kill bit for SMBHSTCNT */
92#define SMBHSTCNT_KILL 2
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094/* Other settings */
95#define MAX_TIMEOUT 100
96#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
97
98/* I801 command constants */
99#define I801_QUICK 0x00
100#define I801_BYTE 0x04
101#define I801_BYTE_DATA 0x08
102#define I801_WORD_DATA 0x0C
Jean Delvareae7b0492008-01-27 18:14:49 +0100103#define I801_PROC_CALL 0x10 /* unimplemented */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104#define I801_BLOCK_DATA 0x14
105#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
106#define I801_BLOCK_LAST 0x34
107#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
108#define I801_START 0x40
Jean Delvareae7b0492008-01-27 18:14:49 +0100109#define I801_PEC_EN 0x80 /* ICH3 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200111/* I801 Hosts Status register bits */
112#define SMBHSTSTS_BYTE_DONE 0x80
113#define SMBHSTSTS_INUSE_STS 0x40
114#define SMBHSTSTS_SMBALERT_STS 0x20
115#define SMBHSTSTS_FAILED 0x10
116#define SMBHSTSTS_BUS_ERR 0x08
117#define SMBHSTSTS_DEV_ERR 0x04
118#define SMBHSTSTS_INTR 0x02
119#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200121static unsigned long i801_smba;
Jean Delvarea5aaea32007-03-22 19:49:01 +0100122static unsigned char i801_original_hstcfg;
Jean Delvared6072f82005-09-25 16:37:04 +0200123static struct pci_driver i801_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124static struct pci_dev *I801_dev;
Jean Delvare369f6f42008-01-27 18:14:50 +0100125
126#define FEATURE_SMBUS_PEC (1 << 0)
127#define FEATURE_BLOCK_BUFFER (1 << 1)
128#define FEATURE_BLOCK_PROC (1 << 2)
129#define FEATURE_I2C_BLOCK_READ (1 << 3)
130static unsigned int i801_features;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200132static int i801_transaction(int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
134 int temp;
135 int result = 0;
136 int timeout = 0;
137
Jean Delvare368609c2005-07-29 12:15:07 -0700138 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
140 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
141 inb_p(SMBHSTDAT1));
142
143 /* Make sure the SMBus host is ready to start transmitting */
144 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
145 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200146 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 temp);
148 outb_p(temp, SMBHSTSTS);
149 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
150 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
151 return -1;
152 } else {
Jean Delvarefcdd96e2007-02-13 22:08:59 +0100153 dev_dbg(&I801_dev->dev, "Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 }
155 }
156
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200157 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
158 * INTREN, SMBSCMD are passed in xact */
159 outb_p(xact | I801_START, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
161 /* We will always wait for a fraction of a second! */
162 do {
163 msleep(1);
164 temp = inb_p(SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200165 } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167 /* If the SMBus is still busy, we give up */
168 if (timeout >= MAX_TIMEOUT) {
169 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
170 result = -1;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200171 /* try to stop the current command */
172 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
173 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
174 msleep(1);
175 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 }
177
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200178 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 result = -1;
180 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
181 }
182
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200183 if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 result = -1;
185 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
186 "until next hard reset. (sorry!)\n");
187 /* Clock stops and slave is stuck in mid-transmission */
188 }
189
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200190 if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 result = -1;
192 dev_dbg(&I801_dev->dev, "Error: no response!\n");
193 }
194
195 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
196 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
197
198 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700199 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 "(%02x)\n", temp);
201 }
202 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
203 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
204 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
205 inb_p(SMBHSTDAT1));
206 return result;
207}
208
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200209/* wait for INTR bit as advised by Intel */
210static void i801_wait_hwpec(void)
211{
212 int timeout = 0;
213 int temp;
214
215 do {
216 msleep(1);
217 temp = inb_p(SMBHSTSTS);
218 } while ((!(temp & SMBHSTSTS_INTR))
219 && (timeout++ < MAX_TIMEOUT));
220
221 if (timeout >= MAX_TIMEOUT) {
222 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
223 }
224 outb_p(temp, SMBHSTSTS);
225}
226
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200227static int i801_block_transaction_by_block(union i2c_smbus_data *data,
228 char read_write, int hwpec)
229{
230 int i, len;
231
232 inb_p(SMBHSTCNT); /* reset the data buffer index */
233
234 /* Use 32-byte buffer to process this transaction */
235 if (read_write == I2C_SMBUS_WRITE) {
236 len = data->block[0];
237 outb_p(len, SMBHSTDAT0);
238 for (i = 0; i < len; i++)
239 outb_p(data->block[i+1], SMBBLKDAT);
240 }
241
242 if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
243 I801_PEC_EN * hwpec))
244 return -1;
245
246 if (read_write == I2C_SMBUS_READ) {
247 len = inb_p(SMBHSTDAT0);
248 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
249 return -1;
250
251 data->block[0] = len;
252 for (i = 0; i < len; i++)
253 data->block[i + 1] = inb_p(SMBBLKDAT);
254 }
255 return 0;
256}
257
258static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
259 char read_write, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
261 int i, len;
262 int smbcmd;
263 int temp;
264 int result = 0;
265 int timeout;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200266 unsigned char errmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200268 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
270 if (read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 outb_p(len, SMBHSTDAT0);
272 outb_p(data->block[1], SMBBLKDAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
274
275 for (i = 1; i <= len; i++) {
276 if (i == len && read_write == I2C_SMBUS_READ)
277 smbcmd = I801_BLOCK_LAST;
278 else
279 smbcmd = I801_BLOCK_DATA;
280 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
281
282 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
283 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
284 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
285 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
286
287 /* Make sure the SMBus host is ready to start transmitting */
288 temp = inb_p(SMBHSTSTS);
289 if (i == 1) {
Jean Delvare002cf632007-08-14 18:37:13 +0200290 /* Erroneous conditions before transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200292 errmask = 0x9f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 } else {
Jean Delvare002cf632007-08-14 18:37:13 +0200294 /* Erroneous conditions during transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 * Failed, Bus_Err, Dev_Err, Intr */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200296 errmask = 0x1e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 }
298 if (temp & errmask) {
299 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200300 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 outb_p(temp, SMBHSTSTS);
302 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
303 dev_err(&I801_dev->dev,
304 "Reset failed! (%02x)\n", temp);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200305 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 }
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200307 if (i != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 /* if die in middle of block transaction, fail */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200309 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 }
311
312 if (i == 1)
313 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
314
315 /* We will always wait for a fraction of a second! */
316 timeout = 0;
317 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200319 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 }
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200321 while ((!(temp & SMBHSTSTS_BYTE_DONE))
322 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
324 /* If the SMBus is still busy, we give up */
325 if (timeout >= MAX_TIMEOUT) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200326 /* try to stop the current command */
327 dev_dbg(&I801_dev->dev, "Terminating the current "
328 "operation\n");
329 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
330 msleep(1);
331 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
332 SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 result = -1;
334 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
335 }
336
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200337 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 result = -1;
339 dev_dbg(&I801_dev->dev,
340 "Error: Failed bus transaction\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200341 } else if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 result = -1;
343 dev_err(&I801_dev->dev, "Bus collision!\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200344 } else if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 result = -1;
346 dev_dbg(&I801_dev->dev, "Error: no response!\n");
347 }
348
349 if (i == 1 && read_write == I2C_SMBUS_READ) {
350 len = inb_p(SMBHSTDAT0);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200351 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
352 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 data->block[0] = len;
354 }
355
356 /* Retrieve/store value in SMBBLKDAT */
357 if (read_write == I2C_SMBUS_READ)
358 data->block[i] = inb_p(SMBBLKDAT);
359 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
360 outb_p(data->block[i+1], SMBBLKDAT);
361 if ((temp & 0x9e) != 0x00)
362 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
363
364 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
365 dev_dbg(&I801_dev->dev,
366 "Bad status (%02x) at end of transaction\n",
367 temp);
368 }
369 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
370 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
371 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
372 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
373
374 if (result < 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200375 return result;
376 }
377 return result;
378}
379
380static int i801_set_block_buffer_mode(void)
381{
382 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
383 if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
384 return -1;
385 return 0;
386}
387
388/* Block transaction function */
389static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
390 int command, int hwpec)
391{
392 int result = 0;
393 unsigned char hostc;
394
395 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
396 if (read_write == I2C_SMBUS_WRITE) {
397 /* set I2C_EN bit in configuration register */
398 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
399 pci_write_config_byte(I801_dev, SMBHSTCFG,
400 hostc | SMBHSTCFG_I2C_EN);
401 } else {
402 dev_err(&I801_dev->dev,
403 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
404 return -1;
405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 }
407
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200408 if (read_write == I2C_SMBUS_WRITE) {
409 if (data->block[0] < 1)
410 data->block[0] = 1;
411 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
412 data->block[0] = I2C_SMBUS_BLOCK_MAX;
413 } else {
414 data->block[0] = 32; /* max for reads */
415 }
416
Jean Delvare369f6f42008-01-27 18:14:50 +0100417 if ((i801_features & FEATURE_BLOCK_BUFFER)
418 && i801_set_block_buffer_mode() == 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200419 result = i801_block_transaction_by_block(data, read_write,
420 hwpec);
421 else
422 result = i801_block_transaction_byte_by_byte(data, read_write,
423 hwpec);
424
425 if (result == 0 && hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200426 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
429 /* restore saved configuration register value */
430 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
431 }
432 return result;
433}
434
435/* Return -1 on error. */
436static s32 i801_access(struct i2c_adapter * adap, u16 addr,
437 unsigned short flags, char read_write, u8 command,
438 int size, union i2c_smbus_data * data)
439{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200440 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 int block = 0;
442 int ret, xact = 0;
443
Jean Delvare369f6f42008-01-27 18:14:50 +0100444 hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200445 && size != I2C_SMBUS_QUICK
446 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
448 switch (size) {
449 case I2C_SMBUS_QUICK:
450 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
451 SMBHSTADD);
452 xact = I801_QUICK;
453 break;
454 case I2C_SMBUS_BYTE:
455 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
456 SMBHSTADD);
457 if (read_write == I2C_SMBUS_WRITE)
458 outb_p(command, SMBHSTCMD);
459 xact = I801_BYTE;
460 break;
461 case I2C_SMBUS_BYTE_DATA:
462 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
463 SMBHSTADD);
464 outb_p(command, SMBHSTCMD);
465 if (read_write == I2C_SMBUS_WRITE)
466 outb_p(data->byte, SMBHSTDAT0);
467 xact = I801_BYTE_DATA;
468 break;
469 case I2C_SMBUS_WORD_DATA:
470 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
471 SMBHSTADD);
472 outb_p(command, SMBHSTCMD);
473 if (read_write == I2C_SMBUS_WRITE) {
474 outb_p(data->word & 0xff, SMBHSTDAT0);
475 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
476 }
477 xact = I801_WORD_DATA;
478 break;
479 case I2C_SMBUS_BLOCK_DATA:
480 case I2C_SMBUS_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
482 SMBHSTADD);
483 outb_p(command, SMBHSTCMD);
484 block = 1;
485 break;
486 case I2C_SMBUS_PROC_CALL:
487 default:
488 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
489 return -1;
490 }
491
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200492 if (hwpec) /* enable/disable hardware PEC */
493 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
494 else
495 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200498 ret = i801_block_transaction(data, read_write, size, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200499 else
500 ret = i801_transaction(xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Jean Delvarec79cfba2006-04-20 02:43:18 -0700502 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200503 time, so we forcibly disable it after every transaction. Turn off
504 E32B for the same reason. */
Jean Delvarec79cfba2006-04-20 02:43:18 -0700505 if (hwpec)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200506 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
507 SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 if(block)
510 return ret;
511 if(ret)
512 return -1;
513 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
514 return 0;
515
516 switch (xact & 0x7f) {
517 case I801_BYTE: /* Result put in SMBHSTDAT0 */
518 case I801_BYTE_DATA:
519 data->byte = inb_p(SMBHSTDAT0);
520 break;
521 case I801_WORD_DATA:
522 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
523 break;
524 }
525 return 0;
526}
527
528
529static u32 i801_func(struct i2c_adapter *adapter)
530{
531 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Jean Delvare369f6f42008-01-27 18:14:50 +0100532 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
533 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
534 ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535}
536
Jean Delvare8f9082c2006-09-03 22:39:46 +0200537static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 .smbus_xfer = i801_access,
539 .functionality = i801_func,
540};
541
542static struct i2c_adapter i801_adapter = {
543 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100544 .id = I2C_HW_SMBUS_I801,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 .class = I2C_CLASS_HWMON,
546 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547};
548
549static struct pci_device_id i801_ids[] = {
550 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
551 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
552 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
553 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
554 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
555 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
556 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
557 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
558 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700559 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800560 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800561 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Jason Gastone07bc672007-10-13 23:56:31 +0200562 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 { 0, }
564};
565
566MODULE_DEVICE_TABLE (pci, i801_ids);
567
568static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
569{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200570 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200571 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200573 I801_dev = dev;
Jean Delvare369f6f42008-01-27 18:14:50 +0100574 i801_features = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100575 switch (dev->device) {
576 case PCI_DEVICE_ID_INTEL_82801DB_3:
577 case PCI_DEVICE_ID_INTEL_82801EB_3:
578 case PCI_DEVICE_ID_INTEL_ESB_4:
579 case PCI_DEVICE_ID_INTEL_ICH6_16:
580 case PCI_DEVICE_ID_INTEL_ICH7_17:
581 case PCI_DEVICE_ID_INTEL_ESB2_17:
582 case PCI_DEVICE_ID_INTEL_ICH8_5:
583 case PCI_DEVICE_ID_INTEL_ICH9_6:
Jason Gastone07bc672007-10-13 23:56:31 +0200584 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
Jean Delvare369f6f42008-01-27 18:14:50 +0100585 i801_features |= FEATURE_SMBUS_PEC;
586 i801_features |= FEATURE_BLOCK_BUFFER;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100587 break;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100588 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200589
590 err = pci_enable_device(dev);
591 if (err) {
592 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
593 err);
594 goto exit;
595 }
596
597 /* Determine the address of the SMBus area */
598 i801_smba = pci_resource_start(dev, SMBBAR);
599 if (!i801_smba) {
600 dev_err(&dev->dev, "SMBus base address uninitialized, "
601 "upgrade BIOS\n");
602 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200603 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200604 }
605
606 err = pci_request_region(dev, SMBBAR, i801_driver.name);
607 if (err) {
608 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700609 "0x%lx-0x%Lx\n", i801_smba,
610 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200611 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200612 }
613
614 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100615 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200616 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
617 if (!(temp & SMBHSTCFG_HST_EN)) {
618 dev_info(&dev->dev, "Enabling SMBus device\n");
619 temp |= SMBHSTCFG_HST_EN;
620 }
621 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
622
623 if (temp & SMBHSTCFG_SMB_SMI_EN)
624 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
625 else
626 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100628 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 i801_adapter.dev.parent = &dev->dev;
630
David Brownell2096b952007-05-01 23:26:28 +0200631 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200632 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200633 err = i2c_add_adapter(&i801_adapter);
634 if (err) {
635 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200636 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200637 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200638 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200639
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200640exit_release:
641 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200642exit:
643 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644}
645
646static void __devexit i801_remove(struct pci_dev *dev)
647{
648 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100649 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200650 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200651 /*
652 * do not call pci_disable_device(dev) since it can cause hard hangs on
653 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
654 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655}
656
Jean Delvarea5aaea32007-03-22 19:49:01 +0100657#ifdef CONFIG_PM
658static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
659{
660 pci_save_state(dev);
661 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
662 pci_set_power_state(dev, pci_choose_state(dev, mesg));
663 return 0;
664}
665
666static int i801_resume(struct pci_dev *dev)
667{
668 pci_set_power_state(dev, PCI_D0);
669 pci_restore_state(dev);
670 return pci_enable_device(dev);
671}
672#else
673#define i801_suspend NULL
674#define i801_resume NULL
675#endif
676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 .name = "i801_smbus",
679 .id_table = i801_ids,
680 .probe = i801_probe,
681 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100682 .suspend = i801_suspend,
683 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684};
685
686static int __init i2c_i801_init(void)
687{
688 return pci_register_driver(&i801_driver);
689}
690
691static void __exit i2c_i801_exit(void)
692{
693 pci_unregister_driver(&i801_driver);
694}
695
696MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
697 "Philip Edelbrock <phil@netroedge.com>, "
698 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
699MODULE_DESCRIPTION("I801 SMBus driver");
700MODULE_LICENSE("GPL");
701
702module_init(i2c_i801_init);
703module_exit(i2c_i801_exit);