blob: a89a21264d37553778b6d5c46526a6a7bfe93442 [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 Delvaref1183012005-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 Delvaref1183012005-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 Delvaref1183012005-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 */
Jean Delvare50c1cc32005-09-22 22:15:53 +0200108static int vt596_transaction(u8 size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
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 */
Jean Delvare50c1cc32005-09-22 22:15:53 +0200134 outb_p(0x40 | (size & 0x3C), 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 Delvaref1183012005-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 Delvaref1183012005-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 Delvaref1183012005-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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
Jean Delvare50c1cc32005-09-22 22:15:53 +0200236 if (vt596_transaction(size)) /* Error in transaction */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 return -1;
238
239 if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
240 return 0;
241
242 switch (size) {
243 case VT596_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 case VT596_BYTE_DATA:
245 data->byte = inb_p(SMBHSTDAT0);
246 break;
247 case VT596_WORD_DATA:
248 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
249 break;
Jean Delvaref1183012005-09-22 21:58:41 +0200250 case VT596_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 case VT596_BLOCK_DATA:
252 data->block[0] = inb_p(SMBHSTDAT0);
253 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
254 data->block[0] = I2C_SMBUS_BLOCK_MAX;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200255 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 for (i = 1; i <= data->block[0]; i++)
257 data->block[i] = inb_p(SMBBLKDAT);
258 break;
259 }
260 return 0;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200261
262exit_unsupported:
263 dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
264 size);
265 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266}
267
268static u32 vt596_func(struct i2c_adapter *adapter)
269{
Jean Delvaref1183012005-09-22 21:58:41 +0200270 u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
272 I2C_FUNC_SMBUS_BLOCK_DATA;
Jean Delvaref1183012005-09-22 21:58:41 +0200273
274 if (vt596_features & FEATURE_I2CBLOCK)
275 func |= I2C_FUNC_SMBUS_I2C_BLOCK;
276 return func;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277}
278
279static struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 .smbus_xfer = vt596_access,
281 .functionality = vt596_func,
282};
283
284static struct i2c_adapter vt596_adapter = {
285 .owner = THIS_MODULE,
286 .class = I2C_CLASS_HWMON,
287 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288};
289
290static int __devinit vt596_probe(struct pci_dev *pdev,
291 const struct pci_device_id *id)
292{
293 unsigned char temp;
294 int error = -ENODEV;
Jean Delvare5f49ef82005-09-22 21:50:47 +0200295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 /* Determine the address of the SMBus areas */
297 if (force_addr) {
298 vt596_smba = force_addr & 0xfff0;
299 force = 0;
300 goto found;
301 }
302
303 if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
Jean Delvarec2f559d2005-09-22 22:01:07 +0200304 !(vt596_smba & 0x0001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 /* try 2nd address and config reg. for 596 */
306 if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
307 !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
Jean Delvarec2f559d2005-09-22 22:01:07 +0200308 (vt596_smba & 0x0001)) {
309 SMBHSTCFG = 0x84;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 } else {
311 /* no matches at all */
312 dev_err(&pdev->dev, "Cannot configure "
313 "SMBus I/O Base address\n");
314 return -ENODEV;
315 }
316 }
317
318 vt596_smba &= 0xfff0;
319 if (vt596_smba == 0) {
320 dev_err(&pdev->dev, "SMBus base address "
321 "uninitialized - upgrade BIOS or use "
322 "force_addr=0xaddr\n");
323 return -ENODEV;
324 }
325
Jean Delvare5f49ef82005-09-22 21:50:47 +0200326found:
Jean Delvarec2f559d2005-09-22 22:01:07 +0200327 if (!request_region(vt596_smba, 8, vt596_driver.name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
Jean Delvare5f49ef82005-09-22 21:50:47 +0200329 vt596_smba);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 return -ENODEV;
331 }
332
333 pci_read_config_byte(pdev, SMBHSTCFG, &temp);
334 /* If force_addr is set, we program the new address here. Just to make
335 sure, we disable the VT596 first. */
336 if (force_addr) {
337 pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
338 pci_write_config_word(pdev, id->driver_data, vt596_smba);
339 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
340 dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
Jean Delvare5f49ef82005-09-22 21:50:47 +0200341 "address 0x%04x!\n", vt596_smba);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200342 } else if (!(temp & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 if (force) {
Jean Delvare5f49ef82005-09-22 21:50:47 +0200344 /* NOTE: This assumes I/O space and other allocations
345 * WERE done by the Bios! Don't complain if your
346 * hardware does weird things after enabling this.
347 * :') Check for Bios updates before resorting to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 * this.
349 */
Jean Delvarec2f559d2005-09-22 22:01:07 +0200350 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 dev_info(&pdev->dev, "Enabling SMBus device\n");
352 } else {
353 dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
354 "controller not enabled! - upgrade BIOS or "
355 "use force=1\n");
356 goto release_region;
357 }
358 }
359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
361
Jean Delvaref1183012005-09-22 21:58:41 +0200362 switch (pdev->device) {
363 case PCI_DEVICE_ID_VIA_8237:
364 case PCI_DEVICE_ID_VIA_8235:
365 case PCI_DEVICE_ID_VIA_8233A:
366 case PCI_DEVICE_ID_VIA_8233_0:
367 vt596_features |= FEATURE_I2CBLOCK;
368 break;
369 case PCI_DEVICE_ID_VIA_82C686_4:
370 /* The VT82C686B (rev 0x40) does support I2C block
371 transactions, but the VT82C686A (rev 0x30) doesn't */
372 if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
373 && temp >= 0x40)
374 vt596_features |= FEATURE_I2CBLOCK;
375 break;
376 }
377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 vt596_adapter.dev.parent = &pdev->dev;
379 snprintf(vt596_adapter.name, I2C_NAME_SIZE,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200380 "SMBus Via Pro adapter at %04x", vt596_smba);
381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 vt596_pdev = pci_dev_get(pdev);
383 if (i2c_add_adapter(&vt596_adapter)) {
384 pci_dev_put(vt596_pdev);
385 vt596_pdev = NULL;
386 }
387
388 /* Always return failure here. This is to allow other drivers to bind
389 * to this pci device. We don't really want to have control over the
390 * pci device, we only wanted to read as few register values from it.
391 */
392 return -ENODEV;
393
Jean Delvare5f49ef82005-09-22 21:50:47 +0200394release_region:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 release_region(vt596_smba, 8);
396 return error;
397}
398
399static struct pci_device_id vt596_ids[] = {
400 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
401 .driver_data = SMBBA1 },
402 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
403 .driver_data = SMBBA1 },
404 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
405 .driver_data = SMBBA1 },
406 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
407 .driver_data = SMBBA3 },
408 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
409 .driver_data = SMBBA3 },
410 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
411 .driver_data = SMBBA3 },
412 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
413 .driver_data = SMBBA3 },
414 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
415 .driver_data = SMBBA1 },
416 { 0, }
417};
418
Jean Delvare5f49ef82005-09-22 21:50:47 +0200419MODULE_DEVICE_TABLE(pci, vt596_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421static struct pci_driver vt596_driver = {
422 .name = "vt596_smbus",
423 .id_table = vt596_ids,
424 .probe = vt596_probe,
425};
426
427static int __init i2c_vt596_init(void)
428{
429 return pci_register_driver(&vt596_driver);
430}
431
432
433static void __exit i2c_vt596_exit(void)
434{
435 pci_unregister_driver(&vt596_driver);
436 if (vt596_pdev != NULL) {
437 i2c_del_adapter(&vt596_adapter);
438 release_region(vt596_smba, 8);
439 pci_dev_put(vt596_pdev);
440 vt596_pdev = NULL;
441 }
442}
443
444MODULE_AUTHOR(
445 "Frodo Looijaard <frodol@dds.nl> and "
446 "Philip Edelbrock <phil@netroedge.com>");
447MODULE_DESCRIPTION("vt82c596 SMBus driver");
448MODULE_LICENSE("GPL");
449
450module_init(i2c_vt596_init);
451module_exit(i2c_vt596_exit);