blob: 1ccc0fbc59472e75fa52dfaf152266fac4338853 [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
Rudolf Marekc2433532006-09-03 22:35:21 +020037 VT8237A 0x3337 yes
38 VT8251 0x3287 yes
Jean Delvareaaf7f142005-09-22 22:09:07 +020039
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 Note: we assume there can only be one device, with one SMBus interface.
41*/
42
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/module.h>
44#include <linux/delay.h>
45#include <linux/pci.h>
46#include <linux/kernel.h>
47#include <linux/stddef.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <linux/ioport.h>
49#include <linux/i2c.h>
50#include <linux/init.h>
51#include <asm/io.h>
52
53static struct pci_dev *vt596_pdev;
54
Jean Delvare5f49ef82005-09-22 21:50:47 +020055#define SMBBA1 0x90
56#define SMBBA2 0x80
57#define SMBBA3 0xD0
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59/* SMBus address offsets */
60static unsigned short vt596_smba;
61#define SMBHSTSTS (vt596_smba + 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#define SMBHSTCNT (vt596_smba + 2)
63#define SMBHSTCMD (vt596_smba + 3)
64#define SMBHSTADD (vt596_smba + 4)
65#define SMBHSTDAT0 (vt596_smba + 5)
66#define SMBHSTDAT1 (vt596_smba + 6)
67#define SMBBLKDAT (vt596_smba + 7)
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
69/* PCI Address Constants */
70
71/* SMBus data in configuration space can be found in two places,
Jean Delvare5f49ef82005-09-22 21:50:47 +020072 We try to select the better one */
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Jean Delvarec2f559d2005-09-22 22:01:07 +020074static unsigned short SMBHSTCFG = 0xD2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76/* Other settings */
77#define MAX_TIMEOUT 500
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79/* VT82C596 constants */
Jean Delvare5f49ef82005-09-22 21:50:47 +020080#define VT596_QUICK 0x00
81#define VT596_BYTE 0x04
82#define VT596_BYTE_DATA 0x08
83#define VT596_WORD_DATA 0x0C
84#define VT596_BLOCK_DATA 0x14
Jean Delvaref1183012005-09-22 21:58:41 +020085#define VT596_I2C_BLOCK_DATA 0x34
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87
88/* If force is set to anything different from 0, we forcibly enable the
89 VT596. DANGEROUS! */
90static int force;
91module_param(force, bool, 0);
92MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
93
94/* If force_addr is set to anything different from 0, we forcibly enable
95 the VT596 at the given address. VERY DANGEROUS! */
96static u16 force_addr;
97module_param(force_addr, ushort, 0);
98MODULE_PARM_DESC(force_addr,
99 "Forcibly enable the SMBus at the given address. "
100 "EXTREMELY DANGEROUS!");
101
102
Jean Delvarec2f559d2005-09-22 22:01:07 +0200103static struct pci_driver vt596_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104static struct i2c_adapter vt596_adapter;
105
Jean Delvaref1183012005-09-22 21:58:41 +0200106#define FEATURE_I2CBLOCK (1<<0)
107static unsigned int vt596_features;
108
Jean Delvareed5453e2005-09-22 22:23:32 +0200109#ifdef DEBUG
110static void vt596_dump_regs(const char *msg, u8 size)
111{
112 dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
113 "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
114 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
115 inb_p(SMBHSTDAT1));
116
117 if (size == VT596_BLOCK_DATA
118 || size == VT596_I2C_BLOCK_DATA) {
119 int i;
120
121 dev_dbg(&vt596_adapter.dev, "BLK=");
122 for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
123 printk("%02x,", inb_p(SMBBLKDAT));
124 printk("\n");
125 dev_dbg(&vt596_adapter.dev, " ");
126 for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
127 printk("%02x,", inb_p(SMBBLKDAT));
128 printk("%02x\n", inb_p(SMBBLKDAT));
129 }
130}
Greg KHca68f112005-09-22 22:23:32 +0200131#else
132static inline void vt596_dump_regs(const char *msg, u8 size) { }
Jean Delvareed5453e2005-09-22 22:23:32 +0200133#endif
134
Jean Delvarec2f559d2005-09-22 22:01:07 +0200135/* Return -1 on error, 0 on success */
Jean Delvare50c1cc32005-09-22 22:15:53 +0200136static int vt596_transaction(u8 size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137{
138 int temp;
139 int result = 0;
140 int timeout = 0;
141
Jean Delvareed5453e2005-09-22 22:23:32 +0200142 vt596_dump_regs("Transaction (pre)", size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
144 /* Make sure the SMBus host is ready to start transmitting */
145 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
146 dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
Jean Delvare87501972005-10-31 18:51:21 +0100147 "Resetting...\n", temp);
Jean Delvare5f49ef82005-09-22 21:50:47 +0200148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 outb_p(temp, SMBHSTSTS);
150 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
Jean Delvare87501972005-10-31 18:51:21 +0100151 dev_err(&vt596_adapter.dev, "SMBus reset failed! "
152 "(0x%02x)\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 }
155 }
156
Jean Delvarec2f559d2005-09-22 22:01:07 +0200157 /* Start the transaction by setting bit 6 */
Jean Delvare87501972005-10-31 18:51:21 +0100158 outb_p(0x40 | size, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
Jean Delvarec2f559d2005-09-22 22:01:07 +0200160 /* We will always wait for a fraction of a second */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 do {
162 msleep(1);
163 temp = inb_p(SMBHSTSTS);
164 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
165
166 /* If the SMBus is still busy, we give up */
167 if (timeout >= MAX_TIMEOUT) {
168 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200169 dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 }
171
172 if (temp & 0x10) {
173 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200174 dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
Jean Delvare87501972005-10-31 18:51:21 +0100175 size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 }
177
178 if (temp & 0x08) {
179 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200180 dev_err(&vt596_adapter.dev, "SMBus collision!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 }
182
183 if (temp & 0x04) {
Jean Delvare87501972005-10-31 18:51:21 +0100184 int read = inb_p(SMBHSTADD) & 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 result = -1;
Jean Delvare87501972005-10-31 18:51:21 +0100186 /* The quick and receive byte commands are used to probe
187 for chips, so errors are expected, and we don't want
188 to frighten the user. */
189 if (!((size == VT596_QUICK && !read) ||
190 (size == VT596_BYTE && read)))
Jean Delvarec2f559d2005-09-22 22:01:07 +0200191 dev_err(&vt596_adapter.dev, "Transaction error!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 }
193
Jean Delvarec2f559d2005-09-22 22:01:07 +0200194 /* Resetting status register */
195 if (temp & 0x1F)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 outb_p(temp, SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
Jean Delvareed5453e2005-09-22 22:23:32 +0200198 vt596_dump_regs("Transaction (post)", size);
Jean Delvare5f49ef82005-09-22 21:50:47 +0200199
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 return result;
201}
202
Jean Delvarec2f559d2005-09-22 22:01:07 +0200203/* Return -1 on error, 0 on success */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200205 unsigned short flags, char read_write, u8 command,
206 int size, union i2c_smbus_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207{
Jean Delvarec2f559d2005-09-22 22:01:07 +0200208 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
210 switch (size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 case I2C_SMBUS_QUICK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 size = VT596_QUICK;
213 break;
214 case I2C_SMBUS_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 if (read_write == I2C_SMBUS_WRITE)
216 outb_p(command, SMBHSTCMD);
217 size = VT596_BYTE;
218 break;
219 case I2C_SMBUS_BYTE_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 outb_p(command, SMBHSTCMD);
221 if (read_write == I2C_SMBUS_WRITE)
222 outb_p(data->byte, SMBHSTDAT0);
223 size = VT596_BYTE_DATA;
224 break;
225 case I2C_SMBUS_WORD_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 outb_p(command, SMBHSTCMD);
227 if (read_write == I2C_SMBUS_WRITE) {
228 outb_p(data->word & 0xff, SMBHSTDAT0);
229 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
230 }
231 size = VT596_WORD_DATA;
232 break;
Jean Delvaref1183012005-09-22 21:58:41 +0200233 case I2C_SMBUS_I2C_BLOCK_DATA:
234 if (!(vt596_features & FEATURE_I2CBLOCK))
Jean Delvarec2f559d2005-09-22 22:01:07 +0200235 goto exit_unsupported;
Jean Delvaref1183012005-09-22 21:58:41 +0200236 if (read_write == I2C_SMBUS_READ)
237 outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
238 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 outb_p(command, SMBHSTCMD);
241 if (read_write == I2C_SMBUS_WRITE) {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200242 u8 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 if (len > I2C_SMBUS_BLOCK_MAX)
244 len = I2C_SMBUS_BLOCK_MAX;
245 outb_p(len, SMBHSTDAT0);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200246 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 for (i = 1; i <= len; i++)
248 outb_p(data->block[i], SMBBLKDAT);
249 }
Jean Delvaref1183012005-09-22 21:58:41 +0200250 size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
251 VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 break;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200253 default:
254 goto exit_unsupported;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 }
256
Jean Delvarec2f559d2005-09-22 22:01:07 +0200257 outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Jean Delvare50c1cc32005-09-22 22:15:53 +0200259 if (vt596_transaction(size)) /* Error in transaction */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 return -1;
261
262 if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
263 return 0;
264
265 switch (size) {
266 case VT596_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 case VT596_BYTE_DATA:
268 data->byte = inb_p(SMBHSTDAT0);
269 break;
270 case VT596_WORD_DATA:
271 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
272 break;
Jean Delvaref1183012005-09-22 21:58:41 +0200273 case VT596_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 case VT596_BLOCK_DATA:
275 data->block[0] = inb_p(SMBHSTDAT0);
276 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
277 data->block[0] = I2C_SMBUS_BLOCK_MAX;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200278 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 for (i = 1; i <= data->block[0]; i++)
280 data->block[i] = inb_p(SMBBLKDAT);
281 break;
282 }
283 return 0;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200284
285exit_unsupported:
286 dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
287 size);
288 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289}
290
291static u32 vt596_func(struct i2c_adapter *adapter)
292{
Jean Delvaref1183012005-09-22 21:58:41 +0200293 u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
295 I2C_FUNC_SMBUS_BLOCK_DATA;
Jean Delvaref1183012005-09-22 21:58:41 +0200296
297 if (vt596_features & FEATURE_I2CBLOCK)
298 func |= I2C_FUNC_SMBUS_I2C_BLOCK;
299 return func;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
302static struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 .smbus_xfer = vt596_access,
304 .functionality = vt596_func,
305};
306
307static struct i2c_adapter vt596_adapter = {
308 .owner = THIS_MODULE,
309 .class = I2C_CLASS_HWMON,
310 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311};
312
313static int __devinit vt596_probe(struct pci_dev *pdev,
314 const struct pci_device_id *id)
315{
316 unsigned char temp;
317 int error = -ENODEV;
Jean Delvare5f49ef82005-09-22 21:50:47 +0200318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 /* Determine the address of the SMBus areas */
320 if (force_addr) {
321 vt596_smba = force_addr & 0xfff0;
322 force = 0;
323 goto found;
324 }
325
326 if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
Jean Delvarec2f559d2005-09-22 22:01:07 +0200327 !(vt596_smba & 0x0001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 /* try 2nd address and config reg. for 596 */
329 if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
330 !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
Jean Delvarec2f559d2005-09-22 22:01:07 +0200331 (vt596_smba & 0x0001)) {
332 SMBHSTCFG = 0x84;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 } else {
334 /* no matches at all */
335 dev_err(&pdev->dev, "Cannot configure "
336 "SMBus I/O Base address\n");
337 return -ENODEV;
338 }
339 }
340
341 vt596_smba &= 0xfff0;
342 if (vt596_smba == 0) {
343 dev_err(&pdev->dev, "SMBus base address "
344 "uninitialized - upgrade BIOS or use "
345 "force_addr=0xaddr\n");
346 return -ENODEV;
347 }
348
Jean Delvare5f49ef82005-09-22 21:50:47 +0200349found:
Jean Delvarec2f559d2005-09-22 22:01:07 +0200350 if (!request_region(vt596_smba, 8, vt596_driver.name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
Jean Delvare5f49ef82005-09-22 21:50:47 +0200352 vt596_smba);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 return -ENODEV;
354 }
355
356 pci_read_config_byte(pdev, SMBHSTCFG, &temp);
357 /* If force_addr is set, we program the new address here. Just to make
358 sure, we disable the VT596 first. */
359 if (force_addr) {
360 pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
361 pci_write_config_word(pdev, id->driver_data, vt596_smba);
362 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
363 dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
Jean Delvare5f49ef82005-09-22 21:50:47 +0200364 "address 0x%04x!\n", vt596_smba);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200365 } else if (!(temp & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 if (force) {
Jean Delvare5f49ef82005-09-22 21:50:47 +0200367 /* NOTE: This assumes I/O space and other allocations
368 * WERE done by the Bios! Don't complain if your
369 * hardware does weird things after enabling this.
370 * :') Check for Bios updates before resorting to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 * this.
372 */
Jean Delvarec2f559d2005-09-22 22:01:07 +0200373 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 dev_info(&pdev->dev, "Enabling SMBus device\n");
375 } else {
376 dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
377 "controller not enabled! - upgrade BIOS or "
378 "use force=1\n");
379 goto release_region;
380 }
381 }
382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
384
Jean Delvaref1183012005-09-22 21:58:41 +0200385 switch (pdev->device) {
Rudolf Marekc2433532006-09-03 22:35:21 +0200386 case PCI_DEVICE_ID_VIA_8251:
Jean Delvaref1183012005-09-22 21:58:41 +0200387 case PCI_DEVICE_ID_VIA_8237:
Rudolf Marekc2433532006-09-03 22:35:21 +0200388 case PCI_DEVICE_ID_VIA_8237A:
Jean Delvaref1183012005-09-22 21:58:41 +0200389 case PCI_DEVICE_ID_VIA_8235:
390 case PCI_DEVICE_ID_VIA_8233A:
391 case PCI_DEVICE_ID_VIA_8233_0:
392 vt596_features |= FEATURE_I2CBLOCK;
393 break;
394 case PCI_DEVICE_ID_VIA_82C686_4:
395 /* The VT82C686B (rev 0x40) does support I2C block
396 transactions, but the VT82C686A (rev 0x30) doesn't */
397 if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
398 && temp >= 0x40)
399 vt596_features |= FEATURE_I2CBLOCK;
400 break;
401 }
402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 vt596_adapter.dev.parent = &pdev->dev;
404 snprintf(vt596_adapter.name, I2C_NAME_SIZE,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200405 "SMBus Via Pro adapter at %04x", vt596_smba);
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 vt596_pdev = pci_dev_get(pdev);
408 if (i2c_add_adapter(&vt596_adapter)) {
409 pci_dev_put(vt596_pdev);
410 vt596_pdev = NULL;
411 }
412
413 /* Always return failure here. This is to allow other drivers to bind
414 * to this pci device. We don't really want to have control over the
415 * pci device, we only wanted to read as few register values from it.
416 */
417 return -ENODEV;
418
Jean Delvare5f49ef82005-09-22 21:50:47 +0200419release_region:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 release_region(vt596_smba, 8);
421 return error;
422}
423
424static struct pci_device_id vt596_ids[] = {
425 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
426 .driver_data = SMBBA1 },
427 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
428 .driver_data = SMBBA1 },
429 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
430 .driver_data = SMBBA1 },
431 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
432 .driver_data = SMBBA3 },
433 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
434 .driver_data = SMBBA3 },
435 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
436 .driver_data = SMBBA3 },
437 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
438 .driver_data = SMBBA3 },
Rudolf Marekc2433532006-09-03 22:35:21 +0200439 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
440 .driver_data = SMBBA3 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
442 .driver_data = SMBBA1 },
Rudolf Marekc2433532006-09-03 22:35:21 +0200443 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
444 .driver_data = SMBBA3 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 { 0, }
446};
447
Jean Delvare5f49ef82005-09-22 21:50:47 +0200448MODULE_DEVICE_TABLE(pci, vt596_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
450static struct pci_driver vt596_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 .name = "vt596_smbus",
452 .id_table = vt596_ids,
453 .probe = vt596_probe,
454};
455
456static int __init i2c_vt596_init(void)
457{
458 return pci_register_driver(&vt596_driver);
459}
460
461
462static void __exit i2c_vt596_exit(void)
463{
464 pci_unregister_driver(&vt596_driver);
465 if (vt596_pdev != NULL) {
466 i2c_del_adapter(&vt596_adapter);
467 release_region(vt596_smba, 8);
468 pci_dev_put(vt596_pdev);
469 vt596_pdev = NULL;
470 }
471}
472
Jean Delvare87501972005-10-31 18:51:21 +0100473MODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>, "
474 "Mark D. Studebaker <mdsxyz123@yahoo.com> and "
475 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476MODULE_DESCRIPTION("vt82c596 SMBus driver");
477MODULE_LICENSE("GPL");
478
479module_init(i2c_vt596_init);
480module_exit(i2c_vt596_exit);