1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * sp5100_tco : TCO timer driver for sp5100 chipsets
5 * (c) Copyright 2009 Google Inc., All Rights Reserved.
8 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights
10 * https://www.kernelconcepts.de
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
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
24 * AMD Publication 55772-A1-PUB "Processor Programming Reference (PPR)
25 * for AMD Family 17h Model 20h, Revision A1
30 * Includes, defines, variables, module parameters, ...
33 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
35 #include <linux/init.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>
45 #include "sp5100_tco.h"
47 #define TCO_DRIVER_NAME "sp5100-tco"
49 /* internal variables */
52 sp5100
, sb800
, efch
, efch_mmio
56 struct watchdog_device wdd
;
57 void __iomem
*tcobase
;
58 enum tco_reg_layout tco_reg_layout
;
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
;
66 /* module parameters */
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
) ")");
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
) ")");
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
) ")");
86 * Some TCO specific functions
89 static enum tco_reg_layout
tco_reg_layout(struct pci_dev
*dev
)
91 if (dev
->vendor
== PCI_VENDOR_ID_ATI
&&
92 dev
->device
== PCI_DEVICE_ID_ATI_SBX00_SMBUS
&&
93 dev
->revision
< 0x40) {
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
) {
99 } else if ((dev
->vendor
== PCI_VENDOR_ID_AMD
|| dev
->vendor
== PCI_VENDOR_ID_HYGON
) &&
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))) {
109 static int tco_timer_start(struct watchdog_device
*wdd
)
111 struct sp5100_tco
*tco
= watchdog_get_drvdata(wdd
);
114 val
= readl(SP5100_WDT_CONTROL(tco
->tcobase
));
115 val
|= SP5100_WDT_START_STOP_BIT
;
116 writel(val
, SP5100_WDT_CONTROL(tco
->tcobase
));
118 /* This must be a distinct write. */
119 val
|= SP5100_WDT_TRIGGER_BIT
;
120 writel(val
, SP5100_WDT_CONTROL(tco
->tcobase
));
125 static int tco_timer_stop(struct watchdog_device
*wdd
)
127 struct sp5100_tco
*tco
= watchdog_get_drvdata(wdd
);
130 val
= readl(SP5100_WDT_CONTROL(tco
->tcobase
));
131 val
&= ~SP5100_WDT_START_STOP_BIT
;
132 writel(val
, SP5100_WDT_CONTROL(tco
->tcobase
));
137 static int tco_timer_ping(struct watchdog_device
*wdd
)
139 struct sp5100_tco
*tco
= watchdog_get_drvdata(wdd
);
142 val
= readl(SP5100_WDT_CONTROL(tco
->tcobase
));
143 val
|= SP5100_WDT_TRIGGER_BIT
;
144 writel(val
, SP5100_WDT_CONTROL(tco
->tcobase
));
149 static int tco_timer_set_timeout(struct watchdog_device
*wdd
,
152 struct sp5100_tco
*tco
= watchdog_get_drvdata(wdd
);
154 /* Write new heartbeat to watchdog */
155 writel(t
, SP5100_WDT_COUNT(tco
->tcobase
));
162 static unsigned int tco_timer_get_timeleft(struct watchdog_device
*wdd
)
164 struct sp5100_tco
*tco
= watchdog_get_drvdata(wdd
);
166 return readl(SP5100_WDT_COUNT(tco
->tcobase
));
169 static u8
sp5100_tco_read_pm_reg8(u8 index
)
171 outb(index
, SP5100_IO_PM_INDEX_REG
);
172 return inb(SP5100_IO_PM_DATA_REG
);
175 static void sp5100_tco_update_pm_reg8(u8 index
, u8 reset
, u8 set
)
179 outb(index
, SP5100_IO_PM_INDEX_REG
);
180 val
= inb(SP5100_IO_PM_DATA_REG
);
183 outb(val
, SP5100_IO_PM_DATA_REG
);
186 static void tco_timer_enable(struct sp5100_tco
*tco
)
190 switch (tco
->tco_reg_layout
) {
192 /* For SB800 or later */
193 /* Set the Watchdog timer resolution to 1 sec */
194 sp5100_tco_update_pm_reg8(SB800_PM_WATCHDOG_CONFIG
,
195 0xff, SB800_PM_WATCHDOG_SECOND_RES
);
197 /* Enable watchdog decode bit and watchdog timer */
198 sp5100_tco_update_pm_reg8(SB800_PM_WATCHDOG_CONTROL
,
199 ~SB800_PM_WATCHDOG_DISABLE
,
200 SB800_PCI_WATCHDOG_DECODE_EN
);
203 /* For SP5100 or SB7x0 */
204 /* Enable watchdog decode bit */
205 pci_read_config_dword(sp5100_tco_pci
,
206 SP5100_PCI_WATCHDOG_MISC_REG
,
209 val
|= SP5100_PCI_WATCHDOG_DECODE_EN
;
211 pci_write_config_dword(sp5100_tco_pci
,
212 SP5100_PCI_WATCHDOG_MISC_REG
,
215 /* Enable Watchdog timer and set the resolution to 1 sec */
216 sp5100_tco_update_pm_reg8(SP5100_PM_WATCHDOG_CONTROL
,
217 ~SP5100_PM_WATCHDOG_DISABLE
,
218 SP5100_PM_WATCHDOG_SECOND_RES
);
221 /* Set the Watchdog timer resolution to 1 sec and enable */
222 sp5100_tco_update_pm_reg8(EFCH_PM_DECODEEN3
,
223 ~EFCH_PM_WATCHDOG_DISABLE
,
224 EFCH_PM_DECODEEN_SECOND_RES
);
231 static u32
sp5100_tco_read_pm_reg32(u8 index
)
236 for (i
= 3; i
>= 0; i
--)
237 val
= (val
<< 8) + sp5100_tco_read_pm_reg8(index
+ i
);
242 static u32
sp5100_tco_request_region(struct device
*dev
,
244 const char *dev_name
)
246 if (!devm_request_mem_region(dev
, mmio_addr
, SP5100_WDT_MEM_MAP_SIZE
,
248 dev_dbg(dev
, "MMIO address 0x%08x already in use\n", mmio_addr
);
255 static u32
sp5100_tco_prepare_base(struct sp5100_tco
*tco
,
258 const char *dev_name
)
260 struct device
*dev
= tco
->wdd
.parent
;
262 dev_dbg(dev
, "Got 0x%08x from SBResource_MMIO register\n", mmio_addr
);
264 if (!mmio_addr
&& !alt_mmio_addr
)
267 /* Check for MMIO address and alternate MMIO address conflicts */
269 mmio_addr
= sp5100_tco_request_region(dev
, mmio_addr
, dev_name
);
271 if (!mmio_addr
&& alt_mmio_addr
)
272 mmio_addr
= sp5100_tco_request_region(dev
, alt_mmio_addr
, dev_name
);
275 dev_err(dev
, "Failed to reserve MMIO or alternate MMIO region\n");
279 tco
->tcobase
= devm_ioremap(dev
, mmio_addr
, SP5100_WDT_MEM_MAP_SIZE
);
281 dev_err(dev
, "MMIO address 0x%08x failed mapping\n", mmio_addr
);
282 devm_release_mem_region(dev
, mmio_addr
, SP5100_WDT_MEM_MAP_SIZE
);
286 dev_info(dev
, "Using 0x%08x for watchdog MMIO address\n", mmio_addr
);
291 static int sp5100_tco_timer_init(struct sp5100_tco
*tco
)
293 struct watchdog_device
*wdd
= &tco
->wdd
;
294 struct device
*dev
= wdd
->parent
;
297 val
= readl(SP5100_WDT_CONTROL(tco
->tcobase
));
298 if (val
& SP5100_WDT_DISABLED
) {
299 dev_err(dev
, "Watchdog hardware is disabled\n");
304 * Save WatchDogFired status, because WatchDogFired flag is
307 if (val
& SP5100_WDT_FIRED
)
308 wdd
->bootstatus
= WDIOF_CARDRESET
;
310 /* Set watchdog action */
312 val
|= SP5100_WDT_ACTION_RESET
;
314 val
&= ~SP5100_WDT_ACTION_RESET
;
315 writel(val
, SP5100_WDT_CONTROL(tco
->tcobase
));
317 /* Set a reasonable heartbeat before we stop the timer */
318 tco_timer_set_timeout(wdd
, wdd
->timeout
);
321 * Stop the TCO before we change anything so we don't race with
329 static u8
efch_read_pm_reg8(void __iomem
*addr
, u8 index
)
331 return readb(addr
+ index
);
334 static void efch_update_pm_reg8(void __iomem
*addr
, u8 index
, u8 reset
, u8 set
)
338 val
= readb(addr
+ index
);
341 writeb(val
, addr
+ index
);
344 static void tco_timer_enable_mmio(void __iomem
*addr
)
346 efch_update_pm_reg8(addr
, EFCH_PM_DECODEEN3
,
347 ~EFCH_PM_WATCHDOG_DISABLE
,
348 EFCH_PM_DECODEEN_SECOND_RES
);
351 static int sp5100_tco_setupdevice_mmio(struct device
*dev
,
352 struct watchdog_device
*wdd
)
354 struct sp5100_tco
*tco
= watchdog_get_drvdata(wdd
);
355 const char *dev_name
= SB800_DEVNAME
;
356 u32 mmio_addr
= 0, alt_mmio_addr
= 0;
357 struct resource
*res
;
362 res
= request_mem_region_muxed(EFCH_PM_ACPI_MMIO_PM_ADDR
,
363 EFCH_PM_ACPI_MMIO_PM_SIZE
,
368 "Memory region 0x%08x already in use\n",
369 EFCH_PM_ACPI_MMIO_PM_ADDR
);
373 addr
= ioremap(EFCH_PM_ACPI_MMIO_PM_ADDR
, EFCH_PM_ACPI_MMIO_PM_SIZE
);
375 dev_err(dev
, "Address mapping failed\n");
381 * EFCH_PM_DECODEEN_WDT_TMREN is dual purpose. This bitfield
382 * enables sp5100_tco register MMIO space decoding. The bitfield
383 * also starts the timer operation. Enable if not already enabled.
385 val
= efch_read_pm_reg8(addr
, EFCH_PM_DECODEEN
);
386 if (!(val
& EFCH_PM_DECODEEN_WDT_TMREN
)) {
387 efch_update_pm_reg8(addr
, EFCH_PM_DECODEEN
, 0xff,
388 EFCH_PM_DECODEEN_WDT_TMREN
);
391 /* Error if the timer could not be enabled */
392 val
= efch_read_pm_reg8(addr
, EFCH_PM_DECODEEN
);
393 if (!(val
& EFCH_PM_DECODEEN_WDT_TMREN
)) {
394 dev_err(dev
, "Failed to enable the timer\n");
399 mmio_addr
= EFCH_PM_WDT_ADDR
;
401 /* Determine alternate MMIO base address */
402 val
= efch_read_pm_reg8(addr
, EFCH_PM_ISACONTROL
);
403 if (val
& EFCH_PM_ISACONTROL_MMIOEN
)
404 alt_mmio_addr
= EFCH_PM_ACPI_MMIO_ADDR
+
405 EFCH_PM_ACPI_MMIO_WDT_OFFSET
;
407 ret
= sp5100_tco_prepare_base(tco
, mmio_addr
, alt_mmio_addr
, dev_name
);
409 tco_timer_enable_mmio(addr
);
410 ret
= sp5100_tco_timer_init(tco
);
417 release_resource(res
);
423 static int sp5100_tco_setupdevice(struct device
*dev
,
424 struct watchdog_device
*wdd
)
426 struct sp5100_tco
*tco
= watchdog_get_drvdata(wdd
);
427 const char *dev_name
;
428 u32 mmio_addr
= 0, val
;
429 u32 alt_mmio_addr
= 0;
432 if (tco
->tco_reg_layout
== efch_mmio
)
433 return sp5100_tco_setupdevice_mmio(dev
, wdd
);
435 /* Request the IO ports used by this driver */
436 if (!request_muxed_region(SP5100_IO_PM_INDEX_REG
,
437 SP5100_PM_IOPORTS_SIZE
, "sp5100_tco")) {
438 dev_err(dev
, "I/O address 0x%04x already in use\n",
439 SP5100_IO_PM_INDEX_REG
);
444 * Determine type of southbridge chipset.
446 switch (tco
->tco_reg_layout
) {
448 dev_name
= SP5100_DEVNAME
;
449 mmio_addr
= sp5100_tco_read_pm_reg32(SP5100_PM_WATCHDOG_BASE
) &
453 * Secondly, find the watchdog timer MMIO address
454 * from SBResource_MMIO register.
457 /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
458 pci_read_config_dword(sp5100_tco_pci
,
459 SP5100_SB_RESOURCE_MMIO_BASE
,
462 /* Verify MMIO is enabled and using bar0 */
463 if ((val
& SB800_ACPI_MMIO_MASK
) == SB800_ACPI_MMIO_DECODE_EN
)
464 alt_mmio_addr
= (val
& ~0xfff) + SB800_PM_WDT_MMIO_OFFSET
;
467 dev_name
= SB800_DEVNAME
;
468 mmio_addr
= sp5100_tco_read_pm_reg32(SB800_PM_WATCHDOG_BASE
) &
471 /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
472 val
= sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN
);
474 /* Verify MMIO is enabled and using bar0 */
475 if ((val
& SB800_ACPI_MMIO_MASK
) == SB800_ACPI_MMIO_DECODE_EN
)
476 alt_mmio_addr
= (val
& ~0xfff) + SB800_PM_WDT_MMIO_OFFSET
;
479 dev_name
= SB800_DEVNAME
;
480 val
= sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN
);
481 if (val
& EFCH_PM_DECODEEN_WDT_TMREN
)
482 mmio_addr
= EFCH_PM_WDT_ADDR
;
484 val
= sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL
);
485 if (val
& EFCH_PM_ISACONTROL_MMIOEN
)
486 alt_mmio_addr
= EFCH_PM_ACPI_MMIO_ADDR
+
487 EFCH_PM_ACPI_MMIO_WDT_OFFSET
;
493 ret
= sp5100_tco_prepare_base(tco
, mmio_addr
, alt_mmio_addr
, dev_name
);
495 /* Setup the watchdog timer */
496 tco_timer_enable(tco
);
497 ret
= sp5100_tco_timer_init(tco
);
500 release_region(SP5100_IO_PM_INDEX_REG
, SP5100_PM_IOPORTS_SIZE
);
504 static struct watchdog_info sp5100_tco_wdt_info
= {
505 .identity
= "SP5100 TCO timer",
506 .options
= WDIOF_SETTIMEOUT
| WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
,
509 static const struct watchdog_ops sp5100_tco_wdt_ops
= {
510 .owner
= THIS_MODULE
,
511 .start
= tco_timer_start
,
512 .stop
= tco_timer_stop
,
513 .ping
= tco_timer_ping
,
514 .set_timeout
= tco_timer_set_timeout
,
515 .get_timeleft
= tco_timer_get_timeleft
,
518 static int sp5100_tco_probe(struct platform_device
*pdev
)
520 struct device
*dev
= &pdev
->dev
;
521 struct watchdog_device
*wdd
;
522 struct sp5100_tco
*tco
;
525 tco
= devm_kzalloc(dev
, sizeof(*tco
), GFP_KERNEL
);
529 tco
->tco_reg_layout
= tco_reg_layout(sp5100_tco_pci
);
533 wdd
->info
= &sp5100_tco_wdt_info
;
534 wdd
->ops
= &sp5100_tco_wdt_ops
;
535 wdd
->timeout
= WATCHDOG_HEARTBEAT
;
536 wdd
->min_timeout
= 1;
537 wdd
->max_timeout
= 0xffff;
539 watchdog_init_timeout(wdd
, heartbeat
, NULL
);
540 watchdog_set_nowayout(wdd
, nowayout
);
541 watchdog_stop_on_reboot(wdd
);
542 watchdog_stop_on_unregister(wdd
);
543 watchdog_set_drvdata(wdd
, tco
);
545 ret
= sp5100_tco_setupdevice(dev
, wdd
);
549 ret
= devm_watchdog_register_device(dev
, wdd
);
553 /* Show module parameters */
554 dev_info(dev
, "initialized. heartbeat=%d sec (nowayout=%d)\n",
555 wdd
->timeout
, nowayout
);
560 static struct platform_driver sp5100_tco_driver
= {
561 .probe
= sp5100_tco_probe
,
563 .name
= TCO_DRIVER_NAME
,
568 * Data for PCI driver interface
570 * This data only exists for exporting the supported
571 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
572 * register a pci_driver, because someone else might
573 * want to register another driver on the same PCI id.
575 static const struct pci_device_id sp5100_tco_pci_tbl
[] = {
576 { PCI_VENDOR_ID_ATI
, PCI_DEVICE_ID_ATI_SBX00_SMBUS
, PCI_ANY_ID
,
578 { PCI_VENDOR_ID_AMD
, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS
, PCI_ANY_ID
,
580 { PCI_VENDOR_ID_AMD
, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS
, PCI_ANY_ID
,
582 { PCI_VENDOR_ID_HYGON
, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS
, PCI_ANY_ID
,
584 { 0, }, /* End of list */
586 MODULE_DEVICE_TABLE(pci
, sp5100_tco_pci_tbl
);
588 static int __init
sp5100_tco_init(void)
590 struct pci_dev
*dev
= NULL
;
593 /* Match the PCI device */
594 for_each_pci_dev(dev
) {
595 if (pci_match_id(sp5100_tco_pci_tbl
, dev
) != NULL
) {
596 sp5100_tco_pci
= dev
;
604 pr_info("SP5100/SB800 TCO WatchDog Timer Driver\n");
606 err
= platform_driver_register(&sp5100_tco_driver
);
610 sp5100_tco_platform_device
=
611 platform_device_register_simple(TCO_DRIVER_NAME
, -1, NULL
, 0);
612 if (IS_ERR(sp5100_tco_platform_device
)) {
613 err
= PTR_ERR(sp5100_tco_platform_device
);
614 goto unreg_platform_driver
;
619 unreg_platform_driver
:
620 platform_driver_unregister(&sp5100_tco_driver
);
624 static void __exit
sp5100_tco_exit(void)
626 platform_device_unregister(sp5100_tco_platform_device
);
627 platform_driver_unregister(&sp5100_tco_driver
);
630 module_init(sp5100_tco_init
);
631 module_exit(sp5100_tco_exit
);
633 MODULE_AUTHOR("Priyanka Gupta");
634 MODULE_DESCRIPTION("TCO timer driver for SP5100/SB800 chipset");
635 MODULE_LICENSE("GPL");