1 // SPDX-License-Identifier: GPL-2.0+
3 * Watchdog driver for TQMx86 PLD.
5 * The watchdog supports power of 2 timeouts from 1 to 4096sec.
6 * Once started, it cannot be stopped.
8 * Based on the vendor code written by Vadim V.Vlasov
9 * <vvlasov@dev.rtsoft.ru>
13 #include <linux/log2.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/timer.h>
17 #include <linux/watchdog.h>
19 /* default timeout (secs) */
20 #define WDT_TIMEOUT 32
22 static unsigned int timeout
;
23 module_param(timeout
, uint
, 0);
24 MODULE_PARM_DESC(timeout
,
25 "Watchdog timeout in seconds. (1<=timeout<=4096, default="
26 __MODULE_STRING(WDT_TIMEOUT
) ")");
28 struct watchdog_device wdd
;
29 void __iomem
*io_base
;
32 #define TQMX86_WDCFG 0x00 /* Watchdog Configuration Register */
33 #define TQMX86_WDCS 0x01 /* Watchdog Config/Status Register */
35 static int tqmx86_wdt_start(struct watchdog_device
*wdd
)
37 struct tqmx86_wdt
*priv
= watchdog_get_drvdata(wdd
);
39 iowrite8(0x81, priv
->io_base
+ TQMX86_WDCS
);
44 static int tqmx86_wdt_set_timeout(struct watchdog_device
*wdd
, unsigned int t
)
46 struct tqmx86_wdt
*priv
= watchdog_get_drvdata(wdd
);
49 t
= roundup_pow_of_two(t
);
50 val
= ilog2(t
) | 0x90;
51 val
+= 3; /* values 0,1,2 correspond to 0.125,0.25,0.5s timeouts */
52 iowrite8(val
, priv
->io_base
+ TQMX86_WDCFG
);
59 static const struct watchdog_info tqmx86_wdt_info
= {
60 .options
= WDIOF_SETTIMEOUT
|
62 .identity
= "TQMx86 Watchdog",
65 static struct watchdog_ops tqmx86_wdt_ops
= {
67 .start
= tqmx86_wdt_start
,
68 .set_timeout
= tqmx86_wdt_set_timeout
,
71 static int tqmx86_wdt_probe(struct platform_device
*pdev
)
73 struct device
*dev
= &pdev
->dev
;
74 struct tqmx86_wdt
*priv
;
78 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
82 res
= platform_get_resource(pdev
, IORESOURCE_IO
, 0);
86 priv
->io_base
= devm_ioport_map(dev
, res
->start
, resource_size(res
));
90 watchdog_set_drvdata(&priv
->wdd
, priv
);
92 priv
->wdd
.parent
= dev
;
93 priv
->wdd
.info
= &tqmx86_wdt_info
;
94 priv
->wdd
.ops
= &tqmx86_wdt_ops
;
95 priv
->wdd
.min_timeout
= 1;
96 priv
->wdd
.max_timeout
= 4096;
97 priv
->wdd
.max_hw_heartbeat_ms
= 4096*1000;
98 priv
->wdd
.timeout
= WDT_TIMEOUT
;
100 watchdog_init_timeout(&priv
->wdd
, timeout
, dev
);
101 watchdog_set_nowayout(&priv
->wdd
, WATCHDOG_NOWAYOUT
);
103 tqmx86_wdt_set_timeout(&priv
->wdd
, priv
->wdd
.timeout
);
105 err
= devm_watchdog_register_device(dev
, &priv
->wdd
);
109 dev_info(dev
, "TQMx86 watchdog\n");
114 static struct platform_driver tqmx86_wdt_driver
= {
116 .name
= "tqmx86-wdt",
118 .probe
= tqmx86_wdt_probe
,
121 module_platform_driver(tqmx86_wdt_driver
);
123 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
124 MODULE_DESCRIPTION("TQMx86 Watchdog");
125 MODULE_ALIAS("platform:tqmx86-wdt");
126 MODULE_LICENSE("GPL");