blob: aa9157913b9addd98182a0b5f16cd92cd0b80ea3 [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>
Jean Delvare63420642008-01-27 18:14:50 +01007 Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24/*
Jean Delvareae7b0492008-01-27 18:14:49 +010025 Supports the following Intel I/O Controller Hubs (ICH):
26
27 I/O Block I2C
28 region SMBus Block proc. block
29 Chip name PCI ID size PEC buffer call read
30 ----------------------------------------------------------------------
31 82801AA (ICH) 0x2413 16 no no no no
32 82801AB (ICH0) 0x2423 16 no no no no
33 82801BA (ICH2) 0x2443 16 no no no no
34 82801CA (ICH3) 0x2483 32 soft no no no
35 82801DB (ICH4) 0x24c3 32 hard yes no no
36 82801E (ICH5) 0x24d3 32 hard yes yes yes
37 6300ESB 0x25a4 32 hard yes yes yes
38 82801F (ICH6) 0x266a 32 hard yes yes yes
39 6310ESB/6320ESB 0x269b 32 hard yes yes yes
40 82801G (ICH7) 0x27da 32 hard yes yes yes
41 82801H (ICH8) 0x283e 32 hard yes yes yes
42 82801I (ICH9) 0x2930 32 hard yes yes yes
43 Tolapai 0x5032 32 hard yes ? ?
44
45 Features supported by this driver:
46 Software PEC no
47 Hardware PEC yes
48 Block buffer yes
49 Block process call transaction no
Jean Delvare63420642008-01-27 18:14:50 +010050 I2C block read transaction yes (doesn't use the block buffer)
Jean Delvareae7b0492008-01-27 18:14:49 +010051
52 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070053*/
54
55/* Note: we assume there can only be one I801, with one SMBus interface */
56
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#include <linux/module.h>
58#include <linux/pci.h>
59#include <linux/kernel.h>
60#include <linux/stddef.h>
61#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#include <linux/ioport.h>
63#include <linux/init.h>
64#include <linux/i2c.h>
65#include <asm/io.h>
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067/* I801 SMBus address offsets */
68#define SMBHSTSTS (0 + i801_smba)
69#define SMBHSTCNT (2 + i801_smba)
70#define SMBHSTCMD (3 + i801_smba)
71#define SMBHSTADD (4 + i801_smba)
72#define SMBHSTDAT0 (5 + i801_smba)
73#define SMBHSTDAT1 (6 + i801_smba)
74#define SMBBLKDAT (7 + i801_smba)
Jean Delvareae7b0492008-01-27 18:14:49 +010075#define SMBPEC (8 + i801_smba) /* ICH3 and later */
76#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */
77#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79/* PCI Address Constants */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020080#define SMBBAR 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83/* Host configuration bits for SMBHSTCFG */
84#define SMBHSTCFG_HST_EN 1
85#define SMBHSTCFG_SMB_SMI_EN 2
86#define SMBHSTCFG_I2C_EN 4
87
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +020088/* Auxillary control register bits, ICH4+ only */
89#define SMBAUXCTL_CRC 1
90#define SMBAUXCTL_E32B 2
91
92/* kill bit for SMBHSTCNT */
93#define SMBHSTCNT_KILL 2
94
Linus Torvalds1da177e2005-04-16 15:20:36 -070095/* Other settings */
96#define MAX_TIMEOUT 100
97#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
98
99/* I801 command constants */
100#define I801_QUICK 0x00
101#define I801_BYTE 0x04
102#define I801_BYTE_DATA 0x08
103#define I801_WORD_DATA 0x0C
Jean Delvareae7b0492008-01-27 18:14:49 +0100104#define I801_PROC_CALL 0x10 /* unimplemented */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105#define I801_BLOCK_DATA 0x14
Jean Delvare63420642008-01-27 18:14:50 +0100106#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107#define I801_BLOCK_LAST 0x34
Jean Delvare63420642008-01-27 18:14:50 +0100108#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109#define I801_START 0x40
Jean Delvareae7b0492008-01-27 18:14:49 +0100110#define I801_PEC_EN 0x80 /* ICH3 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200112/* I801 Hosts Status register bits */
113#define SMBHSTSTS_BYTE_DONE 0x80
114#define SMBHSTSTS_INUSE_STS 0x40
115#define SMBHSTSTS_SMBALERT_STS 0x20
116#define SMBHSTSTS_FAILED 0x10
117#define SMBHSTSTS_BUS_ERR 0x08
118#define SMBHSTSTS_DEV_ERR 0x04
119#define SMBHSTSTS_INTR 0x02
120#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200122static unsigned long i801_smba;
Jean Delvarea5aaea32007-03-22 19:49:01 +0100123static unsigned char i801_original_hstcfg;
Jean Delvared6072f82005-09-25 16:37:04 +0200124static struct pci_driver i801_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125static struct pci_dev *I801_dev;
Jean Delvare369f6f42008-01-27 18:14:50 +0100126
127#define FEATURE_SMBUS_PEC (1 << 0)
128#define FEATURE_BLOCK_BUFFER (1 << 1)
129#define FEATURE_BLOCK_PROC (1 << 2)
130#define FEATURE_I2C_BLOCK_READ (1 << 3)
131static unsigned int i801_features;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200133static int i801_transaction(int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134{
135 int temp;
136 int result = 0;
137 int timeout = 0;
138
Jean Delvare368609c2005-07-29 12:15:07 -0700139 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
141 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
142 inb_p(SMBHSTDAT1));
143
144 /* Make sure the SMBus host is ready to start transmitting */
145 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
146 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200147 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 temp);
149 outb_p(temp, SMBHSTSTS);
150 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
151 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
152 return -1;
153 } else {
Jean Delvarefcdd96e2007-02-13 22:08:59 +0100154 dev_dbg(&I801_dev->dev, "Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 }
156 }
157
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200158 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
159 * INTREN, SMBSCMD are passed in xact */
160 outb_p(xact | I801_START, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
162 /* We will always wait for a fraction of a second! */
163 do {
164 msleep(1);
165 temp = inb_p(SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200166 } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
168 /* If the SMBus is still busy, we give up */
169 if (timeout >= MAX_TIMEOUT) {
170 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
171 result = -1;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200172 /* try to stop the current command */
173 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
174 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
175 msleep(1);
176 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 }
178
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200179 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 result = -1;
181 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
182 }
183
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200184 if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 result = -1;
186 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
187 "until next hard reset. (sorry!)\n");
188 /* Clock stops and slave is stuck in mid-transmission */
189 }
190
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200191 if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 result = -1;
193 dev_dbg(&I801_dev->dev, "Error: no response!\n");
194 }
195
196 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
197 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
198
199 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700200 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 "(%02x)\n", temp);
202 }
203 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
204 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
205 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
206 inb_p(SMBHSTDAT1));
207 return result;
208}
209
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200210/* wait for INTR bit as advised by Intel */
211static void i801_wait_hwpec(void)
212{
213 int timeout = 0;
214 int temp;
215
216 do {
217 msleep(1);
218 temp = inb_p(SMBHSTSTS);
219 } while ((!(temp & SMBHSTSTS_INTR))
220 && (timeout++ < MAX_TIMEOUT));
221
222 if (timeout >= MAX_TIMEOUT) {
223 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
224 }
225 outb_p(temp, SMBHSTSTS);
226}
227
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200228static int i801_block_transaction_by_block(union i2c_smbus_data *data,
229 char read_write, int hwpec)
230{
231 int i, len;
232
233 inb_p(SMBHSTCNT); /* reset the data buffer index */
234
235 /* Use 32-byte buffer to process this transaction */
236 if (read_write == I2C_SMBUS_WRITE) {
237 len = data->block[0];
238 outb_p(len, SMBHSTDAT0);
239 for (i = 0; i < len; i++)
240 outb_p(data->block[i+1], SMBBLKDAT);
241 }
242
243 if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
244 I801_PEC_EN * hwpec))
245 return -1;
246
247 if (read_write == I2C_SMBUS_READ) {
248 len = inb_p(SMBHSTDAT0);
249 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
250 return -1;
251
252 data->block[0] = len;
253 for (i = 0; i < len; i++)
254 data->block[i + 1] = inb_p(SMBBLKDAT);
255 }
256 return 0;
257}
258
259static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
Jean Delvare63420642008-01-27 18:14:50 +0100260 char read_write, int command,
261 int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262{
263 int i, len;
264 int smbcmd;
265 int temp;
266 int result = 0;
267 int timeout;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200268 unsigned char errmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200270 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272 if (read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 outb_p(len, SMBHSTDAT0);
274 outb_p(data->block[1], SMBBLKDAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 }
276
277 for (i = 1; i <= len; i++) {
Jean Delvare63420642008-01-27 18:14:50 +0100278 if (i == len && read_write == I2C_SMBUS_READ) {
279 if (command == I2C_SMBUS_I2C_BLOCK_DATA)
280 smbcmd = I801_I2C_BLOCK_LAST;
281 else
282 smbcmd = I801_BLOCK_LAST;
283 } else {
284 if (command == I2C_SMBUS_I2C_BLOCK_DATA
285 && read_write == I2C_SMBUS_READ)
286 smbcmd = I801_I2C_BLOCK_DATA;
287 else
288 smbcmd = I801_BLOCK_DATA;
289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
291
292 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
Jean Delvare63420642008-01-27 18:14:50 +0100293 "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
Jean Delvare63420642008-01-27 18:14:50 +0100295 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
297 /* Make sure the SMBus host is ready to start transmitting */
298 temp = inb_p(SMBHSTSTS);
299 if (i == 1) {
Jean Delvare002cf632007-08-14 18:37:13 +0200300 /* Erroneous conditions before transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200302 errmask = 0x9f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 } else {
Jean Delvare002cf632007-08-14 18:37:13 +0200304 /* Erroneous conditions during transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 * Failed, Bus_Err, Dev_Err, Intr */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200306 errmask = 0x1e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 }
308 if (temp & errmask) {
309 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200310 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 outb_p(temp, SMBHSTSTS);
312 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
313 dev_err(&I801_dev->dev,
314 "Reset failed! (%02x)\n", temp);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200315 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 }
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200317 if (i != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 /* if die in middle of block transaction, fail */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200319 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 }
321
322 if (i == 1)
323 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
324
325 /* We will always wait for a fraction of a second! */
326 timeout = 0;
327 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200329 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 }
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200331 while ((!(temp & SMBHSTSTS_BYTE_DONE))
332 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 /* If the SMBus is still busy, we give up */
335 if (timeout >= MAX_TIMEOUT) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200336 /* try to stop the current command */
337 dev_dbg(&I801_dev->dev, "Terminating the current "
338 "operation\n");
339 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
340 msleep(1);
341 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
342 SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 result = -1;
344 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
345 }
346
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200347 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 result = -1;
349 dev_dbg(&I801_dev->dev,
350 "Error: Failed bus transaction\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200351 } else if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 result = -1;
353 dev_err(&I801_dev->dev, "Bus collision!\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200354 } else if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 result = -1;
356 dev_dbg(&I801_dev->dev, "Error: no response!\n");
357 }
358
Jean Delvare63420642008-01-27 18:14:50 +0100359 if (i == 1 && read_write == I2C_SMBUS_READ
360 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 len = inb_p(SMBHSTDAT0);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200362 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
363 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 data->block[0] = len;
365 }
366
367 /* Retrieve/store value in SMBBLKDAT */
368 if (read_write == I2C_SMBUS_READ)
369 data->block[i] = inb_p(SMBBLKDAT);
370 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
371 outb_p(data->block[i+1], SMBBLKDAT);
372 if ((temp & 0x9e) != 0x00)
373 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
374
375 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
376 dev_dbg(&I801_dev->dev,
377 "Bad status (%02x) at end of transaction\n",
378 temp);
379 }
380 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
Jean Delvare63420642008-01-27 18:14:50 +0100381 "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
Jean Delvare63420642008-01-27 18:14:50 +0100383 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385 if (result < 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200386 return result;
387 }
388 return result;
389}
390
391static int i801_set_block_buffer_mode(void)
392{
393 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
394 if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
395 return -1;
396 return 0;
397}
398
399/* Block transaction function */
400static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
401 int command, int hwpec)
402{
403 int result = 0;
404 unsigned char hostc;
405
406 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
407 if (read_write == I2C_SMBUS_WRITE) {
408 /* set I2C_EN bit in configuration register */
409 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
410 pci_write_config_byte(I801_dev, SMBHSTCFG,
411 hostc | SMBHSTCFG_I2C_EN);
Jean Delvare63420642008-01-27 18:14:50 +0100412 } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200413 dev_err(&I801_dev->dev,
Jean Delvare63420642008-01-27 18:14:50 +0100414 "I2C block read is unsupported!\n");
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200415 return -1;
416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 }
418
Jean Delvare63420642008-01-27 18:14:50 +0100419 if (read_write == I2C_SMBUS_WRITE
420 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200421 if (data->block[0] < 1)
422 data->block[0] = 1;
423 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
424 data->block[0] = I2C_SMBUS_BLOCK_MAX;
425 } else {
Jean Delvare63420642008-01-27 18:14:50 +0100426 data->block[0] = 32; /* max for SMBus block reads */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200427 }
428
Jean Delvare369f6f42008-01-27 18:14:50 +0100429 if ((i801_features & FEATURE_BLOCK_BUFFER)
Jean Delvare63420642008-01-27 18:14:50 +0100430 && !(command == I2C_SMBUS_I2C_BLOCK_DATA
431 && read_write == I2C_SMBUS_READ)
Jean Delvare369f6f42008-01-27 18:14:50 +0100432 && i801_set_block_buffer_mode() == 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200433 result = i801_block_transaction_by_block(data, read_write,
434 hwpec);
435 else
436 result = i801_block_transaction_byte_by_byte(data, read_write,
Jean Delvare63420642008-01-27 18:14:50 +0100437 command, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200438
439 if (result == 0 && hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200440 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
Jean Delvare63420642008-01-27 18:14:50 +0100442 if (command == I2C_SMBUS_I2C_BLOCK_DATA
443 && read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 /* restore saved configuration register value */
445 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
446 }
447 return result;
448}
449
450/* Return -1 on error. */
451static s32 i801_access(struct i2c_adapter * adap, u16 addr,
452 unsigned short flags, char read_write, u8 command,
453 int size, union i2c_smbus_data * data)
454{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200455 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 int block = 0;
457 int ret, xact = 0;
458
Jean Delvare369f6f42008-01-27 18:14:50 +0100459 hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200460 && size != I2C_SMBUS_QUICK
461 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
463 switch (size) {
464 case I2C_SMBUS_QUICK:
465 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
466 SMBHSTADD);
467 xact = I801_QUICK;
468 break;
469 case I2C_SMBUS_BYTE:
470 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
471 SMBHSTADD);
472 if (read_write == I2C_SMBUS_WRITE)
473 outb_p(command, SMBHSTCMD);
474 xact = I801_BYTE;
475 break;
476 case I2C_SMBUS_BYTE_DATA:
477 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
478 SMBHSTADD);
479 outb_p(command, SMBHSTCMD);
480 if (read_write == I2C_SMBUS_WRITE)
481 outb_p(data->byte, SMBHSTDAT0);
482 xact = I801_BYTE_DATA;
483 break;
484 case I2C_SMBUS_WORD_DATA:
485 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
486 SMBHSTADD);
487 outb_p(command, SMBHSTCMD);
488 if (read_write == I2C_SMBUS_WRITE) {
489 outb_p(data->word & 0xff, SMBHSTDAT0);
490 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
491 }
492 xact = I801_WORD_DATA;
493 break;
494 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
496 SMBHSTADD);
497 outb_p(command, SMBHSTCMD);
498 block = 1;
499 break;
Jean Delvare63420642008-01-27 18:14:50 +0100500 case I2C_SMBUS_I2C_BLOCK_DATA:
501 /* NB: page 240 of ICH5 datasheet shows that the R/#W
502 * bit should be cleared here, even when reading */
503 outb_p((addr & 0x7f) << 1, SMBHSTADD);
504 if (read_write == I2C_SMBUS_READ) {
505 /* NB: page 240 of ICH5 datasheet also shows
506 * that DATA1 is the cmd field when reading */
507 outb_p(command, SMBHSTDAT1);
508 } else
509 outb_p(command, SMBHSTCMD);
510 block = 1;
511 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 case I2C_SMBUS_PROC_CALL:
513 default:
514 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
515 return -1;
516 }
517
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200518 if (hwpec) /* enable/disable hardware PEC */
519 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
520 else
521 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200522
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200524 ret = i801_block_transaction(data, read_write, size, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200525 else
526 ret = i801_transaction(xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
Jean Delvarec79cfba2006-04-20 02:43:18 -0700528 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200529 time, so we forcibly disable it after every transaction. Turn off
530 E32B for the same reason. */
Jean Delvarea0921b62008-01-27 18:14:50 +0100531 if (hwpec || block)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200532 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
533 SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700534
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 if(block)
536 return ret;
537 if(ret)
538 return -1;
539 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
540 return 0;
541
542 switch (xact & 0x7f) {
543 case I801_BYTE: /* Result put in SMBHSTDAT0 */
544 case I801_BYTE_DATA:
545 data->byte = inb_p(SMBHSTDAT0);
546 break;
547 case I801_WORD_DATA:
548 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
549 break;
550 }
551 return 0;
552}
553
554
555static u32 i801_func(struct i2c_adapter *adapter)
556{
557 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Jean Delvare369f6f42008-01-27 18:14:50 +0100558 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
559 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
Jean Delvare63420642008-01-27 18:14:50 +0100560 ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
561 ((i801_features & FEATURE_I2C_BLOCK_READ) ?
562 I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563}
564
Jean Delvare8f9082c2006-09-03 22:39:46 +0200565static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 .smbus_xfer = i801_access,
567 .functionality = i801_func,
568};
569
570static struct i2c_adapter i801_adapter = {
571 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100572 .id = I2C_HW_SMBUS_I801,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 .class = I2C_CLASS_HWMON,
574 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575};
576
577static struct pci_device_id i801_ids[] = {
578 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
579 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
580 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
581 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
582 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
583 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
584 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
585 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
586 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700587 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800588 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800589 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Jason Gastone07bc672007-10-13 23:56:31 +0200590 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 { 0, }
592};
593
594MODULE_DEVICE_TABLE (pci, i801_ids);
595
596static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
597{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200598 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200599 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200601 I801_dev = dev;
Jean Delvare369f6f42008-01-27 18:14:50 +0100602 i801_features = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100603 switch (dev->device) {
Jean Delvare250d1bd2006-12-10 21:21:33 +0100604 case PCI_DEVICE_ID_INTEL_82801EB_3:
605 case PCI_DEVICE_ID_INTEL_ESB_4:
606 case PCI_DEVICE_ID_INTEL_ICH6_16:
607 case PCI_DEVICE_ID_INTEL_ICH7_17:
608 case PCI_DEVICE_ID_INTEL_ESB2_17:
609 case PCI_DEVICE_ID_INTEL_ICH8_5:
610 case PCI_DEVICE_ID_INTEL_ICH9_6:
Jean Delvare63420642008-01-27 18:14:50 +0100611 i801_features |= FEATURE_I2C_BLOCK_READ;
612 /* fall through */
613 case PCI_DEVICE_ID_INTEL_82801DB_3:
Jason Gastone07bc672007-10-13 23:56:31 +0200614 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
Jean Delvare369f6f42008-01-27 18:14:50 +0100615 i801_features |= FEATURE_SMBUS_PEC;
616 i801_features |= FEATURE_BLOCK_BUFFER;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100617 break;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100618 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200619
620 err = pci_enable_device(dev);
621 if (err) {
622 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
623 err);
624 goto exit;
625 }
626
627 /* Determine the address of the SMBus area */
628 i801_smba = pci_resource_start(dev, SMBBAR);
629 if (!i801_smba) {
630 dev_err(&dev->dev, "SMBus base address uninitialized, "
631 "upgrade BIOS\n");
632 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200633 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200634 }
635
636 err = pci_request_region(dev, SMBBAR, i801_driver.name);
637 if (err) {
638 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700639 "0x%lx-0x%Lx\n", i801_smba,
640 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200641 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200642 }
643
644 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100645 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200646 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
647 if (!(temp & SMBHSTCFG_HST_EN)) {
648 dev_info(&dev->dev, "Enabling SMBus device\n");
649 temp |= SMBHSTCFG_HST_EN;
650 }
651 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
652
653 if (temp & SMBHSTCFG_SMB_SMI_EN)
654 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
655 else
656 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
Jean Delvarea0921b62008-01-27 18:14:50 +0100658 /* Clear special mode bits */
659 if (i801_features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
660 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
661 SMBAUXCTL);
662
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100663 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 i801_adapter.dev.parent = &dev->dev;
665
David Brownell2096b952007-05-01 23:26:28 +0200666 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200667 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200668 err = i2c_add_adapter(&i801_adapter);
669 if (err) {
670 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200671 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200672 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200673 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200674
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200675exit_release:
676 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200677exit:
678 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679}
680
681static void __devexit i801_remove(struct pci_dev *dev)
682{
683 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100684 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200685 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200686 /*
687 * do not call pci_disable_device(dev) since it can cause hard hangs on
688 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
689 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690}
691
Jean Delvarea5aaea32007-03-22 19:49:01 +0100692#ifdef CONFIG_PM
693static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
694{
695 pci_save_state(dev);
696 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
697 pci_set_power_state(dev, pci_choose_state(dev, mesg));
698 return 0;
699}
700
701static int i801_resume(struct pci_dev *dev)
702{
703 pci_set_power_state(dev, PCI_D0);
704 pci_restore_state(dev);
705 return pci_enable_device(dev);
706}
707#else
708#define i801_suspend NULL
709#define i801_resume NULL
710#endif
711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 .name = "i801_smbus",
714 .id_table = i801_ids,
715 .probe = i801_probe,
716 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100717 .suspend = i801_suspend,
718 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719};
720
721static int __init i2c_i801_init(void)
722{
723 return pci_register_driver(&i801_driver);
724}
725
726static void __exit i2c_i801_exit(void)
727{
728 pci_unregister_driver(&i801_driver);
729}
730
Jean Delvare63420642008-01-27 18:14:50 +0100731MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
732 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733MODULE_DESCRIPTION("I801 SMBus driver");
734MODULE_LICENSE("GPL");
735
736module_init(i2c_i801_init);
737module_exit(i2c_i801_exit);