blob: bcce18dfcc39cb94e4489a8326afdfe477faad35 [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
Jean Delvareae7b0492008-01-27 18:14:49 +010055
56 Features supported by this driver:
57 Software PEC no
58 Hardware PEC yes
59 Block buffer yes
60 Block process call transaction no
Jean Delvare63420642008-01-27 18:14:50 +010061 I2C block read transaction yes (doesn't use the block buffer)
David Woodhouse55fee8d2010-10-31 21:07:00 +010062 Slave mode no
Daniel Kurtz636752b2012-07-24 14:13:58 +020063 Interrupt processing yes
Jean Delvareae7b0492008-01-27 18:14:49 +010064
65 See the file Documentation/i2c/busses/i2c-i801 for details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070066*/
67
Daniel Kurtz636752b2012-07-24 14:13:58 +020068#include <linux/interrupt.h>
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>
Daniel Kurtz636752b2012-07-24 14:13:58 +020081#include <linux/wait.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Linus Torvalds1da177e2005-04-16 15:20:36 -070083/* I801 SMBus address offsets */
David Woodhouse0cd96eb2010-10-31 21:06:59 +010084#define SMBHSTSTS(p) (0 + (p)->smba)
85#define SMBHSTCNT(p) (2 + (p)->smba)
86#define SMBHSTCMD(p) (3 + (p)->smba)
87#define SMBHSTADD(p) (4 + (p)->smba)
88#define SMBHSTDAT0(p) (5 + (p)->smba)
89#define SMBHSTDAT1(p) (6 + (p)->smba)
90#define SMBBLKDAT(p) (7 + (p)->smba)
91#define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */
92#define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */
93#define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95/* PCI Address Constants */
Jean Delvare6dcc19d2006-06-12 21:53:02 +020096#define SMBBAR 4
Daniel Kurtz636752b2012-07-24 14:13:58 +020097#define SMBPCISTS 0x006
Linus Torvalds1da177e2005-04-16 15:20:36 -070098#define SMBHSTCFG 0x040
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Daniel Kurtz636752b2012-07-24 14:13:58 +0200100/* Host status bits for SMBPCISTS */
101#define SMBPCISTS_INTS 0x08
102
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103/* Host configuration bits for SMBHSTCFG */
104#define SMBHSTCFG_HST_EN 1
105#define SMBHSTCFG_SMB_SMI_EN 2
106#define SMBHSTCFG_I2C_EN 4
107
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300108/* Auxiliary control register bits, ICH4+ only */
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200109#define SMBAUXCTL_CRC 1
110#define SMBAUXCTL_E32B 2
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112/* Other settings */
Jean Delvare84c1af42012-03-26 21:47:19 +0200113#define MAX_RETRIES 400
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
115/* I801 command constants */
116#define I801_QUICK 0x00
117#define I801_BYTE 0x04
118#define I801_BYTE_DATA 0x08
119#define I801_WORD_DATA 0x0C
Jean Delvareae7b0492008-01-27 18:14:49 +0100120#define I801_PROC_CALL 0x10 /* unimplemented */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121#define I801_BLOCK_DATA 0x14
Jean Delvare63420642008-01-27 18:14:50 +0100122#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
Daniel Kurtzedbeea62012-07-24 14:13:58 +0200123
124/* I801 Host Control register bits */
125#define SMBHSTCNT_INTREN 0x01
126#define SMBHSTCNT_KILL 0x02
127#define SMBHSTCNT_LAST_BYTE 0x20
128#define SMBHSTCNT_START 0x40
129#define SMBHSTCNT_PEC_EN 0x80 /* ICH3 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200131/* I801 Hosts Status register bits */
132#define SMBHSTSTS_BYTE_DONE 0x80
133#define SMBHSTSTS_INUSE_STS 0x40
134#define SMBHSTSTS_SMBALERT_STS 0x20
135#define SMBHSTSTS_FAILED 0x10
136#define SMBHSTSTS_BUS_ERR 0x08
137#define SMBHSTSTS_DEV_ERR 0x04
138#define SMBHSTSTS_INTR 0x02
139#define SMBHSTSTS_HOST_BUSY 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Daniel Kurtz70a1cc12012-07-24 14:13:58 +0200141#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
142 SMBHSTSTS_DEV_ERR)
143
144#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \
145 STATUS_ERROR_FLAGS)
Jean Delvarecf898dc2008-07-14 22:38:33 +0200146
Jean Delvarea6e5e2b2011-05-01 18:18:49 +0200147/* Older devices have their ID defined in <linux/pci_ids.h> */
148#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
149#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
David Woodhouse55fee8d2010-10-31 21:07:00 +0100150/* Patsburg also has three 'Integrated Device Function' SMBus controllers */
151#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70
152#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71
153#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72
Seth Heasley6e2a8512011-05-24 20:58:49 +0200154#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
Jean Delvarea6e5e2b2011-05-01 18:18:49 +0200155#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
156#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
Seth Heasley062737f2012-03-26 21:47:19 +0200157#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
David Woodhouse55fee8d2010-10-31 21:07:00 +0100158
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100159struct i801_priv {
160 struct i2c_adapter adapter;
161 unsigned long smba;
162 unsigned char original_hstcfg;
163 struct pci_dev *pci_dev;
164 unsigned int features;
Daniel Kurtz636752b2012-07-24 14:13:58 +0200165
166 /* isr processing */
167 wait_queue_head_t waitq;
168 u8 status;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100169};
170
Jean Delvared6072f82005-09-25 16:37:04 +0200171static struct pci_driver i801_driver;
Jean Delvare369f6f42008-01-27 18:14:50 +0100172
173#define FEATURE_SMBUS_PEC (1 << 0)
174#define FEATURE_BLOCK_BUFFER (1 << 1)
175#define FEATURE_BLOCK_PROC (1 << 2)
176#define FEATURE_I2C_BLOCK_READ (1 << 3)
Daniel Kurtz636752b2012-07-24 14:13:58 +0200177#define FEATURE_IRQ (1 << 4)
Jean Delvaree7198fb2011-05-24 20:58:49 +0200178/* Not really a feature, but it's convenient to handle it as such */
179#define FEATURE_IDF (1 << 15)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Jean Delvareadff6872010-05-21 18:40:54 +0200181static const char *i801_feature_names[] = {
182 "SMBus PEC",
183 "Block buffer",
184 "Block process call",
185 "I2C block read",
Daniel Kurtz636752b2012-07-24 14:13:58 +0200186 "Interrupt",
Jean Delvareadff6872010-05-21 18:40:54 +0200187};
188
189static unsigned int disable_features;
190module_param(disable_features, uint, S_IRUGO | S_IWUSR);
191MODULE_PARM_DESC(disable_features, "Disable selected driver features");
192
Jean Delvarecf898dc2008-07-14 22:38:33 +0200193/* Make sure the SMBus host is ready to start transmitting.
194 Return 0 if it is, -EBUSY if it is not. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100195static int i801_check_pre(struct i801_priv *priv)
Jean Delvarecf898dc2008-07-14 22:38:33 +0200196{
197 int status;
198
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100199 status = inb_p(SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200200 if (status & SMBHSTSTS_HOST_BUSY) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100201 dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200202 return -EBUSY;
203 }
204
205 status &= STATUS_FLAGS;
206 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100207 dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n",
Jean Delvarecf898dc2008-07-14 22:38:33 +0200208 status);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100209 outb_p(status, SMBHSTSTS(priv));
210 status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200211 if (status) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100212 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200213 "Failed clearing status flags (%02x)\n",
214 status);
215 return -EBUSY;
216 }
217 }
218
219 return 0;
220}
221
Jean Delvare6cad93c2012-07-24 14:13:58 +0200222/*
223 * Convert the status register to an error code, and clear it.
224 * Note that status only contains the bits we want to clear, not the
225 * actual register value.
226 */
227static int i801_check_post(struct i801_priv *priv, int status)
Jean Delvarecf898dc2008-07-14 22:38:33 +0200228{
229 int result = 0;
230
Daniel Kurtz636752b2012-07-24 14:13:58 +0200231 /*
232 * If the SMBus is still busy, we give up
233 * Note: This timeout condition only happens when using polling
234 * transactions. For interrupt operation, NAK/timeout is indicated by
235 * DEV_ERR.
236 */
Jean Delvare6cad93c2012-07-24 14:13:58 +0200237 if (unlikely(status < 0)) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100238 dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200239 /* try to stop the current command */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100240 dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
241 outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
242 SMBHSTCNT(priv));
Jean Delvare84c1af42012-03-26 21:47:19 +0200243 usleep_range(1000, 2000);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100244 outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
245 SMBHSTCNT(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200246
247 /* Check if it worked */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100248 status = inb_p(SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200249 if ((status & SMBHSTSTS_HOST_BUSY) ||
250 !(status & SMBHSTSTS_FAILED))
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100251 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200252 "Failed terminating the transaction\n");
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100253 outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200254 return -ETIMEDOUT;
255 }
256
257 if (status & SMBHSTSTS_FAILED) {
258 result = -EIO;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100259 dev_err(&priv->pci_dev->dev, "Transaction failed\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200260 }
261 if (status & SMBHSTSTS_DEV_ERR) {
262 result = -ENXIO;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100263 dev_dbg(&priv->pci_dev->dev, "No response\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200264 }
265 if (status & SMBHSTSTS_BUS_ERR) {
266 result = -EAGAIN;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100267 dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n");
Jean Delvarecf898dc2008-07-14 22:38:33 +0200268 }
269
Jean Delvare6cad93c2012-07-24 14:13:58 +0200270 /* Clear status flags except BYTE_DONE, to be cleared by caller */
271 outb_p(status, SMBHSTSTS(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200272
273 return result;
274}
275
Jean Delvare6cad93c2012-07-24 14:13:58 +0200276/* Wait for BUSY being cleared and either INTR or an error flag being set */
277static int i801_wait_intr(struct i801_priv *priv)
278{
279 int timeout = 0;
280 int status;
281
282 /* We will always wait for a fraction of a second! */
283 do {
284 usleep_range(250, 500);
285 status = inb_p(SMBHSTSTS(priv));
286 } while (((status & SMBHSTSTS_HOST_BUSY) ||
287 !(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) &&
288 (timeout++ < MAX_RETRIES));
289
290 if (timeout > MAX_RETRIES) {
291 dev_dbg(&priv->pci_dev->dev, "INTR Timeout!\n");
292 return -ETIMEDOUT;
293 }
294 return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR);
295}
296
297/* Wait for either BYTE_DONE or an error flag being set */
298static int i801_wait_byte_done(struct i801_priv *priv)
299{
300 int timeout = 0;
301 int status;
302
303 /* We will always wait for a fraction of a second! */
304 do {
305 usleep_range(250, 500);
306 status = inb_p(SMBHSTSTS(priv));
307 } while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) &&
308 (timeout++ < MAX_RETRIES));
309
310 if (timeout > MAX_RETRIES) {
311 dev_dbg(&priv->pci_dev->dev, "BYTE_DONE Timeout!\n");
312 return -ETIMEDOUT;
313 }
314 return status & STATUS_ERROR_FLAGS;
315}
316
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100317static int i801_transaction(struct i801_priv *priv, int xact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
Jean Delvare2b738092008-07-14 22:38:32 +0200319 int status;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200320 int result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100322 result = i801_check_pre(priv);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200323 if (result < 0)
324 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Daniel Kurtz636752b2012-07-24 14:13:58 +0200326 if (priv->features & FEATURE_IRQ) {
327 outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
328 SMBHSTCNT(priv));
329 wait_event(priv->waitq, (status = priv->status));
330 priv->status = 0;
331 return i801_check_post(priv, status);
332 }
333
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200334 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
Daniel Kurtz37af8712012-07-24 14:13:58 +0200335 * SMBSCMD are passed in xact */
Daniel Kurtzedbeea62012-07-24 14:13:58 +0200336 outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Jean Delvare6cad93c2012-07-24 14:13:58 +0200338 status = i801_wait_intr(priv);
339 return i801_check_post(priv, status);
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200340}
341
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100342static int i801_block_transaction_by_block(struct i801_priv *priv,
343 union i2c_smbus_data *data,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200344 char read_write, int hwpec)
345{
346 int i, len;
David Brownell97140342008-07-14 22:38:25 +0200347 int status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200348
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100349 inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200350
351 /* Use 32-byte buffer to process this transaction */
352 if (read_write == I2C_SMBUS_WRITE) {
353 len = data->block[0];
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100354 outb_p(len, SMBHSTDAT0(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200355 for (i = 0; i < len; i++)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100356 outb_p(data->block[i+1], SMBBLKDAT(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200357 }
358
Daniel Kurtz37af8712012-07-24 14:13:58 +0200359 status = i801_transaction(priv, I801_BLOCK_DATA |
Daniel Kurtzedbeea62012-07-24 14:13:58 +0200360 (hwpec ? SMBHSTCNT_PEC_EN : 0));
David Brownell97140342008-07-14 22:38:25 +0200361 if (status)
362 return status;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200363
364 if (read_write == I2C_SMBUS_READ) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100365 len = inb_p(SMBHSTDAT0(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200366 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
David Brownell97140342008-07-14 22:38:25 +0200367 return -EPROTO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200368
369 data->block[0] = len;
370 for (i = 0; i < len; i++)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100371 data->block[i + 1] = inb_p(SMBBLKDAT(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200372 }
373 return 0;
374}
375
Daniel Kurtzefa3cb12012-07-24 14:13:57 +0200376/*
Daniel Kurtz636752b2012-07-24 14:13:58 +0200377 * i801 signals transaction completion with one of these interrupts:
378 * INTR - Success
379 * DEV_ERR - Invalid command, NAK or communication timeout
380 * BUS_ERR - SMI# transaction collision
381 * FAILED - transaction was canceled due to a KILL request
382 * When any of these occur, update ->status and wake up the waitq.
383 * ->status must be cleared before kicking off the next transaction.
384 */
385static irqreturn_t i801_isr(int irq, void *dev_id)
386{
387 struct i801_priv *priv = dev_id;
388 u16 pcists;
389 u8 status;
390
391 /* Confirm this is our interrupt */
392 pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists);
393 if (!(pcists & SMBPCISTS_INTS))
394 return IRQ_NONE;
395
396 status = inb_p(SMBHSTSTS(priv));
397 if (status != 0x42)
398 dev_dbg(&priv->pci_dev->dev, "irq: status = %02x\n", status);
399
400 /*
401 * Clear irq sources and report transaction result.
402 * ->status must be cleared before the next transaction is started.
403 */
404 status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS;
405 if (status) {
406 outb_p(status, SMBHSTSTS(priv));
407 priv->status |= status;
408 wake_up(&priv->waitq);
409 }
410
411 return IRQ_HANDLED;
412}
413
414/*
Daniel Kurtzefa3cb12012-07-24 14:13:57 +0200415 * For "byte-by-byte" block transactions:
416 * I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1
417 * I2C read uses cmd=I801_I2C_BLOCK_DATA
418 */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100419static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
420 union i2c_smbus_data *data,
Jean Delvare63420642008-01-27 18:14:50 +0100421 char read_write, int command,
422 int hwpec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
424 int i, len;
425 int smbcmd;
Jean Delvare2b738092008-07-14 22:38:32 +0200426 int status;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200427 int result;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200428
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100429 result = i801_check_pre(priv);
Jean Delvarecf898dc2008-07-14 22:38:33 +0200430 if (result < 0)
431 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200433 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
435 if (read_write == I2C_SMBUS_WRITE) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100436 outb_p(len, SMBHSTDAT0(priv));
437 outb_p(data->block[1], SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 }
439
Daniel Kurtzefa3cb12012-07-24 14:13:57 +0200440 if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
441 read_write == I2C_SMBUS_READ)
442 smbcmd = I801_I2C_BLOCK_DATA;
443 else
444 smbcmd = I801_BLOCK_DATA;
445
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 for (i = 1; i <= len; i++) {
Daniel Kurtzefa3cb12012-07-24 14:13:57 +0200447 if (i == len && read_write == I2C_SMBUS_READ)
Daniel Kurtzedbeea62012-07-24 14:13:58 +0200448 smbcmd |= SMBHSTCNT_LAST_BYTE;
Daniel Kurtz37af8712012-07-24 14:13:58 +0200449 outb_p(smbcmd, SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 if (i == 1)
Daniel Kurtzedbeea62012-07-24 14:13:58 +0200452 outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100453 SMBHSTCNT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
Jean Delvare6cad93c2012-07-24 14:13:58 +0200455 status = i801_wait_byte_done(priv);
456 if (status)
457 goto exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Jean Delvare63420642008-01-27 18:14:50 +0100459 if (i == 1 && read_write == I2C_SMBUS_READ
460 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100461 len = inb_p(SMBHSTDAT0(priv));
Jean Delvarecf898dc2008-07-14 22:38:33 +0200462 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100463 dev_err(&priv->pci_dev->dev,
Jean Delvarecf898dc2008-07-14 22:38:33 +0200464 "Illegal SMBus block read size %d\n",
465 len);
466 /* Recover */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100467 while (inb_p(SMBHSTSTS(priv)) &
468 SMBHSTSTS_HOST_BUSY)
469 outb_p(SMBHSTSTS_BYTE_DONE,
470 SMBHSTSTS(priv));
471 outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
David Brownell97140342008-07-14 22:38:25 +0200472 return -EPROTO;
Jean Delvarecf898dc2008-07-14 22:38:33 +0200473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 data->block[0] = len;
475 }
476
477 /* Retrieve/store value in SMBBLKDAT */
478 if (read_write == I2C_SMBUS_READ)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100479 data->block[i] = inb_p(SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100481 outb_p(data->block[i+1], SMBBLKDAT(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Jean Delvarecf898dc2008-07-14 22:38:33 +0200483 /* signals SMBBLKDAT ready */
Jean Delvare6cad93c2012-07-24 14:13:58 +0200484 outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200485 }
Jean Delvarecf898dc2008-07-14 22:38:33 +0200486
Jean Delvare6cad93c2012-07-24 14:13:58 +0200487 status = i801_wait_intr(priv);
488exit:
489 return i801_check_post(priv, status);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200490}
491
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100492static int i801_set_block_buffer_mode(struct i801_priv *priv)
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200493{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100494 outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
495 if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
David Brownell97140342008-07-14 22:38:25 +0200496 return -EIO;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200497 return 0;
498}
499
500/* Block transaction function */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100501static int i801_block_transaction(struct i801_priv *priv,
502 union i2c_smbus_data *data, char read_write,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200503 int command, int hwpec)
504{
505 int result = 0;
506 unsigned char hostc;
507
508 if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
509 if (read_write == I2C_SMBUS_WRITE) {
510 /* set I2C_EN bit in configuration register */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100511 pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
512 pci_write_config_byte(priv->pci_dev, SMBHSTCFG,
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200513 hostc | SMBHSTCFG_I2C_EN);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100514 } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
515 dev_err(&priv->pci_dev->dev,
Jean Delvare63420642008-01-27 18:14:50 +0100516 "I2C block read is unsupported!\n");
David Brownell97140342008-07-14 22:38:25 +0200517 return -EOPNOTSUPP;
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 }
520
Jean Delvare63420642008-01-27 18:14:50 +0100521 if (read_write == I2C_SMBUS_WRITE
522 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200523 if (data->block[0] < 1)
524 data->block[0] = 1;
525 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
526 data->block[0] = I2C_SMBUS_BLOCK_MAX;
527 } else {
Jean Delvare63420642008-01-27 18:14:50 +0100528 data->block[0] = 32; /* max for SMBus block reads */
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200529 }
530
Jean Delvarec074c392010-03-13 20:56:53 +0100531 /* Experience has shown that the block buffer can only be used for
532 SMBus (not I2C) block transactions, even though the datasheet
533 doesn't mention this limitation. */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100534 if ((priv->features & FEATURE_BLOCK_BUFFER)
Jean Delvarec074c392010-03-13 20:56:53 +0100535 && command != I2C_SMBUS_I2C_BLOCK_DATA
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100536 && i801_set_block_buffer_mode(priv) == 0)
537 result = i801_block_transaction_by_block(priv, data,
538 read_write, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200539 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100540 result = i801_block_transaction_byte_by_byte(priv, data,
541 read_write,
Jean Delvare63420642008-01-27 18:14:50 +0100542 command, hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200543
Jean Delvare63420642008-01-27 18:14:50 +0100544 if (command == I2C_SMBUS_I2C_BLOCK_DATA
545 && read_write == I2C_SMBUS_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 /* restore saved configuration register value */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100547 pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 }
549 return result;
550}
551
David Brownell97140342008-07-14 22:38:25 +0200552/* Return negative errno on error. */
Ivo Manca3fb21c62010-05-21 18:40:55 +0200553static s32 i801_access(struct i2c_adapter *adap, u16 addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 unsigned short flags, char read_write, u8 command,
Ivo Manca3fb21c62010-05-21 18:40:55 +0200555 int size, union i2c_smbus_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556{
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200557 int hwpec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 int block = 0;
559 int ret, xact = 0;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100560 struct i801_priv *priv = i2c_get_adapdata(adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100562 hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200563 && size != I2C_SMBUS_QUICK
564 && size != I2C_SMBUS_I2C_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
566 switch (size) {
567 case I2C_SMBUS_QUICK:
568 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100569 SMBHSTADD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 xact = I801_QUICK;
571 break;
572 case I2C_SMBUS_BYTE:
573 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100574 SMBHSTADD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 if (read_write == I2C_SMBUS_WRITE)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100576 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 xact = I801_BYTE;
578 break;
579 case I2C_SMBUS_BYTE_DATA:
580 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100581 SMBHSTADD(priv));
582 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 if (read_write == I2C_SMBUS_WRITE)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100584 outb_p(data->byte, SMBHSTDAT0(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 xact = I801_BYTE_DATA;
586 break;
587 case I2C_SMBUS_WORD_DATA:
588 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100589 SMBHSTADD(priv));
590 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 if (read_write == I2C_SMBUS_WRITE) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100592 outb_p(data->word & 0xff, SMBHSTDAT0(priv));
593 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 }
595 xact = I801_WORD_DATA;
596 break;
597 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100599 SMBHSTADD(priv));
600 outb_p(command, SMBHSTCMD(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 block = 1;
602 break;
Jean Delvare63420642008-01-27 18:14:50 +0100603 case I2C_SMBUS_I2C_BLOCK_DATA:
604 /* NB: page 240 of ICH5 datasheet shows that the R/#W
605 * bit should be cleared here, even when reading */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100606 outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100607 if (read_write == I2C_SMBUS_READ) {
608 /* NB: page 240 of ICH5 datasheet also shows
609 * that DATA1 is the cmd field when reading */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100610 outb_p(command, SMBHSTDAT1(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100611 } else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100612 outb_p(command, SMBHSTCMD(priv));
Jean Delvare63420642008-01-27 18:14:50 +0100613 block = 1;
614 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 default:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100616 dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
617 size);
David Brownell97140342008-07-14 22:38:25 +0200618 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 }
620
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200621 if (hwpec) /* enable/disable hardware PEC */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100622 outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
Oleg Ryjkovca8b9e32007-07-12 14:12:31 +0200623 else
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100624 outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
625 SMBAUXCTL(priv));
Jean Delvaree8aac4a2005-10-26 21:34:42 +0200626
Ivo Manca3fb21c62010-05-21 18:40:55 +0200627 if (block)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100628 ret = i801_block_transaction(priv, data, read_write, size,
629 hwpec);
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200630 else
Daniel Kurtz37af8712012-07-24 14:13:58 +0200631 ret = i801_transaction(priv, xact);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Jean Delvarec79cfba2006-04-20 02:43:18 -0700633 /* Some BIOSes don't like it when PEC is enabled at reboot or resume
Oleg Ryjkov7edcb9a2007-07-12 14:12:31 +0200634 time, so we forcibly disable it after every transaction. Turn off
635 E32B for the same reason. */
Jean Delvarea0921b62008-01-27 18:14:50 +0100636 if (hwpec || block)
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100637 outb_p(inb_p(SMBAUXCTL(priv)) &
638 ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
Jean Delvarec79cfba2006-04-20 02:43:18 -0700639
Ivo Manca3fb21c62010-05-21 18:40:55 +0200640 if (block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 return ret;
Ivo Manca3fb21c62010-05-21 18:40:55 +0200642 if (ret)
David Brownell97140342008-07-14 22:38:25 +0200643 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
645 return 0;
646
647 switch (xact & 0x7f) {
648 case I801_BYTE: /* Result put in SMBHSTDAT0 */
649 case I801_BYTE_DATA:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100650 data->byte = inb_p(SMBHSTDAT0(priv));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 break;
652 case I801_WORD_DATA:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100653 data->word = inb_p(SMBHSTDAT0(priv)) +
654 (inb_p(SMBHSTDAT1(priv)) << 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 break;
656 }
657 return 0;
658}
659
660
661static u32 i801_func(struct i2c_adapter *adapter)
662{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100663 struct i801_priv *priv = i2c_get_adapdata(adapter);
664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Jean Delvare369f6f42008-01-27 18:14:50 +0100666 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
667 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100668 ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
669 ((priv->features & FEATURE_I2C_BLOCK_READ) ?
Jean Delvare63420642008-01-27 18:14:50 +0100670 I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671}
672
Jean Delvare8f9082c2006-09-03 22:39:46 +0200673static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 .smbus_xfer = i801_access,
675 .functionality = i801_func,
676};
677
Axel Lin3527bd52012-01-12 20:32:04 +0100678static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
680 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
681 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
682 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
683 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
684 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
685 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
686 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
687 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
Jason Gastonb0a70b52005-04-16 15:24:45 -0700688 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
Jason Gaston8254fc42006-01-09 10:58:08 -0800689 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
Jason Gastonadbc2a12006-11-22 15:19:12 -0800690 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
Seth Heasleycb04e952010-10-04 13:27:14 -0700691 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) },
Gaston, Jason Dd28dc712008-02-24 20:03:42 +0100692 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
693 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
Seth Heasleycb04e952010-10-04 13:27:14 -0700694 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) },
695 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) },
Seth Heasleye30d9852010-10-31 21:06:59 +0100696 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS) },
David Woodhouse55fee8d2010-10-31 21:07:00 +0100697 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) },
698 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) },
699 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
Seth Heasley662cda82011-03-20 14:50:53 +0100700 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
Seth Heasley6e2a8512011-05-24 20:58:49 +0200701 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
Seth Heasley062737f2012-03-26 21:47:19 +0200702 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 { 0, }
704};
705
Ivo Manca3fb21c62010-05-21 18:40:55 +0200706MODULE_DEVICE_TABLE(pci, i801_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Jean Delvare8eacfce2011-05-24 20:58:49 +0200708#if defined CONFIG_X86 && defined CONFIG_DMI
Jean Delvare1561bfe2009-01-07 14:29:17 +0100709static unsigned char apanel_addr;
710
711/* Scan the system ROM for the signature "FJKEYINF" */
712static __init const void __iomem *bios_signature(const void __iomem *bios)
713{
714 ssize_t offset;
715 const unsigned char signature[] = "FJKEYINF";
716
717 for (offset = 0; offset < 0x10000; offset += 0x10) {
718 if (check_signature(bios + offset, signature,
719 sizeof(signature)-1))
720 return bios + offset;
721 }
722 return NULL;
723}
724
725static void __init input_apanel_init(void)
726{
727 void __iomem *bios;
728 const void __iomem *p;
729
730 bios = ioremap(0xF0000, 0x10000); /* Can't fail */
731 p = bios_signature(bios);
732 if (p) {
733 /* just use the first address */
734 apanel_addr = readb(p + 8 + 3) >> 1;
735 }
736 iounmap(bios);
737}
Jean Delvare1561bfe2009-01-07 14:29:17 +0100738
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200739struct dmi_onboard_device_info {
740 const char *name;
741 u8 type;
742 unsigned short i2c_addr;
743 const char *i2c_type;
744};
745
746static struct dmi_onboard_device_info __devinitdata dmi_devices[] = {
747 { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
748 { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
749 { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
750};
751
752static void __devinit dmi_check_onboard_device(u8 type, const char *name,
753 struct i2c_adapter *adap)
754{
755 int i;
756 struct i2c_board_info info;
757
758 for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) {
759 /* & ~0x80, ignore enabled/disabled bit */
760 if ((type & ~0x80) != dmi_devices[i].type)
761 continue;
Jean Delvarefaabd472010-07-09 16:22:51 +0200762 if (strcasecmp(name, dmi_devices[i].name))
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200763 continue;
764
765 memset(&info, 0, sizeof(struct i2c_board_info));
766 info.addr = dmi_devices[i].i2c_addr;
767 strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
768 i2c_new_device(adap, &info);
769 break;
770 }
771}
772
773/* We use our own function to check for onboard devices instead of
774 dmi_find_device() as some buggy BIOS's have the devices we are interested
775 in marked as disabled */
776static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
777 void *adap)
778{
779 int i, count;
780
781 if (dm->type != 10)
782 return;
783
784 count = (dm->length - sizeof(struct dmi_header)) / 2;
785 for (i = 0; i < count; i++) {
786 const u8 *d = (char *)(dm + 1) + (i * 2);
787 const char *name = ((char *) dm) + dm->length;
788 u8 type = d[0];
789 u8 s = d[1];
790
791 if (!s)
792 continue;
793 s--;
794 while (s > 0 && name[0]) {
795 name += strlen(name) + 1;
796 s--;
797 }
798 if (name[0] == 0) /* Bogus string reference */
799 continue;
800
801 dmi_check_onboard_device(type, name, adap);
802 }
803}
Hans de Goedefa5bfab2009-03-30 21:46:44 +0200804
Jean Delvaree7198fb2011-05-24 20:58:49 +0200805/* Register optional slaves */
806static void __devinit i801_probe_optional_slaves(struct i801_priv *priv)
807{
808 /* Only register slaves on main SMBus channel */
809 if (priv->features & FEATURE_IDF)
810 return;
811
Jean Delvaree7198fb2011-05-24 20:58:49 +0200812 if (apanel_addr) {
813 struct i2c_board_info info;
814
815 memset(&info, 0, sizeof(struct i2c_board_info));
816 info.addr = apanel_addr;
817 strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE);
818 i2c_new_device(&priv->adapter, &info);
819 }
Jean Delvare8eacfce2011-05-24 20:58:49 +0200820
Jean Delvaree7198fb2011-05-24 20:58:49 +0200821 if (dmi_name_in_vendors("FUJITSU"))
822 dmi_walk(dmi_check_onboard_devices, &priv->adapter);
Jean Delvaree7198fb2011-05-24 20:58:49 +0200823}
Jean Delvare8eacfce2011-05-24 20:58:49 +0200824#else
825static void __init input_apanel_init(void) {}
826static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
827#endif /* CONFIG_X86 && CONFIG_DMI */
Jean Delvaree7198fb2011-05-24 20:58:49 +0200828
Ivo Manca3fb21c62010-05-21 18:40:55 +0200829static int __devinit i801_probe(struct pci_dev *dev,
830 const struct pci_device_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200832 unsigned char temp;
Jean Delvareadff6872010-05-21 18:40:54 +0200833 int err, i;
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100834 struct i801_priv *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100836 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
837 if (!priv)
838 return -ENOMEM;
839
840 i2c_set_adapdata(&priv->adapter, priv);
841 priv->adapter.owner = THIS_MODULE;
842 priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
843 priv->adapter.algo = &smbus_algorithm;
844
845 priv->pci_dev = dev;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100846 switch (dev->device) {
Jean Delvaree7198fb2011-05-24 20:58:49 +0200847 case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0:
848 case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1:
849 case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2:
850 priv->features |= FEATURE_IDF;
851 /* fall through */
Jean Delvaree0e8398c2010-05-21 18:40:55 +0200852 default:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100853 priv->features |= FEATURE_I2C_BLOCK_READ;
Jean Delvare63420642008-01-27 18:14:50 +0100854 /* fall through */
855 case PCI_DEVICE_ID_INTEL_82801DB_3:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100856 priv->features |= FEATURE_SMBUS_PEC;
857 priv->features |= FEATURE_BLOCK_BUFFER;
Jean Delvaree0e8398c2010-05-21 18:40:55 +0200858 /* fall through */
859 case PCI_DEVICE_ID_INTEL_82801CA_3:
860 case PCI_DEVICE_ID_INTEL_82801BA_2:
861 case PCI_DEVICE_ID_INTEL_82801AB_3:
862 case PCI_DEVICE_ID_INTEL_82801AA_3:
Jean Delvare250d1bd2006-12-10 21:21:33 +0100863 break;
Jean Delvare250d1bd2006-12-10 21:21:33 +0100864 }
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200865
Daniel Kurtz636752b2012-07-24 14:13:58 +0200866 /* IRQ processing only tested on CougarPoint PCH */
867 if (dev->device == PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS)
868 priv->features |= FEATURE_IRQ;
869
Jean Delvareadff6872010-05-21 18:40:54 +0200870 /* Disable features on user request */
871 for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) {
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100872 if (priv->features & disable_features & (1 << i))
Jean Delvareadff6872010-05-21 18:40:54 +0200873 dev_notice(&dev->dev, "%s disabled by user\n",
874 i801_feature_names[i]);
875 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100876 priv->features &= ~disable_features;
Jean Delvareadff6872010-05-21 18:40:54 +0200877
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200878 err = pci_enable_device(dev);
879 if (err) {
880 dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
881 err);
882 goto exit;
883 }
884
885 /* Determine the address of the SMBus area */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100886 priv->smba = pci_resource_start(dev, SMBBAR);
887 if (!priv->smba) {
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200888 dev_err(&dev->dev, "SMBus base address uninitialized, "
889 "upgrade BIOS\n");
890 err = -ENODEV;
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200891 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200892 }
893
Jean Delvare54fb4a052008-07-14 22:38:33 +0200894 err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
Jean Delvare18669ea2009-10-04 22:53:45 +0200895 if (err) {
896 err = -ENODEV;
Jean Delvare54fb4a052008-07-14 22:38:33 +0200897 goto exit;
Jean Delvare18669ea2009-10-04 22:53:45 +0200898 }
Jean Delvare54fb4a052008-07-14 22:38:33 +0200899
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200900 err = pci_request_region(dev, SMBBAR, i801_driver.name);
901 if (err) {
902 dev_err(&dev->dev, "Failed to request SMBus region "
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100903 "0x%lx-0x%Lx\n", priv->smba,
Andrew Morton598736c2006-06-30 01:56:20 -0700904 (unsigned long long)pci_resource_end(dev, SMBBAR));
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200905 goto exit;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200906 }
907
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100908 pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
909 priv->original_hstcfg = temp;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200910 temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
911 if (!(temp & SMBHSTCFG_HST_EN)) {
912 dev_info(&dev->dev, "Enabling SMBus device\n");
913 temp |= SMBHSTCFG_HST_EN;
914 }
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100915 pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200916
Daniel Kurtz636752b2012-07-24 14:13:58 +0200917 if (temp & SMBHSTCFG_SMB_SMI_EN) {
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200918 dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
Daniel Kurtz636752b2012-07-24 14:13:58 +0200919 /* Disable SMBus interrupt feature if SMBus using SMI# */
920 priv->features &= ~FEATURE_IRQ;
921 } else {
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200922 dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
Daniel Kurtz636752b2012-07-24 14:13:58 +0200923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Jean Delvarea0921b62008-01-27 18:14:50 +0100925 /* Clear special mode bits */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100926 if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
927 outb_p(inb_p(SMBAUXCTL(priv)) &
928 ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
Jean Delvarea0921b62008-01-27 18:14:50 +0100929
Daniel Kurtz636752b2012-07-24 14:13:58 +0200930 if (priv->features & FEATURE_IRQ) {
931 init_waitqueue_head(&priv->waitq);
932
933 err = request_irq(dev->irq, i801_isr, IRQF_SHARED,
934 i801_driver.name, priv);
935 if (err) {
936 dev_err(&dev->dev, "Failed to allocate irq %d: %d\n",
937 dev->irq, err);
938 goto exit_release;
939 }
940 }
941
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100942 /* set up the sysfs linkage to our parent device */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100943 priv->adapter.dev.parent = &dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
Jean Delvare7e2193a2009-12-06 17:06:27 +0100945 /* Retry up to 3 times on lost arbitration */
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100946 priv->adapter.retries = 3;
Jean Delvare7e2193a2009-12-06 17:06:27 +0100947
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100948 snprintf(priv->adapter.name, sizeof(priv->adapter.name),
949 "SMBus I801 adapter at %04lx", priv->smba);
950 err = i2c_add_adapter(&priv->adapter);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200951 if (err) {
952 dev_err(&dev->dev, "Failed to add SMBus adapter\n");
Daniel Kurtz636752b2012-07-24 14:13:58 +0200953 goto exit_free_irq;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200954 }
Jean Delvare1561bfe2009-01-07 14:29:17 +0100955
Jean Delvaree7198fb2011-05-24 20:58:49 +0200956 i801_probe_optional_slaves(priv);
Jean Delvare1561bfe2009-01-07 14:29:17 +0100957
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100958 pci_set_drvdata(dev, priv);
Daniel Kurtz636752b2012-07-24 14:13:58 +0200959
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200960 return 0;
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200961
Daniel Kurtz636752b2012-07-24 14:13:58 +0200962exit_free_irq:
963 if (priv->features & FEATURE_IRQ)
964 free_irq(dev->irq, priv);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200965exit_release:
966 pci_release_region(dev, SMBBAR);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200967exit:
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100968 kfree(priv);
Jean Delvare02dd7ae2006-06-12 21:53:41 +0200969 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970}
971
972static void __devexit i801_remove(struct pci_dev *dev)
973{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100974 struct i801_priv *priv = pci_get_drvdata(dev);
975
976 i2c_del_adapter(&priv->adapter);
977 pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
Daniel Kurtz636752b2012-07-24 14:13:58 +0200978
979 if (priv->features & FEATURE_IRQ)
980 free_irq(dev->irq, priv);
Jean Delvare6dcc19d2006-06-12 21:53:02 +0200981 pci_release_region(dev, SMBBAR);
Daniel Kurtz636752b2012-07-24 14:13:58 +0200982
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100983 pci_set_drvdata(dev, NULL);
984 kfree(priv);
Daniel Ritzd6fcb3b2006-06-27 18:40:54 +0200985 /*
986 * do not call pci_disable_device(dev) since it can cause hard hangs on
987 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
988 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989}
990
Jean Delvarea5aaea32007-03-22 19:49:01 +0100991#ifdef CONFIG_PM
992static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
993{
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100994 struct i801_priv *priv = pci_get_drvdata(dev);
995
Jean Delvarea5aaea32007-03-22 19:49:01 +0100996 pci_save_state(dev);
David Woodhouse0cd96eb2010-10-31 21:06:59 +0100997 pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
Jean Delvarea5aaea32007-03-22 19:49:01 +0100998 pci_set_power_state(dev, pci_choose_state(dev, mesg));
999 return 0;
1000}
1001
1002static int i801_resume(struct pci_dev *dev)
1003{
1004 pci_set_power_state(dev, PCI_D0);
1005 pci_restore_state(dev);
1006 return pci_enable_device(dev);
1007}
1008#else
1009#define i801_suspend NULL
1010#define i801_resume NULL
1011#endif
1012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013static struct pci_driver i801_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 .name = "i801_smbus",
1015 .id_table = i801_ids,
1016 .probe = i801_probe,
1017 .remove = __devexit_p(i801_remove),
Jean Delvarea5aaea32007-03-22 19:49:01 +01001018 .suspend = i801_suspend,
1019 .resume = i801_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020};
1021
1022static int __init i2c_i801_init(void)
1023{
Jean Delvare6aa14642011-05-24 20:58:49 +02001024 if (dmi_name_in_vendors("FUJITSU"))
1025 input_apanel_init();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 return pci_register_driver(&i801_driver);
1027}
1028
1029static void __exit i2c_i801_exit(void)
1030{
1031 pci_unregister_driver(&i801_driver);
1032}
1033
Jean Delvare63420642008-01-27 18:14:50 +01001034MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
1035 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036MODULE_DESCRIPTION("I801 SMBus driver");
1037MODULE_LICENSE("GPL");
1038
1039module_init(i2c_i801_init);
1040module_exit(i2c_i801_exit);