blob: 03c5fc868548d3d121aca6d879b06e13031594c2 [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 Delvareab6a6ed2007-02-13 22:09:02 +01007 Copyright (C) 2005 - 2007 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 Delvareab6a6ed2007-02-13 22:09:02 +010039 CX700 0x8324 yes
Jean Delvareaaf7f142005-09-22 22:09:07 +020040
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 Note: we assume there can only be one device, with one SMBus interface.
42*/
43
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/module.h>
45#include <linux/delay.h>
46#include <linux/pci.h>
47#include <linux/kernel.h>
48#include <linux/stddef.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/ioport.h>
50#include <linux/i2c.h>
51#include <linux/init.h>
52#include <asm/io.h>
53
54static struct pci_dev *vt596_pdev;
55
Jean Delvare5f49ef82005-09-22 21:50:47 +020056#define SMBBA1 0x90
57#define SMBBA2 0x80
58#define SMBBA3 0xD0
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60/* SMBus address offsets */
61static unsigned short vt596_smba;
62#define SMBHSTSTS (vt596_smba + 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#define SMBHSTCNT (vt596_smba + 2)
64#define SMBHSTCMD (vt596_smba + 3)
65#define SMBHSTADD (vt596_smba + 4)
66#define SMBHSTDAT0 (vt596_smba + 5)
67#define SMBHSTDAT1 (vt596_smba + 6)
68#define SMBBLKDAT (vt596_smba + 7)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
70/* PCI Address Constants */
71
72/* SMBus data in configuration space can be found in two places,
Jean Delvare5f49ef82005-09-22 21:50:47 +020073 We try to select the better one */
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Jean Delvarec2f559d2005-09-22 22:01:07 +020075static unsigned short SMBHSTCFG = 0xD2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77/* Other settings */
78#define MAX_TIMEOUT 500
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80/* VT82C596 constants */
Jean Delvare5f49ef82005-09-22 21:50:47 +020081#define VT596_QUICK 0x00
82#define VT596_BYTE 0x04
83#define VT596_BYTE_DATA 0x08
84#define VT596_WORD_DATA 0x0C
85#define VT596_BLOCK_DATA 0x14
Jean Delvaref1183012005-09-22 21:58:41 +020086#define VT596_I2C_BLOCK_DATA 0x34
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88
89/* If force is set to anything different from 0, we forcibly enable the
90 VT596. DANGEROUS! */
91static int force;
92module_param(force, bool, 0);
93MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
94
95/* If force_addr is set to anything different from 0, we forcibly enable
96 the VT596 at the given address. VERY DANGEROUS! */
97static u16 force_addr;
98module_param(force_addr, ushort, 0);
99MODULE_PARM_DESC(force_addr,
100 "Forcibly enable the SMBus at the given address. "
101 "EXTREMELY DANGEROUS!");
102
103
Jean Delvarec2f559d2005-09-22 22:01:07 +0200104static struct pci_driver vt596_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105static struct i2c_adapter vt596_adapter;
106
Jean Delvaref1183012005-09-22 21:58:41 +0200107#define FEATURE_I2CBLOCK (1<<0)
108static unsigned int vt596_features;
109
Jean Delvareed5453e2005-09-22 22:23:32 +0200110#ifdef DEBUG
111static void vt596_dump_regs(const char *msg, u8 size)
112{
113 dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
114 "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
115 inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
116 inb_p(SMBHSTDAT1));
117
118 if (size == VT596_BLOCK_DATA
119 || size == VT596_I2C_BLOCK_DATA) {
120 int i;
121
122 dev_dbg(&vt596_adapter.dev, "BLK=");
123 for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
124 printk("%02x,", inb_p(SMBBLKDAT));
125 printk("\n");
126 dev_dbg(&vt596_adapter.dev, " ");
127 for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
128 printk("%02x,", inb_p(SMBBLKDAT));
129 printk("%02x\n", inb_p(SMBBLKDAT));
130 }
131}
Greg KHca68f112005-09-22 22:23:32 +0200132#else
133static inline void vt596_dump_regs(const char *msg, u8 size) { }
Jean Delvareed5453e2005-09-22 22:23:32 +0200134#endif
135
Jean Delvarec2f559d2005-09-22 22:01:07 +0200136/* Return -1 on error, 0 on success */
Jean Delvare50c1cc32005-09-22 22:15:53 +0200137static int vt596_transaction(u8 size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138{
139 int temp;
140 int result = 0;
141 int timeout = 0;
142
Jean Delvareed5453e2005-09-22 22:23:32 +0200143 vt596_dump_regs("Transaction (pre)", size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
145 /* Make sure the SMBus host is ready to start transmitting */
146 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
147 dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
Jean Delvare87501972005-10-31 18:51:21 +0100148 "Resetting...\n", temp);
Jean Delvare5f49ef82005-09-22 21:50:47 +0200149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 outb_p(temp, SMBHSTSTS);
151 if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
Jean Delvare87501972005-10-31 18:51:21 +0100152 dev_err(&vt596_adapter.dev, "SMBus reset failed! "
153 "(0x%02x)\n", temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 }
156 }
157
Jean Delvarec2f559d2005-09-22 22:01:07 +0200158 /* Start the transaction by setting bit 6 */
Jean Delvare87501972005-10-31 18:51:21 +0100159 outb_p(0x40 | size, SMBHSTCNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
Jean Delvarec2f559d2005-09-22 22:01:07 +0200161 /* We will always wait for a fraction of a second */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 do {
163 msleep(1);
164 temp = inb_p(SMBHSTSTS);
165 } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
166
167 /* If the SMBus is still busy, we give up */
168 if (timeout >= MAX_TIMEOUT) {
169 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200170 dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 }
172
173 if (temp & 0x10) {
174 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200175 dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
Jean Delvare87501972005-10-31 18:51:21 +0100176 size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 }
178
179 if (temp & 0x08) {
180 result = -1;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200181 dev_err(&vt596_adapter.dev, "SMBus collision!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 }
183
184 if (temp & 0x04) {
Jean Delvare87501972005-10-31 18:51:21 +0100185 int read = inb_p(SMBHSTADD) & 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 result = -1;
Jean Delvare87501972005-10-31 18:51:21 +0100187 /* The quick and receive byte commands are used to probe
188 for chips, so errors are expected, and we don't want
189 to frighten the user. */
190 if (!((size == VT596_QUICK && !read) ||
191 (size == VT596_BYTE && read)))
Jean Delvarec2f559d2005-09-22 22:01:07 +0200192 dev_err(&vt596_adapter.dev, "Transaction error!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 }
194
Jean Delvarec2f559d2005-09-22 22:01:07 +0200195 /* Resetting status register */
196 if (temp & 0x1F)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 outb_p(temp, SMBHSTSTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Jean Delvareed5453e2005-09-22 22:23:32 +0200199 vt596_dump_regs("Transaction (post)", size);
Jean Delvare5f49ef82005-09-22 21:50:47 +0200200
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 return result;
202}
203
Jean Delvarec2f559d2005-09-22 22:01:07 +0200204/* Return -1 on error, 0 on success */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200206 unsigned short flags, char read_write, u8 command,
207 int size, union i2c_smbus_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208{
Jean Delvarec2f559d2005-09-22 22:01:07 +0200209 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
211 switch (size) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 case I2C_SMBUS_QUICK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 size = VT596_QUICK;
214 break;
215 case I2C_SMBUS_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 if (read_write == I2C_SMBUS_WRITE)
217 outb_p(command, SMBHSTCMD);
218 size = VT596_BYTE;
219 break;
220 case I2C_SMBUS_BYTE_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 outb_p(command, SMBHSTCMD);
222 if (read_write == I2C_SMBUS_WRITE)
223 outb_p(data->byte, SMBHSTDAT0);
224 size = VT596_BYTE_DATA;
225 break;
226 case I2C_SMBUS_WORD_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 outb_p(command, SMBHSTCMD);
228 if (read_write == I2C_SMBUS_WRITE) {
229 outb_p(data->word & 0xff, SMBHSTDAT0);
230 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
231 }
232 size = VT596_WORD_DATA;
233 break;
Jean Delvaref1183012005-09-22 21:58:41 +0200234 case I2C_SMBUS_I2C_BLOCK_DATA:
235 if (!(vt596_features & FEATURE_I2CBLOCK))
Jean Delvarec2f559d2005-09-22 22:01:07 +0200236 goto exit_unsupported;
Jean Delvaref1183012005-09-22 21:58:41 +0200237 if (read_write == I2C_SMBUS_READ)
238 outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
239 /* Fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 case I2C_SMBUS_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 outb_p(command, SMBHSTCMD);
242 if (read_write == I2C_SMBUS_WRITE) {
Jean Delvarec2f559d2005-09-22 22:01:07 +0200243 u8 len = data->block[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 if (len > I2C_SMBUS_BLOCK_MAX)
245 len = I2C_SMBUS_BLOCK_MAX;
246 outb_p(len, SMBHSTDAT0);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200247 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 for (i = 1; i <= len; i++)
249 outb_p(data->block[i], SMBBLKDAT);
250 }
Jean Delvaref1183012005-09-22 21:58:41 +0200251 size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
252 VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 break;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200254 default:
255 goto exit_unsupported;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 }
257
Jean Delvarec2f559d2005-09-22 22:01:07 +0200258 outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
Jean Delvare50c1cc32005-09-22 22:15:53 +0200260 if (vt596_transaction(size)) /* Error in transaction */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 return -1;
262
263 if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
264 return 0;
265
266 switch (size) {
267 case VT596_BYTE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 case VT596_BYTE_DATA:
269 data->byte = inb_p(SMBHSTDAT0);
270 break;
271 case VT596_WORD_DATA:
272 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
273 break;
Jean Delvaref1183012005-09-22 21:58:41 +0200274 case VT596_I2C_BLOCK_DATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 case VT596_BLOCK_DATA:
276 data->block[0] = inb_p(SMBHSTDAT0);
277 if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
278 data->block[0] = I2C_SMBUS_BLOCK_MAX;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200279 inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 for (i = 1; i <= data->block[0]; i++)
281 data->block[i] = inb_p(SMBBLKDAT);
282 break;
283 }
284 return 0;
Jean Delvarec2f559d2005-09-22 22:01:07 +0200285
286exit_unsupported:
287 dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
288 size);
289 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290}
291
292static u32 vt596_func(struct i2c_adapter *adapter)
293{
Jean Delvaref1183012005-09-22 21:58:41 +0200294 u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
296 I2C_FUNC_SMBUS_BLOCK_DATA;
Jean Delvaref1183012005-09-22 21:58:41 +0200297
298 if (vt596_features & FEATURE_I2CBLOCK)
299 func |= I2C_FUNC_SMBUS_I2C_BLOCK;
300 return func;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301}
302
Jean Delvare8f9082c2006-09-03 22:39:46 +0200303static const struct i2c_algorithm smbus_algorithm = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 .smbus_xfer = vt596_access,
305 .functionality = vt596_func,
306};
307
308static struct i2c_adapter vt596_adapter = {
309 .owner = THIS_MODULE,
Stephen Hemminger9ace5552007-02-13 22:09:01 +0100310 .id = I2C_HW_SMBUS_VIA2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 .class = I2C_CLASS_HWMON,
312 .algo = &smbus_algorithm,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313};
314
315static int __devinit vt596_probe(struct pci_dev *pdev,
316 const struct pci_device_id *id)
317{
318 unsigned char temp;
319 int error = -ENODEV;
Jean Delvare5f49ef82005-09-22 21:50:47 +0200320
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 /* Determine the address of the SMBus areas */
322 if (force_addr) {
323 vt596_smba = force_addr & 0xfff0;
324 force = 0;
325 goto found;
326 }
327
328 if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
Jean Delvarec2f559d2005-09-22 22:01:07 +0200329 !(vt596_smba & 0x0001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 /* try 2nd address and config reg. for 596 */
331 if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
332 !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
Jean Delvarec2f559d2005-09-22 22:01:07 +0200333 (vt596_smba & 0x0001)) {
334 SMBHSTCFG = 0x84;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 } else {
336 /* no matches at all */
337 dev_err(&pdev->dev, "Cannot configure "
338 "SMBus I/O Base address\n");
339 return -ENODEV;
340 }
341 }
342
343 vt596_smba &= 0xfff0;
344 if (vt596_smba == 0) {
345 dev_err(&pdev->dev, "SMBus base address "
346 "uninitialized - upgrade BIOS or use "
347 "force_addr=0xaddr\n");
348 return -ENODEV;
349 }
350
Jean Delvare5f49ef82005-09-22 21:50:47 +0200351found:
Jean Delvarec2f559d2005-09-22 22:01:07 +0200352 if (!request_region(vt596_smba, 8, vt596_driver.name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
Jean Delvare5f49ef82005-09-22 21:50:47 +0200354 vt596_smba);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 return -ENODEV;
356 }
357
358 pci_read_config_byte(pdev, SMBHSTCFG, &temp);
359 /* If force_addr is set, we program the new address here. Just to make
360 sure, we disable the VT596 first. */
361 if (force_addr) {
362 pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
363 pci_write_config_word(pdev, id->driver_data, vt596_smba);
364 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
365 dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
Jean Delvare5f49ef82005-09-22 21:50:47 +0200366 "address 0x%04x!\n", vt596_smba);
Jean Delvarec2f559d2005-09-22 22:01:07 +0200367 } else if (!(temp & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 if (force) {
Jean Delvare5f49ef82005-09-22 21:50:47 +0200369 /* NOTE: This assumes I/O space and other allocations
370 * WERE done by the Bios! Don't complain if your
371 * hardware does weird things after enabling this.
372 * :') Check for Bios updates before resorting to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 * this.
374 */
Jean Delvarec2f559d2005-09-22 22:01:07 +0200375 pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 dev_info(&pdev->dev, "Enabling SMBus device\n");
377 } else {
378 dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
379 "controller not enabled! - upgrade BIOS or "
380 "use force=1\n");
381 goto release_region;
382 }
383 }
384
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
386
Jean Delvaref1183012005-09-22 21:58:41 +0200387 switch (pdev->device) {
Jean Delvareab6a6ed2007-02-13 22:09:02 +0100388 case PCI_DEVICE_ID_VIA_CX700:
Rudolf Marekc2433532006-09-03 22:35:21 +0200389 case PCI_DEVICE_ID_VIA_8251:
Jean Delvaref1183012005-09-22 21:58:41 +0200390 case PCI_DEVICE_ID_VIA_8237:
Rudolf Marekc2433532006-09-03 22:35:21 +0200391 case PCI_DEVICE_ID_VIA_8237A:
Jean Delvaref1183012005-09-22 21:58:41 +0200392 case PCI_DEVICE_ID_VIA_8235:
393 case PCI_DEVICE_ID_VIA_8233A:
394 case PCI_DEVICE_ID_VIA_8233_0:
395 vt596_features |= FEATURE_I2CBLOCK;
396 break;
397 case PCI_DEVICE_ID_VIA_82C686_4:
398 /* The VT82C686B (rev 0x40) does support I2C block
399 transactions, but the VT82C686A (rev 0x30) doesn't */
400 if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
401 && temp >= 0x40)
402 vt596_features |= FEATURE_I2CBLOCK;
403 break;
404 }
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 vt596_adapter.dev.parent = &pdev->dev;
407 snprintf(vt596_adapter.name, I2C_NAME_SIZE,
Jean Delvare5f49ef82005-09-22 21:50:47 +0200408 "SMBus Via Pro adapter at %04x", vt596_smba);
409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 vt596_pdev = pci_dev_get(pdev);
411 if (i2c_add_adapter(&vt596_adapter)) {
412 pci_dev_put(vt596_pdev);
413 vt596_pdev = NULL;
414 }
415
416 /* Always return failure here. This is to allow other drivers to bind
417 * to this pci device. We don't really want to have control over the
418 * pci device, we only wanted to read as few register values from it.
419 */
420 return -ENODEV;
421
Jean Delvare5f49ef82005-09-22 21:50:47 +0200422release_region:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 release_region(vt596_smba, 8);
424 return error;
425}
426
427static struct pci_device_id vt596_ids[] = {
428 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
429 .driver_data = SMBBA1 },
430 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
431 .driver_data = SMBBA1 },
432 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
433 .driver_data = SMBBA1 },
434 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
435 .driver_data = SMBBA3 },
436 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
437 .driver_data = SMBBA3 },
438 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
439 .driver_data = SMBBA3 },
440 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
441 .driver_data = SMBBA3 },
Rudolf Marekc2433532006-09-03 22:35:21 +0200442 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
443 .driver_data = SMBBA3 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
445 .driver_data = SMBBA1 },
Rudolf Marekc2433532006-09-03 22:35:21 +0200446 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
447 .driver_data = SMBBA3 },
Jean Delvareab6a6ed2007-02-13 22:09:02 +0100448 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700),
449 .driver_data = SMBBA3 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 { 0, }
451};
452
Jean Delvare5f49ef82005-09-22 21:50:47 +0200453MODULE_DEVICE_TABLE(pci, vt596_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
455static struct pci_driver vt596_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 .name = "vt596_smbus",
457 .id_table = vt596_ids,
458 .probe = vt596_probe,
459};
460
461static int __init i2c_vt596_init(void)
462{
463 return pci_register_driver(&vt596_driver);
464}
465
466
467static void __exit i2c_vt596_exit(void)
468{
469 pci_unregister_driver(&vt596_driver);
470 if (vt596_pdev != NULL) {
471 i2c_del_adapter(&vt596_adapter);
472 release_region(vt596_smba, 8);
473 pci_dev_put(vt596_pdev);
474 vt596_pdev = NULL;
475 }
476}
477
Jean Delvare87501972005-10-31 18:51:21 +0100478MODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>, "
479 "Mark D. Studebaker <mdsxyz123@yahoo.com> and "
480 "Jean Delvare <khali@linux-fr.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481MODULE_DESCRIPTION("vt82c596 SMBus driver");
482MODULE_LICENSE("GPL");
483
484module_init(i2c_vt596_init);
485module_exit(i2c_vt596_exit);