47 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
50 #define DRV_NAME "iTCO_wdt"
51 #define DRV_VERSION "1.10"
54 #include <linux/module.h>
56 #include <linux/types.h>
57 #include <linux/errno.h>
58 #include <linux/kernel.h>
61 #include <linux/watchdog.h>
65 #include <linux/pci.h>
77 #define TCOBASE (iTCO_wdt_private.tco_res->start)
79 #define SMI_EN (iTCO_wdt_private.smi_res->start)
81 #define TCO_RLD (TCOBASE + 0x00)
82 #define TCOv1_TMR (TCOBASE + 0x01)
83 #define TCO_DAT_IN (TCOBASE + 0x02)
84 #define TCO_DAT_OUT (TCOBASE + 0x03)
85 #define TCO1_STS (TCOBASE + 0x04)
86 #define TCO2_STS (TCOBASE + 0x06)
87 #define TCO1_CNT (TCOBASE + 0x08)
88 #define TCO2_CNT (TCOBASE + 0x0a)
89 #define TCOv2_TMR (TCOBASE + 0x12)
108 #define WATCHDOG_TIMEOUT 30
112 "5..76 (TCO v1) or 3..614 (TCO v2), default="
118 "Watchdog cannot be stopped once started (default="
121 static int turn_SMI_watchdog_clear_off = 1;
124 "Turn off SMI clearing watchdog (depends on TCO-version)(default=1)");
130 static inline unsigned int seconds_to_ticks(
int seconds)
134 return (seconds * 10) / 6;
137 static void iTCO_wdt_set_NO_REBOOT_bit(
void)
142 if (iTCO_wdt_private.iTCO_version == 2) {
143 val32 =
readl(iTCO_wdt_private.gcs);
145 writel(val32, iTCO_wdt_private.gcs);
146 }
else if (iTCO_wdt_private.iTCO_version == 1) {
147 pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
149 pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
153 static int iTCO_wdt_unset_NO_REBOOT_bit(
void)
159 if (iTCO_wdt_private.iTCO_version == 2) {
160 val32 =
readl(iTCO_wdt_private.gcs);
162 writel(val32, iTCO_wdt_private.gcs);
164 val32 =
readl(iTCO_wdt_private.gcs);
165 if (val32 & 0x00000020)
167 }
else if (iTCO_wdt_private.iTCO_version == 1) {
168 pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
170 pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
172 pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
173 if (val32 & 0x00000002)
184 spin_lock(&iTCO_wdt_private.io_lock);
189 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
190 spin_unlock(&iTCO_wdt_private.io_lock);
191 pr_err(
"failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
197 if (iTCO_wdt_private.iTCO_version == 2)
199 else if (iTCO_wdt_private.iTCO_version == 1)
207 spin_unlock(&iTCO_wdt_private.io_lock);
218 spin_lock(&iTCO_wdt_private.io_lock);
229 iTCO_wdt_set_NO_REBOOT_bit();
231 spin_unlock(&iTCO_wdt_private.io_lock);
233 if ((val & 0x0800) == 0)
240 spin_lock(&iTCO_wdt_private.io_lock);
245 if (iTCO_wdt_private.iTCO_version == 2)
247 else if (iTCO_wdt_private.iTCO_version == 1) {
255 spin_unlock(&iTCO_wdt_private.io_lock);
259 static int iTCO_wdt_set_timeout(
struct watchdog_device *wd_dev,
unsigned int t)
265 tmrval = seconds_to_ticks(t);
268 if (iTCO_wdt_private.iTCO_version == 1)
275 if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
276 ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
282 if (iTCO_wdt_private.iTCO_version == 2) {
283 spin_lock(&iTCO_wdt_private.io_lock);
289 spin_unlock(&iTCO_wdt_private.io_lock);
291 if ((val16 & 0x3ff) != tmrval)
293 }
else if (iTCO_wdt_private.iTCO_version == 1) {
294 spin_lock(&iTCO_wdt_private.io_lock);
297 val8 |= (tmrval & 0xff);
300 spin_unlock(&iTCO_wdt_private.io_lock);
302 if ((val8 & 0x3f) != tmrval)
310 static unsigned int iTCO_wdt_get_timeleft(
struct watchdog_device *wd_dev)
314 unsigned int time_left = 0;
317 if (iTCO_wdt_private.iTCO_version == 2) {
318 spin_lock(&iTCO_wdt_private.io_lock);
321 spin_unlock(&iTCO_wdt_private.io_lock);
323 time_left = (val16 * 6) / 10;
324 }
else if (iTCO_wdt_private.iTCO_version == 1) {
325 spin_lock(&iTCO_wdt_private.io_lock);
330 spin_unlock(&iTCO_wdt_private.io_lock);
332 time_left = (val8 * 6) / 10;
345 .firmware_version = 0,
351 .start = iTCO_wdt_start,
352 .stop = iTCO_wdt_stop,
353 .ping = iTCO_wdt_ping,
354 .set_timeout = iTCO_wdt_set_timeout,
355 .get_timeleft = iTCO_wdt_get_timeleft,
360 .ops = &iTCO_wdt_ops,
367 static void __devexit iTCO_wdt_cleanup(
void)
371 iTCO_wdt_stop(&iTCO_wdt_watchdog_dev);
378 resource_size(iTCO_wdt_private.tco_res));
380 resource_size(iTCO_wdt_private.smi_res));
381 if (iTCO_wdt_private.iTCO_version == 2) {
384 resource_size(iTCO_wdt_private.gcs_res));
387 iTCO_wdt_private.tco_res =
NULL;
388 iTCO_wdt_private.smi_res =
NULL;
389 iTCO_wdt_private.gcs_res =
NULL;
390 iTCO_wdt_private.gcs =
NULL;
404 iTCO_wdt_private.tco_res =
406 if (!iTCO_wdt_private.tco_res)
409 iTCO_wdt_private.smi_res =
411 if (!iTCO_wdt_private.smi_res)
415 iTCO_wdt_private.dev =
dev;
422 if (iTCO_wdt_private.iTCO_version == 2) {
427 if (!iTCO_wdt_private.gcs_res)
431 resource_size(iTCO_wdt_private.gcs_res), dev->
name)) {
435 iTCO_wdt_private.gcs =
ioremap(iTCO_wdt_private.gcs_res->start,
436 resource_size(iTCO_wdt_private.gcs_res));
437 if (!iTCO_wdt_private.gcs) {
445 pr_info(
"unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
451 iTCO_wdt_set_NO_REBOOT_bit();
455 resource_size(iTCO_wdt_private.smi_res), dev->
name)) {
456 pr_err(
"I/O address 0x%04llx already in use, device disabled\n",
461 if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) {
472 resource_size(iTCO_wdt_private.tco_res), dev->
name)) {
473 pr_err(
"I/O address 0x%04llx already in use, device disabled\n",
479 pr_info(
"Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n",
489 watchdog_set_nowayout(&iTCO_wdt_watchdog_dev, nowayout);
490 iTCO_wdt_watchdog_dev.
parent = dev->
dev.parent;
493 iTCO_wdt_stop(&iTCO_wdt_watchdog_dev);
497 if (iTCO_wdt_set_timeout(&iTCO_wdt_watchdog_dev,
heartbeat)) {
499 pr_info(
"timeout value out of range, using %d\n",
505 pr_err(
"cannot register watchdog device (err=%d)\n", ret);
509 pr_info(
"initialized. heartbeat=%d sec (nowayout=%d)\n",
516 resource_size(iTCO_wdt_private.tco_res));
519 resource_size(iTCO_wdt_private.smi_res));
521 if (iTCO_wdt_private.iTCO_version == 2)
524 if (iTCO_wdt_private.iTCO_version == 2)
526 resource_size(iTCO_wdt_private.gcs_res));
528 iTCO_wdt_private.tco_res =
NULL;
529 iTCO_wdt_private.smi_res =
NULL;
530 iTCO_wdt_private.gcs_res =
NULL;
531 iTCO_wdt_private.gcs =
NULL;
538 if (iTCO_wdt_private.tco_res || iTCO_wdt_private.smi_res)
550 .probe = iTCO_wdt_probe,
552 .shutdown = iTCO_wdt_shutdown,
559 static int __init iTCO_wdt_init_module(
void)
572 static void __exit iTCO_wdt_cleanup_module(
void)
575 pr_info(
"Watchdog Module Unloaded\n");