#include <linux/config.h>
#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/init.h>
#include <asm/io.h>
+static struct pci_dev *vt596_pdev;
+
#define SMBBA1 0x90
#define SMBBA2 0x80
#define SMBBA3 0xD0
/* If force is set to anything different from 0, we forcibly enable the
VT596. DANGEROUS! */
static int force;
-MODULE_PARM(force, "i");
+module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
/* If force_addr is set to anything different from 0, we forcibly enable
the VT596 at the given address. VERY DANGEROUS! */
-static int force_addr;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
MODULE_PARM_DESC(force_addr,
"Forcibly enable the SMBus at the given address. "
"EXTREMELY DANGEROUS!");
/* We will always wait for a fraction of a second!
I don't know if VIA needs this, Intel did */
do {
- i2c_delay(1);
+ msleep(1);
temp = inb_p(SMBHSTSTS);
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
len = data->block[0];
if (len < 0)
len = 0;
- if (len > 32)
- len = 32;
+ if (len > I2C_SMBUS_BLOCK_MAX)
+ len = I2C_SMBUS_BLOCK_MAX;
outb_p(len, SMBHSTDAT0);
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= len; i++)
break;
case VT596_BLOCK_DATA:
data->block[0] = inb_p(SMBHSTDAT0);
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb_p(SMBBLKDAT);
static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE,
- .class = I2C_ADAP_CLASS_SMBUS,
+ .class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
.name = "unset",
};
snprintf(vt596_adapter.name, I2C_NAME_SIZE,
"SMBus Via Pro adapter at %04x", vt596_smba);
- return i2c_add_adapter(&vt596_adapter);
+ vt596_pdev = pci_dev_get(pdev);
+ if (i2c_add_adapter(&vt596_adapter)) {
+ pci_dev_put(vt596_pdev);
+ vt596_pdev = NULL;
+ }
+
+ /* Always return failure here. This is to allow other drivers to bind
+ * to this pci device. We don't really want to have control over the
+ * pci device, we only wanted to read as few register values from it.
+ */
+ return -ENODEV;
release_region:
release_region(vt596_smba, 8);
return error;
}
-static void __devexit vt596_remove(struct pci_dev *pdev)
-{
- i2c_del_adapter(&vt596_adapter);
- release_region(vt596_smba, 8);
-}
-
static struct pci_device_id vt596_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C596_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C596B_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C686_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8233_0,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8233A,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8235,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8237,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8231_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
+ .driver_data = SMBBA1 },
{ 0, }
};
+MODULE_DEVICE_TABLE (pci, vt596_ids);
+
static struct pci_driver vt596_driver = {
- .name = "vt596 smbus",
+ .name = "vt596_smbus",
.id_table = vt596_ids,
.probe = vt596_probe,
- .remove = __devexit_p(vt596_remove),
};
static int __init i2c_vt596_init(void)
{
- return pci_module_init(&vt596_driver);
+ return pci_register_driver(&vt596_driver);
}
static void __exit i2c_vt596_exit(void)
{
pci_unregister_driver(&vt596_driver);
+ if (vt596_pdev != NULL) {
+ i2c_del_adapter(&vt596_adapter);
+ release_region(vt596_smba, 8);
+ pci_dev_put(vt596_pdev);
+ vt596_pdev = NULL;
+ }
}
MODULE_AUTHOR(