2 i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus
4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
5 Philip Edelbrock <phil@netroedge.com>
7 Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L)
26 Note: we assume there can only be one device, with one SMBus interface.
29 #include <linux/module.h>
30 #include <linux/pci.h>
31 #include <linux/kernel.h>
32 #include <linux/delay.h>
33 #include <linux/stddef.h>
34 #include <linux/ioport.h>
35 #include <linux/i2c.h>
36 #include <linux/init.h>
39 /* SCH SMBus address offsets */
40 #define SMBHSTCNT (0 + sch_smba)
41 #define SMBHSTSTS (1 + sch_smba)
42 #define SMBHSTADD (4 + sch_smba) /* TSA */
43 #define SMBHSTCMD (5 + sch_smba)
44 #define SMBHSTDAT0 (6 + sch_smba)
45 #define SMBHSTDAT1 (7 + sch_smba)
46 #define SMBBLKDAT (0x20 + sch_smba)
48 /* count for request_region */
51 /* PCI Address Constants */
52 #define SMBBA_SCH 0x40
55 #define MAX_TIMEOUT 500
58 #define SCH_QUICK 0x00
60 #define SCH_BYTE_DATA 0x02
61 #define SCH_WORD_DATA 0x03
62 #define SCH_BLOCK_DATA 0x05
64 static unsigned short sch_smba;
65 static struct pci_driver sch_driver;
66 static struct i2c_adapter sch_adapter;
69 * Start the i2c transaction -- the i2c_access will prepare the transaction
70 * and this function will execute it.
71 * return 0 for success and others for failure.
73 static int sch_transaction(void)
79 dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
80 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
81 inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
84 /* Make sure the SMBus host is ready to start transmitting */
85 temp = inb(SMBHSTSTS) & 0x0f;
87 /* Can not be busy since we checked it in sch_access */
89 dev_dbg(&sch_adapter.dev, "Completion (%02x). "
93 dev_dbg(&sch_adapter.dev, "SMBus error (%02x). "
94 "Resetting...\n", temp);
96 outb(temp, SMBHSTSTS);
97 temp = inb(SMBHSTSTS) & 0x0f;
99 dev_err(&sch_adapter.dev,
100 "SMBus is not ready: (%02x)\n", temp);
105 /* start the transaction by setting bit 4 */
106 outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT);
110 temp = inb(SMBHSTSTS) & 0x0f;
111 } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
113 /* If the SMBus is still busy, we give up */
114 if (timeout >= MAX_TIMEOUT) {
115 dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
120 dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
121 "locked until next hard reset. (sorry!)\n");
122 /* Clock stops and slave is stuck in mid-transmission */
123 } else if (temp & 0x02) {
125 dev_err(&sch_adapter.dev, "Error: no response!\n");
126 } else if (temp & 0x01) {
127 dev_dbg(&sch_adapter.dev, "Post complete!\n");
128 outb(temp, SMBHSTSTS);
129 temp = inb(SMBHSTSTS) & 0x07;
131 /* Completion clear failed */
132 dev_dbg(&sch_adapter.dev, "Failed reset at end of "
133 "transaction (%02x), Bus error!\n", temp);
137 dev_dbg(&sch_adapter.dev, "No such address.\n");
139 dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
140 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
141 inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
147 * This is the main access entry for i2c-sch access
148 * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write
149 * (0 for read and 1 for write), size is i2c transaction type and data is the
150 * union of transaction for data to be transfered or data read from bus.
151 * return 0 for success and others for failure.
153 static s32 sch_access(struct i2c_adapter *adap, u16 addr,
154 unsigned short flags, char read_write,
155 u8 command, int size, union i2c_smbus_data *data)
157 int i, len, temp, rc;
159 /* Make sure the SMBus host is not busy */
160 temp = inb(SMBHSTSTS) & 0x0f;
162 dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp);
165 dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size,
166 (read_write)?"READ":"WRITE");
168 case I2C_SMBUS_QUICK:
169 outb((addr << 1) | read_write, SMBHSTADD);
173 outb((addr << 1) | read_write, SMBHSTADD);
174 if (read_write == I2C_SMBUS_WRITE)
175 outb(command, SMBHSTCMD);
178 case I2C_SMBUS_BYTE_DATA:
179 outb((addr << 1) | read_write, SMBHSTADD);
180 outb(command, SMBHSTCMD);
181 if (read_write == I2C_SMBUS_WRITE)
182 outb(data->byte, SMBHSTDAT0);
183 size = SCH_BYTE_DATA;
185 case I2C_SMBUS_WORD_DATA:
186 outb((addr << 1) | read_write, SMBHSTADD);
187 outb(command, SMBHSTCMD);
188 if (read_write == I2C_SMBUS_WRITE) {
189 outb(data->word & 0xff, SMBHSTDAT0);
190 outb((data->word & 0xff00) >> 8, SMBHSTDAT1);
192 size = SCH_WORD_DATA;
194 case I2C_SMBUS_BLOCK_DATA:
195 outb((addr << 1) | read_write, SMBHSTADD);
196 outb(command, SMBHSTCMD);
197 if (read_write == I2C_SMBUS_WRITE) {
198 len = data->block[0];
199 if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
201 outb(len, SMBHSTDAT0);
202 for (i = 1; i <= len; i++)
203 outb(data->block[i], SMBBLKDAT+i-1);
205 size = SCH_BLOCK_DATA;
208 dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
211 dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT);
212 outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT);
214 rc = sch_transaction();
215 if (rc) /* Error in transaction */
218 if ((read_write == I2C_SMBUS_WRITE) || (size == SCH_QUICK))
224 data->byte = inb(SMBHSTDAT0);
227 data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8);
230 data->block[0] = inb(SMBHSTDAT0);
231 if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
233 for (i = 1; i <= data->block[0]; i++)
234 data->block[i] = inb(SMBBLKDAT+i-1);
240 static u32 sch_func(struct i2c_adapter *adapter)
242 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
243 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
244 I2C_FUNC_SMBUS_BLOCK_DATA;
247 static const struct i2c_algorithm smbus_algorithm = {
248 .smbus_xfer = sch_access,
249 .functionality = sch_func,
252 static struct i2c_adapter sch_adapter = {
253 .owner = THIS_MODULE,
254 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
255 .algo = &smbus_algorithm,
258 static struct pci_device_id sch_ids[] = {
259 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
263 MODULE_DEVICE_TABLE(pci, sch_ids);
265 static int __devinit sch_probe(struct pci_dev *dev,
266 const struct pci_device_id *id)
271 pci_read_config_dword(dev, SMBBA_SCH, &smba);
272 if (!(smba & (1 << 31))) {
273 dev_err(&dev->dev, "SMBus I/O space disabled!\n");
277 sch_smba = (unsigned short)smba;
279 dev_err(&dev->dev, "SMBus base address uninitialized!\n");
282 if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
283 dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
287 dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
289 /* set up the sysfs linkage to our parent device */
290 sch_adapter.dev.parent = &dev->dev;
292 snprintf(sch_adapter.name, sizeof(sch_adapter.name),
293 "SMBus SCH adapter at %04x", sch_smba);
295 retval = i2c_add_adapter(&sch_adapter);
297 dev_err(&dev->dev, "Couldn't register adapter!\n");
298 release_region(sch_smba, SMBIOSIZE);
305 static void __devexit sch_remove(struct pci_dev *dev)
308 i2c_del_adapter(&sch_adapter);
309 release_region(sch_smba, SMBIOSIZE);
314 static struct pci_driver sch_driver = {
315 .name = "isch_smbus",
318 .remove = __devexit_p(sch_remove),
321 static int __init i2c_sch_init(void)
323 return pci_register_driver(&sch_driver);
326 static void __exit i2c_sch_exit(void)
328 pci_unregister_driver(&sch_driver);
331 MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
332 MODULE_DESCRIPTION("Intel SCH SMBus driver");
333 MODULE_LICENSE("GPL");
335 module_init(i2c_sch_init);
336 module_exit(i2c_sch_exit);