blob: 56883f48c2e4179a136febb4ef4e07489bcb5777 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
3 Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
4 <mdsxyz123@yahoo.com>
Jean Delvarecf898dc2008-07-14 22:38:33 +02005 Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org>
David Woodhouse0cd96eb2010-10-31 21:06:59 +01006 Copyright (C) 2010 Intel Corporation,
7 David Woodhouse <dwmw2@infradead.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
Seth Heasleycb04e952010-10-04 13:27:14 -070043 EP80579 (Tolapai) 0x5032 32 hard yes yes yes
Gaston, Jason Dd28dc712008-02-24 20:03:42 +010044 ICH10 0x3a30 32 hard yes yes yes
45 ICH10 0x3a60 32 hard yes yes yes
Seth Heasleycb04e952010-10-04 13:27:14 -070046 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes
Seth Heasley39376432010-03-02 12:23:39 +010047 Cougar Point (PCH) 0x1c22 32 hard yes yes yes
Seth Heasleye30d9852010-10-31 21:06:59 +010048 Patsburg (PCH) 0x1d22 32 hard yes yes yes
Jean Delvareae7b0492008-01-27 18:14:49 +010049
50 Features supported by this driver:
51 Software PEC no
52 Hardware PEC yes
53 Block buffer yes
54 Block process call transaction no
Jean Delvare63420642008-01-27 18:14:50 +010055 I2C block read transaction yes (doesn't use the block buffer)
Jean Delvareae7b0492008-01-27 18:14:49 +010056
57 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070058*/
59
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#include <linux/module.h>
61#include <linux/pci.h>
62#include <linux/kernel.h>
63#include <linux/stddef.h>
64#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/ioport.h>
66#include <linux/init.h>
67#include <linux/i2c.h>
Jean Delvare54fb4a052008-07-14 22:38:33 +020068#include <linux/acpi.h>
Jean Delvare1561bfe2009-01-07 14:29:17 +010069#include <linux/io.h>
Hans de Goedefa5bfab2009-03-30 21:46:44 +020070#include <linux/dmi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Linus Torvalds1da177e2005-04-16 15:20:36 -070072/* I801 SMBus address offsets */
David Woodhouse0cd96eb2010-10-31 21:06:59 +010073#define SMBHSTSTS(p) (0 + (p)->smba)
74#define SMBHSTCNT(p) (2 + (p)->smba)
75#define SMBHSTCMD(p) (3 + (p)->smba)
76#define SMBHSTADD(p) (4 + (p)->smba)
77#define SMBHSTDAT0(p) (5 + (p)->smba)
78#define SMBHSTDAT1(p) (6 + (p)->smba)
79#define SMBBLKDAT(p) (7 + (p)->smba)
80#define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */
81#define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */
82#define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
84/* PCI Address Constants */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020085#define SMBBAR 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070086#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88/* Host configuration bits for SMBHSTCFG */
89#define SMBHSTCFG_HST_EN 1
90#define SMBHSTCFG_SMB_SMI_EN 2
91#define SMBHSTCFG_I2C_EN 4
92
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +020093/* Auxillary control register bits, ICH4+ only */
94#define SMBAUXCTL_CRC 1
95#define SMBAUXCTL_E32B 2
96
97/* kill bit for SMBHSTCNT */
98#define SMBHSTCNT_KILL 2
99
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100/* Other settings */
101#define MAX_TIMEOUT 100
102#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
103
104/* I801 command constants */
105#define I801_QUICK 0x00
106#define I801_BYTE 0x04
107#define I801_BYTE_DATA 0x08
108#define I801_WORD_DATA 0x0C
Jean Delvareae7b0492008-01-27 18:14:49 +0100109#define I801_PROC_CALL 0x10 /* unimplemented */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110#define I801_BLOCK_DATA 0x14
Jean Delvare63420642008-01-27 18:14:50 +0100111#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#define I801_BLOCK_LAST 0x34
Jean Delvare63420642008-01-27 18:14:50 +0100113#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#define I801_START 0x40
Jean Delvareae7b0492008-01-27 18:14:49 +0100115#define I801_PEC_EN 0x80 /* ICH3 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200117/* I801 Hosts Status register bits */
118#define SMBHSTSTS_BYTE_DONE 0x80
119#define SMBHSTSTS_INUSE_STS 0x40
120#define SMBHSTSTS_SMBALERT_STS 0x20
121#define SMBHSTSTS_FAILED 0x10
122#define SMBHSTSTS_BUS_ERR 0x08
123#define SMBHSTSTS_DEV_ERR 0x04
124#define SMBHSTSTS_INTR 0x02
125#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Jean Delvarecf898dc2008-07-14 22:38:33 +0200127#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
128 SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
129 SMBHSTSTS_INTR)
130
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100131struct i801_priv {
132 struct i2c_adapter adapter;
133 unsigned long smba;
134 unsigned char original_hstcfg;
135 struct pci_dev *pci_dev;
136 unsigned int features;
137};
138
Jean Delvared6072f82005-09-25 16:37:04 +0200139static struct pci_driver i801_driver;
Jean Delvare369f6f42008-01-27 18:14:50 +0100140
141#define FEATURE_SMBUS_PEC (1 << 0)
142#define FEATURE_BLOCK_BUFFER (1 << 1)
143#define FEATURE_BLOCK_PROC (1 << 2)
144#define FEATURE_I2C_BLOCK_READ (1 << 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Jean Delvareadff6872010-05-21 18:40:54 +0200146static const char *i801_feature_names[] = {
147 "SMBus PEC",
148 "Block buffer",
149 "Block process call",
150 "I2C block read",
151};
152
153static unsigned int disable_features;
154module_param(disable_features, uint, S_IRUGO | S_IWUSR);
155MODULE_PARM_DESC(disable_features, "Disable selected driver features");
156
Jean Delvarecf898dc2008-07-14 22:38:33 +0200157/* Make sure the SMBus host is ready to start transmitting.
158 Return 0 if it is, -EBUSY if it is not. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100159static int i801_check_pre(struct i801_priv *priv)
Jean Delvarecf898dc2008-07-14 22:38:33 +0200160{
161 int status;
162
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100163 status = inb_p(SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200164 if (status & SMBHSTSTS_HOST_BUSY) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100165 dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200166 return -EBUSY;
167 }
168
169 status &= STATUS_FLAGS;
170 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100171 dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n",
Jean Delvarecf898dc2008-07-14 22:38:33 +0200172 status);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100173 outb_p(status, SMBHSTSTS(priv));
174 status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200175 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100176 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200177 "Failed clearing status flags (%02x)\n",
178 status);
179 return -EBUSY;
180 }
181 }
182
183 return 0;
184}
185
186/* Convert the status register to an error code, and clear it. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100187static int i801_check_post(struct i801_priv *priv, int status, int timeout)
Jean Delvarecf898dc2008-07-14 22:38:33 +0200188{
189 int result = 0;
190
191 /* If the SMBus is still busy, we give up */
192 if (timeout) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100193 dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200194 /* try to stop the current command */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100195 dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
196 outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
197 SMBHSTCNT(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200198 msleep(1);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100199 outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
200 SMBHSTCNT(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200201
202 /* Check if it worked */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100203 status = inb_p(SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200204 if ((status & SMBHSTSTS_HOST_BUSY) ||
205 !(status & SMBHSTSTS_FAILED))
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100206 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200207 "Failed terminating the transaction\n");
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100208 outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200209 return -ETIMEDOUT;
210 }
211
212 if (status & SMBHSTSTS_FAILED) {
213 result = -EIO;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100214 dev_err(&priv->pci_dev->dev, "Transaction failed\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200215 }
216 if (status & SMBHSTSTS_DEV_ERR) {
217 result = -ENXIO;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100218 dev_dbg(&priv->pci_dev->dev, "No response\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200219 }
220 if (status & SMBHSTSTS_BUS_ERR) {
221 result = -EAGAIN;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100222 dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200223 }
224
225 if (result) {
226 /* Clear error flags */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100227 outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv));
228 status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200229 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100230 dev_warn(&priv->pci_dev->dev, "Failed clearing status "
Jean Delvarecf898dc2008-07-14 22:38:33 +0200231 "flags at end of transaction (%02x)\n",
232 status);
233 }
234 }
235
236 return result;
237}
238
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100239static int i801_transaction(struct i801_priv *priv, int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
Jean Delvare2b738092008-07-14 22:38:32 +0200241 int status;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200242 int result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 int timeout = 0;
244
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100245 result = i801_check_pre(priv);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200246 if (result < 0)
247 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200249 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
250 * INTREN, SMBSCMD are passed in xact */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100251 outb_p(xact | I801_START, SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253 /* We will always wait for a fraction of a second! */
254 do {
255 msleep(1);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100256 status = inb_p(SMBHSTSTS(priv));
Jean Delvare2b738092008-07-14 22:38:32 +0200257 } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100259 result = i801_check_post(priv, status, timeout > MAX_TIMEOUT);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200260 if (result < 0)
261 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100263 outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200264 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265}
266
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200267/* wait for INTR bit as advised by Intel */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100268static void i801_wait_hwpec(struct i801_priv *priv)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200269{
270 int timeout = 0;
Jean Delvare2b738092008-07-14 22:38:32 +0200271 int status;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200272
273 do {
274 msleep(1);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100275 status = inb_p(SMBHSTSTS(priv));
Jean Delvare2b738092008-07-14 22:38:32 +0200276 } while ((!(status & SMBHSTSTS_INTR))
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200277 && (timeout++ < MAX_TIMEOUT));
278
Roel Kluin4ccc28f2009-05-05 08:39:24 +0200279 if (timeout > MAX_TIMEOUT)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100280 dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n");
Roel Kluin4ccc28f2009-05-05 08:39:24 +0200281
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100282 outb_p(status, SMBHSTSTS(priv));
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200283}
284
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100285static int i801_block_transaction_by_block(struct i801_priv *priv,
286 union i2c_smbus_data *data,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200287 char read_write, int hwpec)
288{
289 int i, len;
David Brownell97140342008-07-14 22:38:25 +0200290 int status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200291
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100292 inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200293
294 /* Use 32-byte buffer to process this transaction */
295 if (read_write == I2C_SMBUS_WRITE) {
296 len = data->block[0];
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100297 outb_p(len, SMBHSTDAT0(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200298 for (i = 0; i < len; i++)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100299 outb_p(data->block[i+1], SMBBLKDAT(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200300 }
301
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100302 status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 |
David Brownell97140342008-07-14 22:38:25 +0200303 I801_PEC_EN * hwpec);
304 if (status)
305 return status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200306
307 if (read_write == I2C_SMBUS_READ) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100308 len = inb_p(SMBHSTDAT0(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200309 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
David Brownell97140342008-07-14 22:38:25 +0200310 return -EPROTO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200311
312 data->block[0] = len;
313 for (i = 0; i < len; i++)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100314 data->block[i + 1] = inb_p(SMBBLKDAT(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200315 }
316 return 0;
317}
318
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100319static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
320 union i2c_smbus_data *data,
Jean Delvare63420642008-01-27 18:14:50 +0100321 char read_write, int command,
322 int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
324 int i, len;
325 int smbcmd;
Jean Delvare2b738092008-07-14 22:38:32 +0200326 int status;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200327 int result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 int timeout;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200329
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100330 result = i801_check_pre(priv);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200331 if (result < 0)
332 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200334 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336 if (read_write == I2C_SMBUS_WRITE) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100337 outb_p(len, SMBHSTDAT0(priv));
338 outb_p(data->block[1], SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 }
340
341 for (i = 1; i <= len; i++) {
Jean Delvare63420642008-01-27 18:14:50 +0100342 if (i == len && read_write == I2C_SMBUS_READ) {
343 if (command == I2C_SMBUS_I2C_BLOCK_DATA)
344 smbcmd = I801_I2C_BLOCK_LAST;
345 else
346 smbcmd = I801_BLOCK_LAST;
347 } else {
348 if (command == I2C_SMBUS_I2C_BLOCK_DATA
349 && read_write == I2C_SMBUS_READ)
350 smbcmd = I801_I2C_BLOCK_DATA;
351 else
352 smbcmd = I801_BLOCK_DATA;
353 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100354 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 if (i == 1)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100357 outb_p(inb(SMBHSTCNT(priv)) | I801_START,
358 SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
360 /* We will always wait for a fraction of a second! */
361 timeout = 0;
362 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 msleep(1);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100364 status = inb_p(SMBHSTSTS(priv));
Ivo Manca3fb21c62010-05-21 18:40:55 +0200365 } while ((!(status & SMBHSTSTS_BYTE_DONE))
366 && (timeout++ < MAX_TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100368 result = i801_check_post(priv, status, timeout > MAX_TIMEOUT);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200369 if (result < 0)
370 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Jean Delvare63420642008-01-27 18:14:50 +0100372 if (i == 1 && read_write == I2C_SMBUS_READ
373 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100374 len = inb_p(SMBHSTDAT0(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200375 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100376 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200377 "Illegal SMBus block read size %d\n",
378 len);
379 /* Recover */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100380 while (inb_p(SMBHSTSTS(priv)) &
381 SMBHSTSTS_HOST_BUSY)
382 outb_p(SMBHSTSTS_BYTE_DONE,
383 SMBHSTSTS(priv));
384 outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
David Brownell97140342008-07-14 22:38:25 +0200385 return -EPROTO;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 data->block[0] = len;
388 }
389
390 /* Retrieve/store value in SMBBLKDAT */
391 if (read_write == I2C_SMBUS_READ)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100392 data->block[i] = inb_p(SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100394 outb_p(data->block[i+1], SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Jean Delvarecf898dc2008-07-14 22:38:33 +0200396 /* signals SMBBLKDAT ready */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100397 outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200398 }
Jean Delvarecf898dc2008-07-14 22:38:33 +0200399
400 return 0;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200401}
402
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100403static int i801_set_block_buffer_mode(struct i801_priv *priv)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200404{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100405 outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
406 if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
David Brownell97140342008-07-14 22:38:25 +0200407 return -EIO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200408 return 0;
409}
410
411/* Block transaction function */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100412static int i801_block_transaction(struct i801_priv *priv,
413 union i2c_smbus_data *data, char read_write,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200414 int command, int hwpec)
415{
416 int result = 0;
417 unsigned char hostc;
418
419 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
420 if (read_write == I2C_SMBUS_WRITE) {
421 /* set I2C_EN bit in configuration register */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100422 pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
423 pci_write_config_byte(priv->pci_dev, SMBHSTCFG,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200424 hostc | SMBHSTCFG_I2C_EN);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100425 } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
426 dev_err(&priv->pci_dev->dev,
Jean Delvare63420642008-01-27 18:14:50 +0100427 "I2C block read is unsupported!\n");
David Brownell97140342008-07-14 22:38:25 +0200428 return -EOPNOTSUPP;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 }
431
Jean Delvare63420642008-01-27 18:14:50 +0100432 if (read_write == I2C_SMBUS_WRITE
433 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200434 if (data->block[0] < 1)
435 data->block[0] = 1;
436 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
437 data->block[0] = I2C_SMBUS_BLOCK_MAX;
438 } else {
Jean Delvare63420642008-01-27 18:14:50 +0100439 data->block[0] = 32; /* max for SMBus block reads */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200440 }
441
Jean Delvarec074c392010-03-13 20:56:53 +0100442 /* Experience has shown that the block buffer can only be used for
443 SMBus (not I2C) block transactions, even though the datasheet
444 doesn't mention this limitation. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100445 if ((priv->features & FEATURE_BLOCK_BUFFER)
Jean Delvarec074c392010-03-13 20:56:53 +0100446 && command != I2C_SMBUS_I2C_BLOCK_DATA
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100447 && i801_set_block_buffer_mode(priv) == 0)
448 result = i801_block_transaction_by_block(priv, data,
449 read_write, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200450 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100451 result = i801_block_transaction_byte_by_byte(priv, data,
452 read_write,
Jean Delvare63420642008-01-27 18:14:50 +0100453 command, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200454
455 if (result == 0 && hwpec)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100456 i801_wait_hwpec(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
Jean Delvare63420642008-01-27 18:14:50 +0100458 if (command == I2C_SMBUS_I2C_BLOCK_DATA
459 && read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 /* restore saved configuration register value */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100461 pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 }
463 return result;
464}
465
David Brownell97140342008-07-14 22:38:25 +0200466/* Return negative errno on error. */
Ivo Manca3fb21c62010-05-21 18:40:55 +0200467static s32 i801_access(struct i2c_adapter *adap, u16 addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 unsigned short flags, char read_write, u8 command,
Ivo Manca3fb21c62010-05-21 18:40:55 +0200469 int size, union i2c_smbus_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200471 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 int block = 0;
473 int ret, xact = 0;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100474 struct i801_priv *priv = i2c_get_adapdata(adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100476 hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200477 && size != I2C_SMBUS_QUICK
478 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
480 switch (size) {
481 case I2C_SMBUS_QUICK:
482 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100483 SMBHSTADD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 xact = I801_QUICK;
485 break;
486 case I2C_SMBUS_BYTE:
487 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100488 SMBHSTADD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 if (read_write == I2C_SMBUS_WRITE)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100490 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 xact = I801_BYTE;
492 break;
493 case I2C_SMBUS_BYTE_DATA:
494 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100495 SMBHSTADD(priv));
496 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if (read_write == I2C_SMBUS_WRITE)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100498 outb_p(data->byte, SMBHSTDAT0(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 xact = I801_BYTE_DATA;
500 break;
501 case I2C_SMBUS_WORD_DATA:
502 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100503 SMBHSTADD(priv));
504 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 if (read_write == I2C_SMBUS_WRITE) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100506 outb_p(data->word & 0xff, SMBHSTDAT0(priv));
507 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
509 xact = I801_WORD_DATA;
510 break;
511 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100513 SMBHSTADD(priv));
514 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 block = 1;
516 break;
Jean Delvare63420642008-01-27 18:14:50 +0100517 case I2C_SMBUS_I2C_BLOCK_DATA:
518 /* NB: page 240 of ICH5 datasheet shows that the R/#W
519 * bit should be cleared here, even when reading */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100520 outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100521 if (read_write == I2C_SMBUS_READ) {
522 /* NB: page 240 of ICH5 datasheet also shows
523 * that DATA1 is the cmd field when reading */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100524 outb_p(command, SMBHSTDAT1(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100525 } else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100526 outb_p(command, SMBHSTCMD(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100527 block = 1;
528 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 default:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100530 dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
531 size);
David Brownell97140342008-07-14 22:38:25 +0200532 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 }
534
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200535 if (hwpec) /* enable/disable hardware PEC */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100536 outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200537 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100538 outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
539 SMBAUXCTL(priv));
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200540
Ivo Manca3fb21c62010-05-21 18:40:55 +0200541 if (block)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100542 ret = i801_block_transaction(priv, data, read_write, size,
543 hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200544 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100545 ret = i801_transaction(priv, xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Jean Delvarec79cfba2006-04-20 02:43:18 -0700547 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200548 time, so we forcibly disable it after every transaction. Turn off
549 E32B for the same reason. */
Jean Delvarea0921b62008-01-27 18:14:50 +0100550 if (hwpec || block)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100551 outb_p(inb_p(SMBAUXCTL(priv)) &
552 ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
Jean Delvarec79cfba2006-04-20 02:43:18 -0700553
Ivo Manca3fb21c62010-05-21 18:40:55 +0200554 if (block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 return ret;
Ivo Manca3fb21c62010-05-21 18:40:55 +0200556 if (ret)
David Brownell97140342008-07-14 22:38:25 +0200557 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
559 return 0;
560
561 switch (xact & 0x7f) {
562 case I801_BYTE: /* Result put in SMBHSTDAT0 */
563 case I801_BYTE_DATA:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100564 data->byte = inb_p(SMBHSTDAT0(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 break;
566 case I801_WORD_DATA:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100567 data->word = inb_p(SMBHSTDAT0(priv)) +
568 (inb_p(SMBHSTDAT1(priv)) << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 break;
570 }
571 return 0;
572}
573
574
575static u32 i801_func(struct i2c_adapter *adapter)
576{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100577 struct i801_priv *priv = i2c_get_adapdata(adapter);
578
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Jean Delvare369f6f42008-01-27 18:14:50 +0100580 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
581 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100582 ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
583 ((priv->features & FEATURE_I2C_BLOCK_READ) ?
Jean Delvare63420642008-01-27 18:14:50 +0100584 I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585}
586
Jean Delvare8f9082c2006-09-03 22:39:46 +0200587static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 .smbus_xfer = i801_access,
589 .functionality = i801_func,
590};
591
Márton Németh4111ecd2010-03-02 12:23:37 +0100592static const struct pci_device_id i801_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
594 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
595 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
596 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
597 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
598 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
599 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
600 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
601 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700602 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800603 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800604 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Seth Heasleycb04e952010-10-04 13:27:14 -0700605 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) },
Gaston, Jason Dd28dc712008-02-24 20:03:42 +0100606 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
607 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
Seth Heasleycb04e952010-10-04 13:27:14 -0700608 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) },
609 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) },
Seth Heasleye30d9852010-10-31 21:06:59 +0100610 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 { 0, }
612};
613
Ivo Manca3fb21c62010-05-21 18:40:55 +0200614MODULE_DEVICE_TABLE(pci, i801_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Jean Delvare1561bfe2009-01-07 14:29:17 +0100616#if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE
617static unsigned char apanel_addr;
618
619/* Scan the system ROM for the signature "FJKEYINF" */
620static __init const void __iomem *bios_signature(const void __iomem *bios)
621{
622 ssize_t offset;
623 const unsigned char signature[] = "FJKEYINF";
624
625 for (offset = 0; offset < 0x10000; offset += 0x10) {
626 if (check_signature(bios + offset, signature,
627 sizeof(signature)-1))
628 return bios + offset;
629 }
630 return NULL;
631}
632
633static void __init input_apanel_init(void)
634{
635 void __iomem *bios;
636 const void __iomem *p;
637
638 bios = ioremap(0xF0000, 0x10000); /* Can't fail */
639 p = bios_signature(bios);
640 if (p) {
641 /* just use the first address */
642 apanel_addr = readb(p + 8 + 3) >> 1;
643 }
644 iounmap(bios);
645}
646#else
647static void __init input_apanel_init(void) {}
648#endif
649
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200650#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
651struct dmi_onboard_device_info {
652 const char *name;
653 u8 type;
654 unsigned short i2c_addr;
655 const char *i2c_type;
656};
657
658static struct dmi_onboard_device_info __devinitdata dmi_devices[] = {
659 { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
660 { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
661 { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
662};
663
664static void __devinit dmi_check_onboard_device(u8 type, const char *name,
665 struct i2c_adapter *adap)
666{
667 int i;
668 struct i2c_board_info info;
669
670 for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) {
671 /* & ~0x80, ignore enabled/disabled bit */
672 if ((type & ~0x80) != dmi_devices[i].type)
673 continue;
Jean Delvarefaabd472010-07-09 16:22:51 +0200674 if (strcasecmp(name, dmi_devices[i].name))
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200675 continue;
676
677 memset(&info, 0, sizeof(struct i2c_board_info));
678 info.addr = dmi_devices[i].i2c_addr;
679 strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
680 i2c_new_device(adap, &info);
681 break;
682 }
683}
684
685/* We use our own function to check for onboard devices instead of
686 dmi_find_device() as some buggy BIOS's have the devices we are interested
687 in marked as disabled */
688static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
689 void *adap)
690{
691 int i, count;
692
693 if (dm->type != 10)
694 return;
695
696 count = (dm->length - sizeof(struct dmi_header)) / 2;
697 for (i = 0; i < count; i++) {
698 const u8 *d = (char *)(dm + 1) + (i * 2);
699 const char *name = ((char *) dm) + dm->length;
700 u8 type = d[0];
701 u8 s = d[1];
702
703 if (!s)
704 continue;
705 s--;
706 while (s > 0 && name[0]) {
707 name += strlen(name) + 1;
708 s--;
709 }
710 if (name[0] == 0) /* Bogus string reference */
711 continue;
712
713 dmi_check_onboard_device(type, name, adap);
714 }
715}
716#endif
717
Ivo Manca3fb21c62010-05-21 18:40:55 +0200718static int __devinit i801_probe(struct pci_dev *dev,
719 const struct pci_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200721 unsigned char temp;
Jean Delvareadff6872010-05-21 18:40:54 +0200722 int err, i;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100723 struct i801_priv *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100725 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
726 if (!priv)
727 return -ENOMEM;
728
729 i2c_set_adapdata(&priv->adapter, priv);
730 priv->adapter.owner = THIS_MODULE;
731 priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
732 priv->adapter.algo = &smbus_algorithm;
733
734 priv->pci_dev = dev;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100735 switch (dev->device) {
Jean Delvaree0e8398c2010-05-21 18:40:55 +0200736 default:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100737 priv->features |= FEATURE_I2C_BLOCK_READ;
Jean Delvare63420642008-01-27 18:14:50 +0100738 /* fall through */
739 case PCI_DEVICE_ID_INTEL_82801DB_3:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100740 priv->features |= FEATURE_SMBUS_PEC;
741 priv->features |= FEATURE_BLOCK_BUFFER;
Jean Delvaree0e8398c2010-05-21 18:40:55 +0200742 /* fall through */
743 case PCI_DEVICE_ID_INTEL_82801CA_3:
744 case PCI_DEVICE_ID_INTEL_82801BA_2:
745 case PCI_DEVICE_ID_INTEL_82801AB_3:
746 case PCI_DEVICE_ID_INTEL_82801AA_3:
Jean Delvare250d1bd2006-12-10 21:21:33 +0100747 break;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100748 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200749
Jean Delvareadff6872010-05-21 18:40:54 +0200750 /* Disable features on user request */
751 for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100752 if (priv->features & disable_features & (1 << i))
Jean Delvareadff6872010-05-21 18:40:54 +0200753 dev_notice(&dev->dev, "%s disabled by user\n",
754 i801_feature_names[i]);
755 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100756 priv->features &= ~disable_features;
Jean Delvareadff6872010-05-21 18:40:54 +0200757
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200758 err = pci_enable_device(dev);
759 if (err) {
760 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
761 err);
762 goto exit;
763 }
764
765 /* Determine the address of the SMBus area */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100766 priv->smba = pci_resource_start(dev, SMBBAR);
767 if (!priv->smba) {
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200768 dev_err(&dev->dev, "SMBus base address uninitialized, "
769 "upgrade BIOS\n");
770 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200771 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200772 }
773
Jean Delvare54fb4a052008-07-14 22:38:33 +0200774 err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
Jean Delvare18669ea2009-10-04 22:53:45 +0200775 if (err) {
776 err = -ENODEV;
Jean Delvare54fb4a052008-07-14 22:38:33 +0200777 goto exit;
Jean Delvare18669ea2009-10-04 22:53:45 +0200778 }
Jean Delvare54fb4a052008-07-14 22:38:33 +0200779
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200780 err = pci_request_region(dev, SMBBAR, i801_driver.name);
781 if (err) {
782 dev_err(&dev->dev, "Failed to request SMBus region "
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100783 "0x%lx-0x%Lx\n", priv->smba,
Andrew Morton598736c2006-06-30 01:56:20 -0700784 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200785 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200786 }
787
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100788 pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
789 priv->original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200790 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
791 if (!(temp & SMBHSTCFG_HST_EN)) {
792 dev_info(&dev->dev, "Enabling SMBus device\n");
793 temp |= SMBHSTCFG_HST_EN;
794 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100795 pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200796
797 if (temp & SMBHSTCFG_SMB_SMI_EN)
798 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
799 else
800 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Jean Delvarea0921b62008-01-27 18:14:50 +0100802 /* Clear special mode bits */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100803 if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
804 outb_p(inb_p(SMBAUXCTL(priv)) &
805 ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
Jean Delvarea0921b62008-01-27 18:14:50 +0100806
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100807 /* set up the sysfs linkage to our parent device */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100808 priv->adapter.dev.parent = &dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
Jean Delvare7e2193a2009-12-06 17:06:27 +0100810 /* Retry up to 3 times on lost arbitration */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100811 priv->adapter.retries = 3;
Jean Delvare7e2193a2009-12-06 17:06:27 +0100812
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100813 snprintf(priv->adapter.name, sizeof(priv->adapter.name),
814 "SMBus I801 adapter at %04lx", priv->smba);
815 err = i2c_add_adapter(&priv->adapter);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200816 if (err) {
817 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200818 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200819 }
Jean Delvare1561bfe2009-01-07 14:29:17 +0100820
821 /* Register optional slaves */
822#if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE
823 if (apanel_addr) {
824 struct i2c_board_info info;
825
826 memset(&info, 0, sizeof(struct i2c_board_info));
827 info.addr = apanel_addr;
828 strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100829 i2c_new_device(&priv->adapter, &info);
Jean Delvare1561bfe2009-01-07 14:29:17 +0100830 }
831#endif
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200832#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
Jean Delvarefaabd472010-07-09 16:22:51 +0200833 if (dmi_name_in_vendors("FUJITSU"))
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100834 dmi_walk(dmi_check_onboard_devices, &priv->adapter);
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200835#endif
Jean Delvare1561bfe2009-01-07 14:29:17 +0100836
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100837 pci_set_drvdata(dev, priv);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200838 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200839
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200840exit_release:
841 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200842exit:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100843 kfree(priv);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200844 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845}
846
847static void __devexit i801_remove(struct pci_dev *dev)
848{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100849 struct i801_priv *priv = pci_get_drvdata(dev);
850
851 i2c_del_adapter(&priv->adapter);
852 pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200853 pci_release_region(dev, SMBBAR);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100854 pci_set_drvdata(dev, NULL);
855 kfree(priv);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200856 /*
857 * do not call pci_disable_device(dev) since it can cause hard hangs on
858 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
859 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860}
861
Jean Delvarea5aaea32007-03-22 19:49:01 +0100862#ifdef CONFIG_PM
863static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
864{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100865 struct i801_priv *priv = pci_get_drvdata(dev);
866
Jean Delvarea5aaea32007-03-22 19:49:01 +0100867 pci_save_state(dev);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100868 pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100869 pci_set_power_state(dev, pci_choose_state(dev, mesg));
870 return 0;
871}
872
873static int i801_resume(struct pci_dev *dev)
874{
875 pci_set_power_state(dev, PCI_D0);
876 pci_restore_state(dev);
877 return pci_enable_device(dev);
878}
879#else
880#define i801_suspend NULL
881#define i801_resume NULL
882#endif
883
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 .name = "i801_smbus",
886 .id_table = i801_ids,
887 .probe = i801_probe,
888 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100889 .suspend = i801_suspend,
890 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891};
892
893static int __init i2c_i801_init(void)
894{
Jean Delvare1561bfe2009-01-07 14:29:17 +0100895 input_apanel_init();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 return pci_register_driver(&i801_driver);
897}
898
899static void __exit i2c_i801_exit(void)
900{
901 pci_unregister_driver(&i801_driver);
902}
903
Jean Delvare63420642008-01-27 18:14:50 +0100904MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
905 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906MODULE_DESCRIPTION("I801 SMBus driver");
907MODULE_LICENSE("GPL");
908
909module_init(i2c_i801_init);
910module_exit(i2c_i801_exit);