diff --git a/kernel/busses/i2c-viapro.c b/kernel/busses/i2c-viapro.c index 5ddeb00d..a53a88b3 100644 --- a/kernel/busses/i2c-viapro.c +++ b/kernel/busses/i2c-viapro.c @@ -41,62 +41,43 @@ #include #include #include -#include "version.h" +#include "sensors_compat.h" -#define SMBBA1 0x90 -#define SMBBA2 0x80 -#define SMBBA3 0xD0 - -struct sd { - const unsigned short dev; - const unsigned char base; - const unsigned char hstcfg; - const char *name; -}; - -static struct sd supported[] = { - {PCI_DEVICE_ID_VIA_82C596_3, SMBBA1, 0xD2, "VT82C596A/B"}, - {PCI_DEVICE_ID_VIA_82C596B_3, SMBBA1, 0xD2, "VT82C596B"}, - {PCI_DEVICE_ID_VIA_82C686_4, SMBBA1, 0xD2, "VT82C686A/B"}, - {PCI_DEVICE_ID_VIA_8233_0, SMBBA3, 0xD2, "VT8233"}, - {0x3147, SMBBA3, 0xD2, "VT8233A"}, - {0x3177, SMBBA3, 0xD2, "VT8233A/8235"}, - {0x8235, SMBBA1, 0xD2, "VT8231"}, - {0, 0, 0, NULL} -}; - -static struct sd *num = supported; +#define SMBBA1 0x90 +#define SMBBA2 0x80 +#define SMBBA3 0xD0 /* SMBus address offsets */ -#define SMBHSTSTS (0 + vt596_smba) -#define SMBHSLVSTS (1 + vt596_smba) -#define SMBHSTCNT (2 + vt596_smba) -#define SMBHSTCMD (3 + vt596_smba) -#define SMBHSTADD (4 + vt596_smba) -#define SMBHSTDAT0 (5 + vt596_smba) -#define SMBHSTDAT1 (6 + vt596_smba) -#define SMBBLKDAT (7 + vt596_smba) -#define SMBSLVCNT (8 + vt596_smba) -#define SMBSHDWCMD (9 + vt596_smba) -#define SMBSLVEVT (0xA + vt596_smba) -#define SMBSLVDAT (0xC + vt596_smba) +static unsigned short vt596_smba; +#define SMBHSTSTS (vt596_smba + 0) +#define SMBHSLVSTS (vt596_smba + 1) +#define SMBHSTCNT (vt596_smba + 2) +#define SMBHSTCMD (vt596_smba + 3) +#define SMBHSTADD (vt596_smba + 4) +#define SMBHSTDAT0 (vt596_smba + 5) +#define SMBHSTDAT1 (vt596_smba + 6) +#define SMBBLKDAT (vt596_smba + 7) +#define SMBSLVCNT (vt596_smba + 8) +#define SMBSHDWCMD (vt596_smba + 9) +#define SMBSLVEVT (vt596_smba + 0xA) +#define SMBSLVDAT (vt596_smba + 0xC) /* PCI Address Constants */ /* SMBus data in configuration space can be found in two places, We try to select the better one*/ -static unsigned short smb_cf_hstcfg; +static unsigned short smb_cf_hstcfg = 0xD2; #define SMBHSTCFG (smb_cf_hstcfg) -#define SMBSLVC (SMBHSTCFG+1) -#define SMBSHDW1 (SMBHSTCFG+2) -#define SMBSHDW2 (SMBHSTCFG+3) -#define SMBREV (SMBHSTCFG+4) +#define SMBSLVC (smb_cf_hstcfg + 1) +#define SMBSHDW1 (smb_cf_hstcfg + 2) +#define SMBSHDW2 (smb_cf_hstcfg + 3) +#define SMBREV (smb_cf_hstcfg + 4) /* Other settings */ -#define MAX_TIMEOUT 500 -#define ENABLE_INT9 0 +#define MAX_TIMEOUT 500 +#define ENABLE_INT9 0 /* VT82C596 constants */ #define VT596_QUICK 0x00 @@ -105,177 +86,55 @@ static unsigned short smb_cf_hstcfg; #define VT596_WORD_DATA 0x0C #define VT596_BLOCK_DATA 0x14 -/* insmod parameters */ /* If force is set to anything different from 0, we forcibly enable the VT596. DANGEROUS! */ -static int force = 0; +static int force; MODULE_PARM(force, "i"); 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 = 0; +static int force_addr; MODULE_PARM(force_addr, "i"); MODULE_PARM_DESC(force_addr, "Forcibly enable the SMBus at the given address. " "EXTREMELY DANGEROUS!"); - - - -static void vt596_do_pause(unsigned int amount); -static int vt596_transaction(void); - - - -static unsigned short vt596_smba = 0; - - -/* Detect whether a compatible device can be found, and initialize it. */ -int vt596_setup(void) -{ - unsigned char temp; - - struct pci_dev *VT596_dev = NULL; - - /* First check whether we can access PCI at all */ - if (pci_present() == 0) - return(-ENODEV); - - /* Look for a supported device/function */ - do { - if((VT596_dev = pci_find_device(PCI_VENDOR_ID_VIA, num->dev, - VT596_dev))) - break; - } while ((++num)->dev); - - if (VT596_dev == NULL) - return(-ENODEV); - printk("i2c-viapro.o: Found Via %s device\n", num->name); - -/* Determine the address of the SMBus areas */ - smb_cf_hstcfg = num->hstcfg; - if (force_addr) { - vt596_smba = force_addr & 0xfff0; - force = 0; - } else { - if ((pci_read_config_word(VT596_dev, num->base, &vt596_smba)) - || !(vt596_smba & 0x1)) { - /* try 2nd address and config reg. for 596 */ - if((num->dev == PCI_DEVICE_ID_VIA_82C596_3) && - (!pci_read_config_word(VT596_dev, SMBBA2, &vt596_smba)) && - (vt596_smba & 0x1)) { - smb_cf_hstcfg = 0x84; - } else { - /* no matches at all */ - printk("i2c-viapro.o: Cannot configure SMBus " - "I/O Base address\n"); - return(-ENODEV); - } - } - vt596_smba &= 0xfff0; - if(vt596_smba == 0) { - printk(KERN_ERR "i2c-viapro.o: SMBus base address" - "uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - } - - if (check_region(vt596_smba, 8)) { - printk("i2c-viapro.o: SMBus region 0x%x already in use!\n", - vt596_smba); - return(-ENODEV); - } - - pci_read_config_byte(VT596_dev, SMBHSTCFG, &temp); -/* If force_addr is set, we program the new address here. Just to make - sure, we disable the VT596 first. */ - if (force_addr) { - pci_write_config_byte(VT596_dev, SMBHSTCFG, temp & 0xfe); - pci_write_config_word(VT596_dev, num->base, vt596_smba); - pci_write_config_byte(VT596_dev, SMBHSTCFG, temp | 0x01); - printk - ("i2c-viapro.o: WARNING: SMBus interface set to new " - "address 0x%04x!\n", vt596_smba); - } else if ((temp & 1) == 0) { - if (force) { -/* NOTE: This assumes I/O space and other allocations WERE - done by the Bios! Don't complain if your hardware does weird - things after enabling this. :') Check for Bios updates before - resorting to this. */ - pci_write_config_byte(VT596_dev, SMBHSTCFG, - temp | 1); - printk - ("i2c-viapro.o: enabling SMBus device\n"); - } else { - printk - ("SMBUS: Error: Host SMBus controller not enabled! - " - "upgrade BIOS or use force=1\n"); - return(-ENODEV); - } - } - - /* Everything is happy, let's grab the memory and set things up. */ - request_region(vt596_smba, 8, "viapro-smbus"); - -#ifdef DEBUG - if ((temp & 0x0E) == 8) - printk("i2c-viapro.o: using Interrupt 9 for SMBus.\n"); - else if ((temp & 0x0E) == 0) - printk("i2c-viapro.o: using Interrupt SMI# for SMBus.\n"); - else - printk - ("i2c-viapro.o: Illegal Interrupt configuration (or code out " - "of date)!\n"); - - pci_read_config_byte(VT596_dev, SMBREV, &temp); - printk("i2c-viapro.o: SMBREV = 0x%X\n", temp); - printk("i2c-viapro.o: VT596_smba = 0x%X\n", vt596_smba); -#endif /* DEBUG */ - - return(0); -} - +static struct i2c_adapter vt596_adapter; /* Internally used pause function */ -void vt596_do_pause(unsigned int amount) +static void vt596_do_pause(unsigned int amount) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(amount); } /* Another internally used function */ -int vt596_transaction(void) +static int vt596_transaction(void) { int temp; int result = 0; int timeout = 0; -#ifdef DEBUG - printk - ("i2c-viapro.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " - "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&vt596_adapter, "Transaction (pre): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); /* Make sure the SMBus host is ready to start transmitting */ if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk("i2c-viapro.o: SMBus busy (0x%02x). Resetting... \n", - temp); -#endif + dev_dbg(&vt596_adapter, "SMBus busy (0x%02x). " + "Resetting...\n", temp); + outb_p(temp, SMBHSTSTS); if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk("i2c-viapro.o: Failed! (0x%02x)\n", temp); -#endif + dev_dbg(&vt596_adapter, "Failed! (0x%02x)\n", temp); + return -1; } else { -#ifdef DEBUG - printk("i2c-viapro.o: Successfull!\n"); -#endif + dev_dbg(&vt596_adapter, "Successfull!\n"); } } @@ -291,64 +150,53 @@ int vt596_transaction(void) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { -#ifdef DEBUG - printk("i2c-viapro.o: SMBus Timeout!\n"); result = -1; -#endif + dev_dbg(&vt596_adapter, "SMBus Timeout!\n"); } if (temp & 0x10) { result = -1; -#ifdef DEBUG - printk("i2c-viapro.o: Error: Failed bus transaction\n"); -#endif + dev_dbg(&vt596_adapter, "Error: Failed bus transaction\n"); } if (temp & 0x08) { result = -1; - printk - ("i2c-viapro.o: Bus collision! SMBus may be locked until next hard\n" - "reset. (sorry!)\n"); + dev_info(&vt596_adapter, "Bus collision! SMBus may be " + "locked until next hard\nreset. (sorry!)\n"); /* Clock stops and slave is stuck in mid-transmission */ } if (temp & 0x04) { result = -1; -#ifdef DEBUG - printk("i2c-viapro.o: Error: no response!\n"); -#endif + dev_dbg(&vt596_adapter, "Error: no response!\n"); } if (inb_p(SMBHSTSTS) != 0x00) outb_p(inb(SMBHSTSTS), SMBHSTSTS); if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk - ("i2c-viapro.o: Failed reset at end of transaction (%02x)\n", - temp); -#endif + dev_dbg(&vt596_adapter, "Failed reset at end of " + "transaction (%02x)\n", temp); } -#ifdef DEBUG - printk - ("i2c-viapro.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " - "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&vt596_adapter, "Transaction (post): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); + return result; } /* Return -1 on error. */ -s32 vt596_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, - u8 command, int size, union i2c_smbus_data * data) +static s32 vt596_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data) { int i, len; switch (size) { case I2C_SMBUS_PROC_CALL: - printk - ("i2c-viapro.o: I2C_SMBUS_PROC_CALL not supported!\n"); + dev_info(&vt596_adapter, + "I2C_SMBUS_PROC_CALL not supported!\n"); return -1; case I2C_SMBUS_QUICK: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), @@ -401,18 +249,18 @@ s32 vt596_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); - if (vt596_transaction()) /* Error in transaction */ + if (vt596_transaction()) /* Error in transaction */ return -1; if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) return 0; - switch (size) { - case VT596_BYTE: /* Where is the result put? I assume here it is in - SMBHSTDAT0 but it might just as well be in the - SMBHSTCMD. No clue in the docs */ - + case VT596_BYTE: + /* Where is the result put? I assume here it is in + * SMBHSTDAT0 but it might just as well be in the + * SMBHSTCMD. No clue in the docs + */ data->byte = inb_p(SMBHSTDAT0); break; case VT596_BYTE_DATA: @@ -431,15 +279,13 @@ s32 vt596_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, return 0; } - -u32 vt596_func(struct i2c_adapter *adapter) +static u32 vt596_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA; } - static struct i2c_algorithm smbus_algorithm = { .name = "Non-I2C SMBus adapter", .id = I2C_ALGO_SMBUS, @@ -449,36 +295,165 @@ static struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter vt596_adapter = { .owner = THIS_MODULE, - .name = "unset", .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2, .algo = &smbus_algorithm, + .name = "unset", }; - -static struct pci_device_id vt596_ids[] __devinitdata = { - { 0, } -}; - -static int __devinit vt596_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit vt596_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { + unsigned char temp; + int error = -ENODEV; + + /* Determine the address of the SMBus areas */ + if (force_addr) { + vt596_smba = force_addr & 0xfff0; + force = 0; + goto found; + } - if (vt596_setup()) { - printk - ("i2c-viapro.o: Can't detect vt82c596 or compatible device, module not inserted.\n"); + if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || + !(vt596_smba & 0x1)) { + /* try 2nd address and config reg. for 596 */ + if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && + !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && + (vt596_smba & 0x1)) { + smb_cf_hstcfg = 0x84; + } else { + /* no matches at all */ + dev_err(pdev, "Cannot configure " + "SMBus I/O Base address\n"); + return -ENODEV; + } + } + vt596_smba &= 0xfff0; + if (vt596_smba == 0) { + dev_err(pdev, "SMBus base address " + "uninitialized - upgrade BIOS or use " + "force_addr=0xaddr\n"); return -ENODEV; } - sprintf(vt596_adapter.name, "SMBus Via Pro adapter at %04x", - vt596_smba); - i2c_add_adapter(&vt596_adapter); + found: + if (!request_region(vt596_smba, 8, "viapro-smbus")) { + dev_err(pdev, "SMBus region 0x%x already in use!\n", + vt596_smba); + return -ENODEV; + } + + pci_read_config_byte(pdev, SMBHSTCFG, &temp); + /* If force_addr is set, we program the new address here. Just to make + sure, we disable the VT596 first. */ + if (force_addr) { + pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe); + pci_write_config_word(pdev, id->driver_data, vt596_smba); + pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); + dev_warn(pdev, "WARNING: SMBus interface set to new " + "address 0x%04x!\n", vt596_smba); + } else if ((temp & 1) == 0) { + if (force) { + /* NOTE: This assumes I/O space and other allocations + * WERE done by the Bios! Don't complain if your + * hardware does weird things after enabling this. + * :') Check for Bios updates before resorting to + * this. + */ + pci_write_config_byte(pdev, SMBHSTCFG, temp | 1); + dev_info(pdev, "Enabling SMBus device\n"); + } else { + dev_err(pdev, "SMBUS: Error: Host SMBus " + "controller not enabled! - upgrade BIOS or " + "use force=1\n"); + goto release_region; + } + } + + if ((temp & 0x0E) == 8) + dev_dbg(pdev, "using Interrupt 9 for SMBus.\n"); + else if ((temp & 0x0E) == 0) + dev_dbg(pdev, "using Interrupt SMI# for SMBus.\n"); + else + dev_dbg(pdev, "Illegal Interrupt configuration " + "(or code out of date)!\n"); + + pci_read_config_byte(pdev, SMBREV, &temp); + dev_dbg(pdev, "SMBREV = 0x%X\n", temp); + dev_dbg(pdev, "VT596_smba = 0x%X\n", vt596_smba); + + snprintf(vt596_adapter.name, 32, + "SMBus Via Pro adapter at %04x", vt596_smba); + + return i2c_add_adapter(&vt596_adapter); + + release_region: + release_region(vt596_smba, 8); + return error; } -static void __devexit vt596_remove(struct pci_dev *dev) +static void __devexit vt596_remove(struct pci_dev *pdev) { i2c_del_adapter(&vt596_adapter); + release_region(vt596_smba, 8); } +#ifndef PCI_DEVICE_ID_VIA_8235 +#define PCI_DEVICE_ID_VIA_8235 0x3177 +#endif +static struct pci_device_id vt596_ids[] __devinitdata = { + { + .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_8231_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SMBBA1, + }, + { 0, } +}; + static struct pci_driver vt596_driver = { .name = "vt596 smbus", .id_table = vt596_ids, @@ -488,7 +463,6 @@ static struct pci_driver vt596_driver = { static int __init i2c_vt596_init(void) { - printk("i2c-viapro.o version %s (%s)\n", LM_VERSION, LM_DATE); return pci_module_init(&vt596_driver); } @@ -496,15 +470,12 @@ static int __init i2c_vt596_init(void) static void __exit i2c_vt596_exit(void) { pci_unregister_driver(&vt596_driver); - release_region(vt596_smba, 8); } - - -MODULE_AUTHOR - ("Frodo Looijaard and Philip Edelbrock "); +MODULE_AUTHOR( + "Frodo Looijaard and " + "Philip Edelbrock "); MODULE_DESCRIPTION("vt82c596 SMBus driver"); - MODULE_LICENSE("GPL"); module_init(i2c_vt596_init); diff --git a/kernel/include/sensors_compat.h b/kernel/include/sensors_compat.h new file mode 100644 index 00000000..d9bfb492 --- /dev/null +++ b/kernel/include/sensors_compat.h @@ -0,0 +1,31 @@ +/* + * Stolen from kernel 2.5.69 + * device.h - generic, centralized driver model + * To make it easier to backport from 2.5 + * + * Copyright (c) 2001-2003 Patrick Mochel + * + */ + +#ifndef _SENSORS_COMPAT_H_ +#define _SENSORS_COMPAT_H_ + +/* debugging and troubleshooting/diagnostic helpers. */ +#define dev_printk(level, dev, format, arg...) \ + printk(level "%s: " format , (dev)->name , ## arg) + +#ifdef DEBUG +#define dev_dbg(dev, format, arg...) \ + dev_printk(KERN_DEBUG , dev , format , ## arg) +#else +#define dev_dbg(dev, format, arg...) do {} while (0) +#endif + +#define dev_err(dev, format, arg...) \ + dev_printk(KERN_ERR , dev , format , ## arg) +#define dev_info(dev, format, arg...) \ + dev_printk(KERN_INFO , dev , format , ## arg) +#define dev_warn(dev, format, arg...) \ + dev_printk(KERN_WARNING , dev , format , ## arg) + +#endif /* _SENSORS_COMPAT_H_ */