1// SPDX-License-Identifier: GPL-2.0+
2
3/*
4 * Driver for watchdog aspect of for Zodiac Inflight Innovations RAVE
5 * Supervisory Processor(SP) MCU
6 *
7 * Copyright (C) 2017 Zodiac Inflight Innovation
8 *
9 */
10
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.h>
17#include <linux/platform_device.h>
18#include <linux/reboot.h>
19#include <linux/slab.h>
20#include <linux/watchdog.h>
21
22enum {
23	RAVE_SP_RESET_BYTE = 1,
24	RAVE_SP_RESET_REASON_NORMAL = 0,
25	RAVE_SP_RESET_DELAY_MS = 500,
26};
27
28/**
29 * struct rave_sp_wdt_variant - RAVE SP watchdog variant
30 *
31 * @max_timeout:	Largest possible watchdog timeout setting
32 * @min_timeout:	Smallest possible watchdog timeout setting
33 *
34 * @configure:		Function to send configuration command
35 * @restart:		Function to send "restart" command
36 */
37struct rave_sp_wdt_variant {
38	unsigned int max_timeout;
39	unsigned int min_timeout;
40
41	int (*configure)(struct watchdog_device *, bool);
42	int (*restart)(struct watchdog_device *);
43};
44
45/**
46 * struct rave_sp_wdt - RAVE SP watchdog
47 *
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
52 */
53struct 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;
58};
59
60static struct rave_sp_wdt *to_rave_sp_wdt(struct watchdog_device *wdd)
61{
62	return container_of(wdd, struct rave_sp_wdt, wdd);
63}
64
65static int rave_sp_wdt_exec(struct watchdog_device *wdd, void *data,
66			    size_t data_size)
67{
68	return rave_sp_exec(to_rave_sp_wdt(wdd)->sp,
69			    data, data_size, NULL, 0);
70}
71
72static int rave_sp_wdt_legacy_configure(struct watchdog_device *wdd, bool on)
73{
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,
80	};
81
82	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
83}
84
85static int rave_sp_wdt_rdu_configure(struct watchdog_device *wdd, bool on)
86{
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),
93	};
94
95	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
96}
97
98/**
99 * rave_sp_wdt_configure - Configure watchdog device
100 *
101 * @wdd:	Device to configure
102 * @on:		Desired state of the watchdog timer (ON/OFF)
103 *
104 * This function configures two aspects of the watchdog timer:
105 *
106 *  - Wheither it is ON or OFF
107 *  - Its timeout duration
108 *
109 * with first aspect specified via function argument and second via
110 * the value of 'wdd->timeout'.
111 */
112static int rave_sp_wdt_configure(struct watchdog_device *wdd, bool on)
113{
114	return to_rave_sp_wdt(wdd)->variant->configure(wdd, on);
115}
116
117static int rave_sp_wdt_legacy_restart(struct watchdog_device *wdd)
118{
119	u8 cmd[] = {
120		[0] = RAVE_SP_CMD_RESET,
121		[1] = 0,
122		[2] = RAVE_SP_RESET_BYTE
123	};
124
125	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
126}
127
128static int rave_sp_wdt_rdu_restart(struct watchdog_device *wdd)
129{
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
135	};
136
137	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
138}
139
140static int rave_sp_wdt_reboot_notifier(struct notifier_block *nb,
141				       unsigned long action, void *data)
142{
143	/*
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.
149	 */
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);
153
154		const int ret = sp_wd->variant->restart(&sp_wd->wdd);
155
156		if (ret < 0)
157			dev_err(sp_wd->wdd.parent,
158				"Failed to issue restart command (%d)", ret);
159		return NOTIFY_OK;
160	}
161
162	return NOTIFY_DONE;
163}
164
165static int rave_sp_wdt_restart(struct watchdog_device *wdd,
166			       unsigned long action, void *data)
167{
168	/*
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.
173	 */
174	mdelay(2 * RAVE_SP_RESET_DELAY_MS);
175
176	return -EIO;
177}
178
179static int rave_sp_wdt_start(struct watchdog_device *wdd)
180{
181	int ret;
182
183	ret = rave_sp_wdt_configure(wdd, true);
184	if (!ret)
185		set_bit(WDOG_HW_RUNNING, &wdd->status);
186
187	return ret;
188}
189
190static int rave_sp_wdt_stop(struct watchdog_device *wdd)
191{
192	return rave_sp_wdt_configure(wdd, false);
193}
194
195static int rave_sp_wdt_set_timeout(struct watchdog_device *wdd,
196				   unsigned int timeout)
197{
198	wdd->timeout = timeout;
199
200	return rave_sp_wdt_configure(wdd, watchdog_active(wdd));
201}
202
203static int rave_sp_wdt_ping(struct watchdog_device *wdd)
204{
205	u8 cmd[] = {
206		[0] = RAVE_SP_CMD_PET_WDT,
207		[1] = 0,
208	};
209
210	return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
211}
212
213static const struct watchdog_info rave_sp_wdt_info = {
214	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
215	.identity = "RAVE SP Watchdog",
216};
217
218static 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,
225};
226
227static 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,
232};
233
234static 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,
239};
240
241static const struct of_device_id rave_sp_wdt_of_match[] = {
242	{
243		.compatible = "zii,rave-sp-watchdog-legacy",
244		.data = &rave_sp_wdt_legacy,
245	},
246	{
247		.compatible = "zii,rave-sp-watchdog",
248		.data = &rave_sp_wdt_rdu,
249	},
250	{ /* sentinel */ }
251};
252
253static int rave_sp_wdt_probe(struct platform_device *pdev)
254{
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;
261
262	sp_wd = devm_kzalloc(dev, sizeof(*sp_wd), GFP_KERNEL);
263	if (!sp_wd)
264		return -ENOMEM;
265
266	sp_wd->variant = of_device_get_match_data(dev);
267	sp_wd->sp      = dev_get_drvdata(dev->parent);
268
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;
277
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);
282
283		if (!IS_ERR(value)) {
284			memcpy(&timeout, value, min(len, sizeof(timeout)));
285			kfree(value);
286		}
287		nvmem_cell_put(cell);
288	}
289	watchdog_init_timeout(wdd, le16_to_cpu(timeout), dev);
290	watchdog_set_restart_priority(wdd, 255);
291	watchdog_stop_on_unregister(wdd);
292
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;
298	}
299
300	/*
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
303	 */
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;
309	}
310
311	ret = devm_watchdog_register_device(dev, wdd);
312	if (ret) {
313		rave_sp_wdt_stop(wdd);
314		return ret;
315	}
316
317	return 0;
318}
319
320static struct platform_driver rave_sp_wdt_driver = {
321	.probe = rave_sp_wdt_probe,
322	.driver = {
323		.name = KBUILD_MODNAME,
324		.of_match_table = rave_sp_wdt_of_match,
325	},
326};
327
328module_platform_driver(rave_sp_wdt_driver);
329
330MODULE_DEVICE_TABLE(of, rave_sp_wdt_of_match);
331MODULE_LICENSE("GPL");
332MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
333MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
334MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
335MODULE_DESCRIPTION("RAVE SP Watchdog driver");
336MODULE_ALIAS("platform:rave-sp-watchdog");
337