blob: 289816db52aed4b956dd515238f65a8fda481597 [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
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
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200117static int i801_transaction(int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118{
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
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200142 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
143 * INTREN, SMBSCMD are passed in xact */
144 outb_p(xact | I801_START, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
146 /* We will always wait for a fraction of a second! */
147 do {
148 msleep(1);
149 temp = inb_p(SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200150 } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
152 /* If the SMBus is still busy, we give up */
153 if (timeout >= MAX_TIMEOUT) {
154 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
155 result = -1;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200156 /* try to stop the current command */
157 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
158 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
159 msleep(1);
160 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 }
162
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200163 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 result = -1;
165 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
166 }
167
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200168 if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 result = -1;
170 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
171 "until next hard reset. (sorry!)\n");
172 /* Clock stops and slave is stuck in mid-transmission */
173 }
174
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200175 if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 result = -1;
177 dev_dbg(&I801_dev->dev, "Error: no response!\n");
178 }
179
180 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
181 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
182
183 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700184 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 "(%02x)\n", temp);
186 }
187 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
188 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
189 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
190 inb_p(SMBHSTDAT1));
191 return result;
192}
193
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200194/* wait for INTR bit as advised by Intel */
195static void i801_wait_hwpec(void)
196{
197 int timeout = 0;
198 int temp;
199
200 do {
201 msleep(1);
202 temp = inb_p(SMBHSTSTS);
203 } while ((!(temp & SMBHSTSTS_INTR))
204 && (timeout++ < MAX_TIMEOUT));
205
206 if (timeout >= MAX_TIMEOUT) {
207 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
208 }
209 outb_p(temp, SMBHSTSTS);
210}
211
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200212static int i801_block_transaction_by_block(union i2c_smbus_data *data,
213 char read_write, int hwpec)
214{
215 int i, len;
216
217 inb_p(SMBHSTCNT); /* reset the data buffer index */
218
219 /* Use 32-byte buffer to process this transaction */
220 if (read_write == I2C_SMBUS_WRITE) {
221 len = data->block[0];
222 outb_p(len, SMBHSTDAT0);
223 for (i = 0; i < len; i++)
224 outb_p(data->block[i+1], SMBBLKDAT);
225 }
226
227 if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
228 I801_PEC_EN * hwpec))
229 return -1;
230
231 if (read_write == I2C_SMBUS_READ) {
232 len = inb_p(SMBHSTDAT0);
233 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
234 return -1;
235
236 data->block[0] = len;
237 for (i = 0; i < len; i++)
238 data->block[i + 1] = inb_p(SMBBLKDAT);
239 }
240 return 0;
241}
242
243static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
244 char read_write, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
246 int i, len;
247 int smbcmd;
248 int temp;
249 int result = 0;
250 int timeout;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200251 unsigned char errmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200253 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255 if (read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 outb_p(len, SMBHSTDAT0);
257 outb_p(data->block[1], SMBBLKDAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 }
259
260 for (i = 1; i <= len; i++) {
261 if (i == len && read_write == I2C_SMBUS_READ)
262 smbcmd = I801_BLOCK_LAST;
263 else
264 smbcmd = I801_BLOCK_DATA;
265 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
266
267 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
268 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
269 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
270 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
271
272 /* Make sure the SMBus host is ready to start transmitting */
273 temp = inb_p(SMBHSTSTS);
274 if (i == 1) {
Jean Delvare002cf632007-08-14 18:37:13 +0200275 /* Erroneous conditions before transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200277 errmask = 0x9f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 } else {
Jean Delvare002cf632007-08-14 18:37:13 +0200279 /* Erroneous conditions during transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 * Failed, Bus_Err, Dev_Err, Intr */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200281 errmask = 0x1e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
283 if (temp & errmask) {
284 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200285 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 outb_p(temp, SMBHSTSTS);
287 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
288 dev_err(&I801_dev->dev,
289 "Reset failed! (%02x)\n", temp);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200290 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 }
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200292 if (i != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 /* if die in middle of block transaction, fail */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200294 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 }
296
297 if (i == 1)
298 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
299
300 /* We will always wait for a fraction of a second! */
301 timeout = 0;
302 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200304 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 }
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200306 while ((!(temp & SMBHSTSTS_BYTE_DONE))
307 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309 /* If the SMBus is still busy, we give up */
310 if (timeout >= MAX_TIMEOUT) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200311 /* try to stop the current command */
312 dev_dbg(&I801_dev->dev, "Terminating the current "
313 "operation\n");
314 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
315 msleep(1);
316 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
317 SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 result = -1;
319 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
320 }
321
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200322 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 result = -1;
324 dev_dbg(&I801_dev->dev,
325 "Error: Failed bus transaction\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200326 } else if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 result = -1;
328 dev_err(&I801_dev->dev, "Bus collision!\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200329 } else if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 result = -1;
331 dev_dbg(&I801_dev->dev, "Error: no response!\n");
332 }
333
334 if (i == 1 && read_write == I2C_SMBUS_READ) {
335 len = inb_p(SMBHSTDAT0);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200336 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
337 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 data->block[0] = len;
339 }
340
341 /* Retrieve/store value in SMBBLKDAT */
342 if (read_write == I2C_SMBUS_READ)
343 data->block[i] = inb_p(SMBBLKDAT);
344 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
345 outb_p(data->block[i+1], SMBBLKDAT);
346 if ((temp & 0x9e) != 0x00)
347 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
348
349 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
350 dev_dbg(&I801_dev->dev,
351 "Bad status (%02x) at end of transaction\n",
352 temp);
353 }
354 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
355 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
356 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
357 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
358
359 if (result < 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200360 return result;
361 }
362 return result;
363}
364
365static int i801_set_block_buffer_mode(void)
366{
367 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
368 if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
369 return -1;
370 return 0;
371}
372
373/* Block transaction function */
374static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
375 int command, int hwpec)
376{
377 int result = 0;
378 unsigned char hostc;
379
380 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
381 if (read_write == I2C_SMBUS_WRITE) {
382 /* set I2C_EN bit in configuration register */
383 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
384 pci_write_config_byte(I801_dev, SMBHSTCFG,
385 hostc | SMBHSTCFG_I2C_EN);
386 } else {
387 dev_err(&I801_dev->dev,
388 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
389 return -1;
390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 }
392
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200393 if (read_write == I2C_SMBUS_WRITE) {
394 if (data->block[0] < 1)
395 data->block[0] = 1;
396 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
397 data->block[0] = I2C_SMBUS_BLOCK_MAX;
398 } else {
399 data->block[0] = 32; /* max for reads */
400 }
401
402 if (isich4 && i801_set_block_buffer_mode() == 0 )
403 result = i801_block_transaction_by_block(data, read_write,
404 hwpec);
405 else
406 result = i801_block_transaction_byte_by_byte(data, read_write,
407 hwpec);
408
409 if (result == 0 && hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200410 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
413 /* restore saved configuration register value */
414 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
415 }
416 return result;
417}
418
419/* Return -1 on error. */
420static s32 i801_access(struct i2c_adapter * adap, u16 addr,
421 unsigned short flags, char read_write, u8 command,
422 int size, union i2c_smbus_data * data)
423{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200424 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 int block = 0;
426 int ret, xact = 0;
427
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200428 hwpec = isich4 && (flags & I2C_CLIENT_PEC)
429 && size != I2C_SMBUS_QUICK
430 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432 switch (size) {
433 case I2C_SMBUS_QUICK:
434 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
435 SMBHSTADD);
436 xact = I801_QUICK;
437 break;
438 case I2C_SMBUS_BYTE:
439 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
440 SMBHSTADD);
441 if (read_write == I2C_SMBUS_WRITE)
442 outb_p(command, SMBHSTCMD);
443 xact = I801_BYTE;
444 break;
445 case I2C_SMBUS_BYTE_DATA:
446 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
447 SMBHSTADD);
448 outb_p(command, SMBHSTCMD);
449 if (read_write == I2C_SMBUS_WRITE)
450 outb_p(data->byte, SMBHSTDAT0);
451 xact = I801_BYTE_DATA;
452 break;
453 case I2C_SMBUS_WORD_DATA:
454 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
455 SMBHSTADD);
456 outb_p(command, SMBHSTCMD);
457 if (read_write == I2C_SMBUS_WRITE) {
458 outb_p(data->word & 0xff, SMBHSTDAT0);
459 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
460 }
461 xact = I801_WORD_DATA;
462 break;
463 case I2C_SMBUS_BLOCK_DATA:
464 case I2C_SMBUS_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
466 SMBHSTADD);
467 outb_p(command, SMBHSTCMD);
468 block = 1;
469 break;
470 case I2C_SMBUS_PROC_CALL:
471 default:
472 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
473 return -1;
474 }
475
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200476 if (hwpec) /* enable/disable hardware PEC */
477 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
478 else
479 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200482 ret = i801_block_transaction(data, read_write, size, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200483 else
484 ret = i801_transaction(xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Jean Delvarec79cfba2006-04-20 02:43:18 -0700486 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200487 time, so we forcibly disable it after every transaction. Turn off
488 E32B for the same reason. */
Jean Delvarec79cfba2006-04-20 02:43:18 -0700489 if (hwpec)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200490 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
491 SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 if(block)
494 return ret;
495 if(ret)
496 return -1;
497 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
498 return 0;
499
500 switch (xact & 0x7f) {
501 case I801_BYTE: /* Result put in SMBHSTDAT0 */
502 case I801_BYTE_DATA:
503 data->byte = inb_p(SMBHSTDAT0);
504 break;
505 case I801_WORD_DATA:
506 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
507 break;
508 }
509 return 0;
510}
511
512
513static u32 i801_func(struct i2c_adapter *adapter)
514{
515 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
516 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
517 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
Jean Delvareb8095542005-10-26 21:25:04 +0200518 | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519}
520
Jean Delvare8f9082c2006-09-03 22:39:46 +0200521static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 .smbus_xfer = i801_access,
523 .functionality = i801_func,
524};
525
526static struct i2c_adapter i801_adapter = {
527 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100528 .id = I2C_HW_SMBUS_I801,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 .class = I2C_CLASS_HWMON,
530 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531};
532
533static struct pci_device_id i801_ids[] = {
534 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
535 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
536 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
537 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
538 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
539 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
540 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
541 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
542 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700543 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800544 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800545 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 { 0, }
547};
548
549MODULE_DEVICE_TABLE (pci, i801_ids);
550
551static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
552{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200553 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200554 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200556 I801_dev = dev;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100557 switch (dev->device) {
558 case PCI_DEVICE_ID_INTEL_82801DB_3:
559 case PCI_DEVICE_ID_INTEL_82801EB_3:
560 case PCI_DEVICE_ID_INTEL_ESB_4:
561 case PCI_DEVICE_ID_INTEL_ICH6_16:
562 case PCI_DEVICE_ID_INTEL_ICH7_17:
563 case PCI_DEVICE_ID_INTEL_ESB2_17:
564 case PCI_DEVICE_ID_INTEL_ICH8_5:
565 case PCI_DEVICE_ID_INTEL_ICH9_6:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200566 isich4 = 1;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100567 break;
568 default:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200569 isich4 = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100570 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200571
572 err = pci_enable_device(dev);
573 if (err) {
574 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
575 err);
576 goto exit;
577 }
578
579 /* Determine the address of the SMBus area */
580 i801_smba = pci_resource_start(dev, SMBBAR);
581 if (!i801_smba) {
582 dev_err(&dev->dev, "SMBus base address uninitialized, "
583 "upgrade BIOS\n");
584 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200585 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200586 }
587
588 err = pci_request_region(dev, SMBBAR, i801_driver.name);
589 if (err) {
590 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700591 "0x%lx-0x%Lx\n", i801_smba,
592 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200593 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200594 }
595
596 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100597 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200598 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
599 if (!(temp & SMBHSTCFG_HST_EN)) {
600 dev_info(&dev->dev, "Enabling SMBus device\n");
601 temp |= SMBHSTCFG_HST_EN;
602 }
603 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
604
605 if (temp & SMBHSTCFG_SMB_SMI_EN)
606 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
607 else
608 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100610 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 i801_adapter.dev.parent = &dev->dev;
612
David Brownell2096b952007-05-01 23:26:28 +0200613 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200614 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200615 err = i2c_add_adapter(&i801_adapter);
616 if (err) {
617 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200618 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200619 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200620 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200621
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200622exit_release:
623 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200624exit:
625 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626}
627
628static void __devexit i801_remove(struct pci_dev *dev)
629{
630 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100631 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200632 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200633 /*
634 * do not call pci_disable_device(dev) since it can cause hard hangs on
635 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
636 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637}
638
Jean Delvarea5aaea32007-03-22 19:49:01 +0100639#ifdef CONFIG_PM
640static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
641{
642 pci_save_state(dev);
643 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
644 pci_set_power_state(dev, pci_choose_state(dev, mesg));
645 return 0;
646}
647
648static int i801_resume(struct pci_dev *dev)
649{
650 pci_set_power_state(dev, PCI_D0);
651 pci_restore_state(dev);
652 return pci_enable_device(dev);
653}
654#else
655#define i801_suspend NULL
656#define i801_resume NULL
657#endif
658
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 .name = "i801_smbus",
661 .id_table = i801_ids,
662 .probe = i801_probe,
663 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100664 .suspend = i801_suspend,
665 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666};
667
668static int __init i2c_i801_init(void)
669{
670 return pci_register_driver(&i801_driver);
671}
672
673static void __exit i2c_i801_exit(void)
674{
675 pci_unregister_driver(&i801_driver);
676}
677
678MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
679 "Philip Edelbrock <phil@netroedge.com>, "
680 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
681MODULE_DESCRIPTION("I801 SMBus driver");
682MODULE_LICENSE("GPL");
683
684module_init(i2c_i801_init);
685module_exit(i2c_i801_exit);