blob: 73bd8552734ce555d9382d66d4e57e96fdd863ed [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{
Jean Delvare2b738092008-07-14 22:38:32 +0200137 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 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 */
Jean Delvare2b738092008-07-14 22:38:32 +0200143 if ((status = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare541e6a02005-06-23 22:18:08 +0200144 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
Jean Delvare2b738092008-07-14 22:38:32 +0200145 status);
146 outb_p(status, SMBHSTSTS);
147 if ((status = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
148 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", status);
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);
Jean Delvare2b738092008-07-14 22:38:32 +0200162 status = inb_p(SMBHSTSTS);
163 } while ((status & 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
Jean Delvare2b738092008-07-14 22:38:32 +0200176 if (status & 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
Jean Delvare2b738092008-07-14 22:38:32 +0200181 if (status & SMBHSTSTS_BUS_ERR) {
Jean Delvaredcb5c922008-07-14 22:38:32 +0200182 result = -EAGAIN;
183 dev_dbg(&I801_dev->dev, "Lost arbitration\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 }
185
Jean Delvare2b738092008-07-14 22:38:32 +0200186 if (status & SMBHSTSTS_DEV_ERR) {
David Brownell97140342008-07-14 22:38:25 +0200187 result = -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 dev_dbg(&I801_dev->dev, "Error: no response!\n");
189 }
190
191 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
192 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
193
Jean Delvare2b738092008-07-14 22:38:32 +0200194 if ((status = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
Jean Delvare368609c2005-07-29 12:15:07 -0700195 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
Jean Delvare2b738092008-07-14 22:38:32 +0200196 "(%02x)\n", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return result;
199}
200
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200201/* wait for INTR bit as advised by Intel */
202static void i801_wait_hwpec(void)
203{
204 int timeout = 0;
Jean Delvare2b738092008-07-14 22:38:32 +0200205 int status;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200206
207 do {
208 msleep(1);
Jean Delvare2b738092008-07-14 22:38:32 +0200209 status = inb_p(SMBHSTSTS);
210 } while ((!(status & SMBHSTSTS_INTR))
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200211 && (timeout++ < MAX_TIMEOUT));
212
213 if (timeout >= MAX_TIMEOUT) {
214 dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
215 }
Jean Delvare2b738092008-07-14 22:38:32 +0200216 outb_p(status, SMBHSTSTS);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200217}
218
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200219static int i801_block_transaction_by_block(union i2c_smbus_data *data,
220 char read_write, int hwpec)
221{
222 int i, len;
David Brownell97140342008-07-14 22:38:25 +0200223 int status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200224
225 inb_p(SMBHSTCNT); /* reset the data buffer index */
226
227 /* Use 32-byte buffer to process this transaction */
228 if (read_write == I2C_SMBUS_WRITE) {
229 len = data->block[0];
230 outb_p(len, SMBHSTDAT0);
231 for (i = 0; i < len; i++)
232 outb_p(data->block[i+1], SMBBLKDAT);
233 }
234
David Brownell97140342008-07-14 22:38:25 +0200235 status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
236 I801_PEC_EN * hwpec);
237 if (status)
238 return status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200239
240 if (read_write == I2C_SMBUS_READ) {
241 len = inb_p(SMBHSTDAT0);
242 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
David Brownell97140342008-07-14 22:38:25 +0200243 return -EPROTO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200244
245 data->block[0] = len;
246 for (i = 0; i < len; i++)
247 data->block[i + 1] = inb_p(SMBBLKDAT);
248 }
249 return 0;
250}
251
252static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
Jean Delvare63420642008-01-27 18:14:50 +0100253 char read_write, int command,
254 int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255{
256 int i, len;
257 int smbcmd;
Jean Delvare2b738092008-07-14 22:38:32 +0200258 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 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++) {
Jean Delvare63420642008-01-27 18:14:50 +0100271 if (i == len && read_write == I2C_SMBUS_READ) {
272 if (command == I2C_SMBUS_I2C_BLOCK_DATA)
273 smbcmd = I801_I2C_BLOCK_LAST;
274 else
275 smbcmd = I801_BLOCK_LAST;
276 } else {
277 if (command == I2C_SMBUS_I2C_BLOCK_DATA
278 && read_write == I2C_SMBUS_READ)
279 smbcmd = I801_I2C_BLOCK_DATA;
280 else
281 smbcmd = I801_BLOCK_DATA;
282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 /* Make sure the SMBus host is ready to start transmitting */
Jean Delvare2b738092008-07-14 22:38:32 +0200286 status = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 if (i == 1) {
Jean Delvare002cf632007-08-14 18:37:13 +0200288 /* Erroneous conditions before transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200290 errmask = 0x9f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 } else {
Jean Delvare002cf632007-08-14 18:37:13 +0200292 /* Erroneous conditions during transaction:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 * Failed, Bus_Err, Dev_Err, Intr */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200294 errmask = 0x1e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 }
Jean Delvare2b738092008-07-14 22:38:32 +0200296 if (status & errmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
Jean Delvare2b738092008-07-14 22:38:32 +0200298 "Resetting...\n", status);
299 outb_p(status, SMBHSTSTS);
300 if (((status = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 dev_err(&I801_dev->dev,
Jean Delvare2b738092008-07-14 22:38:32 +0200302 "Reset failed! (%02x)\n", status);
David Brownell97140342008-07-14 22:38:25 +0200303 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 }
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200305 if (i != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 /* if die in middle of block transaction, fail */
David Brownell97140342008-07-14 22:38:25 +0200307 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 }
309
310 if (i == 1)
311 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
312
313 /* We will always wait for a fraction of a second! */
314 timeout = 0;
315 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 msleep(1);
Jean Delvare2b738092008-07-14 22:38:32 +0200317 status = inb_p(SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 }
Jean Delvare2b738092008-07-14 22:38:32 +0200319 while ((!(status & SMBHSTSTS_BYTE_DONE))
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200320 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
322 /* If the SMBus is still busy, we give up */
323 if (timeout >= MAX_TIMEOUT) {
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200324 /* try to stop the current command */
325 dev_dbg(&I801_dev->dev, "Terminating the current "
326 "operation\n");
327 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
328 msleep(1);
329 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
330 SMBHSTCNT);
David Brownell97140342008-07-14 22:38:25 +0200331 result = -ETIMEDOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
333 }
334
Jean Delvare2b738092008-07-14 22:38:32 +0200335 if (status & SMBHSTSTS_FAILED) {
David Brownell97140342008-07-14 22:38:25 +0200336 result = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 dev_dbg(&I801_dev->dev,
338 "Error: Failed bus transaction\n");
Jean Delvare2b738092008-07-14 22:38:32 +0200339 } else if (status & SMBHSTSTS_BUS_ERR) {
Jean Delvaredcb5c922008-07-14 22:38:32 +0200340 result = -EAGAIN;
341 dev_dbg(&I801_dev->dev, "Lost arbitration\n");
Jean Delvare2b738092008-07-14 22:38:32 +0200342 } else if (status & SMBHSTSTS_DEV_ERR) {
David Brownell97140342008-07-14 22:38:25 +0200343 result = -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 dev_dbg(&I801_dev->dev, "Error: no response!\n");
345 }
346
Jean Delvare63420642008-01-27 18:14:50 +0100347 if (i == 1 && read_write == I2C_SMBUS_READ
348 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 len = inb_p(SMBHSTDAT0);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200350 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
David Brownell97140342008-07-14 22:38:25 +0200351 return -EPROTO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 data->block[0] = len;
353 }
354
355 /* Retrieve/store value in SMBBLKDAT */
356 if (read_write == I2C_SMBUS_READ)
357 data->block[i] = inb_p(SMBBLKDAT);
358 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
359 outb_p(data->block[i+1], SMBBLKDAT);
Jean Delvare2b738092008-07-14 22:38:32 +0200360 if ((status & 0x9e) != 0x00)
361 outb_p(status, SMBHSTSTS); /* signals SMBBLKDAT ready */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
Jean Delvare2b738092008-07-14 22:38:32 +0200363 if ((status = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 dev_dbg(&I801_dev->dev,
365 "Bad status (%02x) at end of transaction\n",
Jean Delvare2b738092008-07-14 22:38:32 +0200366 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
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)
David Brownell97140342008-07-14 22:38:25 +0200379 return -EIO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200380 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);
Jean Delvare63420642008-01-27 18:14:50 +0100396 } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200397 dev_err(&I801_dev->dev,
Jean Delvare63420642008-01-27 18:14:50 +0100398 "I2C block read is unsupported!\n");
David Brownell97140342008-07-14 22:38:25 +0200399 return -EOPNOTSUPP;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
402
Jean Delvare63420642008-01-27 18:14:50 +0100403 if (read_write == I2C_SMBUS_WRITE
404 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200405 if (data->block[0] < 1)
406 data->block[0] = 1;
407 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
408 data->block[0] = I2C_SMBUS_BLOCK_MAX;
409 } else {
Jean Delvare63420642008-01-27 18:14:50 +0100410 data->block[0] = 32; /* max for SMBus block reads */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200411 }
412
Jean Delvare369f6f42008-01-27 18:14:50 +0100413 if ((i801_features & FEATURE_BLOCK_BUFFER)
Jean Delvare63420642008-01-27 18:14:50 +0100414 && !(command == I2C_SMBUS_I2C_BLOCK_DATA
415 && read_write == I2C_SMBUS_READ)
Jean Delvare369f6f42008-01-27 18:14:50 +0100416 && i801_set_block_buffer_mode() == 0)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200417 result = i801_block_transaction_by_block(data, read_write,
418 hwpec);
419 else
420 result = i801_block_transaction_byte_by_byte(data, read_write,
Jean Delvare63420642008-01-27 18:14:50 +0100421 command, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200422
423 if (result == 0 && hwpec)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200424 i801_wait_hwpec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Jean Delvare63420642008-01-27 18:14:50 +0100426 if (command == I2C_SMBUS_I2C_BLOCK_DATA
427 && read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 /* restore saved configuration register value */
429 pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
430 }
431 return result;
432}
433
David Brownell97140342008-07-14 22:38:25 +0200434/* Return negative errno on error. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435static s32 i801_access(struct i2c_adapter * adap, u16 addr,
436 unsigned short flags, char read_write, u8 command,
437 int size, union i2c_smbus_data * data)
438{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200439 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 int block = 0;
441 int ret, xact = 0;
442
Jean Delvare369f6f42008-01-27 18:14:50 +0100443 hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200444 && size != I2C_SMBUS_QUICK
445 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
447 switch (size) {
448 case I2C_SMBUS_QUICK:
449 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
450 SMBHSTADD);
451 xact = I801_QUICK;
452 break;
453 case I2C_SMBUS_BYTE:
454 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
455 SMBHSTADD);
456 if (read_write == I2C_SMBUS_WRITE)
457 outb_p(command, SMBHSTCMD);
458 xact = I801_BYTE;
459 break;
460 case I2C_SMBUS_BYTE_DATA:
461 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
462 SMBHSTADD);
463 outb_p(command, SMBHSTCMD);
464 if (read_write == I2C_SMBUS_WRITE)
465 outb_p(data->byte, SMBHSTDAT0);
466 xact = I801_BYTE_DATA;
467 break;
468 case I2C_SMBUS_WORD_DATA:
469 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
470 SMBHSTADD);
471 outb_p(command, SMBHSTCMD);
472 if (read_write == I2C_SMBUS_WRITE) {
473 outb_p(data->word & 0xff, SMBHSTDAT0);
474 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
475 }
476 xact = I801_WORD_DATA;
477 break;
478 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
480 SMBHSTADD);
481 outb_p(command, SMBHSTCMD);
482 block = 1;
483 break;
Jean Delvare63420642008-01-27 18:14:50 +0100484 case I2C_SMBUS_I2C_BLOCK_DATA:
485 /* NB: page 240 of ICH5 datasheet shows that the R/#W
486 * bit should be cleared here, even when reading */
487 outb_p((addr & 0x7f) << 1, SMBHSTADD);
488 if (read_write == I2C_SMBUS_READ) {
489 /* NB: page 240 of ICH5 datasheet also shows
490 * that DATA1 is the cmd field when reading */
491 outb_p(command, SMBHSTDAT1);
492 } else
493 outb_p(command, SMBHSTCMD);
494 block = 1;
495 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 default:
497 dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
David Brownell97140342008-07-14 22:38:25 +0200498 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200501 if (hwpec) /* enable/disable hardware PEC */
502 outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
503 else
504 outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200505
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 if(block)
Jean Delvare585b3162005-10-26 21:31:15 +0200507 ret = i801_block_transaction(data, read_write, size, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200508 else
509 ret = i801_transaction(xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
Jean Delvarec79cfba2006-04-20 02:43:18 -0700511 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200512 time, so we forcibly disable it after every transaction. Turn off
513 E32B for the same reason. */
Jean Delvarea0921b62008-01-27 18:14:50 +0100514 if (hwpec || block)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200515 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
516 SMBAUXCTL);
Jean Delvarec79cfba2006-04-20 02:43:18 -0700517
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if(block)
519 return ret;
520 if(ret)
David Brownell97140342008-07-14 22:38:25 +0200521 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
523 return 0;
524
525 switch (xact & 0x7f) {
526 case I801_BYTE: /* Result put in SMBHSTDAT0 */
527 case I801_BYTE_DATA:
528 data->byte = inb_p(SMBHSTDAT0);
529 break;
530 case I801_WORD_DATA:
531 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
532 break;
533 }
534 return 0;
535}
536
537
538static u32 i801_func(struct i2c_adapter *adapter)
539{
540 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Jean Delvare369f6f42008-01-27 18:14:50 +0100541 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
542 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
Jean Delvare63420642008-01-27 18:14:50 +0100543 ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
544 ((i801_features & FEATURE_I2C_BLOCK_READ) ?
545 I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546}
547
Jean Delvare8f9082c2006-09-03 22:39:46 +0200548static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 .smbus_xfer = i801_access,
550 .functionality = i801_func,
551};
552
553static struct i2c_adapter i801_adapter = {
554 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100555 .id = I2C_HW_SMBUS_I801,
Jean Delvare3401b2f2008-07-14 22:38:29 +0200556 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558};
559
560static struct pci_device_id i801_ids[] = {
561 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
562 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
563 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
564 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
565 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
566 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
567 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
568 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
569 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700570 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800571 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800572 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Jason Gastone07bc672007-10-13 23:56:31 +0200573 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
Gaston, Jason Dd28dc712008-02-24 20:03:42 +0100574 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
575 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 { 0, }
577};
578
579MODULE_DEVICE_TABLE (pci, i801_ids);
580
581static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
582{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200583 unsigned char temp;
Jean Delvare455f3322006-06-12 21:52:02 +0200584 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200586 I801_dev = dev;
Jean Delvare369f6f42008-01-27 18:14:50 +0100587 i801_features = 0;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100588 switch (dev->device) {
Jean Delvare250d1bd2006-12-10 21:21:33 +0100589 case PCI_DEVICE_ID_INTEL_82801EB_3:
590 case PCI_DEVICE_ID_INTEL_ESB_4:
591 case PCI_DEVICE_ID_INTEL_ICH6_16:
592 case PCI_DEVICE_ID_INTEL_ICH7_17:
593 case PCI_DEVICE_ID_INTEL_ESB2_17:
594 case PCI_DEVICE_ID_INTEL_ICH8_5:
595 case PCI_DEVICE_ID_INTEL_ICH9_6:
Gaston, Jason Dd28dc712008-02-24 20:03:42 +0100596 case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
597 case PCI_DEVICE_ID_INTEL_ICH10_4:
598 case PCI_DEVICE_ID_INTEL_ICH10_5:
Jean Delvare63420642008-01-27 18:14:50 +0100599 i801_features |= FEATURE_I2C_BLOCK_READ;
600 /* fall through */
601 case PCI_DEVICE_ID_INTEL_82801DB_3:
Jean Delvare369f6f42008-01-27 18:14:50 +0100602 i801_features |= FEATURE_SMBUS_PEC;
603 i801_features |= FEATURE_BLOCK_BUFFER;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100604 break;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100605 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200606
607 err = pci_enable_device(dev);
608 if (err) {
609 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
610 err);
611 goto exit;
612 }
613
614 /* Determine the address of the SMBus area */
615 i801_smba = pci_resource_start(dev, SMBBAR);
616 if (!i801_smba) {
617 dev_err(&dev->dev, "SMBus base address uninitialized, "
618 "upgrade BIOS\n");
619 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200620 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200621 }
622
623 err = pci_request_region(dev, SMBBAR, i801_driver.name);
624 if (err) {
625 dev_err(&dev->dev, "Failed to request SMBus region "
Andrew Morton598736c2006-06-30 01:56:20 -0700626 "0x%lx-0x%Lx\n", i801_smba,
627 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200628 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200629 }
630
631 pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100632 i801_original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200633 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
634 if (!(temp & SMBHSTCFG_HST_EN)) {
635 dev_info(&dev->dev, "Enabling SMBus device\n");
636 temp |= SMBHSTCFG_HST_EN;
637 }
638 pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
639
640 if (temp & SMBHSTCFG_SMB_SMI_EN)
641 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
642 else
643 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Jean Delvarea0921b62008-01-27 18:14:50 +0100645 /* Clear special mode bits */
646 if (i801_features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
647 outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
648 SMBAUXCTL);
649
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100650 /* set up the sysfs linkage to our parent device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 i801_adapter.dev.parent = &dev->dev;
652
David Brownell2096b952007-05-01 23:26:28 +0200653 snprintf(i801_adapter.name, sizeof(i801_adapter.name),
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200654 "SMBus I801 adapter at %04lx", i801_smba);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200655 err = i2c_add_adapter(&i801_adapter);
656 if (err) {
657 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200658 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200659 }
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200660 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200661
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200662exit_release:
663 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200664exit:
665 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666}
667
668static void __devexit i801_remove(struct pci_dev *dev)
669{
670 i2c_del_adapter(&i801_adapter);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100671 pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200672 pci_release_region(dev, SMBBAR);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200673 /*
674 * do not call pci_disable_device(dev) since it can cause hard hangs on
675 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
676 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677}
678
Jean Delvarea5aaea32007-03-22 19:49:01 +0100679#ifdef CONFIG_PM
680static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
681{
682 pci_save_state(dev);
683 pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg);
684 pci_set_power_state(dev, pci_choose_state(dev, mesg));
685 return 0;
686}
687
688static int i801_resume(struct pci_dev *dev)
689{
690 pci_set_power_state(dev, PCI_D0);
691 pci_restore_state(dev);
692 return pci_enable_device(dev);
693}
694#else
695#define i801_suspend NULL
696#define i801_resume NULL
697#endif
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 .name = "i801_smbus",
701 .id_table = i801_ids,
702 .probe = i801_probe,
703 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100704 .suspend = i801_suspend,
705 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706};
707
708static int __init i2c_i801_init(void)
709{
710 return pci_register_driver(&i801_driver);
711}
712
713static void __exit i2c_i801_exit(void)
714{
715 pci_unregister_driver(&i801_driver);
716}
717
Jean Delvare63420642008-01-27 18:14:50 +0100718MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
719 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720MODULE_DESCRIPTION("I801 SMBus driver");
721MODULE_LICENSE("GPL");
722
723module_init(i2c_i801_init);
724module_exit(i2c_i801_exit);