blob: 3be476cd4bc5ece2f2fe3263e08245706a788c70 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
3 monitoring
Jean Delvare5f49ef82005-09-22 21:50:47 +02004 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
6 Mark D. Studebaker <mdsxyz123@yahoo.com>
Jean Delvaref11830142005-09-22 21:58:41 +02007 Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24/*
Jean Delvareaaf7f142005-09-22 22:09:07 +020025 Supports the following VIA south bridges:
26
27 Chip name PCI ID REV I2C block
28 VT82C596A 0x3050 no
29 VT82C596B 0x3051 no
30 VT82C686A 0x3057 0x30 no
31 VT82C686B 0x3057 0x40 yes
32 VT8231 0x8235 no?
33 VT8233 0x3074 yes
34 VT8233A 0x3147 yes?
35 VT8235 0x3177 yes
36 VT8237R 0x3227 yes
37
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 Note: we assume there can only be one device, with one SMBus interface.
39*/
40
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/module.h>
42#include <linux/delay.h>
43#include <linux/pci.h>
44#include <linux/kernel.h>
45#include <linux/stddef.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/ioport.h>
47#include <linux/i2c.h>
48#include <linux/init.h>
49#include <asm/io.h>
50
51static struct pci_dev *vt596_pdev;
52
Jean Delvare5f49ef82005-09-22 21:50:47 +020053#define SMBBA1 0x90
54#define SMBBA2 0x80
55#define SMBBA3 0xD0
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57/* SMBus address offsets */
58static unsigned short vt596_smba;
59#define SMBHSTSTS (vt596_smba + 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#define SMBHSTCNT (vt596_smba + 2)
61#define SMBHSTCMD (vt596_smba + 3)
62#define SMBHSTADD (vt596_smba + 4)
63#define SMBHSTDAT0 (vt596_smba + 5)
64#define SMBHSTDAT1 (vt596_smba + 6)
65#define SMBBLKDAT (vt596_smba + 7)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67/* PCI Address Constants */
68
69/* SMBus data in configuration space can be found in two places,
Jean Delvare5f49ef82005-09-22 21:50:47 +020070 We try to select the better one */
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Jean Delvarec2f559d2005-09-22 22:01:07 +020072static unsigned short SMBHSTCFG = 0xD2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
74/* Other settings */
75#define MAX_TIMEOUT 500
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77/* VT82C596 constants */
Jean Delvare5f49ef82005-09-22 21:50:47 +020078#define VT596_QUICK 0x00
79#define VT596_BYTE 0x04
80#define VT596_BYTE_DATA 0x08
81#define VT596_WORD_DATA 0x0C
82#define VT596_BLOCK_DATA 0x14
Jean Delvaref11830142005-09-22 21:58:41 +020083#define VT596_I2C_BLOCK_DATA 0x34
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85
86/* If force is set to anything different from 0, we forcibly enable the
87 VT596. DANGEROUS! */
88static int force;
89module_param(force, bool, 0);
90MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
91
92/* If force_addr is set to anything different from 0, we forcibly enable
93 the VT596 at the given address. VERY DANGEROUS! */
94static u16 force_addr;
95module_param(force_addr, ushort, 0);
96MODULE_PARM_DESC(force_addr,
97 "Forcibly enable the SMBus at the given address. "
98 "EXTREMELY DANGEROUS!");
99
100
Jean Delvarec2f559d2005-09-22 22:01:07 +0200101static struct pci_driver vt596_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102static struct i2c_adapter vt596_adapter;
103
Jean Delvaref11830142005-09-22 21:58:41 +0200104#define FEATURE_I2CBLOCK (1<<0)
105static unsigned int vt596_features;
106
Jean Delvarec2f559d2005-09-22 22:01:07 +0200107/* Return -1 on error, 0 on success */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108static int vt596_transaction(void)
109{
110 int temp;
111 int result = 0;
112 int timeout = 0;
113
114 dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
Jean Delvare5f49ef82005-09-22 21:50:47 +0200115 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
116 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 inb_p(SMBHSTDAT1));
118
119 /* Make sure the SMBus host is ready to start transmitting */
120 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
121 dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
Jean Delvarec2f559d2005-09-22 22:01:07 +0200122 "Resetting... ", temp);
Jean Delvare5f49ef82005-09-22 21:50:47 +0200123
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 outb_p(temp, SMBHSTSTS);
125 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200126 printk("Failed! (0x%02x)\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 return -1;
128 } else {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200129 printk("Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 }
131 }
132
Jean Delvarec2f559d2005-09-22 22:01:07 +0200133 /* Start the transaction by setting bit 6 */
134 outb_p(inb(SMBHSTCNT) | 0x40, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
Jean Delvarec2f559d2005-09-22 22:01:07 +0200136 /* We will always wait for a fraction of a second */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 do {
138 msleep(1);
139 temp = inb_p(SMBHSTSTS);
140 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
141
142 /* If the SMBus is still busy, we give up */
143 if (timeout >= MAX_TIMEOUT) {
144 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200145 dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 }
147
148 if (temp & 0x10) {
149 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200150 dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
151 inb_p(SMBHSTCNT) & 0x3C);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 }
153
154 if (temp & 0x08) {
155 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200156 dev_err(&vt596_adapter.dev, "SMBus collision!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 }
158
159 if (temp & 0x04) {
160 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200161 /* Quick commands are used to probe for chips, so
162 errors are expected, and we don't want to frighten the
163 user. */
164 if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK)
165 dev_err(&vt596_adapter.dev, "Transaction error!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 }
167
Jean Delvarec2f559d2005-09-22 22:01:07 +0200168 /* Resetting status register */
169 if (temp & 0x1F)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 outb_p(temp, SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172 dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
173 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
Jean Delvare5f49ef82005-09-22 21:50:47 +0200174 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 inb_p(SMBHSTDAT1));
Jean Delvare5f49ef82005-09-22 21:50:47 +0200176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 return result;
178}
179
Jean Delvarec2f559d2005-09-22 22:01:07 +0200180/* Return -1 on error, 0 on success */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200182 unsigned short flags, char read_write, u8 command,
183 int size, union i2c_smbus_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184{
Jean Delvarec2f559d2005-09-22 22:01:07 +0200185 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
187 switch (size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 case I2C_SMBUS_QUICK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 size = VT596_QUICK;
190 break;
191 case I2C_SMBUS_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 if (read_write == I2C_SMBUS_WRITE)
193 outb_p(command, SMBHSTCMD);
194 size = VT596_BYTE;
195 break;
196 case I2C_SMBUS_BYTE_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 outb_p(command, SMBHSTCMD);
198 if (read_write == I2C_SMBUS_WRITE)
199 outb_p(data->byte, SMBHSTDAT0);
200 size = VT596_BYTE_DATA;
201 break;
202 case I2C_SMBUS_WORD_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 outb_p(command, SMBHSTCMD);
204 if (read_write == I2C_SMBUS_WRITE) {
205 outb_p(data->word & 0xff, SMBHSTDAT0);
206 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
207 }
208 size = VT596_WORD_DATA;
209 break;
Jean Delvaref11830142005-09-22 21:58:41 +0200210 case I2C_SMBUS_I2C_BLOCK_DATA:
211 if (!(vt596_features & FEATURE_I2CBLOCK))
Jean Delvarec2f559d2005-09-22 22:01:07 +0200212 goto exit_unsupported;
Jean Delvaref11830142005-09-22 21:58:41 +0200213 if (read_write == I2C_SMBUS_READ)
214 outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
215 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 outb_p(command, SMBHSTCMD);
218 if (read_write == I2C_SMBUS_WRITE) {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200219 u8 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 if (len > I2C_SMBUS_BLOCK_MAX)
221 len = I2C_SMBUS_BLOCK_MAX;
222 outb_p(len, SMBHSTDAT0);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200223 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 for (i = 1; i <= len; i++)
225 outb_p(data->block[i], SMBBLKDAT);
226 }
Jean Delvaref11830142005-09-22 21:58:41 +0200227 size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
228 VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 break;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200230 default:
231 goto exit_unsupported;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 }
233
Jean Delvarec2f559d2005-09-22 22:01:07 +0200234 outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
235 outb_p((size & 0x3C), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
237 if (vt596_transaction()) /* Error in transaction */
238 return -1;
239
240 if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
241 return 0;
242
243 switch (size) {
244 case VT596_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 case VT596_BYTE_DATA:
246 data->byte = inb_p(SMBHSTDAT0);
247 break;
248 case VT596_WORD_DATA:
249 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
250 break;
Jean Delvaref11830142005-09-22 21:58:41 +0200251 case VT596_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 case VT596_BLOCK_DATA:
253 data->block[0] = inb_p(SMBHSTDAT0);
254 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
255 data->block[0] = I2C_SMBUS_BLOCK_MAX;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200256 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 for (i = 1; i <= data->block[0]; i++)
258 data->block[i] = inb_p(SMBBLKDAT);
259 break;
260 }
261 return 0;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200262
263exit_unsupported:
264 dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
265 size);
266 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267}
268
269static u32 vt596_func(struct i2c_adapter *adapter)
270{
Jean Delvaref11830142005-09-22 21:58:41 +0200271 u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
273 I2C_FUNC_SMBUS_BLOCK_DATA;
Jean Delvaref11830142005-09-22 21:58:41 +0200274
275 if (vt596_features & FEATURE_I2CBLOCK)
276 func |= I2C_FUNC_SMBUS_I2C_BLOCK;
277 return func;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278}
279
280static struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 .smbus_xfer = vt596_access,
282 .functionality = vt596_func,
283};
284
285static struct i2c_adapter vt596_adapter = {
286 .owner = THIS_MODULE,
287 .class = I2C_CLASS_HWMON,
288 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289};
290
291static int __devinit vt596_probe(struct pci_dev *pdev,
292 const struct pci_device_id *id)
293{
294 unsigned char temp;
295 int error = -ENODEV;
Jean Delvare5f49ef82005-09-22 21:50:47 +0200296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 /* Determine the address of the SMBus areas */
298 if (force_addr) {
299 vt596_smba = force_addr & 0xfff0;
300 force = 0;
301 goto found;
302 }
303
304 if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
Jean Delvarec2f559d2005-09-22 22:01:07 +0200305 !(vt596_smba & 0x0001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 /* try 2nd address and config reg. for 596 */
307 if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
308 !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
Jean Delvarec2f559d2005-09-22 22:01:07 +0200309 (vt596_smba & 0x0001)) {
310 SMBHSTCFG = 0x84;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 } else {
312 /* no matches at all */
313 dev_err(&pdev->dev, "Cannot configure "
314 "SMBus I/O Base address\n");
315 return -ENODEV;
316 }
317 }
318
319 vt596_smba &= 0xfff0;
320 if (vt596_smba == 0) {
321 dev_err(&pdev->dev, "SMBus base address "
322 "uninitialized - upgrade BIOS or use "
323 "force_addr=0xaddr\n");
324 return -ENODEV;
325 }
326
Jean Delvare5f49ef82005-09-22 21:50:47 +0200327found:
Jean Delvarec2f559d2005-09-22 22:01:07 +0200328 if (!request_region(vt596_smba, 8, vt596_driver.name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
Jean Delvare5f49ef82005-09-22 21:50:47 +0200330 vt596_smba);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 return -ENODEV;
332 }
333
334 pci_read_config_byte(pdev, SMBHSTCFG, &temp);
335 /* If force_addr is set, we program the new address here. Just to make
336 sure, we disable the VT596 first. */
337 if (force_addr) {
338 pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
339 pci_write_config_word(pdev, id->driver_data, vt596_smba);
340 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
341 dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
Jean Delvare5f49ef82005-09-22 21:50:47 +0200342 "address 0x%04x!\n", vt596_smba);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200343 } else if (!(temp & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 if (force) {
Jean Delvare5f49ef82005-09-22 21:50:47 +0200345 /* NOTE: This assumes I/O space and other allocations
346 * WERE done by the Bios! Don't complain if your
347 * hardware does weird things after enabling this.
348 * :') Check for Bios updates before resorting to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 * this.
350 */
Jean Delvarec2f559d2005-09-22 22:01:07 +0200351 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 dev_info(&pdev->dev, "Enabling SMBus device\n");
353 } else {
354 dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
355 "controller not enabled! - upgrade BIOS or "
356 "use force=1\n");
357 goto release_region;
358 }
359 }
360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
362
Jean Delvaref11830142005-09-22 21:58:41 +0200363 switch (pdev->device) {
364 case PCI_DEVICE_ID_VIA_8237:
365 case PCI_DEVICE_ID_VIA_8235:
366 case PCI_DEVICE_ID_VIA_8233A:
367 case PCI_DEVICE_ID_VIA_8233_0:
368 vt596_features |= FEATURE_I2CBLOCK;
369 break;
370 case PCI_DEVICE_ID_VIA_82C686_4:
371 /* The VT82C686B (rev 0x40) does support I2C block
372 transactions, but the VT82C686A (rev 0x30) doesn't */
373 if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
374 && temp >= 0x40)
375 vt596_features |= FEATURE_I2CBLOCK;
376 break;
377 }
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 vt596_adapter.dev.parent = &pdev->dev;
380 snprintf(vt596_adapter.name, I2C_NAME_SIZE,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200381 "SMBus Via Pro adapter at %04x", vt596_smba);
382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 vt596_pdev = pci_dev_get(pdev);
384 if (i2c_add_adapter(&vt596_adapter)) {
385 pci_dev_put(vt596_pdev);
386 vt596_pdev = NULL;
387 }
388
389 /* Always return failure here. This is to allow other drivers to bind
390 * to this pci device. We don't really want to have control over the
391 * pci device, we only wanted to read as few register values from it.
392 */
393 return -ENODEV;
394
Jean Delvare5f49ef82005-09-22 21:50:47 +0200395release_region:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 release_region(vt596_smba, 8);
397 return error;
398}
399
400static struct pci_device_id vt596_ids[] = {
401 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
402 .driver_data = SMBBA1 },
403 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
404 .driver_data = SMBBA1 },
405 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
406 .driver_data = SMBBA1 },
407 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
408 .driver_data = SMBBA3 },
409 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
410 .driver_data = SMBBA3 },
411 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
412 .driver_data = SMBBA3 },
413 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
414 .driver_data = SMBBA3 },
415 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
416 .driver_data = SMBBA1 },
417 { 0, }
418};
419
Jean Delvare5f49ef82005-09-22 21:50:47 +0200420MODULE_DEVICE_TABLE(pci, vt596_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
422static struct pci_driver vt596_driver = {
423 .name = "vt596_smbus",
424 .id_table = vt596_ids,
425 .probe = vt596_probe,
426};
427
428static int __init i2c_vt596_init(void)
429{
430 return pci_register_driver(&vt596_driver);
431}
432
433
434static void __exit i2c_vt596_exit(void)
435{
436 pci_unregister_driver(&vt596_driver);
437 if (vt596_pdev != NULL) {
438 i2c_del_adapter(&vt596_adapter);
439 release_region(vt596_smba, 8);
440 pci_dev_put(vt596_pdev);
441 vt596_pdev = NULL;
442 }
443}
444
445MODULE_AUTHOR(
446 "Frodo Looijaard <frodol@dds.nl> and "
447 "Philip Edelbrock <phil@netroedge.com>");
448MODULE_DESCRIPTION("vt82c596 SMBus driver");
449MODULE_LICENSE("GPL");
450
451module_init(i2c_vt596_init);
452module_exit(i2c_vt596_exit);