1 // SPDX-License-Identifier: GPL-2.0-only
3 * Watchdog driver for Cirrus Logic EP93xx family of devices.
5 * Copyright (c) 2004 Ray Lehtiniemi
6 * Copyright (c) 2006 Tower Technologies
7 * Based on ep93xx driver, bits from alim7101_wdt.c
9 * Authors: Ray Lehtiniemi <rayl@mail.com>,
10 * Alessandro Zummo <a.zummo@towertech.it>
12 * Copyright (c) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
13 * Convert to a platform device and use the watchdog framework API
15 * This watchdog fires after 250msec, which is a too short interval
16 * for us to rely on the user space daemon alone. So we ping the
17 * wdt each ~200msec and eventually stop doing it if the user space
21 #include <linux/platform_device.h>
22 #include <linux/module.h>
23 #include <linux/watchdog.h>
26 /* default timeout (secs) */
27 #define WDT_TIMEOUT 30
29 static bool nowayout
= WATCHDOG_NOWAYOUT
;
30 module_param(nowayout
, bool, 0);
31 MODULE_PARM_DESC(nowayout
, "Watchdog cannot be stopped once started");
33 static unsigned int timeout
;
34 module_param(timeout
, uint
, 0);
35 MODULE_PARM_DESC(timeout
, "Watchdog timeout in seconds.");
37 #define EP93XX_WATCHDOG 0x00
38 #define EP93XX_WDSTATUS 0x04
40 struct ep93xx_wdt_priv
{
42 struct watchdog_device wdd
;
45 static int ep93xx_wdt_start(struct watchdog_device
*wdd
)
47 struct ep93xx_wdt_priv
*priv
= watchdog_get_drvdata(wdd
);
49 writel(0xaaaa, priv
->mmio
+ EP93XX_WATCHDOG
);
54 static int ep93xx_wdt_stop(struct watchdog_device
*wdd
)
56 struct ep93xx_wdt_priv
*priv
= watchdog_get_drvdata(wdd
);
58 writel(0xaa55, priv
->mmio
+ EP93XX_WATCHDOG
);
63 static int ep93xx_wdt_ping(struct watchdog_device
*wdd
)
65 struct ep93xx_wdt_priv
*priv
= watchdog_get_drvdata(wdd
);
67 writel(0x5555, priv
->mmio
+ EP93XX_WATCHDOG
);
72 static const struct watchdog_info ep93xx_wdt_ident
= {
73 .options
= WDIOF_CARDRESET
|
77 .identity
= "EP93xx Watchdog",
80 static const struct watchdog_ops ep93xx_wdt_ops
= {
82 .start
= ep93xx_wdt_start
,
83 .stop
= ep93xx_wdt_stop
,
84 .ping
= ep93xx_wdt_ping
,
87 static int ep93xx_wdt_probe(struct platform_device
*pdev
)
89 struct device
*dev
= &pdev
->dev
;
90 struct ep93xx_wdt_priv
*priv
;
91 struct watchdog_device
*wdd
;
95 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
99 priv
->mmio
= devm_platform_ioremap_resource(pdev
, 0);
100 if (IS_ERR(priv
->mmio
))
101 return PTR_ERR(priv
->mmio
);
103 val
= readl(priv
->mmio
+ EP93XX_WATCHDOG
);
106 wdd
->bootstatus
= (val
& 0x01) ? WDIOF_CARDRESET
: 0;
107 wdd
->info
= &ep93xx_wdt_ident
;
108 wdd
->ops
= &ep93xx_wdt_ops
;
109 wdd
->min_timeout
= 1;
110 wdd
->max_hw_heartbeat_ms
= 200;
113 watchdog_set_nowayout(wdd
, nowayout
);
115 wdd
->timeout
= WDT_TIMEOUT
;
116 watchdog_init_timeout(wdd
, timeout
, dev
);
118 watchdog_set_drvdata(wdd
, priv
);
120 ret
= devm_watchdog_register_device(dev
, wdd
);
124 dev_info(dev
, "EP93XX watchdog driver %s\n",
125 (val
& 0x08) ? " (nCS1 disable detected)" : "");
130 static struct platform_driver ep93xx_wdt_driver
= {
132 .name
= "ep93xx-wdt",
134 .probe
= ep93xx_wdt_probe
,
137 module_platform_driver(ep93xx_wdt_driver
);
139 MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>");
140 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
141 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
142 MODULE_DESCRIPTION("EP93xx Watchdog");
143 MODULE_LICENSE("GPL");