11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 25f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, 396de0e252cedffad61b3cb5e05662c591898e69aJan Engelhardt Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>, 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Mark D. Studebaker <mdsxyz123@yahoo.com> 50d227a7e724460bddcd603a1feb672267bcb0d6cJean Delvare Copyright (C) 2005 - 2008 Jean Delvare <khali@linux-fr.org> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 23aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare Supports the following VIA south bridges: 24aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare 25aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare Chip name PCI ID REV I2C block 26aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT82C596A 0x3050 no 27aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT82C596B 0x3051 no 28aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT82C686A 0x3057 0x30 no 29aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT82C686B 0x3057 0x40 yes 30aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT8231 0x8235 no? 31aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT8233 0x3074 yes 32aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT8233A 0x3147 yes? 33aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT8235 0x3177 yes 34aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare VT8237R 0x3227 yes 35c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek VT8237A 0x3337 yes 360d227a7e724460bddcd603a1feb672267bcb0d6cJean Delvare VT8237S 0x3372 yes 37c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek VT8251 0x3287 yes 38ab6a6ed271c757b429ddc68f5b93a41f9592ab8bJean Delvare CX700 0x8324 yes 39b806a71a0e9dacb6763371561caa693c78b93d40Rudolf Marek VX800/VX820 0x8353 yes 40a231591f0427cfb91ae247be974a7fa0e6b37389Harald Welte VX855/VX875 0x8409 yes 41aaf7f1477668f34dda65aba17e87c0bc2ebe84d1Jean Delvare 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Note: we assume there can only be one device, with one SMBus interface. 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stddef.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 5354fb4a05af0a4b814e6716cfdf3fa97fc6be7a32Jean Delvare#include <linux/acpi.h> 542178218027e4da0608219fae1d02e5c88f4e560dH Hartley Sweeten#include <linux/io.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_dev *vt596_pdev; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 585f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define SMBBA1 0x90 595f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define SMBBA2 0x80 605f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define SMBBA3 0xD0 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SMBus address offsets */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short vt596_smba; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMBHSTSTS (vt596_smba + 0) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMBHSTCNT (vt596_smba + 2) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMBHSTCMD (vt596_smba + 3) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMBHSTADD (vt596_smba + 4) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMBHSTDAT0 (vt596_smba + 5) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMBHSTDAT1 (vt596_smba + 6) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMBBLKDAT (vt596_smba + 7) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* PCI Address Constants */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SMBus data in configuration space can be found in two places, 755f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare We try to select the better one */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 77c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvarestatic unsigned short SMBHSTCFG = 0xD2; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Other settings */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_TIMEOUT 500 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* VT82C596 constants */ 835f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define VT596_QUICK 0x00 845f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define VT596_BYTE 0x04 855f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define VT596_BYTE_DATA 0x08 865f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define VT596_WORD_DATA 0x0C 87a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha#define VT596_PROC_CALL 0x10 885f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare#define VT596_BLOCK_DATA 0x14 89f118301416953d677de738100c33eb8cfb7adecbJean Delvare#define VT596_I2C_BLOCK_DATA 0x34 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If force is set to anything different from 0, we forcibly enable the 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VT596. DANGEROUS! */ 9490ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool force; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force, bool, 0); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!"); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If force_addr is set to anything different from 0, we forcibly enable 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the VT596 at the given address. VERY DANGEROUS! */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 force_addr; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(force_addr, ushort, 0); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(force_addr, 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Forcibly enable the SMBus at the given address. " 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EXTREMELY DANGEROUS!"); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 107c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvarestatic struct pci_driver vt596_driver; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_adapter vt596_adapter; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 110f118301416953d677de738100c33eb8cfb7adecbJean Delvare#define FEATURE_I2CBLOCK (1<<0) 111f118301416953d677de738100c33eb8cfb7adecbJean Delvarestatic unsigned int vt596_features; 112f118301416953d677de738100c33eb8cfb7adecbJean Delvare 113ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare#ifdef DEBUG 114ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvarestatic void vt596_dump_regs(const char *msg, u8 size) 115ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare{ 116ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x " 117ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), 118ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), 119ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare inb_p(SMBHSTDAT1)); 120ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare 121ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare if (size == VT596_BLOCK_DATA 122ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare || size == VT596_I2C_BLOCK_DATA) { 123ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare int i; 124ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare 125ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare dev_dbg(&vt596_adapter.dev, "BLK="); 126ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++) 127ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare printk("%02x,", inb_p(SMBBLKDAT)); 128ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare printk("\n"); 129ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare dev_dbg(&vt596_adapter.dev, " "); 130ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++) 131ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare printk("%02x,", inb_p(SMBBLKDAT)); 132ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare printk("%02x\n", inb_p(SMBBLKDAT)); 133ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare } 134ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare} 135ca68f1193e8fc86470d4222d563d13b5584dc4f8Greg Kroah-Hartman#else 136ca68f1193e8fc86470d4222d563d13b5584dc4f8Greg Kroah-Hartmanstatic inline void vt596_dump_regs(const char *msg, u8 size) { } 137ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare#endif 138ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare 139c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare/* Return -1 on error, 0 on success */ 14050c1cc339ca72f7cb95d440d384346f4238dc494Jean Delvarestatic int vt596_transaction(u8 size) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int temp; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result = 0; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int timeout = 0; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 146ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare vt596_dump_regs("Transaction (pre)", size); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make sure the SMBus host is ready to start transmitting */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). " 1518750197f0e8f5467297d72e11444cf32f29d790fJean Delvare "Resetting...\n", temp); 1525f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(temp, SMBHSTSTS); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { 1558750197f0e8f5467297d72e11444cf32f29d790fJean Delvare dev_err(&vt596_adapter.dev, "SMBus reset failed! " 1568750197f0e8f5467297d72e11444cf32f29d790fJean Delvare "(0x%02x)\n", temp); 15797140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell return -EBUSY; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare /* Start the transaction by setting bit 6 */ 1628750197f0e8f5467297d72e11444cf32f29d790fJean Delvare outb_p(0x40 | size, SMBHSTCNT); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 164c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare /* We will always wait for a fraction of a second */ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(1); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = inb_p(SMBHSTSTS); 168b6a3195070fe1c12d0bb1099ffe997d8abf9f602Roel Kluin } while ((temp & 0x01) && (++timeout < MAX_TIMEOUT)); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If the SMBus is still busy, we give up */ 171b6a3195070fe1c12d0bb1099ffe997d8abf9f602Roel Kluin if (timeout == MAX_TIMEOUT) { 17297140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell result = -ETIMEDOUT; 173c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare dev_err(&vt596_adapter.dev, "SMBus timeout!\n"); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp & 0x10) { 17797140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell result = -EIO; 178c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n", 1798750197f0e8f5467297d72e11444cf32f29d790fJean Delvare size); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp & 0x08) { 18397140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell result = -EIO; 184c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare dev_err(&vt596_adapter.dev, "SMBus collision!\n"); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (temp & 0x04) { 18897140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell result = -ENXIO; 189bf5d95c82692ead9ba7876af73dac2edcc8a6191Jean Delvare dev_dbg(&vt596_adapter.dev, "No response\n"); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare /* Resetting status register */ 193c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare if (temp & 0x1F) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(temp, SMBHSTSTS); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 196ed5453e54f0c4a29605fd8399f58649d8739f5f0Jean Delvare vt596_dump_regs("Transaction (post)", size); 1975f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20197140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell/* Return negative errno on error, 0 on success */ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic s32 vt596_access(struct i2c_adapter *adap, u16 addr, 2035f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare unsigned short flags, char read_write, u8 command, 2045f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare int size, union i2c_smbus_data *data) 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 206c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare int i; 20797140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell int status; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (size) { 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I2C_SMBUS_QUICK: 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = VT596_QUICK; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I2C_SMBUS_BYTE: 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (read_write == I2C_SMBUS_WRITE) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(command, SMBHSTCMD); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = VT596_BYTE; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I2C_SMBUS_BYTE_DATA: 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(command, SMBHSTCMD); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (read_write == I2C_SMBUS_WRITE) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(data->byte, SMBHSTDAT0); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = VT596_BYTE_DATA; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I2C_SMBUS_WORD_DATA: 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(command, SMBHSTCMD); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (read_write == I2C_SMBUS_WRITE) { 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(data->word & 0xff, SMBHSTDAT0); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = VT596_WORD_DATA; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 232a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha case I2C_SMBUS_PROC_CALL: 233a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha outb_p(command, SMBHSTCMD); 234a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha outb_p(data->word & 0xff, SMBHSTDAT0); 235a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); 236a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha size = VT596_PROC_CALL; 237a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha break; 238f118301416953d677de738100c33eb8cfb7adecbJean Delvare case I2C_SMBUS_I2C_BLOCK_DATA: 239f118301416953d677de738100c33eb8cfb7adecbJean Delvare if (!(vt596_features & FEATURE_I2CBLOCK)) 240c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare goto exit_unsupported; 241f118301416953d677de738100c33eb8cfb7adecbJean Delvare if (read_write == I2C_SMBUS_READ) 2424b2643d7d9bdcd776749e17f73c168ddf02e93cbJean Delvare outb_p(data->block[0], SMBHSTDAT0); 243f118301416953d677de738100c33eb8cfb7adecbJean Delvare /* Fall through */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I2C_SMBUS_BLOCK_DATA: 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(command, SMBHSTCMD); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (read_write == I2C_SMBUS_WRITE) { 247c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare u8 len = data->block[0]; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > I2C_SMBUS_BLOCK_MAX) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = I2C_SMBUS_BLOCK_MAX; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(len, SMBHSTDAT0); 251c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= len; i++) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb_p(data->block[i], SMBBLKDAT); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 255f118301416953d677de738100c33eb8cfb7adecbJean Delvare size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ? 256f118301416953d677de738100c33eb8cfb7adecbJean Delvare VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 258c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare default: 259c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare goto exit_unsupported; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 262c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26497140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell status = vt596_transaction(size); 26597140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell if (status) 26697140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell return status; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha if (size == VT596_PROC_CALL) 269a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha read_write = I2C_SMBUS_READ; 270a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (size) { 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT596_BYTE: 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT596_BYTE_DATA: 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->byte = inb_p(SMBHSTDAT0); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT596_WORD_DATA: 280a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha case VT596_PROC_CALL: 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 283f118301416953d677de738100c33eb8cfb7adecbJean Delvare case VT596_I2C_BLOCK_DATA: 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT596_BLOCK_DATA: 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->block[0] = inb_p(SMBHSTDAT0); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->block[0] > I2C_SMBUS_BLOCK_MAX) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->block[0] = I2C_SMBUS_BLOCK_MAX; 288c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 1; i <= data->block[0]; i++) 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->block[i] = inb_p(SMBBLKDAT); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 294c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare 295c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvareexit_unsupported: 296ac7fc4fb2b6a126af8d07f46500440c9641976cfJean Delvare dev_warn(&vt596_adapter.dev, "Unsupported transaction %d\n", 297c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare size); 29897140342e69d479a3ad82bfd4c154c0b08fe3eeaDavid Brownell return -EOPNOTSUPP; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 vt596_func(struct i2c_adapter *adapter) 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 303f118301416953d677de738100c33eb8cfb7adecbJean Delvare u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 305a05f2c5a2735ee1d68770137fbbfc334d3b9cda9Prakash Mortha I2C_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA; 306f118301416953d677de738100c33eb8cfb7adecbJean Delvare 307f118301416953d677de738100c33eb8cfb7adecbJean Delvare if (vt596_features & FEATURE_I2CBLOCK) 308f118301416953d677de738100c33eb8cfb7adecbJean Delvare func |= I2C_FUNC_SMBUS_I2C_BLOCK; 309f118301416953d677de738100c33eb8cfb7adecbJean Delvare return func; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3128f9082c5ce0e2c2f7ad0211b0c089f680d2efc11Jean Delvarestatic const struct i2c_algorithm smbus_algorithm = { 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .smbus_xfer = vt596_access, 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .functionality = vt596_func, 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_adapter vt596_adapter = { 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 3193401b2fff38fbb8b73ea6bcc69a8370ae5d2a7a0Jean Delvare .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .algo = &smbus_algorithm, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit vt596_probe(struct pci_dev *pdev, 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct pci_device_id *id) 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char temp; 3277c1f59c9d5caf3a84f35549b5d58f3c055a68da5Jean Delvare int error; 3285f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Determine the address of the SMBus areas */ 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (force_addr) { 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt596_smba = force_addr & 0xfff0; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force = 0; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto found; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || 337c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare !(vt596_smba & 0x0001)) { 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try 2nd address and config reg. for 596 */ 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && 341c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare (vt596_smba & 0x0001)) { 342c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare SMBHSTCFG = 0x84; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no matches at all */ 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&pdev->dev, "Cannot configure " 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SMBus I/O Base address\n"); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt596_smba &= 0xfff0; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vt596_smba == 0) { 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&pdev->dev, "SMBus base address " 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "uninitialized - upgrade BIOS or use " 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "force_addr=0xaddr\n"); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3595f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvarefound: 36054fb4a05af0a4b814e6716cfdf3fa97fc6be7a32Jean Delvare error = acpi_check_region(vt596_smba, 8, vt596_driver.name); 36154fb4a05af0a4b814e6716cfdf3fa97fc6be7a32Jean Delvare if (error) 36218669eabde2ff5fc446e72e043f0539059763438Jean Delvare return -ENODEV; 36354fb4a05af0a4b814e6716cfdf3fa97fc6be7a32Jean Delvare 364c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare if (!request_region(vt596_smba, 8, vt596_driver.name)) { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", 3665f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare vt596_smba); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(pdev, SMBHSTCFG, &temp); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If force_addr is set, we program the new address here. Just to make 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sure, we disable the VT596 first. */ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (force_addr) { 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(pdev, id->driver_data, vt596_smba); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_warn(&pdev->dev, "WARNING: SMBus interface set to new " 3785f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare "address 0x%04x!\n", vt596_smba); 379c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare } else if (!(temp & 0x01)) { 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (force) { 3815f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare /* NOTE: This assumes I/O space and other allocations 3825f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare * WERE done by the Bios! Don't complain if your 3835f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare * hardware does weird things after enabling this. 3845f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare * :') Check for Bios updates before resorting to 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this. 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 387c2f559d5df5751780c0bd3ea0bd0aa17d47c0b39Jean Delvare pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_info(&pdev->dev, "Enabling SMBus device\n"); 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&pdev->dev, "SMBUS: Error: Host SMBus " 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "controller not enabled! - upgrade BIOS or " 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "use force=1\n"); 3937c1f59c9d5caf3a84f35549b5d58f3c055a68da5Jean Delvare error = -ENODEV; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto release_region; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 400f118301416953d677de738100c33eb8cfb7adecbJean Delvare switch (pdev->device) { 401ab6a6ed271c757b429ddc68f5b93a41f9592ab8bJean Delvare case PCI_DEVICE_ID_VIA_CX700: 402b806a71a0e9dacb6763371561caa693c78b93d40Rudolf Marek case PCI_DEVICE_ID_VIA_VX800: 403a231591f0427cfb91ae247be974a7fa0e6b37389Harald Welte case PCI_DEVICE_ID_VIA_VX855: 404c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek case PCI_DEVICE_ID_VIA_8251: 405f118301416953d677de738100c33eb8cfb7adecbJean Delvare case PCI_DEVICE_ID_VIA_8237: 406c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek case PCI_DEVICE_ID_VIA_8237A: 4070d227a7e724460bddcd603a1feb672267bcb0d6cJean Delvare case PCI_DEVICE_ID_VIA_8237S: 408f118301416953d677de738100c33eb8cfb7adecbJean Delvare case PCI_DEVICE_ID_VIA_8235: 409f118301416953d677de738100c33eb8cfb7adecbJean Delvare case PCI_DEVICE_ID_VIA_8233A: 410f118301416953d677de738100c33eb8cfb7adecbJean Delvare case PCI_DEVICE_ID_VIA_8233_0: 411f118301416953d677de738100c33eb8cfb7adecbJean Delvare vt596_features |= FEATURE_I2CBLOCK; 412f118301416953d677de738100c33eb8cfb7adecbJean Delvare break; 413f118301416953d677de738100c33eb8cfb7adecbJean Delvare case PCI_DEVICE_ID_VIA_82C686_4: 414f118301416953d677de738100c33eb8cfb7adecbJean Delvare /* The VT82C686B (rev 0x40) does support I2C block 415f118301416953d677de738100c33eb8cfb7adecbJean Delvare transactions, but the VT82C686A (rev 0x30) doesn't */ 41644c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok if (pdev->revision >= 0x40) 417f118301416953d677de738100c33eb8cfb7adecbJean Delvare vt596_features |= FEATURE_I2CBLOCK; 418f118301416953d677de738100c33eb8cfb7adecbJean Delvare break; 419f118301416953d677de738100c33eb8cfb7adecbJean Delvare } 420f118301416953d677de738100c33eb8cfb7adecbJean Delvare 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt596_adapter.dev.parent = &pdev->dev; 4222096b956d24c4b5950b808fc23b218425d79ebb1David Brownell snprintf(vt596_adapter.name, sizeof(vt596_adapter.name), 4235f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare "SMBus Via Pro adapter at %04x", vt596_smba); 4245f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvare 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt596_pdev = pci_dev_get(pdev); 4267c1f59c9d5caf3a84f35549b5d58f3c055a68da5Jean Delvare error = i2c_add_adapter(&vt596_adapter); 4277c1f59c9d5caf3a84f35549b5d58f3c055a68da5Jean Delvare if (error) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dev_put(vt596_pdev); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt596_pdev = NULL; 4307c1f59c9d5caf3a84f35549b5d58f3c055a68da5Jean Delvare goto release_region; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Always return failure here. This is to allow other drivers to bind 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to this pci device. We don't really want to have control over the 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci device, we only wanted to read as few register values from it. 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4395f49ef8e8cefe0a95948b4270db28507c1c287d4Jean Delvarerelease_region: 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(vt596_smba, 8); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4443527bd5045aacb4e4072f9cacb8eb9a433fbad39Axel Linstatic DEFINE_PCI_DEVICE_TABLE(vt596_ids) = { 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3), 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA1 }, 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3), 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA1 }, 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4), 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA1 }, 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0), 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA3 }, 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A), 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA3 }, 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235), 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA3 }, 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237), 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA3 }, 459c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A), 460c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek .driver_data = SMBBA3 }, 4610d227a7e724460bddcd603a1feb672267bcb0d6cJean Delvare { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237S), 4620d227a7e724460bddcd603a1feb672267bcb0d6cJean Delvare .driver_data = SMBBA3 }, 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4), 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .driver_data = SMBBA1 }, 465c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251), 466c243353a90fae3a9a85d2bd79b1df06bb21c568aRudolf Marek .driver_data = SMBBA3 }, 467ab6a6ed271c757b429ddc68f5b93a41f9592ab8bJean Delvare { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700), 468ab6a6ed271c757b429ddc68f5b93a41f9592ab8bJean Delvare .driver_data = SMBBA3 }, 469b806a71a0e9dacb6763371561caa693c78b93d40Rudolf Marek { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800), 470b806a71a0e9dacb6763371561caa693c78b93d40Rudolf Marek .driver_data = SMBBA3 }, 471a231591f0427cfb91ae247be974a7fa0e6b37389Harald Welte { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855), 472a231591f0427cfb91ae247be974a7fa0e6b37389Harald Welte .driver_data = SMBBA3 }, 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, } 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4765f49ef8e8cefe0a95948b4270db28507c1c287d4Jean DelvareMODULE_DEVICE_TABLE(pci, vt596_ids); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver vt596_driver = { 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "vt596_smbus", 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = vt596_ids, 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = vt596_probe, 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init i2c_vt596_init(void) 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pci_register_driver(&vt596_driver); 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit i2c_vt596_exit(void) 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver(&vt596_driver); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vt596_pdev != NULL) { 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_del_adapter(&vt596_adapter); 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(vt596_smba, 8); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dev_put(vt596_pdev); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt596_pdev = NULL; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5018750197f0e8f5467297d72e11444cf32f29d790fJean DelvareMODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>, " 5028750197f0e8f5467297d72e11444cf32f29d790fJean Delvare "Mark D. Studebaker <mdsxyz123@yahoo.com> and " 5038750197f0e8f5467297d72e11444cf32f29d790fJean Delvare "Jean Delvare <khali@linux-fr.org>"); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("vt82c596 SMBus driver"); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(i2c_vt596_init); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(i2c_vt596_exit); 509