2 * Watchdog driver for Technologic Systems TS-72xx based SBCs
3 * (TS-7200, TS-7250 and TS-7260). These boards have external
4 * glue logic CPLD chip, which includes programmable watchdog
7 * Copyright (c) 2009 Mika Westerberg <mika.westerberg@iki.fi>
9 * This driver is based on ep93xx_wdt and wm831x_wdt drivers.
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
16 #include <linux/platform_device.h>
17 #include <linux/module.h>
18 #include <linux/watchdog.h>
21 #define TS72XX_WDT_DEFAULT_TIMEOUT 30
24 module_param(timeout
, int, 0);
25 MODULE_PARM_DESC(timeout
, "Watchdog timeout in seconds.");
27 static bool nowayout
= WATCHDOG_NOWAYOUT
;
28 module_param(nowayout
, bool, 0);
29 MODULE_PARM_DESC(nowayout
, "Disable watchdog shutdown on close");
31 /* priv->control_reg */
32 #define TS72XX_WDT_CTRL_DISABLE 0x00
33 #define TS72XX_WDT_CTRL_250MS 0x01
34 #define TS72XX_WDT_CTRL_500MS 0x02
35 #define TS72XX_WDT_CTRL_1SEC 0x03
36 #define TS72XX_WDT_CTRL_RESERVED 0x04
37 #define TS72XX_WDT_CTRL_2SEC 0x05
38 #define TS72XX_WDT_CTRL_4SEC 0x06
39 #define TS72XX_WDT_CTRL_8SEC 0x07
42 #define TS72XX_WDT_FEED_VAL 0x05
44 struct ts72xx_wdt_priv
{
45 void __iomem
*control_reg
;
46 void __iomem
*feed_reg
;
47 struct watchdog_device wdd
;
51 static int ts72xx_wdt_start(struct watchdog_device
*wdd
)
53 struct ts72xx_wdt_priv
*priv
= watchdog_get_drvdata(wdd
);
55 writeb(TS72XX_WDT_FEED_VAL
, priv
->feed_reg
);
56 writeb(priv
->regval
, priv
->control_reg
);
61 static int ts72xx_wdt_stop(struct watchdog_device
*wdd
)
63 struct ts72xx_wdt_priv
*priv
= watchdog_get_drvdata(wdd
);
65 writeb(TS72XX_WDT_FEED_VAL
, priv
->feed_reg
);
66 writeb(TS72XX_WDT_CTRL_DISABLE
, priv
->control_reg
);
71 static int ts72xx_wdt_ping(struct watchdog_device
*wdd
)
73 struct ts72xx_wdt_priv
*priv
= watchdog_get_drvdata(wdd
);
75 writeb(TS72XX_WDT_FEED_VAL
, priv
->feed_reg
);
80 static int ts72xx_wdt_settimeout(struct watchdog_device
*wdd
, unsigned int to
)
82 struct ts72xx_wdt_priv
*priv
= watchdog_get_drvdata(wdd
);
85 priv
->regval
= TS72XX_WDT_CTRL_1SEC
;
87 priv
->regval
= TS72XX_WDT_CTRL_2SEC
;
89 priv
->regval
= TS72XX_WDT_CTRL_4SEC
;
92 priv
->regval
= TS72XX_WDT_CTRL_8SEC
;
99 if (watchdog_active(wdd
)) {
100 ts72xx_wdt_stop(wdd
);
101 ts72xx_wdt_start(wdd
);
107 static const struct watchdog_info ts72xx_wdt_ident
= {
108 .options
= WDIOF_KEEPALIVEPING
|
111 .firmware_version
= 1,
112 .identity
= "TS-72XX WDT",
115 static const struct watchdog_ops ts72xx_wdt_ops
= {
116 .owner
= THIS_MODULE
,
117 .start
= ts72xx_wdt_start
,
118 .stop
= ts72xx_wdt_stop
,
119 .ping
= ts72xx_wdt_ping
,
120 .set_timeout
= ts72xx_wdt_settimeout
,
123 static int ts72xx_wdt_probe(struct platform_device
*pdev
)
125 struct device
*dev
= &pdev
->dev
;
126 struct ts72xx_wdt_priv
*priv
;
127 struct watchdog_device
*wdd
;
130 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
134 priv
->control_reg
= devm_platform_ioremap_resource(pdev
, 0);
135 if (IS_ERR(priv
->control_reg
))
136 return PTR_ERR(priv
->control_reg
);
138 priv
->feed_reg
= devm_platform_ioremap_resource(pdev
, 1);
139 if (IS_ERR(priv
->feed_reg
))
140 return PTR_ERR(priv
->feed_reg
);
143 wdd
->info
= &ts72xx_wdt_ident
;
144 wdd
->ops
= &ts72xx_wdt_ops
;
145 wdd
->min_timeout
= 1;
146 wdd
->max_hw_heartbeat_ms
= 8000;
149 watchdog_set_nowayout(wdd
, nowayout
);
151 wdd
->timeout
= TS72XX_WDT_DEFAULT_TIMEOUT
;
152 watchdog_init_timeout(wdd
, timeout
, dev
);
154 watchdog_set_drvdata(wdd
, priv
);
156 ret
= devm_watchdog_register_device(dev
, wdd
);
160 dev_info(dev
, "TS-72xx Watchdog driver\n");
165 static struct platform_driver ts72xx_wdt_driver
= {
166 .probe
= ts72xx_wdt_probe
,
168 .name
= "ts72xx-wdt",
172 module_platform_driver(ts72xx_wdt_driver
);
174 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
175 MODULE_DESCRIPTION("TS-72xx SBC Watchdog");
176 MODULE_LICENSE("GPL");
177 MODULE_ALIAS("platform:ts72xx-wdt");