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