1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2017 Google, Inc 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <wdt.h> 10 #include <dm/device-internal.h> 11 #include <dm/lists.h> 12 13 int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) 14 { 15 const struct wdt_ops *ops = device_get_ops(dev); 16 17 if (!ops->start) 18 return -ENOSYS; 19 20 return ops->start(dev, timeout_ms, flags); 21 } 22 23 int wdt_stop(struct udevice *dev) 24 { 25 const struct wdt_ops *ops = device_get_ops(dev); 26 27 if (!ops->stop) 28 return -ENOSYS; 29 30 return ops->stop(dev); 31 } 32 33 int wdt_reset(struct udevice *dev) 34 { 35 const struct wdt_ops *ops = device_get_ops(dev); 36 37 if (!ops->reset) 38 return -ENOSYS; 39 40 return ops->reset(dev); 41 } 42 43 int wdt_expire_now(struct udevice *dev, ulong flags) 44 { 45 int ret = 0; 46 const struct wdt_ops *ops; 47 48 debug("WDT Resetting: %lu\n", flags); 49 ops = device_get_ops(dev); 50 if (ops->expire_now) { 51 return ops->expire_now(dev, flags); 52 } else { 53 if (!ops->start) 54 return -ENOSYS; 55 56 ret = ops->start(dev, 1, flags); 57 if (ret < 0) 58 return ret; 59 60 hang(); 61 } 62 63 return ret; 64 } 65 66 static int wdt_post_bind(struct udevice *dev) 67 { 68 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 69 struct wdt_ops *ops = (struct wdt_ops *)device_get_ops(dev); 70 static int reloc_done; 71 72 if (!reloc_done) { 73 if (ops->start) 74 ops->start += gd->reloc_off; 75 if (ops->stop) 76 ops->stop += gd->reloc_off; 77 if (ops->reset) 78 ops->reset += gd->reloc_off; 79 if (ops->expire_now) 80 ops->expire_now += gd->reloc_off; 81 82 reloc_done++; 83 } 84 #endif 85 return 0; 86 } 87 88 UCLASS_DRIVER(wdt) = { 89 .id = UCLASS_WDT, 90 .name = "watchdog", 91 .flags = DM_UC_FLAG_SEQ_ALIAS, 92 .post_bind = wdt_post_bind, 93 }; 94