blob: 8f16a47bcaf978d06055b2c67d2ad8684db39f22 [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;
125static int isich4;
126
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200127static int i801_transaction(int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128{
129 int temp;
130 int result = 0;
131 int timeout = 0;
132
Jean Delvare368609c2005-07-29 12:15:07 -0700133 dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
135 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
136 inb_p(SMBHSTDAT1));
137
138 /* Make sure the SMBus host is ready to start transmitting */
139 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
140 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200141 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 temp);
143 outb_p(temp, SMBHSTSTS);
144 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
145 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
146 return -1;
147 } else {
Jean Delvarefcdd96e2007-02-13 22:08:59 +0100148 dev_dbg(&I801_dev->dev, "Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 }
150 }
151
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200152 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
153 * INTREN, SMBSCMD are passed in xact */
154 outb_p(xact | I801_START, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156 /* We will always wait for a fraction of a second! */
157 do {
158 msleep(1);
159 temp = inb_p(SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200160 } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
162 /* If the SMBus is still busy, we give up */
163 if (timeout >= MAX_TIMEOUT) {
164 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
165 result = -1;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200166 /* try to stop the current command */
167 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
168 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
169 msleep(1);
170 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 }
172
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200173 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 result = -1;
175 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
176 }
177
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200178 if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 result = -1;
180 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
181 "until next hard reset. (sorry!)\n");
182 /* Clock stops and slave is stuck in mid-transmission */
183 }
184
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200185 if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 result = -1;
187 dev_dbg(&I801_dev->dev, "Error: no response!\n");
188 }
189
190 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
191 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
192
193 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700194 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 "(%02x)\n", temp);
196 }
197 dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
198 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
199 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
200 inb_p(SMBHSTDAT1));
201 return result;
202}
203
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200204/* wait for INTR bit as advised by Intel */
205static void i801_wait_hwpec(void)
206{
207 int timeout = 0;
208 int temp;
209
210 do {
211 msleep(1);
212 temp = inb_p(SMBHSTSTS);
213 } while ((!(temp & SMBHSTSTS_INTR))
214 && (timeout++ < MAX_TIMEOUT));
215
216 if (timeout >= MAX_TIMEOUT) {
217 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
218 }
219 outb_p(temp, SMBHSTSTS);
220}
221
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200222static int i801_block_transaction_by_block(union i2c_smbus_data *data,
223 char read_write, int hwpec)
224{
225 int i, len;
226
227 inb_p(SMBHSTCNT); /* reset the data buffer index */
228
229 /* Use 32-byte buffer to process this transaction */
230 if (read_write == I2C_SMBUS_WRITE) {
231 len = data->block[0];
232 outb_p(len, SMBHSTDAT0);
233 for (i = 0; i < len; i++)
234 outb_p(data->block[i+1], SMBBLKDAT);
235 }
236
237 if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
238 I801_PEC_EN * hwpec))
239 return -1;
240
241 if (read_write == I2C_SMBUS_READ) {
242 len = inb_p(SMBHSTDAT0);
243 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
244 return -1;
245
246 data->block[0] = len;
247 for (i = 0; i < len; i++)
248 data->block[i + 1] = inb_p(SMBBLKDAT);
249 }
250 return 0;
251}
252
253static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
254 char read_write, int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255{
256 int i, len;
257 int smbcmd;
258 int temp;
259 int result = 0;
260 int timeout;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200261 unsigned char errmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200263 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
265 if (read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 outb_p(len, SMBHSTDAT0);
267 outb_p(data->block[1], SMBBLKDAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 }
269
270 for (i = 1; i <= len; i++) {
271 if (i == len && read_write == I2C_SMBUS_READ)
272 smbcmd = I801_BLOCK_LAST;
273 else
274 smbcmd = I801_BLOCK_DATA;
275 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
276
277 dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
278 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
279 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
280 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
281
282 /* Make sure the SMBus host is ready to start transmitting */
283 temp = inb_p(SMBHSTSTS);
284 if (i == 1) {
Jean Delvare002cf632007-08-14 18:37:13 +0200285 /* Erroneous conditions before transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200287 errmask = 0x9f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 } else {
Jean Delvare002cf632007-08-14 18:37:13 +0200289 /* Erroneous conditions during transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 * Failed, Bus_Err, Dev_Err, Intr */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200291 errmask = 0x1e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 }
293 if (temp & errmask) {
294 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare541e6a02005-06-23 22:18:08 +0200295 "Resetting...\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 outb_p(temp, SMBHSTSTS);
297 if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
298 dev_err(&I801_dev->dev,
299 "Reset failed! (%02x)\n", temp);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200300 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 }
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200302 if (i != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 /* if die in middle of block transaction, fail */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200304 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 }
306
307 if (i == 1)
308 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
309
310 /* We will always wait for a fraction of a second! */
311 timeout = 0;
312 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 msleep(1);
Jean Delvare397e2f62006-06-12 21:49:36 +0200314 temp = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 }
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200316 while ((!(temp & SMBHSTSTS_BYTE_DONE))
317 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
319 /* If the SMBus is still busy, we give up */
320 if (timeout >= MAX_TIMEOUT) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200321 /* try to stop the current command */
322 dev_dbg(&I801_dev->dev, "Terminating the current "
323 "operation\n");
324 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
325 msleep(1);
326 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
327 SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 result = -1;
329 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
330 }
331
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200332 if (temp & SMBHSTSTS_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 result = -1;
334 dev_dbg(&I801_dev->dev,
335 "Error: Failed bus transaction\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200336 } else if (temp & SMBHSTSTS_BUS_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 result = -1;
338 dev_err(&I801_dev->dev, "Bus collision!\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200339 } else if (temp & SMBHSTSTS_DEV_ERR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 result = -1;
341 dev_dbg(&I801_dev->dev, "Error: no response!\n");
342 }
343
344 if (i == 1 && read_write == I2C_SMBUS_READ) {
345 len = inb_p(SMBHSTDAT0);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200346 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
347 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 data->block[0] = len;
349 }
350
351 /* Retrieve/store value in SMBBLKDAT */
352 if (read_write == I2C_SMBUS_READ)
353 data->block[i] = inb_p(SMBBLKDAT);
354 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
355 outb_p(data->block[i+1], SMBBLKDAT);
356 if ((temp & 0x9e) != 0x00)
357 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
358
359 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
360 dev_dbg(&I801_dev->dev,
361 "Bad status (%02x) at end of transaction\n",
362 temp);
363 }
364 dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
365 "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
366 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
367 inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
368
369 if (result < 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200370 return result;
371 }
372 return result;
373}
374
375static int i801_set_block_buffer_mode(void)
376{
377 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
378 if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
379 return -1;
380 return 0;
381}
382
383/* Block transaction function */
384static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
385 int command, int hwpec)
386{
387 int result = 0;
388 unsigned char hostc;
389
390 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
391 if (read_write == I2C_SMBUS_WRITE) {
392 /* set I2C_EN bit in configuration register */
393 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
394 pci_write_config_byte(I801_dev, SMBHSTCFG,
395 hostc | SMBHSTCFG_I2C_EN);
396 } else {
397 dev_err(&I801_dev->dev,
398 "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
399 return -1;
400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
402
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200403 if (read_write == I2C_SMBUS_WRITE) {
404 if (data->block[0] < 1)
405 data->block[0] = 1;
406 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
407 data->block[0] = I2C_SMBUS_BLOCK_MAX;
408 } else {
409 data->block[0] = 32; /* max for reads */
410 }
411
412 if (isich4 && i801_set_block_buffer_mode() == 0 )
413 result = i801_block_transaction_by_block(data, read_write,
414 hwpec);
415 else
416 result = i801_block_transaction_byte_by_byte(data, read_write,
417 hwpec);
418
419 if (result == 0 && hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200420 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
423 /* restore saved configuration register value */
424 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
425 }
426 return result;
427}
428
429/* Return -1 on error. */
430static s32 i801_access(struct i2c_adapter * adap, u16 addr,
431 unsigned short flags, char read_write, u8 command,
432 int size, union i2c_smbus_data * data)
433{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200434 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 int block = 0;
436 int ret, xact = 0;
437
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200438 hwpec = isich4 && (flags & I2C_CLIENT_PEC)
439 && size != I2C_SMBUS_QUICK
440 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442 switch (size) {
443 case I2C_SMBUS_QUICK:
444 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
445 SMBHSTADD);
446 xact = I801_QUICK;
447 break;
448 case I2C_SMBUS_BYTE:
449 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
450 SMBHSTADD);
451 if (read_write == I2C_SMBUS_WRITE)
452 outb_p(command, SMBHSTCMD);
453 xact = I801_BYTE;
454 break;
455 case I2C_SMBUS_BYTE_DATA:
456 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
457 SMBHSTADD);
458 outb_p(command, SMBHSTCMD);
459 if (read_write == I2C_SMBUS_WRITE)
460 outb_p(data->byte, SMBHSTDAT0);
461 xact = I801_BYTE_DATA;
462 break;
463 case I2C_SMBUS_WORD_DATA:
464 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
465 SMBHSTADD);
466 outb_p(command, SMBHSTCMD);
467 if (read_write == I2C_SMBUS_WRITE) {
468 outb_p(data->word & 0xff, SMBHSTDAT0);
469 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
470 }
471 xact = I801_WORD_DATA;
472 break;
473 case I2C_SMBUS_BLOCK_DATA:
474 case I2C_SMBUS_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
476 SMBHSTADD);
477 outb_p(command, SMBHSTCMD);
478 block = 1;
479 break;
480 case I2C_SMBUS_PROC_CALL:
481 default:
482 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
483 return -1;
484 }
485
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200486 if (hwpec) /* enable/disable hardware PEC */
487 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
488 else
489 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200490
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200492 ret = i801_block_transaction(data, read_write, size, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200493 else
494 ret = i801_transaction(xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
Jean Delvarec79cfba2006-04-20 02:43:18 -0700496 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200497 time, so we forcibly disable it after every transaction. Turn off
498 E32B for the same reason. */
Jean Delvarec79cfba2006-04-20 02:43:18 -0700499 if (hwpec)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200500 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
501 SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 if(block)
504 return ret;
505 if(ret)
506 return -1;
507 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
508 return 0;
509
510 switch (xact & 0x7f) {
511 case I801_BYTE: /* Result put in SMBHSTDAT0 */
512 case I801_BYTE_DATA:
513 data->byte = inb_p(SMBHSTDAT0);
514 break;
515 case I801_WORD_DATA:
516 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
517 break;
518 }
519 return 0;
520}
521
522
523static u32 i801_func(struct i2c_adapter *adapter)
524{
525 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
526 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
527 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
David Brownell6662cbb2007-10-13 23:56:33 +0200528 | (isich4 ? I2C_FUNC_SMBUS_PEC : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529}
530
Jean Delvare8f9082c2006-09-03 22:39:46 +0200531static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 .smbus_xfer = i801_access,
533 .functionality = i801_func,
534};
535
536static struct i2c_adapter i801_adapter = {
537 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100538 .id = I2C_HW_SMBUS_I801,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 .class = I2C_CLASS_HWMON,
540 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541};
542
543static struct pci_device_id i801_ids[] = {
544 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
545 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
546 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
547 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
548 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
549 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
550 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
551 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
552 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700553 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800554 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800555 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Jason Gastone07bc672007-10-13 23:56:31 +0200556 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 { 0, }
558};
559
560MODULE_DEVICE_TABLE (pci, i801_ids);
561
562static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
563{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200564 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200565 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200567 I801_dev = dev;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100568 switch (dev->device) {
569 case PCI_DEVICE_ID_INTEL_82801DB_3:
570 case PCI_DEVICE_ID_INTEL_82801EB_3:
571 case PCI_DEVICE_ID_INTEL_ESB_4:
572 case PCI_DEVICE_ID_INTEL_ICH6_16:
573 case PCI_DEVICE_ID_INTEL_ICH7_17:
574 case PCI_DEVICE_ID_INTEL_ESB2_17:
575 case PCI_DEVICE_ID_INTEL_ICH8_5:
576 case PCI_DEVICE_ID_INTEL_ICH9_6:
Jason Gastone07bc672007-10-13 23:56:31 +0200577 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200578 isich4 = 1;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100579 break;
580 default:
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200581 isich4 = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100582 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200583
584 err = pci_enable_device(dev);
585 if (err) {
586 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
587 err);
588 goto exit;
589 }
590
591 /* Determine the address of the SMBus area */
592 i801_smba = pci_resource_start(dev, SMBBAR);
593 if (!i801_smba) {
594 dev_err(&dev->dev, "SMBus base address uninitialized, "
595 "upgrade BIOS\n");
596 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200597 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200598 }
599
600 err = pci_request_region(dev, SMBBAR, i801_driver.name);
601 if (err) {
602 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700603 "0x%lx-0x%Lx\n", i801_smba,
604 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200605 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200606 }
607
608 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100609 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200610 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
611 if (!(temp & SMBHSTCFG_HST_EN)) {
612 dev_info(&dev->dev, "Enabling SMBus device\n");
613 temp |= SMBHSTCFG_HST_EN;
614 }
615 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
616
617 if (temp & SMBHSTCFG_SMB_SMI_EN)
618 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
619 else
620 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100622 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 i801_adapter.dev.parent = &dev->dev;
624
David Brownell2096b952007-05-01 23:26:28 +0200625 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200626 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200627 err = i2c_add_adapter(&i801_adapter);
628 if (err) {
629 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200630 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200631 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200632 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200633
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200634exit_release:
635 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200636exit:
637 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638}
639
640static void __devexit i801_remove(struct pci_dev *dev)
641{
642 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100643 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200644 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200645 /*
646 * do not call pci_disable_device(dev) since it can cause hard hangs on
647 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
648 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649}
650
Jean Delvarea5aaea32007-03-22 19:49:01 +0100651#ifdef CONFIG_PM
652static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
653{
654 pci_save_state(dev);
655 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
656 pci_set_power_state(dev, pci_choose_state(dev, mesg));
657 return 0;
658}
659
660static int i801_resume(struct pci_dev *dev)
661{
662 pci_set_power_state(dev, PCI_D0);
663 pci_restore_state(dev);
664 return pci_enable_device(dev);
665}
666#else
667#define i801_suspend NULL
668#define i801_resume NULL
669#endif
670
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 .name = "i801_smbus",
673 .id_table = i801_ids,
674 .probe = i801_probe,
675 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100676 .suspend = i801_suspend,
677 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678};
679
680static int __init i2c_i801_init(void)
681{
682 return pci_register_driver(&i801_driver);
683}
684
685static void __exit i2c_i801_exit(void)
686{
687 pci_unregister_driver(&i801_driver);
688}
689
690MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
691 "Philip Edelbrock <phil@netroedge.com>, "
692 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
693MODULE_DESCRIPTION("I801 SMBus driver");
694MODULE_LICENSE("GPL");
695
696module_init(i2c_i801_init);
697module_exit(i2c_i801_exit);