Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

watchdog: Convert iTCO_wdt driver to mfd model

This patch converts the iTCO_wdt driver to use the multi-function device
driver model. It uses resources discovered by the lpc_ich driver, so that
it no longer does its own PCI scanning.

Signed-off-by: Aaron Sierra <asierra@xes-inc.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Aaron Sierra and committed by
Samuel Ortiz
887c8ec7 16c5c023

+313 -447
+2 -1
drivers/mfd/Kconfig
··· 785 785 help 786 786 The LPC bridge function of the Intel ICH provides support for 787 787 many functional units. This driver provides needed support for 788 - other drivers to control these functions, currently GPIO. 788 + other drivers to control these functions, currently GPIO and 789 + watchdog. 789 790 790 791 config MFD_RDC321X 791 792 tristate "Support for RDC-R321x southbridge"
+170 -1
drivers/mfd/lpc_ich.c
··· 65 65 #define ACPIBASE 0x40 66 66 #define ACPIBASE_GPE_OFF 0x28 67 67 #define ACPIBASE_GPE_END 0x2f 68 + #define ACPIBASE_SMI_OFF 0x30 69 + #define ACPIBASE_SMI_END 0x33 70 + #define ACPIBASE_TCO_OFF 0x60 71 + #define ACPIBASE_TCO_END 0x7f 68 72 #define ACPICTRL 0x44 73 + 74 + #define ACPIBASE_GCS_OFF 0x3410 75 + #define ACPIBASE_GCS_END 0x3414 69 76 70 77 #define GPIOBASE 0x48 71 78 #define GPIOCTRL 0x4C 72 79 80 + #define RCBABASE 0xf0 81 + 82 + #define wdt_io_res(i) wdt_res(0, i) 83 + #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) 84 + #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) 85 + 73 86 static int lpc_ich_acpi_save = -1; 74 87 static int lpc_ich_gpio_save = -1; 88 + 89 + static struct resource wdt_ich_res[] = { 90 + /* ACPI - TCO */ 91 + { 92 + .flags = IORESOURCE_IO, 93 + }, 94 + /* ACPI - SMI */ 95 + { 96 + .flags = IORESOURCE_IO, 97 + }, 98 + /* GCS */ 99 + { 100 + .flags = IORESOURCE_MEM, 101 + }, 102 + }; 75 103 76 104 static struct resource gpio_ich_res[] = { 77 105 /* GPIO */ ··· 113 85 }; 114 86 115 87 enum lpc_cells { 116 - LPC_GPIO = 0, 88 + LPC_WDT = 0, 89 + LPC_GPIO, 117 90 }; 118 91 119 92 static struct mfd_cell lpc_ich_cells[] = { 93 + [LPC_WDT] = { 94 + .name = "iTCO_wdt", 95 + .num_resources = ARRAY_SIZE(wdt_ich_res), 96 + .resources = wdt_ich_res, 97 + .ignore_resource_conflicts = true, 98 + }, 120 99 [LPC_GPIO] = { 121 100 .name = "gpio_ich", 122 101 .num_resources = ARRAY_SIZE(gpio_ich_res), ··· 197 162 struct lpc_ich_info lpc_chipset_info[] __devinitdata = { 198 163 [LPC_ICH] = { 199 164 .name = "ICH", 165 + .iTCO_version = 1, 200 166 }, 201 167 [LPC_ICH0] = { 202 168 .name = "ICH0", 169 + .iTCO_version = 1, 203 170 }, 204 171 [LPC_ICH2] = { 205 172 .name = "ICH2", 173 + .iTCO_version = 1, 206 174 }, 207 175 [LPC_ICH2M] = { 208 176 .name = "ICH2-M", 177 + .iTCO_version = 1, 209 178 }, 210 179 [LPC_ICH3] = { 211 180 .name = "ICH3-S", 181 + .iTCO_version = 1, 212 182 }, 213 183 [LPC_ICH3M] = { 214 184 .name = "ICH3-M", 185 + .iTCO_version = 1, 215 186 }, 216 187 [LPC_ICH4] = { 217 188 .name = "ICH4", 189 + .iTCO_version = 1, 218 190 }, 219 191 [LPC_ICH4M] = { 220 192 .name = "ICH4-M", 193 + .iTCO_version = 1, 221 194 }, 222 195 [LPC_CICH] = { 223 196 .name = "C-ICH", 197 + .iTCO_version = 1, 224 198 }, 225 199 [LPC_ICH5] = { 226 200 .name = "ICH5 or ICH5R", 201 + .iTCO_version = 1, 227 202 }, 228 203 [LPC_6300ESB] = { 229 204 .name = "6300ESB", 205 + .iTCO_version = 1, 230 206 }, 231 207 [LPC_ICH6] = { 232 208 .name = "ICH6 or ICH6R", 209 + .iTCO_version = 2, 233 210 .gpio_version = ICH_V6_GPIO, 234 211 }, 235 212 [LPC_ICH6M] = { 236 213 .name = "ICH6-M", 214 + .iTCO_version = 2, 237 215 .gpio_version = ICH_V6_GPIO, 238 216 }, 239 217 [LPC_ICH6W] = { 240 218 .name = "ICH6W or ICH6RW", 219 + .iTCO_version = 2, 241 220 .gpio_version = ICH_V6_GPIO, 242 221 }, 243 222 [LPC_631XESB] = { 244 223 .name = "631xESB/632xESB", 224 + .iTCO_version = 2, 245 225 .gpio_version = ICH_V6_GPIO, 246 226 }, 247 227 [LPC_ICH7] = { 248 228 .name = "ICH7 or ICH7R", 229 + .iTCO_version = 2, 249 230 .gpio_version = ICH_V7_GPIO, 250 231 }, 251 232 [LPC_ICH7DH] = { 252 233 .name = "ICH7DH", 234 + .iTCO_version = 2, 253 235 .gpio_version = ICH_V7_GPIO, 254 236 }, 255 237 [LPC_ICH7M] = { 256 238 .name = "ICH7-M or ICH7-U", 239 + .iTCO_version = 2, 257 240 .gpio_version = ICH_V7_GPIO, 258 241 }, 259 242 [LPC_ICH7MDH] = { 260 243 .name = "ICH7-M DH", 244 + .iTCO_version = 2, 261 245 .gpio_version = ICH_V7_GPIO, 262 246 }, 263 247 [LPC_NM10] = { 264 248 .name = "NM10", 249 + .iTCO_version = 2, 265 250 }, 266 251 [LPC_ICH8] = { 267 252 .name = "ICH8 or ICH8R", 253 + .iTCO_version = 2, 268 254 .gpio_version = ICH_V7_GPIO, 269 255 }, 270 256 [LPC_ICH8DH] = { 271 257 .name = "ICH8DH", 258 + .iTCO_version = 2, 272 259 .gpio_version = ICH_V7_GPIO, 273 260 }, 274 261 [LPC_ICH8DO] = { 275 262 .name = "ICH8DO", 263 + .iTCO_version = 2, 276 264 .gpio_version = ICH_V7_GPIO, 277 265 }, 278 266 [LPC_ICH8M] = { 279 267 .name = "ICH8M", 268 + .iTCO_version = 2, 280 269 .gpio_version = ICH_V7_GPIO, 281 270 }, 282 271 [LPC_ICH8ME] = { 283 272 .name = "ICH8M-E", 273 + .iTCO_version = 2, 284 274 .gpio_version = ICH_V7_GPIO, 285 275 }, 286 276 [LPC_ICH9] = { 287 277 .name = "ICH9", 278 + .iTCO_version = 2, 288 279 .gpio_version = ICH_V9_GPIO, 289 280 }, 290 281 [LPC_ICH9R] = { 291 282 .name = "ICH9R", 283 + .iTCO_version = 2, 292 284 .gpio_version = ICH_V9_GPIO, 293 285 }, 294 286 [LPC_ICH9DH] = { 295 287 .name = "ICH9DH", 288 + .iTCO_version = 2, 296 289 .gpio_version = ICH_V9_GPIO, 297 290 }, 298 291 [LPC_ICH9DO] = { 299 292 .name = "ICH9DO", 293 + .iTCO_version = 2, 300 294 .gpio_version = ICH_V9_GPIO, 301 295 }, 302 296 [LPC_ICH9M] = { 303 297 .name = "ICH9M", 298 + .iTCO_version = 2, 304 299 .gpio_version = ICH_V9_GPIO, 305 300 }, 306 301 [LPC_ICH9ME] = { 307 302 .name = "ICH9M-E", 303 + .iTCO_version = 2, 308 304 .gpio_version = ICH_V9_GPIO, 309 305 }, 310 306 [LPC_ICH10] = { 311 307 .name = "ICH10", 308 + .iTCO_version = 2, 312 309 .gpio_version = ICH_V10CONS_GPIO, 313 310 }, 314 311 [LPC_ICH10R] = { 315 312 .name = "ICH10R", 313 + .iTCO_version = 2, 316 314 .gpio_version = ICH_V10CONS_GPIO, 317 315 }, 318 316 [LPC_ICH10D] = { 319 317 .name = "ICH10D", 318 + .iTCO_version = 2, 320 319 .gpio_version = ICH_V10CORP_GPIO, 321 320 }, 322 321 [LPC_ICH10DO] = { 323 322 .name = "ICH10DO", 323 + .iTCO_version = 2, 324 324 .gpio_version = ICH_V10CORP_GPIO, 325 325 }, 326 326 [LPC_PCH] = { 327 327 .name = "PCH Desktop Full Featured", 328 + .iTCO_version = 2, 328 329 .gpio_version = ICH_V5_GPIO, 329 330 }, 330 331 [LPC_PCHM] = { 331 332 .name = "PCH Mobile Full Featured", 333 + .iTCO_version = 2, 332 334 .gpio_version = ICH_V5_GPIO, 333 335 }, 334 336 [LPC_P55] = { 335 337 .name = "P55", 338 + .iTCO_version = 2, 336 339 .gpio_version = ICH_V5_GPIO, 337 340 }, 338 341 [LPC_PM55] = { 339 342 .name = "PM55", 343 + .iTCO_version = 2, 340 344 .gpio_version = ICH_V5_GPIO, 341 345 }, 342 346 [LPC_H55] = { 343 347 .name = "H55", 348 + .iTCO_version = 2, 344 349 .gpio_version = ICH_V5_GPIO, 345 350 }, 346 351 [LPC_QM57] = { 347 352 .name = "QM57", 353 + .iTCO_version = 2, 348 354 .gpio_version = ICH_V5_GPIO, 349 355 }, 350 356 [LPC_H57] = { 351 357 .name = "H57", 358 + .iTCO_version = 2, 352 359 .gpio_version = ICH_V5_GPIO, 353 360 }, 354 361 [LPC_HM55] = { 355 362 .name = "HM55", 363 + .iTCO_version = 2, 356 364 .gpio_version = ICH_V5_GPIO, 357 365 }, 358 366 [LPC_Q57] = { 359 367 .name = "Q57", 368 + .iTCO_version = 2, 360 369 .gpio_version = ICH_V5_GPIO, 361 370 }, 362 371 [LPC_HM57] = { 363 372 .name = "HM57", 373 + .iTCO_version = 2, 364 374 .gpio_version = ICH_V5_GPIO, 365 375 }, 366 376 [LPC_PCHMSFF] = { 367 377 .name = "PCH Mobile SFF Full Featured", 378 + .iTCO_version = 2, 368 379 .gpio_version = ICH_V5_GPIO, 369 380 }, 370 381 [LPC_QS57] = { 371 382 .name = "QS57", 383 + .iTCO_version = 2, 372 384 .gpio_version = ICH_V5_GPIO, 373 385 }, 374 386 [LPC_3400] = { 375 387 .name = "3400", 388 + .iTCO_version = 2, 376 389 .gpio_version = ICH_V5_GPIO, 377 390 }, 378 391 [LPC_3420] = { 379 392 .name = "3420", 393 + .iTCO_version = 2, 380 394 .gpio_version = ICH_V5_GPIO, 381 395 }, 382 396 [LPC_3450] = { 383 397 .name = "3450", 398 + .iTCO_version = 2, 384 399 .gpio_version = ICH_V5_GPIO, 385 400 }, 386 401 [LPC_EP80579] = { 387 402 .name = "EP80579", 403 + .iTCO_version = 2, 388 404 }, 389 405 [LPC_CPT] = { 390 406 .name = "Cougar Point", 407 + .iTCO_version = 2, 391 408 .gpio_version = ICH_V5_GPIO, 392 409 }, 393 410 [LPC_CPTD] = { 394 411 .name = "Cougar Point Desktop", 412 + .iTCO_version = 2, 395 413 .gpio_version = ICH_V5_GPIO, 396 414 }, 397 415 [LPC_CPTM] = { 398 416 .name = "Cougar Point Mobile", 417 + .iTCO_version = 2, 399 418 .gpio_version = ICH_V5_GPIO, 400 419 }, 401 420 [LPC_PBG] = { 402 421 .name = "Patsburg", 422 + .iTCO_version = 2, 403 423 }, 404 424 [LPC_DH89XXCC] = { 405 425 .name = "DH89xxCC", 426 + .iTCO_version = 2, 406 427 }, 407 428 [LPC_PPT] = { 408 429 .name = "Panther Point", 430 + .iTCO_version = 2, 409 431 }, 410 432 [LPC_LPT] = { 411 433 .name = "Lynx Point", 434 + .iTCO_version = 2, 412 435 }, 413 436 }; 414 437 ··· 759 666 return ret; 760 667 } 761 668 669 + static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, 670 + const struct pci_device_id *id) 671 + { 672 + u32 base_addr_cfg; 673 + u32 base_addr; 674 + int ret; 675 + bool acpi_conflict = false; 676 + struct resource *res; 677 + 678 + /* Setup power management base register */ 679 + pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg); 680 + base_addr = base_addr_cfg & 0x0000ff80; 681 + if (!base_addr) { 682 + dev_err(&dev->dev, "I/O space for ACPI uninitialized\n"); 683 + ret = -ENODEV; 684 + goto wdt_done; 685 + } 686 + 687 + res = wdt_io_res(ICH_RES_IO_TCO); 688 + res->start = base_addr + ACPIBASE_TCO_OFF; 689 + res->end = base_addr + ACPIBASE_TCO_END; 690 + ret = acpi_check_resource_conflict(res); 691 + if (ret) { 692 + acpi_conflict = true; 693 + goto wdt_done; 694 + } 695 + 696 + res = wdt_io_res(ICH_RES_IO_SMI); 697 + res->start = base_addr + ACPIBASE_SMI_OFF; 698 + res->end = base_addr + ACPIBASE_SMI_END; 699 + ret = acpi_check_resource_conflict(res); 700 + if (ret) { 701 + acpi_conflict = true; 702 + goto wdt_done; 703 + } 704 + lpc_ich_enable_acpi_space(dev); 705 + 706 + /* 707 + * Get the Memory-Mapped GCS register. To get access to it 708 + * we have to read RCBA from PCI Config space 0xf0 and use 709 + * it as base. GCS = RCBA + ICH6_GCS(0x3410). 710 + */ 711 + if (lpc_chipset_info[id->driver_data].iTCO_version == 2) { 712 + pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); 713 + base_addr = base_addr_cfg & 0xffffc000; 714 + if (!(base_addr_cfg & 1)) { 715 + pr_err("RCBA is disabled by hardware/BIOS, " 716 + "device disabled\n"); 717 + ret = -ENODEV; 718 + goto wdt_done; 719 + } 720 + res = wdt_mem_res(ICH_RES_MEM_GCS); 721 + res->start = base_addr + ACPIBASE_GCS_OFF; 722 + res->end = base_addr + ACPIBASE_GCS_END; 723 + ret = acpi_check_resource_conflict(res); 724 + if (ret) { 725 + acpi_conflict = true; 726 + goto wdt_done; 727 + } 728 + } 729 + 730 + lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); 731 + ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], 732 + 1, NULL, 0); 733 + 734 + wdt_done: 735 + if (acpi_conflict) 736 + pr_warn("Resource conflict(s) found affecting %s\n", 737 + lpc_ich_cells[LPC_WDT].name); 738 + return ret; 739 + } 740 + 762 741 static int __devinit lpc_ich_probe(struct pci_dev *dev, 763 742 const struct pci_device_id *id) 764 743 { 765 744 int ret; 766 745 bool cell_added = false; 746 + 747 + ret = lpc_ich_init_wdt(dev, id); 748 + if (!ret) 749 + cell_added = true; 767 750 768 751 ret = lpc_ich_init_gpio(dev, id); 769 752 if (!ret)
+1
drivers/watchdog/Kconfig
··· 563 563 config ITCO_WDT 564 564 tristate "Intel TCO Timer/Watchdog" 565 565 depends on (X86 || IA64) && PCI 566 + select LPC_ICH 566 567 ---help--- 567 568 Hardware driver for the intel TCO timer based watchdog devices. 568 569 These drivers are included in the Intel 82801 I/O Controller
+3 -3
drivers/watchdog/iTCO_vendor.h
··· 1 1 /* iTCO Vendor Specific Support hooks */ 2 2 #ifdef CONFIG_ITCO_VENDOR_SUPPORT 3 - extern void iTCO_vendor_pre_start(unsigned long, unsigned int); 4 - extern void iTCO_vendor_pre_stop(unsigned long); 5 - extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int); 3 + extern void iTCO_vendor_pre_start(struct resource *, unsigned int); 4 + extern void iTCO_vendor_pre_stop(struct resource *); 5 + extern void iTCO_vendor_pre_keepalive(struct resource *, unsigned int); 6 6 extern void iTCO_vendor_pre_set_heartbeat(unsigned int); 7 7 extern int iTCO_vendor_check_noreboot_on(void); 8 8 #else
+19 -24
drivers/watchdog/iTCO_vendor_support.c
··· 35 35 36 36 #include "iTCO_vendor.h" 37 37 38 - /* iTCO defines */ 39 - #define SMI_EN (acpibase + 0x30) /* SMI Control and Enable Register */ 40 - #define TCOBASE (acpibase + 0x60) /* TCO base address */ 41 - #define TCO1_STS (TCOBASE + 0x04) /* TCO1 Status Register */ 42 - 43 38 /* List of vendor support modes */ 44 39 /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ 45 40 #define SUPERMICRO_OLD_BOARD 1 ··· 77 82 * 20.6 seconds. 78 83 */ 79 84 80 - static void supermicro_old_pre_start(unsigned long acpibase) 85 + static void supermicro_old_pre_start(struct resource *smires) 81 86 { 82 87 unsigned long val32; 83 88 84 89 /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ 85 - val32 = inl(SMI_EN); 90 + val32 = inl(smires->start); 86 91 val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ 87 - outl(val32, SMI_EN); /* Needed to activate watchdog */ 92 + outl(val32, smires->start); /* Needed to activate watchdog */ 88 93 } 89 94 90 - static void supermicro_old_pre_stop(unsigned long acpibase) 95 + static void supermicro_old_pre_stop(struct resource *smires) 91 96 { 92 97 unsigned long val32; 93 98 94 99 /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */ 95 - val32 = inl(SMI_EN); 100 + val32 = inl(smires->start); 96 101 val32 |= 0x00002000; /* Turn on SMI clearing watchdog */ 97 - outl(val32, SMI_EN); /* Needed to deactivate watchdog */ 102 + outl(val32, smires->start); /* Needed to deactivate watchdog */ 98 103 } 99 104 100 105 /* ··· 265 270 * Don't use this fix if you don't need to!!! 266 271 */ 267 272 268 - static void broken_bios_start(unsigned long acpibase) 273 + static void broken_bios_start(struct resource *smires) 269 274 { 270 275 unsigned long val32; 271 276 272 - val32 = inl(SMI_EN); 277 + val32 = inl(smires->start); 273 278 /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# 274 279 Bit 0: GBL_SMI_EN -> 0 = No SMI# will be generated by ICH. */ 275 280 val32 &= 0xffffdffe; 276 - outl(val32, SMI_EN); 281 + outl(val32, smires->start); 277 282 } 278 283 279 - static void broken_bios_stop(unsigned long acpibase) 284 + static void broken_bios_stop(struct resource *smires) 280 285 { 281 286 unsigned long val32; 282 287 283 - val32 = inl(SMI_EN); 288 + val32 = inl(smires->start); 284 289 /* Bit 13: TCO_EN -> 1 = Enables TCO logic generating an SMI# 285 290 Bit 0: GBL_SMI_EN -> 1 = Turn global SMI on again. */ 286 291 val32 |= 0x00002001; 287 - outl(val32, SMI_EN); 292 + outl(val32, smires->start); 288 293 } 289 294 290 295 /* 291 296 * Generic Support Functions 292 297 */ 293 298 294 - void iTCO_vendor_pre_start(unsigned long acpibase, 299 + void iTCO_vendor_pre_start(struct resource *smires, 295 300 unsigned int heartbeat) 296 301 { 297 302 switch (vendorsupport) { 298 303 case SUPERMICRO_OLD_BOARD: 299 - supermicro_old_pre_start(acpibase); 304 + supermicro_old_pre_start(smires); 300 305 break; 301 306 case SUPERMICRO_NEW_BOARD: 302 307 supermicro_new_pre_start(heartbeat); 303 308 break; 304 309 case BROKEN_BIOS: 305 - broken_bios_start(acpibase); 310 + broken_bios_start(smires); 306 311 break; 307 312 } 308 313 } 309 314 EXPORT_SYMBOL(iTCO_vendor_pre_start); 310 315 311 - void iTCO_vendor_pre_stop(unsigned long acpibase) 316 + void iTCO_vendor_pre_stop(struct resource *smires) 312 317 { 313 318 switch (vendorsupport) { 314 319 case SUPERMICRO_OLD_BOARD: 315 - supermicro_old_pre_stop(acpibase); 320 + supermicro_old_pre_stop(smires); 316 321 break; 317 322 case SUPERMICRO_NEW_BOARD: 318 323 supermicro_new_pre_stop(); 319 324 break; 320 325 case BROKEN_BIOS: 321 - broken_bios_stop(acpibase); 326 + broken_bios_stop(smires); 322 327 break; 323 328 } 324 329 } 325 330 EXPORT_SYMBOL(iTCO_vendor_pre_stop); 326 331 327 - void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat) 332 + void iTCO_vendor_pre_keepalive(struct resource *smires, unsigned int heartbeat) 328 333 { 329 334 if (vendorsupport == SUPERMICRO_NEW_BOARD) 330 335 supermicro_new_pre_set_heartbeat(heartbeat);
+111 -418
drivers/watchdog/iTCO_wdt.c
··· 66 66 #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 67 67 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ 68 68 #include <linux/io.h> /* For inb/outb/... */ 69 + #include <linux/mfd/core.h> 70 + #include <linux/mfd/lpc_ich.h> 69 71 70 72 #include "iTCO_vendor.h" 71 73 72 - /* TCO related info */ 73 - enum iTCO_chipsets { 74 - TCO_ICH = 0, /* ICH */ 75 - TCO_ICH0, /* ICH0 */ 76 - TCO_ICH2, /* ICH2 */ 77 - TCO_ICH2M, /* ICH2-M */ 78 - TCO_ICH3, /* ICH3-S */ 79 - TCO_ICH3M, /* ICH3-M */ 80 - TCO_ICH4, /* ICH4 */ 81 - TCO_ICH4M, /* ICH4-M */ 82 - TCO_CICH, /* C-ICH */ 83 - TCO_ICH5, /* ICH5 & ICH5R */ 84 - TCO_6300ESB, /* 6300ESB */ 85 - TCO_ICH6, /* ICH6 & ICH6R */ 86 - TCO_ICH6M, /* ICH6-M */ 87 - TCO_ICH6W, /* ICH6W & ICH6RW */ 88 - TCO_631XESB, /* 631xESB/632xESB */ 89 - TCO_ICH7, /* ICH7 & ICH7R */ 90 - TCO_ICH7DH, /* ICH7DH */ 91 - TCO_ICH7M, /* ICH7-M & ICH7-U */ 92 - TCO_ICH7MDH, /* ICH7-M DH */ 93 - TCO_NM10, /* NM10 */ 94 - TCO_ICH8, /* ICH8 & ICH8R */ 95 - TCO_ICH8DH, /* ICH8DH */ 96 - TCO_ICH8DO, /* ICH8DO */ 97 - TCO_ICH8M, /* ICH8M */ 98 - TCO_ICH8ME, /* ICH8M-E */ 99 - TCO_ICH9, /* ICH9 */ 100 - TCO_ICH9R, /* ICH9R */ 101 - TCO_ICH9DH, /* ICH9DH */ 102 - TCO_ICH9DO, /* ICH9DO */ 103 - TCO_ICH9M, /* ICH9M */ 104 - TCO_ICH9ME, /* ICH9M-E */ 105 - TCO_ICH10, /* ICH10 */ 106 - TCO_ICH10R, /* ICH10R */ 107 - TCO_ICH10D, /* ICH10D */ 108 - TCO_ICH10DO, /* ICH10DO */ 109 - TCO_PCH, /* PCH Desktop Full Featured */ 110 - TCO_PCHM, /* PCH Mobile Full Featured */ 111 - TCO_P55, /* P55 */ 112 - TCO_PM55, /* PM55 */ 113 - TCO_H55, /* H55 */ 114 - TCO_QM57, /* QM57 */ 115 - TCO_H57, /* H57 */ 116 - TCO_HM55, /* HM55 */ 117 - TCO_Q57, /* Q57 */ 118 - TCO_HM57, /* HM57 */ 119 - TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ 120 - TCO_QS57, /* QS57 */ 121 - TCO_3400, /* 3400 */ 122 - TCO_3420, /* 3420 */ 123 - TCO_3450, /* 3450 */ 124 - TCO_EP80579, /* EP80579 */ 125 - TCO_CPT, /* Cougar Point */ 126 - TCO_CPTD, /* Cougar Point Desktop */ 127 - TCO_CPTM, /* Cougar Point Mobile */ 128 - TCO_PBG, /* Patsburg */ 129 - TCO_DH89XXCC, /* DH89xxCC */ 130 - TCO_PPT, /* Panther Point */ 131 - TCO_LPT, /* Lynx Point */ 132 - }; 133 - 134 - static struct { 135 - char *name; 136 - unsigned int iTCO_version; 137 - } iTCO_chipset_info[] __devinitdata = { 138 - {"ICH", 1}, 139 - {"ICH0", 1}, 140 - {"ICH2", 1}, 141 - {"ICH2-M", 1}, 142 - {"ICH3-S", 1}, 143 - {"ICH3-M", 1}, 144 - {"ICH4", 1}, 145 - {"ICH4-M", 1}, 146 - {"C-ICH", 1}, 147 - {"ICH5 or ICH5R", 1}, 148 - {"6300ESB", 1}, 149 - {"ICH6 or ICH6R", 2}, 150 - {"ICH6-M", 2}, 151 - {"ICH6W or ICH6RW", 2}, 152 - {"631xESB/632xESB", 2}, 153 - {"ICH7 or ICH7R", 2}, 154 - {"ICH7DH", 2}, 155 - {"ICH7-M or ICH7-U", 2}, 156 - {"ICH7-M DH", 2}, 157 - {"NM10", 2}, 158 - {"ICH8 or ICH8R", 2}, 159 - {"ICH8DH", 2}, 160 - {"ICH8DO", 2}, 161 - {"ICH8M", 2}, 162 - {"ICH8M-E", 2}, 163 - {"ICH9", 2}, 164 - {"ICH9R", 2}, 165 - {"ICH9DH", 2}, 166 - {"ICH9DO", 2}, 167 - {"ICH9M", 2}, 168 - {"ICH9M-E", 2}, 169 - {"ICH10", 2}, 170 - {"ICH10R", 2}, 171 - {"ICH10D", 2}, 172 - {"ICH10DO", 2}, 173 - {"PCH Desktop Full Featured", 2}, 174 - {"PCH Mobile Full Featured", 2}, 175 - {"P55", 2}, 176 - {"PM55", 2}, 177 - {"H55", 2}, 178 - {"QM57", 2}, 179 - {"H57", 2}, 180 - {"HM55", 2}, 181 - {"Q57", 2}, 182 - {"HM57", 2}, 183 - {"PCH Mobile SFF Full Featured", 2}, 184 - {"QS57", 2}, 185 - {"3400", 2}, 186 - {"3420", 2}, 187 - {"3450", 2}, 188 - {"EP80579", 2}, 189 - {"Cougar Point", 2}, 190 - {"Cougar Point Desktop", 2}, 191 - {"Cougar Point Mobile", 2}, 192 - {"Patsburg", 2}, 193 - {"DH89xxCC", 2}, 194 - {"Panther Point", 2}, 195 - {"Lynx Point", 2}, 196 - {NULL, 0} 197 - }; 198 - 199 - /* 200 - * This data only exists for exporting the supported PCI ids 201 - * via MODULE_DEVICE_TABLE. We do not actually register a 202 - * pci_driver, because the I/O Controller Hub has also other 203 - * functions that probably will be registered by other drivers. 204 - */ 205 - static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { 206 - { PCI_VDEVICE(INTEL, 0x2410), TCO_ICH}, 207 - { PCI_VDEVICE(INTEL, 0x2420), TCO_ICH0}, 208 - { PCI_VDEVICE(INTEL, 0x2440), TCO_ICH2}, 209 - { PCI_VDEVICE(INTEL, 0x244c), TCO_ICH2M}, 210 - { PCI_VDEVICE(INTEL, 0x2480), TCO_ICH3}, 211 - { PCI_VDEVICE(INTEL, 0x248c), TCO_ICH3M}, 212 - { PCI_VDEVICE(INTEL, 0x24c0), TCO_ICH4}, 213 - { PCI_VDEVICE(INTEL, 0x24cc), TCO_ICH4M}, 214 - { PCI_VDEVICE(INTEL, 0x2450), TCO_CICH}, 215 - { PCI_VDEVICE(INTEL, 0x24d0), TCO_ICH5}, 216 - { PCI_VDEVICE(INTEL, 0x25a1), TCO_6300ESB}, 217 - { PCI_VDEVICE(INTEL, 0x2640), TCO_ICH6}, 218 - { PCI_VDEVICE(INTEL, 0x2641), TCO_ICH6M}, 219 - { PCI_VDEVICE(INTEL, 0x2642), TCO_ICH6W}, 220 - { PCI_VDEVICE(INTEL, 0x2670), TCO_631XESB}, 221 - { PCI_VDEVICE(INTEL, 0x2671), TCO_631XESB}, 222 - { PCI_VDEVICE(INTEL, 0x2672), TCO_631XESB}, 223 - { PCI_VDEVICE(INTEL, 0x2673), TCO_631XESB}, 224 - { PCI_VDEVICE(INTEL, 0x2674), TCO_631XESB}, 225 - { PCI_VDEVICE(INTEL, 0x2675), TCO_631XESB}, 226 - { PCI_VDEVICE(INTEL, 0x2676), TCO_631XESB}, 227 - { PCI_VDEVICE(INTEL, 0x2677), TCO_631XESB}, 228 - { PCI_VDEVICE(INTEL, 0x2678), TCO_631XESB}, 229 - { PCI_VDEVICE(INTEL, 0x2679), TCO_631XESB}, 230 - { PCI_VDEVICE(INTEL, 0x267a), TCO_631XESB}, 231 - { PCI_VDEVICE(INTEL, 0x267b), TCO_631XESB}, 232 - { PCI_VDEVICE(INTEL, 0x267c), TCO_631XESB}, 233 - { PCI_VDEVICE(INTEL, 0x267d), TCO_631XESB}, 234 - { PCI_VDEVICE(INTEL, 0x267e), TCO_631XESB}, 235 - { PCI_VDEVICE(INTEL, 0x267f), TCO_631XESB}, 236 - { PCI_VDEVICE(INTEL, 0x27b8), TCO_ICH7}, 237 - { PCI_VDEVICE(INTEL, 0x27b0), TCO_ICH7DH}, 238 - { PCI_VDEVICE(INTEL, 0x27b9), TCO_ICH7M}, 239 - { PCI_VDEVICE(INTEL, 0x27bd), TCO_ICH7MDH}, 240 - { PCI_VDEVICE(INTEL, 0x27bc), TCO_NM10}, 241 - { PCI_VDEVICE(INTEL, 0x2810), TCO_ICH8}, 242 - { PCI_VDEVICE(INTEL, 0x2812), TCO_ICH8DH}, 243 - { PCI_VDEVICE(INTEL, 0x2814), TCO_ICH8DO}, 244 - { PCI_VDEVICE(INTEL, 0x2815), TCO_ICH8M}, 245 - { PCI_VDEVICE(INTEL, 0x2811), TCO_ICH8ME}, 246 - { PCI_VDEVICE(INTEL, 0x2918), TCO_ICH9}, 247 - { PCI_VDEVICE(INTEL, 0x2916), TCO_ICH9R}, 248 - { PCI_VDEVICE(INTEL, 0x2912), TCO_ICH9DH}, 249 - { PCI_VDEVICE(INTEL, 0x2914), TCO_ICH9DO}, 250 - { PCI_VDEVICE(INTEL, 0x2919), TCO_ICH9M}, 251 - { PCI_VDEVICE(INTEL, 0x2917), TCO_ICH9ME}, 252 - { PCI_VDEVICE(INTEL, 0x3a18), TCO_ICH10}, 253 - { PCI_VDEVICE(INTEL, 0x3a16), TCO_ICH10R}, 254 - { PCI_VDEVICE(INTEL, 0x3a1a), TCO_ICH10D}, 255 - { PCI_VDEVICE(INTEL, 0x3a14), TCO_ICH10DO}, 256 - { PCI_VDEVICE(INTEL, 0x3b00), TCO_PCH}, 257 - { PCI_VDEVICE(INTEL, 0x3b01), TCO_PCHM}, 258 - { PCI_VDEVICE(INTEL, 0x3b02), TCO_P55}, 259 - { PCI_VDEVICE(INTEL, 0x3b03), TCO_PM55}, 260 - { PCI_VDEVICE(INTEL, 0x3b06), TCO_H55}, 261 - { PCI_VDEVICE(INTEL, 0x3b07), TCO_QM57}, 262 - { PCI_VDEVICE(INTEL, 0x3b08), TCO_H57}, 263 - { PCI_VDEVICE(INTEL, 0x3b09), TCO_HM55}, 264 - { PCI_VDEVICE(INTEL, 0x3b0a), TCO_Q57}, 265 - { PCI_VDEVICE(INTEL, 0x3b0b), TCO_HM57}, 266 - { PCI_VDEVICE(INTEL, 0x3b0d), TCO_PCHMSFF}, 267 - { PCI_VDEVICE(INTEL, 0x3b0f), TCO_QS57}, 268 - { PCI_VDEVICE(INTEL, 0x3b12), TCO_3400}, 269 - { PCI_VDEVICE(INTEL, 0x3b14), TCO_3420}, 270 - { PCI_VDEVICE(INTEL, 0x3b16), TCO_3450}, 271 - { PCI_VDEVICE(INTEL, 0x5031), TCO_EP80579}, 272 - { PCI_VDEVICE(INTEL, 0x1c41), TCO_CPT}, 273 - { PCI_VDEVICE(INTEL, 0x1c42), TCO_CPTD}, 274 - { PCI_VDEVICE(INTEL, 0x1c43), TCO_CPTM}, 275 - { PCI_VDEVICE(INTEL, 0x1c44), TCO_CPT}, 276 - { PCI_VDEVICE(INTEL, 0x1c45), TCO_CPT}, 277 - { PCI_VDEVICE(INTEL, 0x1c46), TCO_CPT}, 278 - { PCI_VDEVICE(INTEL, 0x1c47), TCO_CPT}, 279 - { PCI_VDEVICE(INTEL, 0x1c48), TCO_CPT}, 280 - { PCI_VDEVICE(INTEL, 0x1c49), TCO_CPT}, 281 - { PCI_VDEVICE(INTEL, 0x1c4a), TCO_CPT}, 282 - { PCI_VDEVICE(INTEL, 0x1c4b), TCO_CPT}, 283 - { PCI_VDEVICE(INTEL, 0x1c4c), TCO_CPT}, 284 - { PCI_VDEVICE(INTEL, 0x1c4d), TCO_CPT}, 285 - { PCI_VDEVICE(INTEL, 0x1c4e), TCO_CPT}, 286 - { PCI_VDEVICE(INTEL, 0x1c4f), TCO_CPT}, 287 - { PCI_VDEVICE(INTEL, 0x1c50), TCO_CPT}, 288 - { PCI_VDEVICE(INTEL, 0x1c51), TCO_CPT}, 289 - { PCI_VDEVICE(INTEL, 0x1c52), TCO_CPT}, 290 - { PCI_VDEVICE(INTEL, 0x1c53), TCO_CPT}, 291 - { PCI_VDEVICE(INTEL, 0x1c54), TCO_CPT}, 292 - { PCI_VDEVICE(INTEL, 0x1c55), TCO_CPT}, 293 - { PCI_VDEVICE(INTEL, 0x1c56), TCO_CPT}, 294 - { PCI_VDEVICE(INTEL, 0x1c57), TCO_CPT}, 295 - { PCI_VDEVICE(INTEL, 0x1c58), TCO_CPT}, 296 - { PCI_VDEVICE(INTEL, 0x1c59), TCO_CPT}, 297 - { PCI_VDEVICE(INTEL, 0x1c5a), TCO_CPT}, 298 - { PCI_VDEVICE(INTEL, 0x1c5b), TCO_CPT}, 299 - { PCI_VDEVICE(INTEL, 0x1c5c), TCO_CPT}, 300 - { PCI_VDEVICE(INTEL, 0x1c5d), TCO_CPT}, 301 - { PCI_VDEVICE(INTEL, 0x1c5e), TCO_CPT}, 302 - { PCI_VDEVICE(INTEL, 0x1c5f), TCO_CPT}, 303 - { PCI_VDEVICE(INTEL, 0x1d40), TCO_PBG}, 304 - { PCI_VDEVICE(INTEL, 0x1d41), TCO_PBG}, 305 - { PCI_VDEVICE(INTEL, 0x2310), TCO_DH89XXCC}, 306 - { PCI_VDEVICE(INTEL, 0x1e40), TCO_PPT}, 307 - { PCI_VDEVICE(INTEL, 0x1e41), TCO_PPT}, 308 - { PCI_VDEVICE(INTEL, 0x1e42), TCO_PPT}, 309 - { PCI_VDEVICE(INTEL, 0x1e43), TCO_PPT}, 310 - { PCI_VDEVICE(INTEL, 0x1e44), TCO_PPT}, 311 - { PCI_VDEVICE(INTEL, 0x1e45), TCO_PPT}, 312 - { PCI_VDEVICE(INTEL, 0x1e46), TCO_PPT}, 313 - { PCI_VDEVICE(INTEL, 0x1e47), TCO_PPT}, 314 - { PCI_VDEVICE(INTEL, 0x1e48), TCO_PPT}, 315 - { PCI_VDEVICE(INTEL, 0x1e49), TCO_PPT}, 316 - { PCI_VDEVICE(INTEL, 0x1e4a), TCO_PPT}, 317 - { PCI_VDEVICE(INTEL, 0x1e4b), TCO_PPT}, 318 - { PCI_VDEVICE(INTEL, 0x1e4c), TCO_PPT}, 319 - { PCI_VDEVICE(INTEL, 0x1e4d), TCO_PPT}, 320 - { PCI_VDEVICE(INTEL, 0x1e4e), TCO_PPT}, 321 - { PCI_VDEVICE(INTEL, 0x1e4f), TCO_PPT}, 322 - { PCI_VDEVICE(INTEL, 0x1e50), TCO_PPT}, 323 - { PCI_VDEVICE(INTEL, 0x1e51), TCO_PPT}, 324 - { PCI_VDEVICE(INTEL, 0x1e52), TCO_PPT}, 325 - { PCI_VDEVICE(INTEL, 0x1e53), TCO_PPT}, 326 - { PCI_VDEVICE(INTEL, 0x1e54), TCO_PPT}, 327 - { PCI_VDEVICE(INTEL, 0x1e55), TCO_PPT}, 328 - { PCI_VDEVICE(INTEL, 0x1e56), TCO_PPT}, 329 - { PCI_VDEVICE(INTEL, 0x1e57), TCO_PPT}, 330 - { PCI_VDEVICE(INTEL, 0x1e58), TCO_PPT}, 331 - { PCI_VDEVICE(INTEL, 0x1e59), TCO_PPT}, 332 - { PCI_VDEVICE(INTEL, 0x1e5a), TCO_PPT}, 333 - { PCI_VDEVICE(INTEL, 0x1e5b), TCO_PPT}, 334 - { PCI_VDEVICE(INTEL, 0x1e5c), TCO_PPT}, 335 - { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT}, 336 - { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT}, 337 - { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT}, 338 - { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT}, 339 - { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT}, 340 - { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT}, 341 - { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT}, 342 - { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT}, 343 - { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT}, 344 - { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT}, 345 - { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT}, 346 - { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT}, 347 - { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT}, 348 - { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT}, 349 - { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT}, 350 - { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT}, 351 - { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT}, 352 - { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT}, 353 - { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT}, 354 - { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT}, 355 - { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT}, 356 - { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT}, 357 - { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT}, 358 - { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT}, 359 - { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT}, 360 - { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT}, 361 - { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT}, 362 - { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT}, 363 - { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT}, 364 - { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT}, 365 - { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT}, 366 - { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT}, 367 - { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT}, 368 - { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT}, 369 - { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT}, 370 - { 0, }, /* End of list */ 371 - }; 372 - MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); 373 - 374 74 /* Address definitions for the TCO */ 375 75 /* TCO base address */ 376 - #define TCOBASE (iTCO_wdt_private.ACPIBASE + 0x60) 76 + #define TCOBASE (iTCO_wdt_private.tco_res->start) 377 77 /* SMI Control and Enable Register */ 378 - #define SMI_EN (iTCO_wdt_private.ACPIBASE + 0x30) 78 + #define SMI_EN (iTCO_wdt_private.smi_res->start) 379 79 380 80 #define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */ 381 81 #define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */ ··· 93 393 static struct { /* this is private data for the iTCO_wdt device */ 94 394 /* TCO version/generation */ 95 395 unsigned int iTCO_version; 96 - /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ 97 - unsigned long ACPIBASE; 396 + struct resource *tco_res; 397 + struct resource *smi_res; 398 + struct resource *gcs_res; 98 399 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ 99 400 unsigned long __iomem *gcs; 100 401 /* the lock for io operations */ 101 402 spinlock_t io_lock; 403 + struct platform_device *dev; 102 404 /* the PCI-device */ 103 405 struct pci_dev *pdev; 104 406 } iTCO_wdt_private; 105 - 106 - /* the watchdog platform device */ 107 - static struct platform_device *iTCO_wdt_platform_device; 108 407 109 408 /* module parameters */ 110 409 #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ ··· 184 485 185 486 spin_lock(&iTCO_wdt_private.io_lock); 186 487 187 - iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat); 488 + iTCO_vendor_pre_start(iTCO_wdt_private.smi_res, heartbeat); 188 489 189 490 /* disable chipset's NO_REBOOT bit */ 190 491 if (iTCO_wdt_unset_NO_REBOOT_bit()) { ··· 218 519 219 520 spin_lock(&iTCO_wdt_private.io_lock); 220 521 221 - iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE); 522 + iTCO_vendor_pre_stop(iTCO_wdt_private.smi_res); 222 523 223 524 /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ 224 525 val = inw(TCO1_CNT); ··· 240 541 { 241 542 spin_lock(&iTCO_wdt_private.io_lock); 242 543 243 - iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); 544 + iTCO_vendor_pre_keepalive(iTCO_wdt_private.smi_res, heartbeat); 244 545 245 546 /* Reload the timer by writing to the TCO Timer Counter register */ 246 547 if (iTCO_wdt_private.iTCO_version == 2) ··· 485 786 * Init & exit routines 486 787 */ 487 788 488 - static int __devinit iTCO_wdt_init(struct pci_dev *pdev, 489 - const struct pci_device_id *ent, struct platform_device *dev) 789 + static void __devexit iTCO_wdt_cleanup(void) 490 790 { 491 - int ret; 492 - u32 base_address; 493 - unsigned long RCBA; 791 + /* Stop the timer before we leave */ 792 + if (!nowayout) 793 + iTCO_wdt_stop(); 794 + 795 + /* Deregister */ 796 + misc_deregister(&iTCO_wdt_miscdev); 797 + 798 + /* release resources */ 799 + release_region(iTCO_wdt_private.tco_res->start, 800 + resource_size(iTCO_wdt_private.tco_res)); 801 + release_region(iTCO_wdt_private.smi_res->start, 802 + resource_size(iTCO_wdt_private.smi_res)); 803 + if (iTCO_wdt_private.iTCO_version == 2) { 804 + iounmap(iTCO_wdt_private.gcs); 805 + release_mem_region(iTCO_wdt_private.gcs_res->start, 806 + resource_size(iTCO_wdt_private.gcs_res)); 807 + } 808 + 809 + iTCO_wdt_private.tco_res = NULL; 810 + iTCO_wdt_private.smi_res = NULL; 811 + iTCO_wdt_private.gcs_res = NULL; 812 + iTCO_wdt_private.gcs = NULL; 813 + } 814 + 815 + static int __devinit iTCO_wdt_probe(struct platform_device *dev) 816 + { 817 + int ret = -ENODEV; 494 818 unsigned long val32; 819 + struct lpc_ich_info *ich_info = dev->dev.platform_data; 820 + 821 + if (!ich_info) 822 + goto out; 823 + 824 + spin_lock_init(&iTCO_wdt_private.io_lock); 825 + 826 + iTCO_wdt_private.tco_res = 827 + platform_get_resource(dev, IORESOURCE_IO, ICH_RES_IO_TCO); 828 + if (!iTCO_wdt_private.tco_res) 829 + goto out; 830 + 831 + iTCO_wdt_private.smi_res = 832 + platform_get_resource(dev, IORESOURCE_IO, ICH_RES_IO_SMI); 833 + if (!iTCO_wdt_private.smi_res) 834 + goto out; 835 + 836 + iTCO_wdt_private.iTCO_version = ich_info->iTCO_version; 837 + iTCO_wdt_private.dev = dev; 838 + iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent); 495 839 496 840 /* 497 - * Find the ACPI/PM base I/O address which is the base 498 - * for the TCO registers (TCOBASE=ACPIBASE + 0x60) 499 - * ACPIBASE is bits [15:7] from 0x40-0x43 841 + * Get the Memory-Mapped GCS register, we need it for the 842 + * NO_REBOOT flag (TCO v2). 500 843 */ 501 - pci_read_config_dword(pdev, 0x40, &base_address); 502 - base_address &= 0x0000ff80; 503 - if (base_address == 0x00000000) { 504 - /* Something's wrong here, ACPIBASE has to be set */ 505 - pr_err("failed to get TCOBASE address, device disabled by hardware/BIOS\n"); 506 - return -ENODEV; 507 - } 508 - iTCO_wdt_private.iTCO_version = 509 - iTCO_chipset_info[ent->driver_data].iTCO_version; 510 - iTCO_wdt_private.ACPIBASE = base_address; 511 - iTCO_wdt_private.pdev = pdev; 512 - 513 - /* Get the Memory-Mapped GCS register, we need it for the 514 - NO_REBOOT flag (TCO v2). To get access to it you have to 515 - read RCBA from PCI Config space 0xf0 and use it as base. 516 - GCS = RCBA + ICH6_GCS(0x3410). */ 517 844 if (iTCO_wdt_private.iTCO_version == 2) { 518 - pci_read_config_dword(pdev, 0xf0, &base_address); 519 - if ((base_address & 1) == 0) { 520 - pr_err("RCBA is disabled by hardware/BIOS, device disabled\n"); 521 - ret = -ENODEV; 845 + iTCO_wdt_private.gcs_res = platform_get_resource(dev, 846 + IORESOURCE_MEM, 847 + ICH_RES_MEM_GCS); 848 + 849 + if (!iTCO_wdt_private.gcs_res) 850 + goto out; 851 + 852 + if (!request_mem_region(iTCO_wdt_private.gcs_res->start, 853 + resource_size(iTCO_wdt_private.gcs_res), dev->name)) { 854 + ret = -EBUSY; 522 855 goto out; 523 856 } 524 - RCBA = base_address & 0xffffc000; 525 - iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); 857 + iTCO_wdt_private.gcs = ioremap(iTCO_wdt_private.gcs_res->start, 858 + resource_size(iTCO_wdt_private.gcs_res)); 859 + if (!iTCO_wdt_private.gcs) { 860 + ret = -EIO; 861 + goto unreg_gcs; 862 + } 526 863 } 527 864 528 865 /* Check chipset's NO_REBOOT bit */ 529 866 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { 530 867 pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); 531 868 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ 532 - goto out_unmap; 869 + goto unmap_gcs; 533 870 } 534 871 535 872 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ 536 873 iTCO_wdt_set_NO_REBOOT_bit(); 537 874 538 875 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 539 - if (!request_region(SMI_EN, 4, "iTCO_wdt")) { 540 - pr_err("I/O address 0x%04lx already in use, device disabled\n", 876 + if (!request_region(iTCO_wdt_private.smi_res->start, 877 + resource_size(iTCO_wdt_private.smi_res), dev->name)) { 878 + pr_err("I/O address 0x%04llx already in use, device disabled\n", 541 879 SMI_EN); 542 - ret = -EIO; 543 - goto out_unmap; 880 + ret = -EBUSY; 881 + goto unmap_gcs; 544 882 } 545 883 if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) { 546 - /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ 884 + /* 885 + * Bit 13: TCO_EN -> 0 886 + * Disables TCO logic generating an SMI# 887 + */ 547 888 val32 = inl(SMI_EN); 548 889 val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ 549 890 outl(val32, SMI_EN); 550 891 } 551 892 552 - /* The TCO I/O registers reside in a 32-byte range pointed to 553 - by the TCOBASE value */ 554 - if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { 555 - pr_err("I/O address 0x%04lx already in use, device disabled\n", 893 + if (!request_region(iTCO_wdt_private.tco_res->start, 894 + resource_size(iTCO_wdt_private.tco_res), dev->name)) { 895 + pr_err("I/O address 0x%04llx already in use, device disabled\n", 556 896 TCOBASE); 557 - ret = -EIO; 558 - goto unreg_smi_en; 897 + ret = -EBUSY; 898 + goto unreg_smi; 559 899 } 560 900 561 - pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n", 562 - iTCO_chipset_info[ent->driver_data].name, 563 - iTCO_chipset_info[ent->driver_data].iTCO_version, 564 - TCOBASE); 901 + pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n", 902 + ich_info->name, ich_info->iTCO_version, TCOBASE); 565 903 566 904 /* Clear out the (probably old) status */ 567 905 outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ ··· 619 883 if (ret != 0) { 620 884 pr_err("cannot register miscdev on minor=%d (err=%d)\n", 621 885 WATCHDOG_MINOR, ret); 622 - goto unreg_region; 886 + goto unreg_tco; 623 887 } 624 888 625 889 pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n", ··· 627 891 628 892 return 0; 629 893 630 - unreg_region: 631 - release_region(TCOBASE, 0x20); 632 - unreg_smi_en: 633 - release_region(SMI_EN, 4); 634 - out_unmap: 894 + unreg_tco: 895 + release_region(iTCO_wdt_private.tco_res->start, 896 + resource_size(iTCO_wdt_private.tco_res)); 897 + unreg_smi: 898 + release_region(iTCO_wdt_private.smi_res->start, 899 + resource_size(iTCO_wdt_private.smi_res)); 900 + unmap_gcs: 635 901 if (iTCO_wdt_private.iTCO_version == 2) 636 902 iounmap(iTCO_wdt_private.gcs); 903 + unreg_gcs: 904 + if (iTCO_wdt_private.iTCO_version == 2) 905 + release_mem_region(iTCO_wdt_private.gcs_res->start, 906 + resource_size(iTCO_wdt_private.gcs_res)); 637 907 out: 638 - iTCO_wdt_private.ACPIBASE = 0; 639 - return ret; 640 - } 641 - 642 - static void __devexit iTCO_wdt_cleanup(void) 643 - { 644 - /* Stop the timer before we leave */ 645 - if (!nowayout) 646 - iTCO_wdt_stop(); 647 - 648 - /* Deregister */ 649 - misc_deregister(&iTCO_wdt_miscdev); 650 - release_region(TCOBASE, 0x20); 651 - release_region(SMI_EN, 4); 652 - if (iTCO_wdt_private.iTCO_version == 2) 653 - iounmap(iTCO_wdt_private.gcs); 654 - pci_dev_put(iTCO_wdt_private.pdev); 655 - iTCO_wdt_private.ACPIBASE = 0; 656 - } 657 - 658 - static int __devinit iTCO_wdt_probe(struct platform_device *dev) 659 - { 660 - int ret = -ENODEV; 661 - int found = 0; 662 - struct pci_dev *pdev = NULL; 663 - const struct pci_device_id *ent; 664 - 665 - spin_lock_init(&iTCO_wdt_private.io_lock); 666 - 667 - for_each_pci_dev(pdev) { 668 - ent = pci_match_id(iTCO_wdt_pci_tbl, pdev); 669 - if (ent) { 670 - found++; 671 - ret = iTCO_wdt_init(pdev, ent, dev); 672 - if (!ret) 673 - break; 674 - } 675 - } 676 - 677 - if (!found) 678 - pr_info("No device detected\n"); 908 + iTCO_wdt_private.tco_res = NULL; 909 + iTCO_wdt_private.smi_res = NULL; 910 + iTCO_wdt_private.gcs_res = NULL; 911 + iTCO_wdt_private.gcs = NULL; 679 912 680 913 return ret; 681 914 } 682 915 683 916 static int __devexit iTCO_wdt_remove(struct platform_device *dev) 684 917 { 685 - if (iTCO_wdt_private.ACPIBASE) 918 + if (iTCO_wdt_private.tco_res || iTCO_wdt_private.smi_res) 686 919 iTCO_wdt_cleanup(); 687 920 688 921 return 0; ··· 682 977 if (err) 683 978 return err; 684 979 685 - iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, 686 - -1, NULL, 0); 687 - if (IS_ERR(iTCO_wdt_platform_device)) { 688 - err = PTR_ERR(iTCO_wdt_platform_device); 689 - goto unreg_platform_driver; 690 - } 691 - 692 980 return 0; 693 - 694 - unreg_platform_driver: 695 - platform_driver_unregister(&iTCO_wdt_driver); 696 - return err; 697 981 } 698 982 699 983 static void __exit iTCO_wdt_cleanup_module(void) 700 984 { 701 - platform_device_unregister(iTCO_wdt_platform_device); 702 985 platform_driver_unregister(&iTCO_wdt_driver); 703 986 pr_info("Watchdog Module Unloaded\n"); 704 987 }
+7
include/linux/mfd/lpc_ich.h
··· 20 20 #ifndef LPC_ICH_H 21 21 #define LPC_ICH_H 22 22 23 + /* Watchdog resources */ 24 + #define ICH_RES_IO_TCO 0 25 + #define ICH_RES_IO_SMI 1 26 + #define ICH_RES_MEM_OFF 2 27 + #define ICH_RES_MEM_GCS 0 28 + 23 29 /* GPIO resources */ 24 30 #define ICH_RES_GPIO 0 25 31 #define ICH_RES_GPE0 1 ··· 41 35 42 36 struct lpc_ich_info { 43 37 char name[32]; 38 + unsigned int iTCO_version; 44 39 unsigned int gpio_version; 45 40 }; 46 41