| 44 | | #include "version.h" |
| 45 | | |
| 46 | | #define SMBBA1 0x90 |
| 47 | | #define SMBBA2 0x80 |
| 48 | | #define SMBBA3 0xD0 |
| 49 | | |
| 50 | | struct sd { |
| 51 | | const unsigned short dev; |
| 52 | | const unsigned char base; |
| 53 | | const unsigned char hstcfg; |
| 54 | | const char *name; |
| 55 | | }; |
| 56 | | |
| 57 | | static struct sd supported[] = { |
| 58 | | {PCI_DEVICE_ID_VIA_82C596_3, SMBBA1, 0xD2, "VT82C596A/B"}, |
| 59 | | {PCI_DEVICE_ID_VIA_82C596B_3, SMBBA1, 0xD2, "VT82C596B"}, |
| 60 | | {PCI_DEVICE_ID_VIA_82C686_4, SMBBA1, 0xD2, "VT82C686A/B"}, |
| 61 | | {PCI_DEVICE_ID_VIA_8233_0, SMBBA3, 0xD2, "VT8233"}, |
| 62 | | {0x3147, SMBBA3, 0xD2, "VT8233A"}, |
| 63 | | {0x3177, SMBBA3, 0xD2, "VT8233A/8235"}, |
| 64 | | {0x8235, SMBBA1, 0xD2, "VT8231"}, |
| 65 | | {0, 0, 0, NULL} |
| 66 | | }; |
| 67 | | |
| 68 | | static struct sd *num = supported; |
| | 44 | #include "sensors_compat.h" |
| | 45 | |
| | 46 | #define SMBBA1 0x90 |
| | 47 | #define SMBBA2 0x80 |
| | 48 | #define SMBBA3 0xD0 |
| 71 | | #define SMBHSTSTS (0 + vt596_smba) |
| 72 | | #define SMBHSLVSTS (1 + vt596_smba) |
| 73 | | #define SMBHSTCNT (2 + vt596_smba) |
| 74 | | #define SMBHSTCMD (3 + vt596_smba) |
| 75 | | #define SMBHSTADD (4 + vt596_smba) |
| 76 | | #define SMBHSTDAT0 (5 + vt596_smba) |
| 77 | | #define SMBHSTDAT1 (6 + vt596_smba) |
| 78 | | #define SMBBLKDAT (7 + vt596_smba) |
| 79 | | #define SMBSLVCNT (8 + vt596_smba) |
| 80 | | #define SMBSHDWCMD (9 + vt596_smba) |
| 81 | | #define SMBSLVEVT (0xA + vt596_smba) |
| 82 | | #define SMBSLVDAT (0xC + vt596_smba) |
| | 51 | static unsigned short vt596_smba; |
| | 52 | #define SMBHSTSTS (vt596_smba + 0) |
| | 53 | #define SMBHSLVSTS (vt596_smba + 1) |
| | 54 | #define SMBHSTCNT (vt596_smba + 2) |
| | 55 | #define SMBHSTCMD (vt596_smba + 3) |
| | 56 | #define SMBHSTADD (vt596_smba + 4) |
| | 57 | #define SMBHSTDAT0 (vt596_smba + 5) |
| | 58 | #define SMBHSTDAT1 (vt596_smba + 6) |
| | 59 | #define SMBBLKDAT (vt596_smba + 7) |
| | 60 | #define SMBSLVCNT (vt596_smba + 8) |
| | 61 | #define SMBSHDWCMD (vt596_smba + 9) |
| | 62 | #define SMBSLVEVT (vt596_smba + 0xA) |
| | 63 | #define SMBSLVDAT (vt596_smba + 0xC) |
| 125 | | |
| 126 | | |
| 127 | | |
| 128 | | static void vt596_do_pause(unsigned int amount); |
| 129 | | static int vt596_transaction(void); |
| 130 | | |
| 131 | | |
| 132 | | |
| 133 | | static unsigned short vt596_smba = 0; |
| 134 | | |
| 135 | | |
| 136 | | /* Detect whether a compatible device can be found, and initialize it. */ |
| 137 | | int vt596_setup(void) |
| 138 | | { |
| 139 | | unsigned char temp; |
| 140 | | |
| 141 | | struct pci_dev *VT596_dev = NULL; |
| 142 | | |
| 143 | | /* First check whether we can access PCI at all */ |
| 144 | | if (pci_present() == 0) |
| 145 | | return(-ENODEV); |
| 146 | | |
| 147 | | /* Look for a supported device/function */ |
| 148 | | do { |
| 149 | | if((VT596_dev = pci_find_device(PCI_VENDOR_ID_VIA, num->dev, |
| 150 | | VT596_dev))) |
| 151 | | break; |
| 152 | | } while ((++num)->dev); |
| 153 | | |
| 154 | | if (VT596_dev == NULL) |
| 155 | | return(-ENODEV); |
| 156 | | printk("i2c-viapro.o: Found Via %s device\n", num->name); |
| 157 | | |
| 158 | | /* Determine the address of the SMBus areas */ |
| 159 | | smb_cf_hstcfg = num->hstcfg; |
| 160 | | if (force_addr) { |
| 161 | | vt596_smba = force_addr & 0xfff0; |
| 162 | | force = 0; |
| 163 | | } else { |
| 164 | | if ((pci_read_config_word(VT596_dev, num->base, &vt596_smba)) |
| 165 | | || !(vt596_smba & 0x1)) { |
| 166 | | /* try 2nd address and config reg. for 596 */ |
| 167 | | if((num->dev == PCI_DEVICE_ID_VIA_82C596_3) && |
| 168 | | (!pci_read_config_word(VT596_dev, SMBBA2, &vt596_smba)) && |
| 169 | | (vt596_smba & 0x1)) { |
| 170 | | smb_cf_hstcfg = 0x84; |
| 171 | | } else { |
| 172 | | /* no matches at all */ |
| 173 | | printk("i2c-viapro.o: Cannot configure SMBus " |
| 174 | | "I/O Base address\n"); |
| 175 | | return(-ENODEV); |
| 176 | | } |
| 177 | | } |
| 178 | | vt596_smba &= 0xfff0; |
| 179 | | if(vt596_smba == 0) { |
| 180 | | printk(KERN_ERR "i2c-viapro.o: SMBus base address" |
| 181 | | "uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); |
| 182 | | return -ENODEV; |
| 183 | | } |
| 184 | | } |
| 185 | | |
| 186 | | if (check_region(vt596_smba, 8)) { |
| 187 | | printk("i2c-viapro.o: SMBus region 0x%x already in use!\n", |
| 188 | | vt596_smba); |
| 189 | | return(-ENODEV); |
| 190 | | } |
| 191 | | |
| 192 | | pci_read_config_byte(VT596_dev, SMBHSTCFG, &temp); |
| 193 | | /* If force_addr is set, we program the new address here. Just to make |
| 194 | | sure, we disable the VT596 first. */ |
| 195 | | if (force_addr) { |
| 196 | | pci_write_config_byte(VT596_dev, SMBHSTCFG, temp & 0xfe); |
| 197 | | pci_write_config_word(VT596_dev, num->base, vt596_smba); |
| 198 | | pci_write_config_byte(VT596_dev, SMBHSTCFG, temp | 0x01); |
| 199 | | printk |
| 200 | | ("i2c-viapro.o: WARNING: SMBus interface set to new " |
| 201 | | "address 0x%04x!\n", vt596_smba); |
| 202 | | } else if ((temp & 1) == 0) { |
| 203 | | if (force) { |
| 204 | | /* NOTE: This assumes I/O space and other allocations WERE |
| 205 | | done by the Bios! Don't complain if your hardware does weird |
| 206 | | things after enabling this. :') Check for Bios updates before |
| 207 | | resorting to this. */ |
| 208 | | pci_write_config_byte(VT596_dev, SMBHSTCFG, |
| 209 | | temp | 1); |
| 210 | | printk |
| 211 | | ("i2c-viapro.o: enabling SMBus device\n"); |
| 212 | | } else { |
| 213 | | printk |
| 214 | | ("SMBUS: Error: Host SMBus controller not enabled! - " |
| 215 | | "upgrade BIOS or use force=1\n"); |
| 216 | | return(-ENODEV); |
| 217 | | } |
| 218 | | } |
| 219 | | |
| 220 | | /* Everything is happy, let's grab the memory and set things up. */ |
| 221 | | request_region(vt596_smba, 8, "viapro-smbus"); |
| 222 | | |
| 223 | | #ifdef DEBUG |
| 224 | | if ((temp & 0x0E) == 8) |
| 225 | | printk("i2c-viapro.o: using Interrupt 9 for SMBus.\n"); |
| 226 | | else if ((temp & 0x0E) == 0) |
| 227 | | printk("i2c-viapro.o: using Interrupt SMI# for SMBus.\n"); |
| 228 | | else |
| 229 | | printk |
| 230 | | ("i2c-viapro.o: Illegal Interrupt configuration (or code out " |
| 231 | | "of date)!\n"); |
| 232 | | |
| 233 | | pci_read_config_byte(VT596_dev, SMBREV, &temp); |
| 234 | | printk("i2c-viapro.o: SMBREV = 0x%X\n", temp); |
| 235 | | printk("i2c-viapro.o: VT596_smba = 0x%X\n", vt596_smba); |
| 236 | | #endif /* DEBUG */ |
| 237 | | |
| 238 | | return(0); |
| 239 | | } |
| 240 | | |
| | 105 | static struct i2c_adapter vt596_adapter; |
| 256 | | #ifdef DEBUG |
| 257 | | printk |
| 258 | | ("i2c-viapro.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " |
| 259 | | "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), |
| 260 | | inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); |
| 261 | | #endif |
| | 121 | dev_dbg(&vt596_adapter, "Transaction (pre): CNT=%02x, CMD=%02x, " |
| | 122 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), |
| | 123 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), |
| | 124 | inb_p(SMBHSTDAT1)); |
| 326 | | #ifdef DEBUG |
| 327 | | printk |
| 328 | | ("i2c-viapro.o: Failed reset at end of transaction (%02x)\n", |
| 329 | | temp); |
| 330 | | #endif |
| 331 | | } |
| 332 | | #ifdef DEBUG |
| 333 | | printk |
| 334 | | ("i2c-viapro.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " |
| 335 | | "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), |
| 336 | | inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); |
| 337 | | #endif |
| | 178 | dev_dbg(&vt596_adapter, "Failed reset at end of " |
| | 179 | "transaction (%02x)\n", temp); |
| | 180 | } |
| | 181 | dev_dbg(&vt596_adapter, "Transaction (post): CNT=%02x, CMD=%02x, " |
| | 182 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), |
| | 183 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), |
| | 184 | inb_p(SMBHSTDAT1)); |
| | 185 | |
| 457 | | |
| | 303 | static int __devinit vt596_probe(struct pci_dev *pdev, |
| | 304 | const struct pci_device_id *id) |
| | 305 | { |
| | 306 | unsigned char temp; |
| | 307 | int error = -ENODEV; |
| | 308 | |
| | 309 | /* Determine the address of the SMBus areas */ |
| | 310 | if (force_addr) { |
| | 311 | vt596_smba = force_addr & 0xfff0; |
| | 312 | force = 0; |
| | 313 | goto found; |
| | 314 | } |
| | 315 | |
| | 316 | if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || |
| | 317 | !(vt596_smba & 0x1)) { |
| | 318 | /* try 2nd address and config reg. for 596 */ |
| | 319 | if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && |
| | 320 | !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && |
| | 321 | (vt596_smba & 0x1)) { |
| | 322 | smb_cf_hstcfg = 0x84; |
| | 323 | } else { |
| | 324 | /* no matches at all */ |
| | 325 | dev_err(pdev, "Cannot configure " |
| | 326 | "SMBus I/O Base address\n"); |
| | 327 | return -ENODEV; |
| | 328 | } |
| | 329 | } |
| | 330 | |
| | 331 | vt596_smba &= 0xfff0; |
| | 332 | if (vt596_smba == 0) { |
| | 333 | dev_err(pdev, "SMBus base address " |
| | 334 | "uninitialized - upgrade BIOS or use " |
| | 335 | "force_addr=0xaddr\n"); |
| | 336 | return -ENODEV; |
| | 337 | } |
| | 338 | |
| | 339 | found: |
| | 340 | if (!request_region(vt596_smba, 8, "viapro-smbus")) { |
| | 341 | dev_err(pdev, "SMBus region 0x%x already in use!\n", |
| | 342 | vt596_smba); |
| | 343 | return -ENODEV; |
| | 344 | } |
| | 345 | |
| | 346 | pci_read_config_byte(pdev, SMBHSTCFG, &temp); |
| | 347 | /* If force_addr is set, we program the new address here. Just to make |
| | 348 | sure, we disable the VT596 first. */ |
| | 349 | if (force_addr) { |
| | 350 | pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe); |
| | 351 | pci_write_config_word(pdev, id->driver_data, vt596_smba); |
| | 352 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); |
| | 353 | dev_warn(pdev, "WARNING: SMBus interface set to new " |
| | 354 | "address 0x%04x!\n", vt596_smba); |
| | 355 | } else if ((temp & 1) == 0) { |
| | 356 | if (force) { |
| | 357 | /* NOTE: This assumes I/O space and other allocations |
| | 358 | * WERE done by the Bios! Don't complain if your |
| | 359 | * hardware does weird things after enabling this. |
| | 360 | * :') Check for Bios updates before resorting to |
| | 361 | * this. |
| | 362 | */ |
| | 363 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 1); |
| | 364 | dev_info(pdev, "Enabling SMBus device\n"); |
| | 365 | } else { |
| | 366 | dev_err(pdev, "SMBUS: Error: Host SMBus " |
| | 367 | "controller not enabled! - upgrade BIOS or " |
| | 368 | "use force=1\n"); |
| | 369 | goto release_region; |
| | 370 | } |
| | 371 | } |
| | 372 | |
| | 373 | if ((temp & 0x0E) == 8) |
| | 374 | dev_dbg(pdev, "using Interrupt 9 for SMBus.\n"); |
| | 375 | else if ((temp & 0x0E) == 0) |
| | 376 | dev_dbg(pdev, "using Interrupt SMI# for SMBus.\n"); |
| | 377 | else |
| | 378 | dev_dbg(pdev, "Illegal Interrupt configuration " |
| | 379 | "(or code out of date)!\n"); |
| | 380 | |
| | 381 | pci_read_config_byte(pdev, SMBREV, &temp); |
| | 382 | dev_dbg(pdev, "SMBREV = 0x%X\n", temp); |
| | 383 | dev_dbg(pdev, "VT596_smba = 0x%X\n", vt596_smba); |
| | 384 | |
| | 385 | snprintf(vt596_adapter.name, 32, |
| | 386 | "SMBus Via Pro adapter at %04x", vt596_smba); |
| | 387 | |
| | 388 | return i2c_add_adapter(&vt596_adapter); |
| | 389 | |
| | 390 | release_region: |
| | 391 | release_region(vt596_smba, 8); |
| | 392 | return error; |
| | 393 | } |
| | 394 | |
| | 395 | static void __devexit vt596_remove(struct pci_dev *pdev) |
| | 396 | { |
| | 397 | i2c_del_adapter(&vt596_adapter); |
| | 398 | release_region(vt596_smba, 8); |
| | 399 | } |
| | 400 | |
| | 401 | #ifndef PCI_DEVICE_ID_VIA_8235 |
| | 402 | #define PCI_DEVICE_ID_VIA_8235 0x3177 |
| | 403 | #endif |
| | 405 | { |
| | 406 | .vendor = PCI_VENDOR_ID_VIA, |
| | 407 | .device = PCI_DEVICE_ID_VIA_82C596_3, |
| | 408 | .subvendor = PCI_ANY_ID, |
| | 409 | .subdevice = PCI_ANY_ID, |
| | 410 | .driver_data = SMBBA1, |
| | 411 | }, |
| | 412 | { |
| | 413 | .vendor = PCI_VENDOR_ID_VIA, |
| | 414 | .device = PCI_DEVICE_ID_VIA_82C596B_3, |
| | 415 | .subvendor = PCI_ANY_ID, |
| | 416 | .subdevice = PCI_ANY_ID, |
| | 417 | .driver_data = SMBBA1, |
| | 418 | }, |
| | 419 | { |
| | 420 | .vendor = PCI_VENDOR_ID_VIA, |
| | 421 | .device = PCI_DEVICE_ID_VIA_82C686_4, |
| | 422 | .subvendor = PCI_ANY_ID, |
| | 423 | .subdevice = PCI_ANY_ID, |
| | 424 | .driver_data = SMBBA1, |
| | 425 | }, |
| | 426 | { |
| | 427 | .vendor = PCI_VENDOR_ID_VIA, |
| | 428 | .device = PCI_DEVICE_ID_VIA_8233_0, |
| | 429 | .subvendor = PCI_ANY_ID, |
| | 430 | .subdevice = PCI_ANY_ID, |
| | 431 | .driver_data = SMBBA3 |
| | 432 | }, |
| | 433 | { |
| | 434 | .vendor = PCI_VENDOR_ID_VIA, |
| | 435 | .device = PCI_DEVICE_ID_VIA_8233A, |
| | 436 | .subvendor = PCI_ANY_ID, |
| | 437 | .subdevice = PCI_ANY_ID, |
| | 438 | .driver_data = SMBBA3, |
| | 439 | }, |
| | 440 | { |
| | 441 | .vendor = PCI_VENDOR_ID_VIA, |
| | 442 | .device = PCI_DEVICE_ID_VIA_8235, |
| | 443 | .subvendor = PCI_ANY_ID, |
| | 444 | .subdevice = PCI_ANY_ID, |
| | 445 | .driver_data = SMBBA3 |
| | 446 | }, |
| | 447 | { |
| | 448 | .vendor = PCI_VENDOR_ID_VIA, |
| | 449 | .device = PCI_DEVICE_ID_VIA_8231_4, |
| | 450 | .subvendor = PCI_ANY_ID, |
| | 451 | .subdevice = PCI_ANY_ID, |
| | 452 | .driver_data = SMBBA1, |
| | 453 | }, |