/*
- i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
VT8237S 0x3372 yes
VT8251 0x3287 yes
CX700 0x8324 yes
+ VX800/VX820 0x8353 yes
+ VX855/VX875 0x8409 yes
Note: we assume there can only be one device, with one SMBus interface.
*/
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static struct pci_dev *vt596_pdev;
#define VT596_BYTE 0x04
#define VT596_BYTE_DATA 0x08
#define VT596_WORD_DATA 0x0C
+#define VT596_PROC_CALL 0x10
#define VT596_BLOCK_DATA 0x14
#define VT596_I2C_BLOCK_DATA 0x34
}
size = VT596_WORD_DATA;
break;
+ case I2C_SMBUS_PROC_CALL:
+ outb_p(command, SMBHSTCMD);
+ outb_p(data->word & 0xff, SMBHSTDAT0);
+ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+ size = VT596_PROC_CALL;
+ break;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (!(vt596_features & FEATURE_I2CBLOCK))
goto exit_unsupported;
if (status)
return status;
+ if (size == VT596_PROC_CALL)
+ read_write = I2C_SMBUS_READ;
+
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
return 0;
data->byte = inb_p(SMBHSTDAT0);
break;
case VT596_WORD_DATA:
+ case VT596_PROC_CALL:
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
break;
case VT596_I2C_BLOCK_DATA:
{
u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA;
+ I2C_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA;
if (vt596_features & FEATURE_I2CBLOCK)
func |= I2C_FUNC_SMBUS_I2C_BLOCK;
static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_VIA2,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
unsigned char temp;
int error = -ENODEV;
- /* driver_data might come from user-space, so check it */
- if (id->driver_data & 1 || id->driver_data > 0xff)
- return -EINVAL;
-
/* Determine the address of the SMBus areas */
if (force_addr) {
vt596_smba = force_addr & 0xfff0;
}
found:
+ error = acpi_check_region(vt596_smba, 8, vt596_driver.name);
+ if (error)
+ return -ENODEV;
+
if (!request_region(vt596_smba, 8, vt596_driver.name)) {
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
vt596_smba);
switch (pdev->device) {
case PCI_DEVICE_ID_VIA_CX700:
+ case PCI_DEVICE_ID_VIA_VX800:
+ case PCI_DEVICE_ID_VIA_VX855:
case PCI_DEVICE_ID_VIA_8251:
case PCI_DEVICE_ID_VIA_8237:
case PCI_DEVICE_ID_VIA_8237A:
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700),
.driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855),
+ .driver_data = SMBBA3 },
{ 0, }
};
.name = "vt596_smbus",
.id_table = vt596_ids,
.probe = vt596_probe,
- .dynids.use_driver_data = 1,
};
static int __init i2c_vt596_init(void)