1 // SPDX-License-Identifier: GPL-2.0+
4 * Driver for watchdog aspect of for Zodiac Inflight Innovations RAVE
5 * Supervisory Processor(SP) MCU
7 * Copyright (C) 2017 Zodiac Inflight Innovation
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>
23 RAVE_SP_RESET_BYTE
= 1,
24 RAVE_SP_RESET_REASON_NORMAL
= 0,
25 RAVE_SP_RESET_DELAY_MS
= 500,
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
*);
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
54 struct watchdog_device wdd
;
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
,
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
)
75 [0] = RAVE_SP_CMD_SW_WDT
,
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
)
88 [0] = RAVE_SP_CMD_SW_WDT
,
91 [3] = (u8
)wdd
->timeout
,
92 [4] = (u8
)(wdd
->timeout
>> 8),
95 return rave_sp_wdt_exec(wdd
, cmd
, sizeof(cmd
));
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
)
120 [0] = RAVE_SP_CMD_RESET
,
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
)
131 [0] = RAVE_SP_CMD_RESET
,
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
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
);
157 dev_err(sp_wd
->wdd
.parent
,
158 "Failed to issue restart command (%d)", ret
);
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
);
179 static int rave_sp_wdt_start(struct watchdog_device
*wdd
)
183 ret
= rave_sp_wdt_configure(wdd
, true);
185 set_bit(WDOG_HW_RUNNING
, &wdd
->status
);
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
)
206 [0] = RAVE_SP_CMD_PET_WDT
,
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
= {
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
= {
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
,
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
;
262 sp_wd
= devm_kzalloc(dev
, sizeof(*sp_wd
), GFP_KERNEL
);
266 sp_wd
->variant
= of_device_get_match_data(dev
);
267 sp_wd
->sp
= dev_get_drvdata(dev
->parent
);
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
;
278 cell
= nvmem_cell_get(dev
, "wdt-timeout");
281 void *value
= nvmem_cell_read(cell
, &len
);
283 if (!IS_ERR(value
)) {
284 memcpy(&timeout
, value
, min(len
, sizeof(timeout
)));
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
);
296 dev_err(dev
, "Failed to register reboot notifier\n");
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
);
307 dev_err(dev
, "Watchdog didn't start\n");
311 ret
= devm_watchdog_register_device(dev
, wdd
);
313 dev_err(dev
, "Failed to register watchdog device\n");
314 rave_sp_wdt_stop(wdd
);
321 static struct platform_driver rave_sp_wdt_driver
= {
322 .probe
= rave_sp_wdt_probe
,
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");