1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * sp5100_tco : TCO timer driver for sp5100 chipsets 4 * 5 * (c) Copyright 2009 Google Inc., All Rights Reserved. 6 * 7 * Based on i8xx_tco.c: 8 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights 9 * Reserved. 10 * https://www.kernelconcepts.de 11 * 12 * See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide", 13 * AMD Publication 44413 "AMD SP5100 Register Reference Guide" 14 * AMD Publication 45482 "AMD SB800-Series Southbridges Register 15 * Reference Guide" 16 * AMD Publication 48751 "BIOS and Kernel Developer’s Guide (BKDG) 17 * for AMD Family 16h Models 00h-0Fh Processors" 18 * AMD Publication 51192 "AMD Bolton FCH Register Reference Guide" 19 * AMD Publication 52740 "BIOS and Kernel Developer’s Guide (BKDG) 20 * for AMD Family 16h Models 30h-3Fh Processors" 21 * AMD Publication 55570-B1-PUB "Processor Programming Reference (PPR) 22 * for AMD Family 17h Model 18h, Revision B1 23 * Processors (PUB) 24 * AMD Publication 55772-A1-PUB "Processor Programming Reference (PPR) 25 * for AMD Family 17h Model 20h, Revision A1 26 * Processors (PUB) 27 */ 28 29 /* 30 * Includes, defines, variables, module parameters, ... 31 */ 32 33 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 34 35 #include <linux/init.h> 36 #include <linux/io.h> 37 #include <linux/ioport.h> 38 #include <linux/module.h> 39 #include <linux/moduleparam.h> 40 #include <linux/pci.h> 41 #include <linux/platform_device.h> 42 #include <linux/types.h> 43 #include <linux/watchdog.h> 44 45 #include "sp5100_tco.h" 46 47 #define TCO_DRIVER_NAME "sp5100-tco" 48 49 /* internal variables */ 50 51 enum tco_reg_layout { 52 sp5100, sb800, efch, efch_mmio 53 }; 54 55 struct sp5100_tco { 56 struct watchdog_device wdd; 57 void __iomem *tcobase; 58 enum tco_reg_layout tco_reg_layout; 59 }; 60 61 /* the watchdog platform device */ 62 static struct platform_device *sp5100_tco_platform_device; 63 /* the associated PCI device */ 64 static struct pci_dev *sp5100_tco_pci; 65 66 /* module parameters */ 67 68 #define WATCHDOG_ACTION 0 69 static bool action = WATCHDOG_ACTION; 70 module_param(action, bool, 0); 71 MODULE_PARM_DESC(action, "Action taken when watchdog expires, 0 to reset, 1 to poweroff (default=" 72 __MODULE_STRING(WATCHDOG_ACTION) ")"); 73 74 #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat. */ 75 static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 76 module_param(heartbeat, int, 0); 77 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default=" 78 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 79 80 static bool nowayout = WATCHDOG_NOWAYOUT; 81 module_param(nowayout, bool, 0); 82 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started." 83 " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 84 85 /* 86 * Some TCO specific functions 87 */ 88 89 static enum tco_reg_layout tco_reg_layout(struct pci_dev *dev) 90 { 91 if (dev->vendor == PCI_VENDOR_ID_ATI && 92 dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && 93 dev->revision < 0x40) { 94 return sp5100; 95 } else if (dev->vendor == PCI_VENDOR_ID_AMD && 96 sp5100_tco_pci->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS && 97 sp5100_tco_pci->revision >= AMD_ZEN_SMBUS_PCI_REV) { 98 return efch_mmio; 99 } else if (dev->vendor == PCI_VENDOR_ID_AMD && 100 ((dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && 101 dev->revision >= 0x41) || 102 (dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS && 103 dev->revision >= 0x49))) { 104 return efch; 105 } 106 return sb800; 107 } 108 109 static int tco_timer_start(struct watchdog_device *wdd) 110 { 111 struct sp5100_tco *tco = watchdog_get_drvdata(wdd); 112 u32 val; 113 114 val = readl(SP5100_WDT_CONTROL(tco->tcobase)); 115 val |= SP5100_WDT_START_STOP_BIT; 116 writel(val, SP5100_WDT_CONTROL(tco->tcobase)); 117 118 return 0; 119 } 120 121 static int tco_timer_stop(struct watchdog_device *wdd) 122 { 123 struct sp5100_tco *tco = watchdog_get_drvdata(wdd); 124 u32 val; 125 126 val = readl(SP5100_WDT_CONTROL(tco->tcobase)); 127 val &= ~SP5100_WDT_START_STOP_BIT; 128 writel(val, SP5100_WDT_CONTROL(tco->tcobase)); 129 130 return 0; 131 } 132 133 static int tco_timer_ping(struct watchdog_device *wdd) 134 { 135 struct sp5100_tco *tco = watchdog_get_drvdata(wdd); 136 u32 val; 137 138 val = readl(SP5100_WDT_CONTROL(tco->tcobase)); 139 val |= SP5100_WDT_TRIGGER_BIT; 140 writel(val, SP5100_WDT_CONTROL(tco->tcobase)); 141 142 return 0; 143 } 144 145 static int tco_timer_set_timeout(struct watchdog_device *wdd, 146 unsigned int t) 147 { 148 struct sp5100_tco *tco = watchdog_get_drvdata(wdd); 149 150 /* Write new heartbeat to watchdog */ 151 writel(t, SP5100_WDT_COUNT(tco->tcobase)); 152 153 wdd->timeout = t; 154 155 return 0; 156 } 157 158 static unsigned int tco_timer_get_timeleft(struct watchdog_device *wdd) 159 { 160 struct sp5100_tco *tco = watchdog_get_drvdata(wdd); 161 162 return readl(SP5100_WDT_COUNT(tco->tcobase)); 163 } 164 165 static u8 sp5100_tco_read_pm_reg8(u8 index) 166 { 167 outb(index, SP5100_IO_PM_INDEX_REG); 168 return inb(SP5100_IO_PM_DATA_REG); 169 } 170 171 static void sp5100_tco_update_pm_reg8(u8 index, u8 reset, u8 set) 172 { 173 u8 val; 174 175 outb(index, SP5100_IO_PM_INDEX_REG); 176 val = inb(SP5100_IO_PM_DATA_REG); 177 val &= reset; 178 val |= set; 179 outb(val, SP5100_IO_PM_DATA_REG); 180 } 181 182 static void tco_timer_enable(struct sp5100_tco *tco) 183 { 184 u32 val; 185 186 switch (tco->tco_reg_layout) { 187 case sb800: 188 /* For SB800 or later */ 189 /* Set the Watchdog timer resolution to 1 sec */ 190 sp5100_tco_update_pm_reg8(SB800_PM_WATCHDOG_CONFIG, 191 0xff, SB800_PM_WATCHDOG_SECOND_RES); 192 193 /* Enable watchdog decode bit and watchdog timer */ 194 sp5100_tco_update_pm_reg8(SB800_PM_WATCHDOG_CONTROL, 195 ~SB800_PM_WATCHDOG_DISABLE, 196 SB800_PCI_WATCHDOG_DECODE_EN); 197 break; 198 case sp5100: 199 /* For SP5100 or SB7x0 */ 200 /* Enable watchdog decode bit */ 201 pci_read_config_dword(sp5100_tco_pci, 202 SP5100_PCI_WATCHDOG_MISC_REG, 203 &val); 204 205 val |= SP5100_PCI_WATCHDOG_DECODE_EN; 206 207 pci_write_config_dword(sp5100_tco_pci, 208 SP5100_PCI_WATCHDOG_MISC_REG, 209 val); 210 211 /* Enable Watchdog timer and set the resolution to 1 sec */ 212 sp5100_tco_update_pm_reg8(SP5100_PM_WATCHDOG_CONTROL, 213 ~SP5100_PM_WATCHDOG_DISABLE, 214 SP5100_PM_WATCHDOG_SECOND_RES); 215 break; 216 case efch: 217 /* Set the Watchdog timer resolution to 1 sec and enable */ 218 sp5100_tco_update_pm_reg8(EFCH_PM_DECODEEN3, 219 ~EFCH_PM_WATCHDOG_DISABLE, 220 EFCH_PM_DECODEEN_SECOND_RES); 221 break; 222 default: 223 break; 224 } 225 } 226 227 static u32 sp5100_tco_read_pm_reg32(u8 index) 228 { 229 u32 val = 0; 230 int i; 231 232 for (i = 3; i >= 0; i--) 233 val = (val << 8) + sp5100_tco_read_pm_reg8(index + i); 234 235 return val; 236 } 237 238 static u32 sp5100_tco_request_region(struct device *dev, 239 u32 mmio_addr, 240 const char *dev_name) 241 { 242 if (!devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE, 243 dev_name)) { 244 dev_dbg(dev, "MMIO address 0x%08x already in use\n", mmio_addr); 245 return 0; 246 } 247 248 return mmio_addr; 249 } 250 251 static u32 sp5100_tco_prepare_base(struct sp5100_tco *tco, 252 u32 mmio_addr, 253 u32 alt_mmio_addr, 254 const char *dev_name) 255 { 256 struct device *dev = tco->wdd.parent; 257 258 dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n", mmio_addr); 259 260 if (!mmio_addr && !alt_mmio_addr) 261 return -ENODEV; 262 263 /* Check for MMIO address and alternate MMIO address conflicts */ 264 if (mmio_addr) 265 mmio_addr = sp5100_tco_request_region(dev, mmio_addr, dev_name); 266 267 if (!mmio_addr && alt_mmio_addr) 268 mmio_addr = sp5100_tco_request_region(dev, alt_mmio_addr, dev_name); 269 270 if (!mmio_addr) { 271 dev_err(dev, "Failed to reserve MMIO or alternate MMIO region\n"); 272 return -EBUSY; 273 } 274 275 tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE); 276 if (!tco->tcobase) { 277 dev_err(dev, "MMIO address 0x%08x failed mapping\n", mmio_addr); 278 devm_release_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE); 279 return -ENOMEM; 280 } 281 282 dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr); 283 284 return 0; 285 } 286 287 static int sp5100_tco_timer_init(struct sp5100_tco *tco) 288 { 289 struct watchdog_device *wdd = &tco->wdd; 290 struct device *dev = wdd->parent; 291 u32 val; 292 293 val = readl(SP5100_WDT_CONTROL(tco->tcobase)); 294 if (val & SP5100_WDT_DISABLED) { 295 dev_err(dev, "Watchdog hardware is disabled\n"); 296 return -ENODEV; 297 } 298 299 /* 300 * Save WatchDogFired status, because WatchDogFired flag is 301 * cleared here. 302 */ 303 if (val & SP5100_WDT_FIRED) 304 wdd->bootstatus = WDIOF_CARDRESET; 305 306 /* Set watchdog action */ 307 if (action) 308 val |= SP5100_WDT_ACTION_RESET; 309 else 310 val &= ~SP5100_WDT_ACTION_RESET; 311 writel(val, SP5100_WDT_CONTROL(tco->tcobase)); 312 313 /* Set a reasonable heartbeat before we stop the timer */ 314 tco_timer_set_timeout(wdd, wdd->timeout); 315 316 /* 317 * Stop the TCO before we change anything so we don't race with 318 * a zeroed timer. 319 */ 320 tco_timer_stop(wdd); 321 322 return 0; 323 } 324 325 static u8 efch_read_pm_reg8(void __iomem *addr, u8 index) 326 { 327 return readb(addr + index); 328 } 329 330 static void efch_update_pm_reg8(void __iomem *addr, u8 index, u8 reset, u8 set) 331 { 332 u8 val; 333 334 val = readb(addr + index); 335 val &= reset; 336 val |= set; 337 writeb(val, addr + index); 338 } 339 340 static void tco_timer_enable_mmio(void __iomem *addr) 341 { 342 efch_update_pm_reg8(addr, EFCH_PM_DECODEEN3, 343 ~EFCH_PM_WATCHDOG_DISABLE, 344 EFCH_PM_DECODEEN_SECOND_RES); 345 } 346 347 static int sp5100_tco_setupdevice_mmio(struct device *dev, 348 struct watchdog_device *wdd) 349 { 350 struct sp5100_tco *tco = watchdog_get_drvdata(wdd); 351 const char *dev_name = SB800_DEVNAME; 352 u32 mmio_addr = 0, alt_mmio_addr = 0; 353 struct resource *res; 354 void __iomem *addr; 355 int ret; 356 u32 val; 357 358 res = request_mem_region_muxed(EFCH_PM_ACPI_MMIO_PM_ADDR, 359 EFCH_PM_ACPI_MMIO_PM_SIZE, 360 "sp5100_tco"); 361 362 if (!res) { 363 dev_err(dev, 364 "Memory region 0x%08x already in use\n", 365 EFCH_PM_ACPI_MMIO_PM_ADDR); 366 return -EBUSY; 367 } 368 369 addr = ioremap(EFCH_PM_ACPI_MMIO_PM_ADDR, EFCH_PM_ACPI_MMIO_PM_SIZE); 370 if (!addr) { 371 dev_err(dev, "Address mapping failed\n"); 372 ret = -ENOMEM; 373 goto out; 374 } 375 376 /* 377 * EFCH_PM_DECODEEN_WDT_TMREN is dual purpose. This bitfield 378 * enables sp5100_tco register MMIO space decoding. The bitfield 379 * also starts the timer operation. Enable if not already enabled. 380 */ 381 val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN); 382 if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) { 383 efch_update_pm_reg8(addr, EFCH_PM_DECODEEN, 0xff, 384 EFCH_PM_DECODEEN_WDT_TMREN); 385 } 386 387 /* Error if the timer could not be enabled */ 388 val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN); 389 if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) { 390 dev_err(dev, "Failed to enable the timer\n"); 391 ret = -EFAULT; 392 goto out; 393 } 394 395 mmio_addr = EFCH_PM_WDT_ADDR; 396 397 /* Determine alternate MMIO base address */ 398 val = efch_read_pm_reg8(addr, EFCH_PM_ISACONTROL); 399 if (val & EFCH_PM_ISACONTROL_MMIOEN) 400 alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR + 401 EFCH_PM_ACPI_MMIO_WDT_OFFSET; 402 403 ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name); 404 if (!ret) { 405 tco_timer_enable_mmio(addr); 406 ret = sp5100_tco_timer_init(tco); 407 } 408 409 out: 410 if (addr) 411 iounmap(addr); 412 413 release_resource(res); 414 kfree(res); 415 416 return ret; 417 } 418 419 static int sp5100_tco_setupdevice(struct device *dev, 420 struct watchdog_device *wdd) 421 { 422 struct sp5100_tco *tco = watchdog_get_drvdata(wdd); 423 const char *dev_name; 424 u32 mmio_addr = 0, val; 425 u32 alt_mmio_addr = 0; 426 int ret; 427 428 if (tco->tco_reg_layout == efch_mmio) 429 return sp5100_tco_setupdevice_mmio(dev, wdd); 430 431 /* Request the IO ports used by this driver */ 432 if (!request_muxed_region(SP5100_IO_PM_INDEX_REG, 433 SP5100_PM_IOPORTS_SIZE, "sp5100_tco")) { 434 dev_err(dev, "I/O address 0x%04x already in use\n", 435 SP5100_IO_PM_INDEX_REG); 436 return -EBUSY; 437 } 438 439 /* 440 * Determine type of southbridge chipset. 441 */ 442 switch (tco->tco_reg_layout) { 443 case sp5100: 444 dev_name = SP5100_DEVNAME; 445 mmio_addr = sp5100_tco_read_pm_reg32(SP5100_PM_WATCHDOG_BASE) & 446 0xfffffff8; 447 448 /* 449 * Secondly, find the watchdog timer MMIO address 450 * from SBResource_MMIO register. 451 */ 452 453 /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */ 454 pci_read_config_dword(sp5100_tco_pci, 455 SP5100_SB_RESOURCE_MMIO_BASE, 456 &val); 457 458 /* Verify MMIO is enabled and using bar0 */ 459 if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN) 460 alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET; 461 break; 462 case sb800: 463 dev_name = SB800_DEVNAME; 464 mmio_addr = sp5100_tco_read_pm_reg32(SB800_PM_WATCHDOG_BASE) & 465 0xfffffff8; 466 467 /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */ 468 val = sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN); 469 470 /* Verify MMIO is enabled and using bar0 */ 471 if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN) 472 alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET; 473 break; 474 case efch: 475 dev_name = SB800_DEVNAME; 476 val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN); 477 if (val & EFCH_PM_DECODEEN_WDT_TMREN) 478 mmio_addr = EFCH_PM_WDT_ADDR; 479 480 val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL); 481 if (val & EFCH_PM_ISACONTROL_MMIOEN) 482 alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR + 483 EFCH_PM_ACPI_MMIO_WDT_OFFSET; 484 break; 485 default: 486 return -ENODEV; 487 } 488 489 ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name); 490 if (!ret) { 491 /* Setup the watchdog timer */ 492 tco_timer_enable(tco); 493 ret = sp5100_tco_timer_init(tco); 494 } 495 496 release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE); 497 return ret; 498 } 499 500 static struct watchdog_info sp5100_tco_wdt_info = { 501 .identity = "SP5100 TCO timer", 502 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 503 }; 504 505 static const struct watchdog_ops sp5100_tco_wdt_ops = { 506 .owner = THIS_MODULE, 507 .start = tco_timer_start, 508 .stop = tco_timer_stop, 509 .ping = tco_timer_ping, 510 .set_timeout = tco_timer_set_timeout, 511 .get_timeleft = tco_timer_get_timeleft, 512 }; 513 514 static int sp5100_tco_probe(struct platform_device *pdev) 515 { 516 struct device *dev = &pdev->dev; 517 struct watchdog_device *wdd; 518 struct sp5100_tco *tco; 519 int ret; 520 521 tco = devm_kzalloc(dev, sizeof(*tco), GFP_KERNEL); 522 if (!tco) 523 return -ENOMEM; 524 525 tco->tco_reg_layout = tco_reg_layout(sp5100_tco_pci); 526 527 wdd = &tco->wdd; 528 wdd->parent = dev; 529 wdd->info = &sp5100_tco_wdt_info; 530 wdd->ops = &sp5100_tco_wdt_ops; 531 wdd->timeout = WATCHDOG_HEARTBEAT; 532 wdd->min_timeout = 1; 533 wdd->max_timeout = 0xffff; 534 535 watchdog_init_timeout(wdd, heartbeat, NULL); 536 watchdog_set_nowayout(wdd, nowayout); 537 watchdog_stop_on_reboot(wdd); 538 watchdog_stop_on_unregister(wdd); 539 watchdog_set_drvdata(wdd, tco); 540 541 ret = sp5100_tco_setupdevice(dev, wdd); 542 if (ret) 543 return ret; 544 545 ret = devm_watchdog_register_device(dev, wdd); 546 if (ret) 547 return ret; 548 549 /* Show module parameters */ 550 dev_info(dev, "initialized. heartbeat=%d sec (nowayout=%d)\n", 551 wdd->timeout, nowayout); 552 553 return 0; 554 } 555 556 static struct platform_driver sp5100_tco_driver = { 557 .probe = sp5100_tco_probe, 558 .driver = { 559 .name = TCO_DRIVER_NAME, 560 }, 561 }; 562 563 /* 564 * Data for PCI driver interface 565 * 566 * This data only exists for exporting the supported 567 * PCI ids via MODULE_DEVICE_TABLE. We do not actually 568 * register a pci_driver, because someone else might 569 * want to register another driver on the same PCI id. 570 */ 571 static const struct pci_device_id sp5100_tco_pci_tbl[] = { 572 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID, 573 PCI_ANY_ID, }, 574 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID, 575 PCI_ANY_ID, }, 576 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, PCI_ANY_ID, 577 PCI_ANY_ID, }, 578 { 0, }, /* End of list */ 579 }; 580 MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl); 581 582 static int __init sp5100_tco_init(void) 583 { 584 struct pci_dev *dev = NULL; 585 int err; 586 587 /* Match the PCI device */ 588 for_each_pci_dev(dev) { 589 if (pci_match_id(sp5100_tco_pci_tbl, dev) != NULL) { 590 sp5100_tco_pci = dev; 591 break; 592 } 593 } 594 595 if (!sp5100_tco_pci) 596 return -ENODEV; 597 598 pr_info("SP5100/SB800 TCO WatchDog Timer Driver\n"); 599 600 err = platform_driver_register(&sp5100_tco_driver); 601 if (err) 602 return err; 603 604 sp5100_tco_platform_device = 605 platform_device_register_simple(TCO_DRIVER_NAME, -1, NULL, 0); 606 if (IS_ERR(sp5100_tco_platform_device)) { 607 err = PTR_ERR(sp5100_tco_platform_device); 608 goto unreg_platform_driver; 609 } 610 611 return 0; 612 613 unreg_platform_driver: 614 platform_driver_unregister(&sp5100_tco_driver); 615 return err; 616 } 617 618 static void __exit sp5100_tco_exit(void) 619 { 620 platform_device_unregister(sp5100_tco_platform_device); 621 platform_driver_unregister(&sp5100_tco_driver); 622 } 623 624 module_init(sp5100_tco_init); 625 module_exit(sp5100_tco_exit); 626 627 MODULE_AUTHOR("Priyanka Gupta"); 628 MODULE_DESCRIPTION("TCO timer driver for SP5100/SB800 chipset"); 629 MODULE_LICENSE("GPL"); 630