blob: 965905fb5d56220992d4f97a7e248916fe1e1b2f [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
Gaston, Jason Dd28dc712008-02-24 20:03:42 +010043 Tolapai 0x5032 32 hard yes yes yes
44 ICH10 0x3a30 32 hard yes yes yes
45 ICH10 0x3a60 32 hard yes yes yes
Jean Delvareae7b0492008-01-27 18:14:49 +010046
47 Features supported by this driver:
48 Software PEC no
49 Hardware PEC yes
50 Block buffer yes
51 Block process call transaction no
Jean Delvare63420642008-01-27 18:14:50 +010052 I2C block read transaction yes (doesn't use the block buffer)
Jean Delvareae7b0492008-01-27 18:14:49 +010053
54 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070055*/
56
57/* Note: we assume there can only be one I801, with one SMBus interface */
58
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <linux/module.h>
60#include <linux/pci.h>
61#include <linux/kernel.h>
62#include <linux/stddef.h>
63#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#include <linux/ioport.h>
65#include <linux/init.h>
66#include <linux/i2c.h>
67#include <asm/io.h>
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069/* I801 SMBus address offsets */
70#define SMBHSTSTS (0 + i801_smba)
71#define SMBHSTCNT (2 + i801_smba)
72#define SMBHSTCMD (3 + i801_smba)
73#define SMBHSTADD (4 + i801_smba)
74#define SMBHSTDAT0 (5 + i801_smba)
75#define SMBHSTDAT1 (6 + i801_smba)
76#define SMBBLKDAT (7 + i801_smba)
Jean Delvareae7b0492008-01-27 18:14:49 +010077#define SMBPEC (8 + i801_smba) /* ICH3 and later */
78#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */
79#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
81/* PCI Address Constants */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020082#define SMBBAR 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070083#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85/* Host configuration bits for SMBHSTCFG */
86#define SMBHSTCFG_HST_EN 1
87#define SMBHSTCFG_SMB_SMI_EN 2
88#define SMBHSTCFG_I2C_EN 4
89
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +020090/* Auxillary control register bits, ICH4+ only */
91#define SMBAUXCTL_CRC 1
92#define SMBAUXCTL_E32B 2
93
94/* kill bit for SMBHSTCNT */
95#define SMBHSTCNT_KILL 2
96
Linus Torvalds1da177e2005-04-16 15:20:36 -070097/* Other settings */
98#define MAX_TIMEOUT 100
99#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
100
101/* I801 command constants */
102#define I801_QUICK 0x00
103#define I801_BYTE 0x04
104#define I801_BYTE_DATA 0x08
105#define I801_WORD_DATA 0x0C
Jean Delvareae7b0492008-01-27 18:14:49 +0100106#define I801_PROC_CALL 0x10 /* unimplemented */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107#define I801_BLOCK_DATA 0x14
Jean Delvare63420642008-01-27 18:14:50 +0100108#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109#define I801_BLOCK_LAST 0x34
Jean Delvare63420642008-01-27 18:14:50 +0100110#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111#define I801_START 0x40
Jean Delvareae7b0492008-01-27 18:14:49 +0100112#define I801_PEC_EN 0x80 /* ICH3 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200114/* I801 Hosts Status register bits */
115#define SMBHSTSTS_BYTE_DONE 0x80
116#define SMBHSTSTS_INUSE_STS 0x40
117#define SMBHSTSTS_SMBALERT_STS 0x20
118#define SMBHSTSTS_FAILED 0x10
119#define SMBHSTSTS_BUS_ERR 0x08
120#define SMBHSTSTS_DEV_ERR 0x04
121#define SMBHSTSTS_INTR 0x02
122#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200124static unsigned long i801_smba;
Jean Delvarea5aaea32007-03-22 19:49:01 +0100125static unsigned char i801_original_hstcfg;
Jean Delvared6072f82005-09-25 16:37:04 +0200126static struct pci_driver i801_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127static struct pci_dev *I801_dev;
Jean Delvare369f6f42008-01-27 18:14:50 +0100128
129#define FEATURE_SMBUS_PEC (1 << 0)
130#define FEATURE_BLOCK_BUFFER (1 << 1)
131#define FEATURE_BLOCK_PROC (1 << 2)
132#define FEATURE_I2C_BLOCK_READ (1 << 3)
133static unsigned int i801_features;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200135static int i801_transaction(int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
137 int temp;
138 int result = 0;
139 int timeout = 0;
140
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 /* Make sure the SMBus host is ready to start transmitting */
142 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
143 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200144 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 temp);
146 outb_p(temp, SMBHSTSTS);
147 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
148 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
David Brownell97140342008-07-14 22:38:25 +0200149 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 } else {
Jean Delvarefcdd96e2007-02-13 22:08:59 +0100151 dev_dbg(&I801_dev->dev, "Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 }
153 }
154
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200155 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
156 * INTREN, SMBSCMD are passed in xact */
157 outb_p(xact | I801_START, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
159 /* We will always wait for a fraction of a second! */
160 do {
161 msleep(1);
162 temp = inb_p(SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200163 } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
165 /* If the SMBus is still busy, we give up */
166 if (timeout >= MAX_TIMEOUT) {
167 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
David Brownell97140342008-07-14 22:38:25 +0200168 result = -ETIMEDOUT;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200169 /* try to stop the current command */
170 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
171 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
172 msleep(1);
173 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 }
175
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200176 if (temp & SMBHSTSTS_FAILED) {
David Brownell97140342008-07-14 22:38:25 +0200177 result = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
179 }
180
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200181 if (temp & SMBHSTSTS_BUS_ERR) {
David Brownell97140342008-07-14 22:38:25 +0200182 result = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
184 "until next hard reset. (sorry!)\n");
185 /* Clock stops and slave is stuck in mid-transmission */
186 }
187
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200188 if (temp & SMBHSTSTS_DEV_ERR) {
David Brownell97140342008-07-14 22:38:25 +0200189 result = -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 dev_dbg(&I801_dev->dev, "Error: no response!\n");
191 }
192
193 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
194 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
195
196 if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700197 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 "(%02x)\n", temp);
199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 return result;
201}
202
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200203/* wait for INTR bit as advised by Intel */
204static void i801_wait_hwpec(void)
205{
206 int timeout = 0;
207 int temp;
208
209 do {
210 msleep(1);
211 temp = inb_p(SMBHSTSTS);
212 } while ((!(temp & SMBHSTSTS_INTR))
213 && (timeout++ < MAX_TIMEOUT));
214
215 if (timeout >= MAX_TIMEOUT) {
216 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
217 }
218 outb_p(temp, SMBHSTSTS);
219}
220
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200221static int i801_block_transaction_by_block(union i2c_smbus_data *data,
222 char read_write, int hwpec)
223{
224 int i, len;
David Brownell97140342008-07-14 22:38:25 +0200225 int status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200226
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
David Brownell97140342008-07-14 22:38:25 +0200237 status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
238 I801_PEC_EN * hwpec);
239 if (status)
240 return status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200241
242 if (read_write == I2C_SMBUS_READ) {
243 len = inb_p(SMBHSTDAT0);
244 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
David Brownell97140342008-07-14 22:38:25 +0200245 return -EPROTO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200246
247 data->block[0] = len;
248 for (i = 0; i < len; i++)
249 data->block[i + 1] = inb_p(SMBBLKDAT);
250 }
251 return 0;
252}
253
254static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
Jean Delvare63420642008-01-27 18:14:50 +0100255 char read_write, int command,
256 int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257{
258 int i, len;
259 int smbcmd;
260 int temp;
261 int result = 0;
262 int timeout;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200263 unsigned char errmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200265 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
267 if (read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 outb_p(len, SMBHSTDAT0);
269 outb_p(data->block[1], SMBBLKDAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 }
271
272 for (i = 1; i <= len; i++) {
Jean Delvare63420642008-01-27 18:14:50 +0100273 if (i == len && read_write == I2C_SMBUS_READ) {
274 if (command == I2C_SMBUS_I2C_BLOCK_DATA)
275 smbcmd = I801_I2C_BLOCK_LAST;
276 else
277 smbcmd = I801_BLOCK_LAST;
278 } else {
279 if (command == I2C_SMBUS_I2C_BLOCK_DATA
280 && read_write == I2C_SMBUS_READ)
281 smbcmd = I801_I2C_BLOCK_DATA;
282 else
283 smbcmd = I801_BLOCK_DATA;
284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 /* 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);
David Brownell97140342008-07-14 22:38:25 +0200305 return -EBUSY;
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 */
David Brownell97140342008-07-14 22:38:25 +0200309 return -EIO;
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);
David Brownell97140342008-07-14 22:38:25 +0200333 result = -ETIMEDOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
335 }
336
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200337 if (temp & SMBHSTSTS_FAILED) {
David Brownell97140342008-07-14 22:38:25 +0200338 result = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 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) {
David Brownell97140342008-07-14 22:38:25 +0200342 result = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 dev_err(&I801_dev->dev, "Bus collision!\n");
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200344 } else if (temp & SMBHSTSTS_DEV_ERR) {
David Brownell97140342008-07-14 22:38:25 +0200345 result = -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 dev_dbg(&I801_dev->dev, "Error: no response!\n");
347 }
348
Jean Delvare63420642008-01-27 18:14:50 +0100349 if (i == 1 && read_write == I2C_SMBUS_READ
350 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 len = inb_p(SMBHSTDAT0);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200352 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
David Brownell97140342008-07-14 22:38:25 +0200353 return -EPROTO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 data->block[0] = len;
355 }
356
357 /* Retrieve/store value in SMBBLKDAT */
358 if (read_write == I2C_SMBUS_READ)
359 data->block[i] = inb_p(SMBBLKDAT);
360 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
361 outb_p(data->block[i+1], SMBBLKDAT);
362 if ((temp & 0x9e) != 0x00)
363 outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */
364
365 if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
366 dev_dbg(&I801_dev->dev,
367 "Bad status (%02x) at end of transaction\n",
368 temp);
369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
371 if (result < 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200372 return result;
373 }
374 return result;
375}
376
377static int i801_set_block_buffer_mode(void)
378{
379 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
380 if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
David Brownell97140342008-07-14 22:38:25 +0200381 return -EIO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200382 return 0;
383}
384
385/* Block transaction function */
386static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
387 int command, int hwpec)
388{
389 int result = 0;
390 unsigned char hostc;
391
392 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
393 if (read_write == I2C_SMBUS_WRITE) {
394 /* set I2C_EN bit in configuration register */
395 pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
396 pci_write_config_byte(I801_dev, SMBHSTCFG,
397 hostc | SMBHSTCFG_I2C_EN);
Jean Delvare63420642008-01-27 18:14:50 +0100398 } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200399 dev_err(&I801_dev->dev,
Jean Delvare63420642008-01-27 18:14:50 +0100400 "I2C block read is unsupported!\n");
David Brownell97140342008-07-14 22:38:25 +0200401 return -EOPNOTSUPP;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 }
404
Jean Delvare63420642008-01-27 18:14:50 +0100405 if (read_write == I2C_SMBUS_WRITE
406 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200407 if (data->block[0] < 1)
408 data->block[0] = 1;
409 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
410 data->block[0] = I2C_SMBUS_BLOCK_MAX;
411 } else {
Jean Delvare63420642008-01-27 18:14:50 +0100412 data->block[0] = 32; /* max for SMBus block reads */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200413 }
414
Jean Delvare369f6f42008-01-27 18:14:50 +0100415 if ((i801_features & FEATURE_BLOCK_BUFFER)
Jean Delvare63420642008-01-27 18:14:50 +0100416 && !(command == I2C_SMBUS_I2C_BLOCK_DATA
417 && read_write == I2C_SMBUS_READ)
Jean Delvare369f6f42008-01-27 18:14:50 +0100418 && 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,
Jean Delvare63420642008-01-27 18:14:50 +0100423 command, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200424
425 if (result == 0 && hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200426 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Jean Delvare63420642008-01-27 18:14:50 +0100428 if (command == I2C_SMBUS_I2C_BLOCK_DATA
429 && read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 /* restore saved configuration register value */
431 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
432 }
433 return result;
434}
435
David Brownell97140342008-07-14 22:38:25 +0200436/* Return negative errno on error. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437static s32 i801_access(struct i2c_adapter * adap, u16 addr,
438 unsigned short flags, char read_write, u8 command,
439 int size, union i2c_smbus_data * data)
440{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200441 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 int block = 0;
443 int ret, xact = 0;
444
Jean Delvare369f6f42008-01-27 18:14:50 +0100445 hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200446 && size != I2C_SMBUS_QUICK
447 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449 switch (size) {
450 case I2C_SMBUS_QUICK:
451 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
452 SMBHSTADD);
453 xact = I801_QUICK;
454 break;
455 case I2C_SMBUS_BYTE:
456 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
457 SMBHSTADD);
458 if (read_write == I2C_SMBUS_WRITE)
459 outb_p(command, SMBHSTCMD);
460 xact = I801_BYTE;
461 break;
462 case I2C_SMBUS_BYTE_DATA:
463 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
464 SMBHSTADD);
465 outb_p(command, SMBHSTCMD);
466 if (read_write == I2C_SMBUS_WRITE)
467 outb_p(data->byte, SMBHSTDAT0);
468 xact = I801_BYTE_DATA;
469 break;
470 case I2C_SMBUS_WORD_DATA:
471 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
472 SMBHSTADD);
473 outb_p(command, SMBHSTCMD);
474 if (read_write == I2C_SMBUS_WRITE) {
475 outb_p(data->word & 0xff, SMBHSTDAT0);
476 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
477 }
478 xact = I801_WORD_DATA;
479 break;
480 case I2C_SMBUS_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;
Jean Delvare63420642008-01-27 18:14:50 +0100486 case I2C_SMBUS_I2C_BLOCK_DATA:
487 /* NB: page 240 of ICH5 datasheet shows that the R/#W
488 * bit should be cleared here, even when reading */
489 outb_p((addr & 0x7f) << 1, SMBHSTADD);
490 if (read_write == I2C_SMBUS_READ) {
491 /* NB: page 240 of ICH5 datasheet also shows
492 * that DATA1 is the cmd field when reading */
493 outb_p(command, SMBHSTDAT1);
494 } else
495 outb_p(command, SMBHSTCMD);
496 block = 1;
497 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 default:
499 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
David Brownell97140342008-07-14 22:38:25 +0200500 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 }
502
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200503 if (hwpec) /* enable/disable hardware PEC */
504 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
505 else
506 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200509 ret = i801_block_transaction(data, read_write, size, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200510 else
511 ret = i801_transaction(xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Jean Delvarec79cfba2006-04-20 02:43:18 -0700513 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200514 time, so we forcibly disable it after every transaction. Turn off
515 E32B for the same reason. */
Jean Delvarea0921b62008-01-27 18:14:50 +0100516 if (hwpec || block)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200517 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
518 SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 if(block)
521 return ret;
522 if(ret)
David Brownell97140342008-07-14 22:38:25 +0200523 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
525 return 0;
526
527 switch (xact & 0x7f) {
528 case I801_BYTE: /* Result put in SMBHSTDAT0 */
529 case I801_BYTE_DATA:
530 data->byte = inb_p(SMBHSTDAT0);
531 break;
532 case I801_WORD_DATA:
533 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
534 break;
535 }
536 return 0;
537}
538
539
540static u32 i801_func(struct i2c_adapter *adapter)
541{
542 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Jean Delvare369f6f42008-01-27 18:14:50 +0100543 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
544 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
Jean Delvare63420642008-01-27 18:14:50 +0100545 ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
546 ((i801_features & FEATURE_I2C_BLOCK_READ) ?
547 I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548}
549
Jean Delvare8f9082c2006-09-03 22:39:46 +0200550static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 .smbus_xfer = i801_access,
552 .functionality = i801_func,
553};
554
555static struct i2c_adapter i801_adapter = {
556 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100557 .id = I2C_HW_SMBUS_I801,
Jean Delvare3401b2f2008-07-14 22:38:29 +0200558 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560};
561
562static struct pci_device_id i801_ids[] = {
563 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
564 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
565 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
566 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
567 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
568 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
569 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
570 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
571 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700572 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800573 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800574 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Jason Gastone07bc672007-10-13 23:56:31 +0200575 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
Gaston, Jason Dd28dc712008-02-24 20:03:42 +0100576 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
577 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 { 0, }
579};
580
581MODULE_DEVICE_TABLE (pci, i801_ids);
582
583static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
584{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200585 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200586 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200588 I801_dev = dev;
Jean Delvare369f6f42008-01-27 18:14:50 +0100589 i801_features = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100590 switch (dev->device) {
Jean Delvare250d1bd2006-12-10 21:21:33 +0100591 case PCI_DEVICE_ID_INTEL_82801EB_3:
592 case PCI_DEVICE_ID_INTEL_ESB_4:
593 case PCI_DEVICE_ID_INTEL_ICH6_16:
594 case PCI_DEVICE_ID_INTEL_ICH7_17:
595 case PCI_DEVICE_ID_INTEL_ESB2_17:
596 case PCI_DEVICE_ID_INTEL_ICH8_5:
597 case PCI_DEVICE_ID_INTEL_ICH9_6:
Gaston, Jason Dd28dc712008-02-24 20:03:42 +0100598 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
599 case PCI_DEVICE_ID_INTEL_ICH10_4:
600 case PCI_DEVICE_ID_INTEL_ICH10_5:
Jean Delvare63420642008-01-27 18:14:50 +0100601 i801_features |= FEATURE_I2C_BLOCK_READ;
602 /* fall through */
603 case PCI_DEVICE_ID_INTEL_82801DB_3:
Jean Delvare369f6f42008-01-27 18:14:50 +0100604 i801_features |= FEATURE_SMBUS_PEC;
605 i801_features |= FEATURE_BLOCK_BUFFER;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100606 break;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100607 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200608
609 err = pci_enable_device(dev);
610 if (err) {
611 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
612 err);
613 goto exit;
614 }
615
616 /* Determine the address of the SMBus area */
617 i801_smba = pci_resource_start(dev, SMBBAR);
618 if (!i801_smba) {
619 dev_err(&dev->dev, "SMBus base address uninitialized, "
620 "upgrade BIOS\n");
621 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200622 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200623 }
624
625 err = pci_request_region(dev, SMBBAR, i801_driver.name);
626 if (err) {
627 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700628 "0x%lx-0x%Lx\n", i801_smba,
629 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200630 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200631 }
632
633 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100634 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200635 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
636 if (!(temp & SMBHSTCFG_HST_EN)) {
637 dev_info(&dev->dev, "Enabling SMBus device\n");
638 temp |= SMBHSTCFG_HST_EN;
639 }
640 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
641
642 if (temp & SMBHSTCFG_SMB_SMI_EN)
643 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
644 else
645 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Jean Delvarea0921b62008-01-27 18:14:50 +0100647 /* Clear special mode bits */
648 if (i801_features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
649 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
650 SMBAUXCTL);
651
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100652 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 i801_adapter.dev.parent = &dev->dev;
654
David Brownell2096b952007-05-01 23:26:28 +0200655 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200656 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200657 err = i2c_add_adapter(&i801_adapter);
658 if (err) {
659 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200660 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200661 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200662 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200663
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200664exit_release:
665 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200666exit:
667 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668}
669
670static void __devexit i801_remove(struct pci_dev *dev)
671{
672 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100673 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200674 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200675 /*
676 * do not call pci_disable_device(dev) since it can cause hard hangs on
677 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
678 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679}
680
Jean Delvarea5aaea32007-03-22 19:49:01 +0100681#ifdef CONFIG_PM
682static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
683{
684 pci_save_state(dev);
685 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
686 pci_set_power_state(dev, pci_choose_state(dev, mesg));
687 return 0;
688}
689
690static int i801_resume(struct pci_dev *dev)
691{
692 pci_set_power_state(dev, PCI_D0);
693 pci_restore_state(dev);
694 return pci_enable_device(dev);
695}
696#else
697#define i801_suspend NULL
698#define i801_resume NULL
699#endif
700
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 .name = "i801_smbus",
703 .id_table = i801_ids,
704 .probe = i801_probe,
705 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100706 .suspend = i801_suspend,
707 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708};
709
710static int __init i2c_i801_init(void)
711{
712 return pci_register_driver(&i801_driver);
713}
714
715static void __exit i2c_i801_exit(void)
716{
717 pci_unregister_driver(&i801_driver);
718}
719
Jean Delvare63420642008-01-27 18:14:50 +0100720MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
721 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722MODULE_DESCRIPTION("I801 SMBus driver");
723MODULE_LICENSE("GPL");
724
725module_init(i2c_i801_init);
726module_exit(i2c_i801_exit);