blob: d63e130690e99faf5c47542dbe92cb254205ef49 [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 Delvare84c1af42012-03-26 21:47:19 +02005 Copyright (C) 2007 - 2012 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 Heasley662cda82011-03-20 14:50:53 +010047 6 Series (PCH) 0x1c22 32 hard yes yes yes
Seth Heasleye30d9852010-10-31 21:06:59 +010048 Patsburg (PCH) 0x1d22 32 hard yes yes yes
David Woodhouse55fee8d2010-10-31 21:07:00 +010049 Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes
50 Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes
51 Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes
Seth Heasley662cda82011-03-20 14:50:53 +010052 DH89xxCC (PCH) 0x2330 32 hard yes yes yes
Seth Heasley6e2a8512011-05-24 20:58:49 +020053 Panther Point (PCH) 0x1e22 32 hard yes yes yes
Seth Heasley062737f2012-03-26 21:47:19 +020054 Lynx Point (PCH) 0x8c22 32 hard yes yes yes
James Ralston7db3f562012-09-10 10:14:02 +020055 Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes
Seth Heasley3e80f4c2013-01-30 15:25:32 +000056 Avoton (SOC) 0x1f3c 32 hard yes yes yes
Jean Delvareae7b0492008-01-27 18:14:49 +010057
58 Features supported by this driver:
59 Software PEC no
60 Hardware PEC yes
61 Block buffer yes
62 Block process call transaction no
Jean Delvare63420642008-01-27 18:14:50 +010063 I2C block read transaction yes (doesn't use the block buffer)
David Woodhouse55fee8d2010-10-31 21:07:00 +010064 Slave mode no
Jean Delvareae7b0492008-01-27 18:14:49 +010065
66 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070067*/
68
Linus Torvalds1da177e2005-04-16 15:20:36 -070069#include <linux/module.h>
70#include <linux/pci.h>
71#include <linux/kernel.h>
72#include <linux/stddef.h>
73#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#include <linux/ioport.h>
75#include <linux/init.h>
76#include <linux/i2c.h>
Jean Delvare54fb4a052008-07-14 22:38:33 +020077#include <linux/acpi.h>
Jean Delvare1561bfe2009-01-07 14:29:17 +010078#include <linux/io.h>
Hans de Goedefa5bfab2009-03-30 21:46:44 +020079#include <linux/dmi.h>
Ben Hutchings665a96b2011-01-10 22:11:22 +010080#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Linus Torvalds1da177e2005-04-16 15:20:36 -070082/* I801 SMBus address offsets */
David Woodhouse0cd96eb2010-10-31 21:06:59 +010083#define SMBHSTSTS(p) (0 + (p)->smba)
84#define SMBHSTCNT(p) (2 + (p)->smba)
85#define SMBHSTCMD(p) (3 + (p)->smba)
86#define SMBHSTADD(p) (4 + (p)->smba)
87#define SMBHSTDAT0(p) (5 + (p)->smba)
88#define SMBHSTDAT1(p) (6 + (p)->smba)
89#define SMBBLKDAT(p) (7 + (p)->smba)
90#define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */
91#define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */
92#define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94/* PCI Address Constants */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020095#define SMBBAR 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070096#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
98/* Host configuration bits for SMBHSTCFG */
99#define SMBHSTCFG_HST_EN 1
100#define SMBHSTCFG_SMB_SMI_EN 2
101#define SMBHSTCFG_I2C_EN 4
102
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300103/* Auxiliary control register bits, ICH4+ only */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200104#define SMBAUXCTL_CRC 1
105#define SMBAUXCTL_E32B 2
106
107/* kill bit for SMBHSTCNT */
108#define SMBHSTCNT_KILL 2
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110/* Other settings */
Jean Delvare84c1af42012-03-26 21:47:19 +0200111#define MAX_RETRIES 400
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
113
114/* I801 command constants */
115#define I801_QUICK 0x00
116#define I801_BYTE 0x04
117#define I801_BYTE_DATA 0x08
118#define I801_WORD_DATA 0x0C
Jean Delvareae7b0492008-01-27 18:14:49 +0100119#define I801_PROC_CALL 0x10 /* unimplemented */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120#define I801_BLOCK_DATA 0x14
Jean Delvare63420642008-01-27 18:14:50 +0100121#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122#define I801_BLOCK_LAST 0x34
Jean Delvare63420642008-01-27 18:14:50 +0100123#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124#define I801_START 0x40
Jean Delvareae7b0492008-01-27 18:14:49 +0100125#define I801_PEC_EN 0x80 /* ICH3 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200127/* I801 Hosts Status register bits */
128#define SMBHSTSTS_BYTE_DONE 0x80
129#define SMBHSTSTS_INUSE_STS 0x40
130#define SMBHSTSTS_SMBALERT_STS 0x20
131#define SMBHSTSTS_FAILED 0x10
132#define SMBHSTSTS_BUS_ERR 0x08
133#define SMBHSTSTS_DEV_ERR 0x04
134#define SMBHSTSTS_INTR 0x02
135#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
Jean Delvarecf898dc2008-07-14 22:38:33 +0200137#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
138 SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
139 SMBHSTSTS_INTR)
140
Jean Delvarea6e5e2b2011-05-01 18:18:49 +0200141/* Older devices have their ID defined in <linux/pci_ids.h> */
142#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
143#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
David Woodhouse55fee8d2010-10-31 21:07:00 +0100144/* Patsburg also has three 'Integrated Device Function' SMBus controllers */
145#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70
146#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71
147#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72
Seth Heasley6e2a8512011-05-24 20:58:49 +0200148#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
Seth Heasley3e80f4c2013-01-30 15:25:32 +0000149#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c
Jean Delvarea6e5e2b2011-05-01 18:18:49 +0200150#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
151#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
Seth Heasley062737f2012-03-26 21:47:19 +0200152#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
James Ralston7db3f562012-09-10 10:14:02 +0200153#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
David Woodhouse55fee8d2010-10-31 21:07:00 +0100154
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100155struct i801_priv {
156 struct i2c_adapter adapter;
157 unsigned long smba;
158 unsigned char original_hstcfg;
159 struct pci_dev *pci_dev;
160 unsigned int features;
161};
162
Jean Delvared6072f82005-09-25 16:37:04 +0200163static struct pci_driver i801_driver;
Jean Delvare369f6f42008-01-27 18:14:50 +0100164
165#define FEATURE_SMBUS_PEC (1 << 0)
166#define FEATURE_BLOCK_BUFFER (1 << 1)
167#define FEATURE_BLOCK_PROC (1 << 2)
168#define FEATURE_I2C_BLOCK_READ (1 << 3)
Jean Delvaree7198fb2011-05-24 20:58:49 +0200169/* Not really a feature, but it's convenient to handle it as such */
170#define FEATURE_IDF (1 << 15)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Jean Delvareadff6872010-05-21 18:40:54 +0200172static const char *i801_feature_names[] = {
173 "SMBus PEC",
174 "Block buffer",
175 "Block process call",
176 "I2C block read",
177};
178
179static unsigned int disable_features;
180module_param(disable_features, uint, S_IRUGO | S_IWUSR);
181MODULE_PARM_DESC(disable_features, "Disable selected driver features");
182
Jean Delvarecf898dc2008-07-14 22:38:33 +0200183/* Make sure the SMBus host is ready to start transmitting.
184 Return 0 if it is, -EBUSY if it is not. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100185static int i801_check_pre(struct i801_priv *priv)
Jean Delvarecf898dc2008-07-14 22:38:33 +0200186{
187 int status;
188
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100189 status = inb_p(SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200190 if (status & SMBHSTSTS_HOST_BUSY) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100191 dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200192 return -EBUSY;
193 }
194
195 status &= STATUS_FLAGS;
196 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100197 dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n",
Jean Delvarecf898dc2008-07-14 22:38:33 +0200198 status);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100199 outb_p(status, SMBHSTSTS(priv));
200 status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200201 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100202 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200203 "Failed clearing status flags (%02x)\n",
204 status);
205 return -EBUSY;
206 }
207 }
208
209 return 0;
210}
211
212/* Convert the status register to an error code, and clear it. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100213static int i801_check_post(struct i801_priv *priv, int status, int timeout)
Jean Delvarecf898dc2008-07-14 22:38:33 +0200214{
215 int result = 0;
216
217 /* If the SMBus is still busy, we give up */
218 if (timeout) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100219 dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200220 /* try to stop the current command */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100221 dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
222 outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
223 SMBHSTCNT(priv));
Jean Delvare84c1af42012-03-26 21:47:19 +0200224 usleep_range(1000, 2000);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100225 outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
226 SMBHSTCNT(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200227
228 /* Check if it worked */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100229 status = inb_p(SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200230 if ((status & SMBHSTSTS_HOST_BUSY) ||
231 !(status & SMBHSTSTS_FAILED))
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100232 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200233 "Failed terminating the transaction\n");
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100234 outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200235 return -ETIMEDOUT;
236 }
237
238 if (status & SMBHSTSTS_FAILED) {
239 result = -EIO;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100240 dev_err(&priv->pci_dev->dev, "Transaction failed\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200241 }
242 if (status & SMBHSTSTS_DEV_ERR) {
243 result = -ENXIO;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100244 dev_dbg(&priv->pci_dev->dev, "No response\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200245 }
246 if (status & SMBHSTSTS_BUS_ERR) {
247 result = -EAGAIN;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100248 dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200249 }
250
251 if (result) {
252 /* Clear error flags */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100253 outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv));
254 status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200255 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100256 dev_warn(&priv->pci_dev->dev, "Failed clearing status "
Jean Delvarecf898dc2008-07-14 22:38:33 +0200257 "flags at end of transaction (%02x)\n",
258 status);
259 }
260 }
261
262 return result;
263}
264
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100265static int i801_transaction(struct i801_priv *priv, int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
Jean Delvare2b738092008-07-14 22:38:32 +0200267 int status;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200268 int result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 int timeout = 0;
270
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100271 result = i801_check_pre(priv);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200272 if (result < 0)
273 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200275 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
276 * INTREN, SMBSCMD are passed in xact */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100277 outb_p(xact | I801_START, SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
279 /* We will always wait for a fraction of a second! */
280 do {
Jean Delvare84c1af42012-03-26 21:47:19 +0200281 usleep_range(250, 500);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100282 status = inb_p(SMBHSTSTS(priv));
Jean Delvare84c1af42012-03-26 21:47:19 +0200283 } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Jean Delvare84c1af42012-03-26 21:47:19 +0200285 result = i801_check_post(priv, status, timeout > MAX_RETRIES);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200286 if (result < 0)
287 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100289 outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200290 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291}
292
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200293/* wait for INTR bit as advised by Intel */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100294static void i801_wait_hwpec(struct i801_priv *priv)
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200295{
296 int timeout = 0;
Jean Delvare2b738092008-07-14 22:38:32 +0200297 int status;
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200298
299 do {
Jean Delvare84c1af42012-03-26 21:47:19 +0200300 usleep_range(250, 500);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100301 status = inb_p(SMBHSTSTS(priv));
Jean Delvare2b738092008-07-14 22:38:32 +0200302 } while ((!(status & SMBHSTSTS_INTR))
Jean Delvare84c1af42012-03-26 21:47:19 +0200303 && (timeout++ < MAX_RETRIES));
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200304
Jean Delvare84c1af42012-03-26 21:47:19 +0200305 if (timeout > MAX_RETRIES)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100306 dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n");
Roel Kluin4ccc28f2009-05-05 08:39:24 +0200307
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100308 outb_p(status, SMBHSTSTS(priv));
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200309}
310
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100311static int i801_block_transaction_by_block(struct i801_priv *priv,
312 union i2c_smbus_data *data,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200313 char read_write, int hwpec)
314{
315 int i, len;
David Brownell97140342008-07-14 22:38:25 +0200316 int status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200317
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100318 inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200319
320 /* Use 32-byte buffer to process this transaction */
321 if (read_write == I2C_SMBUS_WRITE) {
322 len = data->block[0];
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100323 outb_p(len, SMBHSTDAT0(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200324 for (i = 0; i < len; i++)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100325 outb_p(data->block[i+1], SMBBLKDAT(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200326 }
327
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100328 status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 |
David Brownell97140342008-07-14 22:38:25 +0200329 I801_PEC_EN * hwpec);
330 if (status)
331 return status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200332
333 if (read_write == I2C_SMBUS_READ) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100334 len = inb_p(SMBHSTDAT0(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200335 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
David Brownell97140342008-07-14 22:38:25 +0200336 return -EPROTO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200337
338 data->block[0] = len;
339 for (i = 0; i < len; i++)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100340 data->block[i + 1] = inb_p(SMBBLKDAT(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200341 }
342 return 0;
343}
344
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100345static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
346 union i2c_smbus_data *data,
Jean Delvare63420642008-01-27 18:14:50 +0100347 char read_write, int command,
348 int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349{
350 int i, len;
351 int smbcmd;
Jean Delvare2b738092008-07-14 22:38:32 +0200352 int status;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200353 int result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 int timeout;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200355
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100356 result = i801_check_pre(priv);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200357 if (result < 0)
358 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200360 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
362 if (read_write == I2C_SMBUS_WRITE) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100363 outb_p(len, SMBHSTDAT0(priv));
364 outb_p(data->block[1], SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 }
366
367 for (i = 1; i <= len; i++) {
Jean Delvare63420642008-01-27 18:14:50 +0100368 if (i == len && read_write == I2C_SMBUS_READ) {
369 if (command == I2C_SMBUS_I2C_BLOCK_DATA)
370 smbcmd = I801_I2C_BLOCK_LAST;
371 else
372 smbcmd = I801_BLOCK_LAST;
373 } else {
374 if (command == I2C_SMBUS_I2C_BLOCK_DATA
375 && read_write == I2C_SMBUS_READ)
376 smbcmd = I801_I2C_BLOCK_DATA;
377 else
378 smbcmd = I801_BLOCK_DATA;
379 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100380 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 if (i == 1)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100383 outb_p(inb(SMBHSTCNT(priv)) | I801_START,
384 SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
386 /* We will always wait for a fraction of a second! */
387 timeout = 0;
388 do {
Jean Delvare84c1af42012-03-26 21:47:19 +0200389 usleep_range(250, 500);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100390 status = inb_p(SMBHSTSTS(priv));
Ivo Manca3fb21c62010-05-21 18:40:55 +0200391 } while ((!(status & SMBHSTSTS_BYTE_DONE))
Jean Delvare84c1af42012-03-26 21:47:19 +0200392 && (timeout++ < MAX_RETRIES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Jean Delvare84c1af42012-03-26 21:47:19 +0200394 result = i801_check_post(priv, status, timeout > MAX_RETRIES);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200395 if (result < 0)
396 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Jean Delvare63420642008-01-27 18:14:50 +0100398 if (i == 1 && read_write == I2C_SMBUS_READ
399 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100400 len = inb_p(SMBHSTDAT0(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200401 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100402 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200403 "Illegal SMBus block read size %d\n",
404 len);
405 /* Recover */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100406 while (inb_p(SMBHSTSTS(priv)) &
407 SMBHSTSTS_HOST_BUSY)
408 outb_p(SMBHSTSTS_BYTE_DONE,
409 SMBHSTSTS(priv));
410 outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
David Brownell97140342008-07-14 22:38:25 +0200411 return -EPROTO;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 data->block[0] = len;
414 }
415
416 /* Retrieve/store value in SMBBLKDAT */
417 if (read_write == I2C_SMBUS_READ)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100418 data->block[i] = inb_p(SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100420 outb_p(data->block[i+1], SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Jean Delvarecf898dc2008-07-14 22:38:33 +0200422 /* signals SMBBLKDAT ready */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100423 outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200424 }
Jean Delvarecf898dc2008-07-14 22:38:33 +0200425
426 return 0;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200427}
428
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100429static int i801_set_block_buffer_mode(struct i801_priv *priv)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200430{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100431 outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
432 if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
David Brownell97140342008-07-14 22:38:25 +0200433 return -EIO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200434 return 0;
435}
436
437/* Block transaction function */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100438static int i801_block_transaction(struct i801_priv *priv,
439 union i2c_smbus_data *data, char read_write,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200440 int command, int hwpec)
441{
442 int result = 0;
443 unsigned char hostc;
444
445 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
446 if (read_write == I2C_SMBUS_WRITE) {
447 /* set I2C_EN bit in configuration register */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100448 pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
449 pci_write_config_byte(priv->pci_dev, SMBHSTCFG,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200450 hostc | SMBHSTCFG_I2C_EN);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100451 } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
452 dev_err(&priv->pci_dev->dev,
Jean Delvare63420642008-01-27 18:14:50 +0100453 "I2C block read is unsupported!\n");
David Brownell97140342008-07-14 22:38:25 +0200454 return -EOPNOTSUPP;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 }
457
Jean Delvare63420642008-01-27 18:14:50 +0100458 if (read_write == I2C_SMBUS_WRITE
459 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200460 if (data->block[0] < 1)
461 data->block[0] = 1;
462 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
463 data->block[0] = I2C_SMBUS_BLOCK_MAX;
464 } else {
Jean Delvare63420642008-01-27 18:14:50 +0100465 data->block[0] = 32; /* max for SMBus block reads */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200466 }
467
Jean Delvarec074c392010-03-13 20:56:53 +0100468 /* Experience has shown that the block buffer can only be used for
469 SMBus (not I2C) block transactions, even though the datasheet
470 doesn't mention this limitation. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100471 if ((priv->features & FEATURE_BLOCK_BUFFER)
Jean Delvarec074c392010-03-13 20:56:53 +0100472 && command != I2C_SMBUS_I2C_BLOCK_DATA
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100473 && i801_set_block_buffer_mode(priv) == 0)
474 result = i801_block_transaction_by_block(priv, data,
475 read_write, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200476 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100477 result = i801_block_transaction_byte_by_byte(priv, data,
478 read_write,
Jean Delvare63420642008-01-27 18:14:50 +0100479 command, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200480
481 if (result == 0 && hwpec)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100482 i801_wait_hwpec(priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
Jean Delvare63420642008-01-27 18:14:50 +0100484 if (command == I2C_SMBUS_I2C_BLOCK_DATA
485 && read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 /* restore saved configuration register value */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100487 pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 }
489 return result;
490}
491
David Brownell97140342008-07-14 22:38:25 +0200492/* Return negative errno on error. */
Ivo Manca3fb21c62010-05-21 18:40:55 +0200493static s32 i801_access(struct i2c_adapter *adap, u16 addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 unsigned short flags, char read_write, u8 command,
Ivo Manca3fb21c62010-05-21 18:40:55 +0200495 int size, union i2c_smbus_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200497 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 int block = 0;
499 int ret, xact = 0;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100500 struct i801_priv *priv = i2c_get_adapdata(adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100502 hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200503 && size != I2C_SMBUS_QUICK
504 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
506 switch (size) {
507 case I2C_SMBUS_QUICK:
508 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100509 SMBHSTADD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 xact = I801_QUICK;
511 break;
512 case I2C_SMBUS_BYTE:
513 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100514 SMBHSTADD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 if (read_write == I2C_SMBUS_WRITE)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100516 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 xact = I801_BYTE;
518 break;
519 case I2C_SMBUS_BYTE_DATA:
520 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100521 SMBHSTADD(priv));
522 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 if (read_write == I2C_SMBUS_WRITE)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100524 outb_p(data->byte, SMBHSTDAT0(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 xact = I801_BYTE_DATA;
526 break;
527 case I2C_SMBUS_WORD_DATA:
528 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100529 SMBHSTADD(priv));
530 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (read_write == I2C_SMBUS_WRITE) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100532 outb_p(data->word & 0xff, SMBHSTDAT0(priv));
533 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 }
535 xact = I801_WORD_DATA;
536 break;
537 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100539 SMBHSTADD(priv));
540 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 block = 1;
542 break;
Jean Delvare63420642008-01-27 18:14:50 +0100543 case I2C_SMBUS_I2C_BLOCK_DATA:
544 /* NB: page 240 of ICH5 datasheet shows that the R/#W
545 * bit should be cleared here, even when reading */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100546 outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100547 if (read_write == I2C_SMBUS_READ) {
548 /* NB: page 240 of ICH5 datasheet also shows
549 * that DATA1 is the cmd field when reading */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100550 outb_p(command, SMBHSTDAT1(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100551 } else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100552 outb_p(command, SMBHSTCMD(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100553 block = 1;
554 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 default:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100556 dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
557 size);
David Brownell97140342008-07-14 22:38:25 +0200558 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 }
560
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200561 if (hwpec) /* enable/disable hardware PEC */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100562 outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200563 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100564 outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
565 SMBAUXCTL(priv));
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200566
Ivo Manca3fb21c62010-05-21 18:40:55 +0200567 if (block)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100568 ret = i801_block_transaction(priv, data, read_write, size,
569 hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200570 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100571 ret = i801_transaction(priv, xact | ENABLE_INT9);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Jean Delvarec79cfba2006-04-20 02:43:18 -0700573 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200574 time, so we forcibly disable it after every transaction. Turn off
575 E32B for the same reason. */
Jean Delvarea0921b62008-01-27 18:14:50 +0100576 if (hwpec || block)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100577 outb_p(inb_p(SMBAUXCTL(priv)) &
578 ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
Jean Delvarec79cfba2006-04-20 02:43:18 -0700579
Ivo Manca3fb21c62010-05-21 18:40:55 +0200580 if (block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 return ret;
Ivo Manca3fb21c62010-05-21 18:40:55 +0200582 if (ret)
David Brownell97140342008-07-14 22:38:25 +0200583 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
585 return 0;
586
587 switch (xact & 0x7f) {
588 case I801_BYTE: /* Result put in SMBHSTDAT0 */
589 case I801_BYTE_DATA:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100590 data->byte = inb_p(SMBHSTDAT0(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 break;
592 case I801_WORD_DATA:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100593 data->word = inb_p(SMBHSTDAT0(priv)) +
594 (inb_p(SMBHSTDAT1(priv)) << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 break;
596 }
597 return 0;
598}
599
600
601static u32 i801_func(struct i2c_adapter *adapter)
602{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100603 struct i801_priv *priv = i2c_get_adapdata(adapter);
604
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Jean Delvare369f6f42008-01-27 18:14:50 +0100606 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
607 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100608 ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
609 ((priv->features & FEATURE_I2C_BLOCK_READ) ?
Jean Delvare63420642008-01-27 18:14:50 +0100610 I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611}
612
Jean Delvare8f9082c2006-09-03 22:39:46 +0200613static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 .smbus_xfer = i801_access,
615 .functionality = i801_func,
616};
617
Axel Lin3527bd52012-01-12 20:32:04 +0100618static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
620 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
621 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
622 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
623 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
624 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
625 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
626 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
627 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700628 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800629 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800630 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Seth Heasleycb04e952010-10-04 13:27:14 -0700631 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) },
Gaston, Jason Dd28dc712008-02-24 20:03:42 +0100632 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
633 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
Seth Heasleycb04e952010-10-04 13:27:14 -0700634 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) },
635 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) },
Seth Heasleye30d9852010-10-31 21:06:59 +0100636 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS) },
David Woodhouse55fee8d2010-10-31 21:07:00 +0100637 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) },
638 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) },
639 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
Seth Heasley662cda82011-03-20 14:50:53 +0100640 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
Seth Heasley6e2a8512011-05-24 20:58:49 +0200641 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
Seth Heasley062737f2012-03-26 21:47:19 +0200642 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
James Ralston7db3f562012-09-10 10:14:02 +0200643 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) },
Seth Heasley3e80f4c2013-01-30 15:25:32 +0000644 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMBUS) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 { 0, }
646};
647
Ivo Manca3fb21c62010-05-21 18:40:55 +0200648MODULE_DEVICE_TABLE(pci, i801_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Jean Delvare8eacfce2011-05-24 20:58:49 +0200650#if defined CONFIG_X86 && defined CONFIG_DMI
Jean Delvare1561bfe2009-01-07 14:29:17 +0100651static unsigned char apanel_addr;
652
653/* Scan the system ROM for the signature "FJKEYINF" */
654static __init const void __iomem *bios_signature(const void __iomem *bios)
655{
656 ssize_t offset;
657 const unsigned char signature[] = "FJKEYINF";
658
659 for (offset = 0; offset < 0x10000; offset += 0x10) {
660 if (check_signature(bios + offset, signature,
661 sizeof(signature)-1))
662 return bios + offset;
663 }
664 return NULL;
665}
666
667static void __init input_apanel_init(void)
668{
669 void __iomem *bios;
670 const void __iomem *p;
671
672 bios = ioremap(0xF0000, 0x10000); /* Can't fail */
673 p = bios_signature(bios);
674 if (p) {
675 /* just use the first address */
676 apanel_addr = readb(p + 8 + 3) >> 1;
677 }
678 iounmap(bios);
679}
Jean Delvare1561bfe2009-01-07 14:29:17 +0100680
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200681struct dmi_onboard_device_info {
682 const char *name;
683 u8 type;
684 unsigned short i2c_addr;
685 const char *i2c_type;
686};
687
688static struct dmi_onboard_device_info __devinitdata dmi_devices[] = {
689 { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
690 { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
691 { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
692};
693
694static void __devinit dmi_check_onboard_device(u8 type, const char *name,
695 struct i2c_adapter *adap)
696{
697 int i;
698 struct i2c_board_info info;
699
700 for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) {
701 /* & ~0x80, ignore enabled/disabled bit */
702 if ((type & ~0x80) != dmi_devices[i].type)
703 continue;
Jean Delvarefaabd472010-07-09 16:22:51 +0200704 if (strcasecmp(name, dmi_devices[i].name))
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200705 continue;
706
707 memset(&info, 0, sizeof(struct i2c_board_info));
708 info.addr = dmi_devices[i].i2c_addr;
709 strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
710 i2c_new_device(adap, &info);
711 break;
712 }
713}
714
715/* We use our own function to check for onboard devices instead of
716 dmi_find_device() as some buggy BIOS's have the devices we are interested
717 in marked as disabled */
718static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
719 void *adap)
720{
721 int i, count;
722
723 if (dm->type != 10)
724 return;
725
726 count = (dm->length - sizeof(struct dmi_header)) / 2;
727 for (i = 0; i < count; i++) {
728 const u8 *d = (char *)(dm + 1) + (i * 2);
729 const char *name = ((char *) dm) + dm->length;
730 u8 type = d[0];
731 u8 s = d[1];
732
733 if (!s)
734 continue;
735 s--;
736 while (s > 0 && name[0]) {
737 name += strlen(name) + 1;
738 s--;
739 }
740 if (name[0] == 0) /* Bogus string reference */
741 continue;
742
743 dmi_check_onboard_device(type, name, adap);
744 }
745}
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200746
Jean Delvaree7198fb2011-05-24 20:58:49 +0200747/* Register optional slaves */
748static void __devinit i801_probe_optional_slaves(struct i801_priv *priv)
749{
750 /* Only register slaves on main SMBus channel */
751 if (priv->features & FEATURE_IDF)
752 return;
753
Jean Delvaree7198fb2011-05-24 20:58:49 +0200754 if (apanel_addr) {
755 struct i2c_board_info info;
756
757 memset(&info, 0, sizeof(struct i2c_board_info));
758 info.addr = apanel_addr;
759 strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE);
760 i2c_new_device(&priv->adapter, &info);
761 }
Jean Delvare8eacfce2011-05-24 20:58:49 +0200762
Jean Delvaree7198fb2011-05-24 20:58:49 +0200763 if (dmi_name_in_vendors("FUJITSU"))
764 dmi_walk(dmi_check_onboard_devices, &priv->adapter);
Jean Delvaree7198fb2011-05-24 20:58:49 +0200765}
Jean Delvare8eacfce2011-05-24 20:58:49 +0200766#else
767static void __init input_apanel_init(void) {}
768static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
769#endif /* CONFIG_X86 && CONFIG_DMI */
Jean Delvaree7198fb2011-05-24 20:58:49 +0200770
Ivo Manca3fb21c62010-05-21 18:40:55 +0200771static int __devinit i801_probe(struct pci_dev *dev,
772 const struct pci_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200774 unsigned char temp;
Jean Delvareadff6872010-05-21 18:40:54 +0200775 int err, i;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100776 struct i801_priv *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100778 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
779 if (!priv)
780 return -ENOMEM;
781
782 i2c_set_adapdata(&priv->adapter, priv);
783 priv->adapter.owner = THIS_MODULE;
784 priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
785 priv->adapter.algo = &smbus_algorithm;
786
787 priv->pci_dev = dev;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100788 switch (dev->device) {
Jean Delvaree7198fb2011-05-24 20:58:49 +0200789 case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0:
790 case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1:
791 case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2:
792 priv->features |= FEATURE_IDF;
793 /* fall through */
Jean Delvaree0e83982010-05-21 18:40:55 +0200794 default:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100795 priv->features |= FEATURE_I2C_BLOCK_READ;
Jean Delvare63420642008-01-27 18:14:50 +0100796 /* fall through */
797 case PCI_DEVICE_ID_INTEL_82801DB_3:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100798 priv->features |= FEATURE_SMBUS_PEC;
799 priv->features |= FEATURE_BLOCK_BUFFER;
Jean Delvaree0e83982010-05-21 18:40:55 +0200800 /* fall through */
801 case PCI_DEVICE_ID_INTEL_82801CA_3:
802 case PCI_DEVICE_ID_INTEL_82801BA_2:
803 case PCI_DEVICE_ID_INTEL_82801AB_3:
804 case PCI_DEVICE_ID_INTEL_82801AA_3:
Jean Delvare250d1bd2006-12-10 21:21:33 +0100805 break;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100806 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200807
Jean Delvareadff6872010-05-21 18:40:54 +0200808 /* Disable features on user request */
809 for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100810 if (priv->features & disable_features & (1 << i))
Jean Delvareadff6872010-05-21 18:40:54 +0200811 dev_notice(&dev->dev, "%s disabled by user\n",
812 i801_feature_names[i]);
813 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100814 priv->features &= ~disable_features;
Jean Delvareadff6872010-05-21 18:40:54 +0200815
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200816 err = pci_enable_device(dev);
817 if (err) {
818 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
819 err);
820 goto exit;
821 }
822
823 /* Determine the address of the SMBus area */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100824 priv->smba = pci_resource_start(dev, SMBBAR);
825 if (!priv->smba) {
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200826 dev_err(&dev->dev, "SMBus base address uninitialized, "
827 "upgrade BIOS\n");
828 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200829 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200830 }
831
Jean Delvare54fb4a052008-07-14 22:38:33 +0200832 err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
Jean Delvare18669ea2009-10-04 22:53:45 +0200833 if (err) {
834 err = -ENODEV;
Jean Delvare54fb4a052008-07-14 22:38:33 +0200835 goto exit;
Jean Delvare18669ea2009-10-04 22:53:45 +0200836 }
Jean Delvare54fb4a052008-07-14 22:38:33 +0200837
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200838 err = pci_request_region(dev, SMBBAR, i801_driver.name);
839 if (err) {
840 dev_err(&dev->dev, "Failed to request SMBus region "
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100841 "0x%lx-0x%Lx\n", priv->smba,
Andrew Morton598736c2006-06-30 01:56:20 -0700842 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200843 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200844 }
845
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100846 pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
847 priv->original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200848 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
849 if (!(temp & SMBHSTCFG_HST_EN)) {
850 dev_info(&dev->dev, "Enabling SMBus device\n");
851 temp |= SMBHSTCFG_HST_EN;
852 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100853 pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200854
855 if (temp & SMBHSTCFG_SMB_SMI_EN)
856 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
857 else
858 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Jean Delvarea0921b62008-01-27 18:14:50 +0100860 /* Clear special mode bits */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100861 if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
862 outb_p(inb_p(SMBAUXCTL(priv)) &
863 ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
Jean Delvarea0921b62008-01-27 18:14:50 +0100864
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100865 /* set up the sysfs linkage to our parent device */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100866 priv->adapter.dev.parent = &dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Jean Delvare7e2193a2009-12-06 17:06:27 +0100868 /* Retry up to 3 times on lost arbitration */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100869 priv->adapter.retries = 3;
Jean Delvare7e2193a2009-12-06 17:06:27 +0100870
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100871 snprintf(priv->adapter.name, sizeof(priv->adapter.name),
872 "SMBus I801 adapter at %04lx", priv->smba);
873 err = i2c_add_adapter(&priv->adapter);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200874 if (err) {
875 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200876 goto exit_release;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200877 }
Jean Delvare1561bfe2009-01-07 14:29:17 +0100878
Jean Delvaree7198fb2011-05-24 20:58:49 +0200879 i801_probe_optional_slaves(priv);
Jean Delvare1561bfe2009-01-07 14:29:17 +0100880
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100881 pci_set_drvdata(dev, priv);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200882 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200883
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200884exit_release:
885 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200886exit:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100887 kfree(priv);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200888 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889}
890
891static void __devexit i801_remove(struct pci_dev *dev)
892{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100893 struct i801_priv *priv = pci_get_drvdata(dev);
894
895 i2c_del_adapter(&priv->adapter);
896 pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200897 pci_release_region(dev, SMBBAR);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100898 pci_set_drvdata(dev, NULL);
899 kfree(priv);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200900 /*
901 * do not call pci_disable_device(dev) since it can cause hard hangs on
902 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
903 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904}
905
Jean Delvarea5aaea32007-03-22 19:49:01 +0100906#ifdef CONFIG_PM
907static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
908{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100909 struct i801_priv *priv = pci_get_drvdata(dev);
910
Jean Delvarea5aaea32007-03-22 19:49:01 +0100911 pci_save_state(dev);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100912 pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100913 pci_set_power_state(dev, pci_choose_state(dev, mesg));
914 return 0;
915}
916
917static int i801_resume(struct pci_dev *dev)
918{
919 pci_set_power_state(dev, PCI_D0);
920 pci_restore_state(dev);
921 return pci_enable_device(dev);
922}
923#else
924#define i801_suspend NULL
925#define i801_resume NULL
926#endif
927
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 .name = "i801_smbus",
930 .id_table = i801_ids,
931 .probe = i801_probe,
932 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +0100933 .suspend = i801_suspend,
934 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935};
936
937static int __init i2c_i801_init(void)
938{
Jean Delvare6aa14642011-05-24 20:58:49 +0200939 if (dmi_name_in_vendors("FUJITSU"))
940 input_apanel_init();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 return pci_register_driver(&i801_driver);
942}
943
944static void __exit i2c_i801_exit(void)
945{
946 pci_unregister_driver(&i801_driver);
947}
948
Jean Delvare63420642008-01-27 18:14:50 +0100949MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
950 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951MODULE_DESCRIPTION("I801 SMBus driver");
952MODULE_LICENSE("GPL");
953
954module_init(i2c_i801_init);
955module_exit(i2c_i801_exit);