blob: 35efcac59dda973387d3d92c7d06439b75ae25df [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +02002/*
3 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +02004 */
5
6#include <common.h>
7#include <dm.h>
Samuel Hollanda8f63d12021-11-03 22:55:14 -05008#include <dm/device-internal.h>
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +02009#include <errno.h>
Samuel Hollanda8f63d12021-11-03 22:55:14 -050010#include <malloc.h>
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020011#include <sysreset.h>
12#include <wdt.h>
13
Samuel Holland5544a012021-11-03 22:55:13 -050014struct wdt_reboot_plat {
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020015 struct udevice *wdt;
16};
17
18static int wdt_reboot_request(struct udevice *dev, enum sysreset_t type)
19{
Samuel Holland5544a012021-11-03 22:55:13 -050020 struct wdt_reboot_plat *plat = dev_get_plat(dev);
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020021 int ret;
22
Samuel Holland5544a012021-11-03 22:55:13 -050023 ret = wdt_expire_now(plat->wdt, 0);
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020024 if (ret)
25 return ret;
26
27 return -EINPROGRESS;
28}
29
30static struct sysreset_ops wdt_reboot_ops = {
31 .request = wdt_reboot_request,
32};
33
Samuel Holland5544a012021-11-03 22:55:13 -050034static int wdt_reboot_of_to_plat(struct udevice *dev)
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020035{
Samuel Holland5544a012021-11-03 22:55:13 -050036 struct wdt_reboot_plat *plat = dev_get_plat(dev);
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020037 int err;
38
39 err = uclass_get_device_by_phandle(UCLASS_WDT, dev,
Samuel Holland5544a012021-11-03 22:55:13 -050040 "wdt", &plat->wdt);
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020041 if (err) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +090042 pr_err("unable to find wdt device\n");
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020043 return err;
44 }
45
46 return 0;
47}
48
49static const struct udevice_id wdt_reboot_ids[] = {
50 { .compatible = "wdt-reboot" },
51 { /* sentinel */ }
52};
53
54U_BOOT_DRIVER(wdt_reboot) = {
55 .name = "wdt_reboot",
56 .id = UCLASS_SYSRESET,
57 .of_match = wdt_reboot_ids,
Samuel Holland5544a012021-11-03 22:55:13 -050058 .of_to_plat = wdt_reboot_of_to_plat,
59 .plat_auto = sizeof(struct wdt_reboot_plat),
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020060 .ops = &wdt_reboot_ops,
Álvaro Fernández Rojas17a0c142017-05-16 18:29:13 +020061};
Samuel Hollanda8f63d12021-11-03 22:55:14 -050062
63#if IS_ENABLED(CONFIG_SYSRESET_WATCHDOG_AUTO)
64int sysreset_register_wdt(struct udevice *dev)
65{
66 struct wdt_reboot_plat *plat = malloc(sizeof(*plat));
67 int ret;
68
69 if (!plat)
70 return -ENOMEM;
71
72 plat->wdt = dev;
73
74 ret = device_bind(dev, DM_DRIVER_GET(wdt_reboot),
75 dev->name, plat, ofnode_null(), NULL);
76 if (ret) {
77 free(plat);
78 return ret;
79 }
80
81 return 0;
82}
83#endif