Linux 4.19.133
[linux/fpc-iii.git] / drivers / watchdog / rave-sp-wdt.c
blob35db173252f9fadd1edbf4cabec152535a01af1d
1 // SPDX-License-Identifier: GPL-2.0+
3 /*
4 * Driver for watchdog aspect of for Zodiac Inflight Innovations RAVE
5 * Supervisory Processor(SP) MCU
7 * Copyright (C) 2017 Zodiac Inflight Innovation
9 */
11 #include <linux/delay.h>
12 #include <linux/kernel.h>
13 #include <linux/mfd/rave-sp.h>
14 #include <linux/module.h>
15 #include <linux/nvmem-consumer.h>
16 #include <linux/of_device.h>
17 #include <linux/platform_device.h>
18 #include <linux/reboot.h>
19 #include <linux/slab.h>
20 #include <linux/watchdog.h>
22 enum {
23 RAVE_SP_RESET_BYTE = 1,
24 RAVE_SP_RESET_REASON_NORMAL = 0,
25 RAVE_SP_RESET_DELAY_MS = 500,
28 /**
29 * struct rave_sp_wdt_variant - RAVE SP watchdog variant
31 * @max_timeout: Largest possible watchdog timeout setting
32 * @min_timeout: Smallest possible watchdog timeout setting
34 * @configure: Function to send configuration command
35 * @restart: Function to send "restart" command
37 struct rave_sp_wdt_variant {
38 unsigned int max_timeout;
39 unsigned int min_timeout;
41 int (*configure)(struct watchdog_device *, bool);
42 int (*restart)(struct watchdog_device *);
45 /**
46 * struct rave_sp_wdt - RAVE SP watchdog
48 * @wdd: Underlying watchdog device
49 * @sp: Pointer to parent RAVE SP device
50 * @variant: Device specific variant information
51 * @reboot_notifier: Reboot notifier implementing machine reset
53 struct rave_sp_wdt {
54 struct watchdog_device wdd;
55 struct rave_sp *sp;
56 const struct rave_sp_wdt_variant *variant;
57 struct notifier_block reboot_notifier;
60 static struct rave_sp_wdt *to_rave_sp_wdt(struct watchdog_device *wdd)
62 return container_of(wdd, struct rave_sp_wdt, wdd);
65 static int rave_sp_wdt_exec(struct watchdog_device *wdd, void *data,
66 size_t data_size)
68 return rave_sp_exec(to_rave_sp_wdt(wdd)->sp,
69 data, data_size, NULL, 0);
72 static int rave_sp_wdt_legacy_configure(struct watchdog_device *wdd, bool on)
74 u8 cmd[] = {
75 [0] = RAVE_SP_CMD_SW_WDT,
76 [1] = 0,
77 [2] = 0,
78 [3] = on,
79 [4] = on ? wdd->timeout : 0,
82 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
85 static int rave_sp_wdt_rdu_configure(struct watchdog_device *wdd, bool on)
87 u8 cmd[] = {
88 [0] = RAVE_SP_CMD_SW_WDT,
89 [1] = 0,
90 [2] = on,
91 [3] = (u8)wdd->timeout,
92 [4] = (u8)(wdd->timeout >> 8),
95 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
98 /**
99 * rave_sp_wdt_configure - Configure watchdog device
101 * @wdd: Device to configure
102 * @on: Desired state of the watchdog timer (ON/OFF)
104 * This function configures two aspects of the watchdog timer:
106 * - Wheither it is ON or OFF
107 * - Its timeout duration
109 * with first aspect specified via function argument and second via
110 * the value of 'wdd->timeout'.
112 static int rave_sp_wdt_configure(struct watchdog_device *wdd, bool on)
114 return to_rave_sp_wdt(wdd)->variant->configure(wdd, on);
117 static int rave_sp_wdt_legacy_restart(struct watchdog_device *wdd)
119 u8 cmd[] = {
120 [0] = RAVE_SP_CMD_RESET,
121 [1] = 0,
122 [2] = RAVE_SP_RESET_BYTE
125 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
128 static int rave_sp_wdt_rdu_restart(struct watchdog_device *wdd)
130 u8 cmd[] = {
131 [0] = RAVE_SP_CMD_RESET,
132 [1] = 0,
133 [2] = RAVE_SP_RESET_BYTE,
134 [3] = RAVE_SP_RESET_REASON_NORMAL
137 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
140 static int rave_sp_wdt_reboot_notifier(struct notifier_block *nb,
141 unsigned long action, void *data)
144 * Restart handler is called in atomic context which means we
145 * can't communicate to SP via UART. Luckily for use SP will
146 * wait 500ms before actually resetting us, so we ask it to do
147 * so here and let the rest of the system go on wrapping
148 * things up.
150 if (action == SYS_DOWN || action == SYS_HALT) {
151 struct rave_sp_wdt *sp_wd =
152 container_of(nb, struct rave_sp_wdt, reboot_notifier);
154 const int ret = sp_wd->variant->restart(&sp_wd->wdd);
156 if (ret < 0)
157 dev_err(sp_wd->wdd.parent,
158 "Failed to issue restart command (%d)", ret);
159 return NOTIFY_OK;
162 return NOTIFY_DONE;
165 static int rave_sp_wdt_restart(struct watchdog_device *wdd,
166 unsigned long action, void *data)
169 * The actual work was done by reboot notifier above. SP
170 * firmware waits 500 ms before issuing reset, so let's hang
171 * here for twice that delay and hopefuly we'd never reach
172 * the return statement.
174 mdelay(2 * RAVE_SP_RESET_DELAY_MS);
176 return -EIO;
179 static int rave_sp_wdt_start(struct watchdog_device *wdd)
181 int ret;
183 ret = rave_sp_wdt_configure(wdd, true);
184 if (!ret)
185 set_bit(WDOG_HW_RUNNING, &wdd->status);
187 return ret;
190 static int rave_sp_wdt_stop(struct watchdog_device *wdd)
192 return rave_sp_wdt_configure(wdd, false);
195 static int rave_sp_wdt_set_timeout(struct watchdog_device *wdd,
196 unsigned int timeout)
198 wdd->timeout = timeout;
200 return rave_sp_wdt_configure(wdd, watchdog_active(wdd));
203 static int rave_sp_wdt_ping(struct watchdog_device *wdd)
205 u8 cmd[] = {
206 [0] = RAVE_SP_CMD_PET_WDT,
207 [1] = 0,
210 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
213 static const struct watchdog_info rave_sp_wdt_info = {
214 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
215 .identity = "RAVE SP Watchdog",
218 static const struct watchdog_ops rave_sp_wdt_ops = {
219 .owner = THIS_MODULE,
220 .start = rave_sp_wdt_start,
221 .stop = rave_sp_wdt_stop,
222 .ping = rave_sp_wdt_ping,
223 .set_timeout = rave_sp_wdt_set_timeout,
224 .restart = rave_sp_wdt_restart,
227 static const struct rave_sp_wdt_variant rave_sp_wdt_legacy = {
228 .max_timeout = 255,
229 .min_timeout = 1,
230 .configure = rave_sp_wdt_legacy_configure,
231 .restart = rave_sp_wdt_legacy_restart,
234 static const struct rave_sp_wdt_variant rave_sp_wdt_rdu = {
235 .max_timeout = 180,
236 .min_timeout = 60,
237 .configure = rave_sp_wdt_rdu_configure,
238 .restart = rave_sp_wdt_rdu_restart,
241 static const struct of_device_id rave_sp_wdt_of_match[] = {
243 .compatible = "zii,rave-sp-watchdog-legacy",
244 .data = &rave_sp_wdt_legacy,
247 .compatible = "zii,rave-sp-watchdog",
248 .data = &rave_sp_wdt_rdu,
250 { /* sentinel */ }
253 static int rave_sp_wdt_probe(struct platform_device *pdev)
255 struct device *dev = &pdev->dev;
256 struct watchdog_device *wdd;
257 struct rave_sp_wdt *sp_wd;
258 struct nvmem_cell *cell;
259 __le16 timeout = 0;
260 int ret;
262 sp_wd = devm_kzalloc(dev, sizeof(*sp_wd), GFP_KERNEL);
263 if (!sp_wd)
264 return -ENOMEM;
266 sp_wd->variant = of_device_get_match_data(dev);
267 sp_wd->sp = dev_get_drvdata(dev->parent);
269 wdd = &sp_wd->wdd;
270 wdd->parent = dev;
271 wdd->info = &rave_sp_wdt_info;
272 wdd->ops = &rave_sp_wdt_ops;
273 wdd->min_timeout = sp_wd->variant->min_timeout;
274 wdd->max_timeout = sp_wd->variant->max_timeout;
275 wdd->status = WATCHDOG_NOWAYOUT_INIT_STATUS;
276 wdd->timeout = 60;
278 cell = nvmem_cell_get(dev, "wdt-timeout");
279 if (!IS_ERR(cell)) {
280 size_t len;
281 void *value = nvmem_cell_read(cell, &len);
283 if (!IS_ERR(value)) {
284 memcpy(&timeout, value, min(len, sizeof(timeout)));
285 kfree(value);
287 nvmem_cell_put(cell);
289 watchdog_init_timeout(wdd, le16_to_cpu(timeout), dev);
290 watchdog_set_restart_priority(wdd, 255);
291 watchdog_stop_on_unregister(wdd);
293 sp_wd->reboot_notifier.notifier_call = rave_sp_wdt_reboot_notifier;
294 ret = devm_register_reboot_notifier(dev, &sp_wd->reboot_notifier);
295 if (ret) {
296 dev_err(dev, "Failed to register reboot notifier\n");
297 return ret;
301 * We don't know if watchdog is running now. To be sure, let's
302 * start it and depend on watchdog core to ping it
304 wdd->max_hw_heartbeat_ms = wdd->max_timeout * 1000;
305 ret = rave_sp_wdt_start(wdd);
306 if (ret) {
307 dev_err(dev, "Watchdog didn't start\n");
308 return ret;
311 ret = devm_watchdog_register_device(dev, wdd);
312 if (ret) {
313 dev_err(dev, "Failed to register watchdog device\n");
314 rave_sp_wdt_stop(wdd);
315 return ret;
318 return 0;
321 static struct platform_driver rave_sp_wdt_driver = {
322 .probe = rave_sp_wdt_probe,
323 .driver = {
324 .name = KBUILD_MODNAME,
325 .of_match_table = rave_sp_wdt_of_match,
329 module_platform_driver(rave_sp_wdt_driver);
331 MODULE_DEVICE_TABLE(of, rave_sp_wdt_of_match);
332 MODULE_LICENSE("GPL");
333 MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
334 MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
335 MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
336 MODULE_DESCRIPTION("RAVE SP Watchdog driver");
337 MODULE_ALIAS("platform:rave-sp-watchdog");