diff options
author | H Hartley Sweeten <hsweeten@visionengravers.com> | 2017-01-31 11:33:29 -0500 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2017-02-24 17:00:23 -0500 |
commit | 917003610d178b8bc3cbc63ee9fd203a7b01c444 (patch) | |
tree | 8b277b40845ca84b13a02b10f284f567fa6e9157 | |
parent | 8751f90c819c156befc630d467adbc003bd59d87 (diff) |
watchdog: ep93xx_wdt: cleanup and let the core handle the heartbeat
Cleanup this driver and remove the 200ms heartbeat timer. The core now
has the ability to handle the heartbeat.
Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
[groeck: Dropped 0-initialization of static variable]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/watchdog/ep93xx_wdt.c | 114 |
1 files changed, 44 insertions, 70 deletions
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 8a6e1a7c63ae..f9b14e6efd9a 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c | |||
@@ -19,21 +19,13 @@ | |||
19 | * for us to rely on the user space daemon alone. So we ping the | 19 | * for us to rely on the user space daemon alone. So we ping the |
20 | * wdt each ~200msec and eventually stop doing it if the user space | 20 | * wdt each ~200msec and eventually stop doing it if the user space |
21 | * daemon dies. | 21 | * daemon dies. |
22 | * | ||
23 | * TODO: | ||
24 | * | ||
25 | * - Test last reset from watchdog status | ||
26 | * - Add a few missing ioctls | ||
27 | */ | 22 | */ |
28 | 23 | ||
29 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
30 | #include <linux/module.h> | 25 | #include <linux/module.h> |
31 | #include <linux/watchdog.h> | 26 | #include <linux/watchdog.h> |
32 | #include <linux/timer.h> | ||
33 | #include <linux/io.h> | 27 | #include <linux/io.h> |
34 | 28 | ||
35 | #define WDT_VERSION "0.4" | ||
36 | |||
37 | /* default timeout (secs) */ | 29 | /* default timeout (secs) */ |
38 | #define WDT_TIMEOUT 30 | 30 | #define WDT_TIMEOUT 30 |
39 | 31 | ||
@@ -41,59 +33,48 @@ static bool nowayout = WATCHDOG_NOWAYOUT; | |||
41 | module_param(nowayout, bool, 0); | 33 | module_param(nowayout, bool, 0); |
42 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | 34 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); |
43 | 35 | ||
44 | static unsigned int timeout = WDT_TIMEOUT; | 36 | static unsigned int timeout; |
45 | module_param(timeout, uint, 0); | 37 | module_param(timeout, uint, 0); |
46 | MODULE_PARM_DESC(timeout, | 38 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds."); |
47 | "Watchdog timeout in seconds. (1<=timeout<=3600, default=" | ||
48 | __MODULE_STRING(WDT_TIMEOUT) ")"); | ||
49 | |||
50 | static void __iomem *mmio_base; | ||
51 | static struct timer_list timer; | ||
52 | static unsigned long next_heartbeat; | ||
53 | 39 | ||
54 | #define EP93XX_WATCHDOG 0x00 | 40 | #define EP93XX_WATCHDOG 0x00 |
55 | #define EP93XX_WDSTATUS 0x04 | 41 | #define EP93XX_WDSTATUS 0x04 |
56 | 42 | ||
57 | /* reset the wdt every ~200ms - the heartbeat of the device is 0.250 seconds*/ | 43 | struct ep93xx_wdt_priv { |
58 | #define WDT_INTERVAL (HZ/5) | 44 | void __iomem *mmio; |
59 | 45 | struct watchdog_device wdd; | |
60 | static void ep93xx_wdt_timer_ping(unsigned long data) | 46 | }; |
61 | { | ||
62 | if (time_before(jiffies, next_heartbeat)) | ||
63 | writel(0x5555, mmio_base + EP93XX_WATCHDOG); | ||
64 | |||
65 | /* Re-set the timer interval */ | ||
66 | mod_timer(&timer, jiffies + WDT_INTERVAL); | ||
67 | } | ||
68 | 47 | ||
69 | static int ep93xx_wdt_start(struct watchdog_device *wdd) | 48 | static int ep93xx_wdt_start(struct watchdog_device *wdd) |
70 | { | 49 | { |
71 | next_heartbeat = jiffies + (timeout * HZ); | 50 | struct ep93xx_wdt_priv *priv = watchdog_get_drvdata(wdd); |
72 | 51 | ||
73 | writel(0xaaaa, mmio_base + EP93XX_WATCHDOG); | 52 | writel(0xaaaa, priv->mmio + EP93XX_WATCHDOG); |
74 | mod_timer(&timer, jiffies + WDT_INTERVAL); | ||
75 | 53 | ||
76 | return 0; | 54 | return 0; |
77 | } | 55 | } |
78 | 56 | ||
79 | static int ep93xx_wdt_stop(struct watchdog_device *wdd) | 57 | static int ep93xx_wdt_stop(struct watchdog_device *wdd) |
80 | { | 58 | { |
81 | del_timer_sync(&timer); | 59 | struct ep93xx_wdt_priv *priv = watchdog_get_drvdata(wdd); |
82 | writel(0xaa55, mmio_base + EP93XX_WATCHDOG); | 60 | |
61 | writel(0xaa55, priv->mmio + EP93XX_WATCHDOG); | ||
83 | 62 | ||
84 | return 0; | 63 | return 0; |
85 | } | 64 | } |
86 | 65 | ||
87 | static int ep93xx_wdt_keepalive(struct watchdog_device *wdd) | 66 | static int ep93xx_wdt_ping(struct watchdog_device *wdd) |
88 | { | 67 | { |
89 | /* user land ping */ | 68 | struct ep93xx_wdt_priv *priv = watchdog_get_drvdata(wdd); |
90 | next_heartbeat = jiffies + (timeout * HZ); | 69 | |
70 | writel(0x5555, priv->mmio + EP93XX_WATCHDOG); | ||
91 | 71 | ||
92 | return 0; | 72 | return 0; |
93 | } | 73 | } |
94 | 74 | ||
95 | static const struct watchdog_info ep93xx_wdt_ident = { | 75 | static const struct watchdog_info ep93xx_wdt_ident = { |
96 | .options = WDIOF_CARDRESET | | 76 | .options = WDIOF_CARDRESET | |
77 | WDIOF_SETTIMEOUT | | ||
97 | WDIOF_MAGICCLOSE | | 78 | WDIOF_MAGICCLOSE | |
98 | WDIOF_KEEPALIVEPING, | 79 | WDIOF_KEEPALIVEPING, |
99 | .identity = "EP93xx Watchdog", | 80 | .identity = "EP93xx Watchdog", |
@@ -103,55 +84,50 @@ static const struct watchdog_ops ep93xx_wdt_ops = { | |||
103 | .owner = THIS_MODULE, | 84 | .owner = THIS_MODULE, |
104 | .start = ep93xx_wdt_start, | 85 | .start = ep93xx_wdt_start, |
105 | .stop = ep93xx_wdt_stop, | 86 | .stop = ep93xx_wdt_stop, |
106 | .ping = ep93xx_wdt_keepalive, | 87 | .ping = ep93xx_wdt_ping, |
107 | }; | ||
108 | |||
109 | static struct watchdog_device ep93xx_wdt_wdd = { | ||
110 | .info = &ep93xx_wdt_ident, | ||
111 | .ops = &ep93xx_wdt_ops, | ||
112 | }; | 88 | }; |
113 | 89 | ||
114 | static int ep93xx_wdt_probe(struct platform_device *pdev) | 90 | static int ep93xx_wdt_probe(struct platform_device *pdev) |
115 | { | 91 | { |
92 | struct ep93xx_wdt_priv *priv; | ||
93 | struct watchdog_device *wdd; | ||
116 | struct resource *res; | 94 | struct resource *res; |
117 | unsigned long val; | 95 | unsigned long val; |
118 | int err; | 96 | int ret; |
97 | |||
98 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
99 | if (!priv) | ||
100 | return -ENOMEM; | ||
119 | 101 | ||
120 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 102 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
121 | mmio_base = devm_ioremap_resource(&pdev->dev, res); | 103 | priv->mmio = devm_ioremap_resource(&pdev->dev, res); |
122 | if (IS_ERR(mmio_base)) | 104 | if (IS_ERR(priv->mmio)) |
123 | return PTR_ERR(mmio_base); | 105 | return PTR_ERR(priv->mmio); |
124 | 106 | ||
125 | if (timeout < 1 || timeout > 3600) { | 107 | val = readl(priv->mmio + EP93XX_WATCHDOG); |
126 | timeout = WDT_TIMEOUT; | ||
127 | dev_warn(&pdev->dev, | ||
128 | "timeout value must be 1<=x<=3600, using %d\n", | ||
129 | timeout); | ||
130 | } | ||
131 | 108 | ||
132 | val = readl(mmio_base + EP93XX_WATCHDOG); | 109 | wdd = &priv->wdd; |
133 | ep93xx_wdt_wdd.bootstatus = (val & 0x01) ? WDIOF_CARDRESET : 0; | 110 | wdd->bootstatus = (val & 0x01) ? WDIOF_CARDRESET : 0; |
134 | ep93xx_wdt_wdd.timeout = timeout; | 111 | wdd->info = &ep93xx_wdt_ident; |
135 | ep93xx_wdt_wdd.parent = &pdev->dev; | 112 | wdd->ops = &ep93xx_wdt_ops; |
113 | wdd->min_timeout = 1; | ||
114 | wdd->max_hw_heartbeat_ms = 200; | ||
115 | wdd->parent = &pdev->dev; | ||
136 | 116 | ||
137 | watchdog_set_nowayout(&ep93xx_wdt_wdd, nowayout); | 117 | watchdog_set_nowayout(wdd, nowayout); |
138 | 118 | ||
139 | setup_timer(&timer, ep93xx_wdt_timer_ping, 1); | 119 | wdd->timeout = WDT_TIMEOUT; |
120 | watchdog_init_timeout(wdd, timeout, &pdev->dev); | ||
140 | 121 | ||
141 | err = watchdog_register_device(&ep93xx_wdt_wdd); | 122 | watchdog_set_drvdata(wdd, priv); |
142 | if (err) | ||
143 | return err; | ||
144 | 123 | ||
145 | dev_info(&pdev->dev, | 124 | ret = devm_watchdog_register_device(&pdev->dev, wdd); |
146 | "EP93XX watchdog, driver version " WDT_VERSION "%s\n", | 125 | if (ret) |
147 | (val & 0x08) ? " (nCS1 disable detected)" : ""); | 126 | return ret; |
148 | 127 | ||
149 | return 0; | 128 | dev_info(&pdev->dev, "EP93XX watchdog driver %s\n", |
150 | } | 129 | (val & 0x08) ? " (nCS1 disable detected)" : ""); |
151 | 130 | ||
152 | static int ep93xx_wdt_remove(struct platform_device *pdev) | ||
153 | { | ||
154 | watchdog_unregister_device(&ep93xx_wdt_wdd); | ||
155 | return 0; | 131 | return 0; |
156 | } | 132 | } |
157 | 133 | ||
@@ -160,7 +136,6 @@ static struct platform_driver ep93xx_wdt_driver = { | |||
160 | .name = "ep93xx-wdt", | 136 | .name = "ep93xx-wdt", |
161 | }, | 137 | }, |
162 | .probe = ep93xx_wdt_probe, | 138 | .probe = ep93xx_wdt_probe, |
163 | .remove = ep93xx_wdt_remove, | ||
164 | }; | 139 | }; |
165 | 140 | ||
166 | module_platform_driver(ep93xx_wdt_driver); | 141 | module_platform_driver(ep93xx_wdt_driver); |
@@ -170,4 +145,3 @@ MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | |||
170 | MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); | 145 | MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); |
171 | MODULE_DESCRIPTION("EP93xx Watchdog"); | 146 | MODULE_DESCRIPTION("EP93xx Watchdog"); |
172 | MODULE_LICENSE("GPL"); | 147 | MODULE_LICENSE("GPL"); |
173 | MODULE_VERSION(WDT_VERSION); | ||