1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright 2019 Broadcom. 4 */ 5 6 #ifndef __DRIVERS_WDT_H 7 #define __DRIVERS_WDT_H 8 9 #include <assert.h> 10 #include <kernel/interrupt.h> 11 #include <kernel/thread.h> 12 #include <sm/sm.h> 13 #include <tee_api_types.h> 14 15 struct wdt_chip { 16 const struct wdt_ops *ops; 17 struct itr_handler *wdt_itr; 18 }; 19 20 /* 21 * struct wdt_ops - The watchdog device operations 22 * 23 * @init: The routine to initialized the watchdog resources. 24 * @start: The routine for starting the watchdog device. 25 * @stop: The routine for stopping the watchdog device. 26 * @ping: The routine that sends a keepalive ping to the watchdog device. 27 * @set_timeout:The routine that finds the load value that will reset system in 28 * required timeout (in seconds). 29 * @get_timeleft:The optional routine that finds if the watchdog is already 30 * started and the time left (in seconds) before the watchdog timeouts. 31 * 32 * The wdt_ops structure contains a list of low-level operations 33 * that control a watchdog device. 34 */ 35 struct wdt_ops { 36 TEE_Result (*init)(struct wdt_chip *chip, unsigned long *min_timeout, 37 unsigned long *max_timeout); 38 void (*start)(struct wdt_chip *chip); 39 void (*stop)(struct wdt_chip *chip); 40 void (*ping)(struct wdt_chip *chip); 41 TEE_Result (*set_timeout)(struct wdt_chip *chip, unsigned long timeout); 42 TEE_Result (*get_timeleft)(struct wdt_chip *chip, bool *is_started, 43 unsigned long *timeleft); 44 }; 45 46 #ifdef CFG_WDT 47 extern struct wdt_chip *wdt_chip; 48 49 /* Register a watchdog as the system watchdog */ 50 TEE_Result watchdog_register(struct wdt_chip *chip); 51 52 static inline 53 TEE_Result watchdog_init(unsigned long *min_timeout, unsigned long *max_timeout) 54 { 55 if (!wdt_chip) 56 return TEE_ERROR_NOT_SUPPORTED; 57 58 if (!wdt_chip->ops->init) 59 return TEE_SUCCESS; 60 61 return wdt_chip->ops->init(wdt_chip, min_timeout, max_timeout); 62 } 63 64 static inline void watchdog_start(void) 65 { 66 if (wdt_chip) 67 wdt_chip->ops->start(wdt_chip); 68 } 69 70 static inline void watchdog_stop(void) 71 { 72 if (wdt_chip && wdt_chip->ops->stop) 73 wdt_chip->ops->stop(wdt_chip); 74 } 75 76 static inline void watchdog_ping(void) 77 { 78 if (wdt_chip) 79 wdt_chip->ops->ping(wdt_chip); 80 } 81 82 static inline void watchdog_settimeout(unsigned long timeout) 83 { 84 if (wdt_chip) 85 wdt_chip->ops->set_timeout(wdt_chip, timeout); 86 } 87 88 /* 89 * watchdog_gettimeleft() - Get the time left before the watchdog timeouts 90 * @is_started: [out] true if watchdog has started, false otherwise 91 * @timeleft: [out] time left in seconds before expiration if @is_started==true 92 */ 93 static inline TEE_Result watchdog_gettimeleft(bool *is_started, 94 unsigned long *timeleft) 95 { 96 if (!wdt_chip || !wdt_chip->ops->get_timeleft) 97 return TEE_ERROR_NOT_SUPPORTED; 98 99 return wdt_chip->ops->get_timeleft(wdt_chip, is_started, timeleft); 100 } 101 #else 102 static inline TEE_Result watchdog_register(struct wdt_chip *chip __unused) 103 { 104 return TEE_ERROR_NOT_SUPPORTED; 105 } 106 107 static inline TEE_Result watchdog_init(unsigned long *min_timeout __unused, 108 unsigned long *max_timeout __unused) 109 { 110 return TEE_ERROR_NOT_SUPPORTED; 111 } 112 113 static inline void watchdog_start(void) {} 114 static inline void watchdog_stop(void) {} 115 static inline void watchdog_ping(void) {} 116 static inline void watchdog_settimeout(unsigned long timeout __unused) {} 117 static inline TEE_Result watchdog_gettimeleft(bool *is_started __unused, 118 unsigned long *timeleft __unused) 119 { 120 return TEE_ERROR_NOT_SUPPORTED; 121 } 122 #endif 123 124 #ifdef CFG_WDT_SM_HANDLER 125 enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args); 126 127 static inline 128 enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args) 129 { 130 if (args->a0 != CFG_WDT_SM_HANDLER_ID) 131 return SM_HANDLER_PENDING_SMC; 132 133 return __wdt_sm_handler(args); 134 } 135 #else 136 static inline 137 enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused) 138 { 139 return SM_HANDLER_PENDING_SMC; 140 } 141 #endif 142 143 #endif /* __DRIVERS_WDT_H */ 144