1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Watchdog commands
4 *
5 * Copyright (c) 2019 Michael Walle <michael@walle.cc>
6 */
7
8#include <common.h>
9#include <command.h>
10#include <dm.h>
11#include <wdt.h>
12
13static struct udevice *currdev;
14
15static int do_wdt_list(struct cmd_tbl *cmdtp, int flag, int argc,
16		       char *const argv[])
17{
18	struct udevice *dev;
19	struct uclass *uc;
20	int ret;
21
22	ret = uclass_get(UCLASS_WDT, &uc);
23	if (ret)
24		return CMD_RET_FAILURE;
25
26	uclass_foreach_dev(dev, uc)
27		printf("%s (%s)\n", dev->name, dev->driver->name);
28
29	return CMD_RET_SUCCESS;
30}
31
32static int do_wdt_dev(struct cmd_tbl *cmdtp, int flag, int argc,
33		      char *const argv[])
34{
35	int ret;
36
37	if (argc > 1) {
38		ret = uclass_get_device_by_name(UCLASS_WDT, argv[1], &currdev);
39		if (ret) {
40			printf("Can't get the watchdog timer: %s\n", argv[1]);
41			return CMD_RET_FAILURE;
42		}
43	} else {
44		if (!currdev) {
45			printf("No watchdog timer device set!\n");
46			return CMD_RET_FAILURE;
47		}
48		printf("dev: %s\n", currdev->name);
49	}
50
51	return CMD_RET_SUCCESS;
52}
53
54static int check_currdev(void)
55{
56	if (!currdev) {
57		printf("No device set, use 'wdt dev' first\n");
58		return CMD_RET_FAILURE;
59	}
60	return 0;
61}
62
63static int do_wdt_start(struct cmd_tbl *cmdtp, int flag, int argc,
64			char *const argv[])
65{
66	int ret;
67	u64 timeout;
68	ulong flags = 0;
69
70	if (argc < 2)
71		return CMD_RET_USAGE;
72
73	ret = check_currdev();
74	if (ret)
75		return ret;
76
77	timeout = simple_strtoull(argv[1], NULL, 0);
78	if (argc > 2)
79		flags = simple_strtoul(argv[2], NULL, 0);
80
81	ret = wdt_start(currdev, timeout, flags);
82	if (ret == -ENOSYS) {
83		printf("Starting watchdog timer not supported.\n");
84		return CMD_RET_FAILURE;
85	} else if (ret) {
86		printf("Starting watchdog timer failed (%d)\n", ret);
87		return CMD_RET_FAILURE;
88	}
89
90	return CMD_RET_SUCCESS;
91}
92
93static int do_wdt_stop(struct cmd_tbl *cmdtp, int flag, int argc,
94		       char *const argv[])
95{
96	int ret;
97
98	ret = check_currdev();
99	if (ret)
100		return ret;
101
102	ret = wdt_stop(currdev);
103	if (ret == -ENOSYS) {
104		printf("Stopping watchdog timer not supported.\n");
105		return CMD_RET_FAILURE;
106	} else if (ret) {
107		printf("Stopping watchdog timer failed (%d)\n", ret);
108		return CMD_RET_FAILURE;
109	}
110
111	return CMD_RET_SUCCESS;
112}
113
114static int do_wdt_reset(struct cmd_tbl *cmdtp, int flag, int argc,
115			char *const argv[])
116{
117	int ret;
118
119	ret = check_currdev();
120	if (ret)
121		return ret;
122
123	ret = wdt_reset(currdev);
124	if (ret == -ENOSYS) {
125		printf("Resetting watchdog timer not supported.\n");
126		return CMD_RET_FAILURE;
127	} else if (ret) {
128		printf("Resetting watchdog timer failed (%d)\n", ret);
129		return CMD_RET_FAILURE;
130	}
131
132	return CMD_RET_SUCCESS;
133}
134
135static int do_wdt_expire(struct cmd_tbl *cmdtp, int flag, int argc,
136			 char *const argv[])
137{
138	int ret;
139	ulong flags = 0;
140
141	ret = check_currdev();
142	if (ret)
143		return ret;
144
145	if (argc > 1)
146		flags = simple_strtoul(argv[1], NULL, 0);
147
148	ret = wdt_expire_now(currdev, flags);
149	if (ret == -ENOSYS) {
150		printf("Expiring watchdog timer not supported.\n");
151		return CMD_RET_FAILURE;
152	} else if (ret) {
153		printf("Expiring watchdog timer failed (%d)\n", ret);
154		return CMD_RET_FAILURE;
155	}
156
157	return CMD_RET_SUCCESS;
158}
159
160U_BOOT_LONGHELP(wdt,
161	"list - list watchdog devices\n"
162	"wdt dev [<name>] - get/set current watchdog device\n"
163	"wdt start <timeout ms> [flags] - start watchdog timer\n"
164	"wdt stop - stop watchdog timer\n"
165	"wdt reset - reset watchdog timer\n"
166	"wdt expire [flags] - expire watchdog timer immediately\n");
167
168U_BOOT_CMD_WITH_SUBCMDS(wdt, "Watchdog sub-system", wdt_help_text,
169	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_wdt_list),
170	U_BOOT_SUBCMD_MKENT(dev, 2, 1, do_wdt_dev),
171	U_BOOT_SUBCMD_MKENT(start, 3, 1, do_wdt_start),
172	U_BOOT_SUBCMD_MKENT(stop, 1, 1, do_wdt_stop),
173	U_BOOT_SUBCMD_MKENT(reset, 1, 1, do_wdt_reset),
174	U_BOOT_SUBCMD_MKENT(expire, 2, 1, do_wdt_expire));
175