blob: c1c9eb1d714f3a283d5d4e9a3d3c8ceccff2538c [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 Delvareed5453e2005-09-22 22:23:32 +0200107#ifdef DEBUG
108static void vt596_dump_regs(const char *msg, u8 size)
109{
110 dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
111 "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
112 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
113 inb_p(SMBHSTDAT1));
114
115 if (size == VT596_BLOCK_DATA
116 || size == VT596_I2C_BLOCK_DATA) {
117 int i;
118
119 dev_dbg(&vt596_adapter.dev, "BLK=");
120 for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
121 printk("%02x,", inb_p(SMBBLKDAT));
122 printk("\n");
123 dev_dbg(&vt596_adapter.dev, " ");
124 for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
125 printk("%02x,", inb_p(SMBBLKDAT));
126 printk("%02x\n", inb_p(SMBBLKDAT));
127 }
128}
129#endif
130
Jean Delvarec2f559d2005-09-22 22:01:07 +0200131/* Return -1 on error, 0 on success */
Jean Delvare50c1cc32005-09-22 22:15:53 +0200132static int vt596_transaction(u8 size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
134 int temp;
135 int result = 0;
136 int timeout = 0;
137
Jean Delvareed5453e2005-09-22 22:23:32 +0200138#ifdef DEBUG
139 vt596_dump_regs("Transaction (pre)", size);
140#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
142 /* Make sure the SMBus host is ready to start transmitting */
143 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
144 dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
Jean Delvarec2f559d2005-09-22 22:01:07 +0200145 "Resetting... ", temp);
Jean Delvare5f49ef82005-09-22 21:50:47 +0200146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 outb_p(temp, SMBHSTSTS);
148 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200149 printk("Failed! (0x%02x)\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 return -1;
151 } else {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200152 printk("Successful!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 }
154 }
155
Jean Delvarec2f559d2005-09-22 22:01:07 +0200156 /* Start the transaction by setting bit 6 */
Jean Delvare50c1cc32005-09-22 22:15:53 +0200157 outb_p(0x40 | (size & 0x3C), SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Jean Delvarec2f559d2005-09-22 22:01:07 +0200159 /* We will always wait for a fraction of a second */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 do {
161 msleep(1);
162 temp = inb_p(SMBHSTSTS);
163 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
164
165 /* If the SMBus is still busy, we give up */
166 if (timeout >= MAX_TIMEOUT) {
167 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200168 dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 }
170
171 if (temp & 0x10) {
172 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200173 dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
174 inb_p(SMBHSTCNT) & 0x3C);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 }
176
177 if (temp & 0x08) {
178 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200179 dev_err(&vt596_adapter.dev, "SMBus collision!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 }
181
182 if (temp & 0x04) {
183 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200184 /* Quick commands are used to probe for chips, so
185 errors are expected, and we don't want to frighten the
186 user. */
187 if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK)
188 dev_err(&vt596_adapter.dev, "Transaction error!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 }
190
Jean Delvarec2f559d2005-09-22 22:01:07 +0200191 /* Resetting status register */
192 if (temp & 0x1F)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 outb_p(temp, SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194
Jean Delvareed5453e2005-09-22 22:23:32 +0200195#ifdef DEBUG
196 vt596_dump_regs("Transaction (post)", size);
197#endif
Jean Delvare5f49ef82005-09-22 21:50:47 +0200198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 return result;
200}
201
Jean Delvarec2f559d2005-09-22 22:01:07 +0200202/* Return -1 on error, 0 on success */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200204 unsigned short flags, char read_write, u8 command,
205 int size, union i2c_smbus_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206{
Jean Delvarec2f559d2005-09-22 22:01:07 +0200207 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
209 switch (size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 case I2C_SMBUS_QUICK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 size = VT596_QUICK;
212 break;
213 case I2C_SMBUS_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 if (read_write == I2C_SMBUS_WRITE)
215 outb_p(command, SMBHSTCMD);
216 size = VT596_BYTE;
217 break;
218 case I2C_SMBUS_BYTE_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 outb_p(command, SMBHSTCMD);
220 if (read_write == I2C_SMBUS_WRITE)
221 outb_p(data->byte, SMBHSTDAT0);
222 size = VT596_BYTE_DATA;
223 break;
224 case I2C_SMBUS_WORD_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 outb_p(command, SMBHSTCMD);
226 if (read_write == I2C_SMBUS_WRITE) {
227 outb_p(data->word & 0xff, SMBHSTDAT0);
228 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
229 }
230 size = VT596_WORD_DATA;
231 break;
Jean Delvaref1183012005-09-22 21:58:41 +0200232 case I2C_SMBUS_I2C_BLOCK_DATA:
233 if (!(vt596_features & FEATURE_I2CBLOCK))
Jean Delvarec2f559d2005-09-22 22:01:07 +0200234 goto exit_unsupported;
Jean Delvaref1183012005-09-22 21:58:41 +0200235 if (read_write == I2C_SMBUS_READ)
236 outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
237 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 outb_p(command, SMBHSTCMD);
240 if (read_write == I2C_SMBUS_WRITE) {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200241 u8 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 if (len > I2C_SMBUS_BLOCK_MAX)
243 len = I2C_SMBUS_BLOCK_MAX;
244 outb_p(len, SMBHSTDAT0);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200245 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 for (i = 1; i <= len; i++)
247 outb_p(data->block[i], SMBBLKDAT);
248 }
Jean Delvaref1183012005-09-22 21:58:41 +0200249 size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
250 VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 break;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200252 default:
253 goto exit_unsupported;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 }
255
Jean Delvarec2f559d2005-09-22 22:01:07 +0200256 outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Jean Delvare50c1cc32005-09-22 22:15:53 +0200258 if (vt596_transaction(size)) /* Error in transaction */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 return -1;
260
261 if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
262 return 0;
263
264 switch (size) {
265 case VT596_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 case VT596_BYTE_DATA:
267 data->byte = inb_p(SMBHSTDAT0);
268 break;
269 case VT596_WORD_DATA:
270 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
271 break;
Jean Delvaref1183012005-09-22 21:58:41 +0200272 case VT596_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 case VT596_BLOCK_DATA:
274 data->block[0] = inb_p(SMBHSTDAT0);
275 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
276 data->block[0] = I2C_SMBUS_BLOCK_MAX;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200277 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 for (i = 1; i <= data->block[0]; i++)
279 data->block[i] = inb_p(SMBBLKDAT);
280 break;
281 }
282 return 0;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200283
284exit_unsupported:
285 dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
286 size);
287 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288}
289
290static u32 vt596_func(struct i2c_adapter *adapter)
291{
Jean Delvaref1183012005-09-22 21:58:41 +0200292 u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
294 I2C_FUNC_SMBUS_BLOCK_DATA;
Jean Delvaref1183012005-09-22 21:58:41 +0200295
296 if (vt596_features & FEATURE_I2CBLOCK)
297 func |= I2C_FUNC_SMBUS_I2C_BLOCK;
298 return func;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299}
300
301static struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 .smbus_xfer = vt596_access,
303 .functionality = vt596_func,
304};
305
306static struct i2c_adapter vt596_adapter = {
307 .owner = THIS_MODULE,
308 .class = I2C_CLASS_HWMON,
309 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310};
311
312static int __devinit vt596_probe(struct pci_dev *pdev,
313 const struct pci_device_id *id)
314{
315 unsigned char temp;
316 int error = -ENODEV;
Jean Delvare5f49ef82005-09-22 21:50:47 +0200317
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 /* Determine the address of the SMBus areas */
319 if (force_addr) {
320 vt596_smba = force_addr & 0xfff0;
321 force = 0;
322 goto found;
323 }
324
325 if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
Jean Delvarec2f559d2005-09-22 22:01:07 +0200326 !(vt596_smba & 0x0001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 /* try 2nd address and config reg. for 596 */
328 if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
329 !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
Jean Delvarec2f559d2005-09-22 22:01:07 +0200330 (vt596_smba & 0x0001)) {
331 SMBHSTCFG = 0x84;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 } else {
333 /* no matches at all */
334 dev_err(&pdev->dev, "Cannot configure "
335 "SMBus I/O Base address\n");
336 return -ENODEV;
337 }
338 }
339
340 vt596_smba &= 0xfff0;
341 if (vt596_smba == 0) {
342 dev_err(&pdev->dev, "SMBus base address "
343 "uninitialized - upgrade BIOS or use "
344 "force_addr=0xaddr\n");
345 return -ENODEV;
346 }
347
Jean Delvare5f49ef82005-09-22 21:50:47 +0200348found:
Jean Delvarec2f559d2005-09-22 22:01:07 +0200349 if (!request_region(vt596_smba, 8, vt596_driver.name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
Jean Delvare5f49ef82005-09-22 21:50:47 +0200351 vt596_smba);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 return -ENODEV;
353 }
354
355 pci_read_config_byte(pdev, SMBHSTCFG, &temp);
356 /* If force_addr is set, we program the new address here. Just to make
357 sure, we disable the VT596 first. */
358 if (force_addr) {
359 pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
360 pci_write_config_word(pdev, id->driver_data, vt596_smba);
361 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
362 dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
Jean Delvare5f49ef82005-09-22 21:50:47 +0200363 "address 0x%04x!\n", vt596_smba);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200364 } else if (!(temp & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 if (force) {
Jean Delvare5f49ef82005-09-22 21:50:47 +0200366 /* NOTE: This assumes I/O space and other allocations
367 * WERE done by the Bios! Don't complain if your
368 * hardware does weird things after enabling this.
369 * :') Check for Bios updates before resorting to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 * this.
371 */
Jean Delvarec2f559d2005-09-22 22:01:07 +0200372 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 dev_info(&pdev->dev, "Enabling SMBus device\n");
374 } else {
375 dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
376 "controller not enabled! - upgrade BIOS or "
377 "use force=1\n");
378 goto release_region;
379 }
380 }
381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
383
Jean Delvaref1183012005-09-22 21:58:41 +0200384 switch (pdev->device) {
385 case PCI_DEVICE_ID_VIA_8237:
386 case PCI_DEVICE_ID_VIA_8235:
387 case PCI_DEVICE_ID_VIA_8233A:
388 case PCI_DEVICE_ID_VIA_8233_0:
389 vt596_features |= FEATURE_I2CBLOCK;
390 break;
391 case PCI_DEVICE_ID_VIA_82C686_4:
392 /* The VT82C686B (rev 0x40) does support I2C block
393 transactions, but the VT82C686A (rev 0x30) doesn't */
394 if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
395 && temp >= 0x40)
396 vt596_features |= FEATURE_I2CBLOCK;
397 break;
398 }
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 vt596_adapter.dev.parent = &pdev->dev;
401 snprintf(vt596_adapter.name, I2C_NAME_SIZE,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200402 "SMBus Via Pro adapter at %04x", vt596_smba);
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 vt596_pdev = pci_dev_get(pdev);
405 if (i2c_add_adapter(&vt596_adapter)) {
406 pci_dev_put(vt596_pdev);
407 vt596_pdev = NULL;
408 }
409
410 /* Always return failure here. This is to allow other drivers to bind
411 * to this pci device. We don't really want to have control over the
412 * pci device, we only wanted to read as few register values from it.
413 */
414 return -ENODEV;
415
Jean Delvare5f49ef82005-09-22 21:50:47 +0200416release_region:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 release_region(vt596_smba, 8);
418 return error;
419}
420
421static struct pci_device_id vt596_ids[] = {
422 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
423 .driver_data = SMBBA1 },
424 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
425 .driver_data = SMBBA1 },
426 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
427 .driver_data = SMBBA1 },
428 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
429 .driver_data = SMBBA3 },
430 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
431 .driver_data = SMBBA3 },
432 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
433 .driver_data = SMBBA3 },
434 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
435 .driver_data = SMBBA3 },
436 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
437 .driver_data = SMBBA1 },
438 { 0, }
439};
440
Jean Delvare5f49ef82005-09-22 21:50:47 +0200441MODULE_DEVICE_TABLE(pci, vt596_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
443static struct pci_driver vt596_driver = {
444 .name = "vt596_smbus",
445 .id_table = vt596_ids,
446 .probe = vt596_probe,
447};
448
449static int __init i2c_vt596_init(void)
450{
451 return pci_register_driver(&vt596_driver);
452}
453
454
455static void __exit i2c_vt596_exit(void)
456{
457 pci_unregister_driver(&vt596_driver);
458 if (vt596_pdev != NULL) {
459 i2c_del_adapter(&vt596_adapter);
460 release_region(vt596_smba, 8);
461 pci_dev_put(vt596_pdev);
462 vt596_pdev = NULL;
463 }
464}
465
466MODULE_AUTHOR(
467 "Frodo Looijaard <frodol@dds.nl> and "
468 "Philip Edelbrock <phil@netroedge.com>");
469MODULE_DESCRIPTION("vt82c596 SMBus driver");
470MODULE_LICENSE("GPL");
471
472module_init(i2c_vt596_init);
473module_exit(i2c_vt596_exit);