1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2022 Microchip 4 */ 5 6 #include <drivers/wdt.h> 7 #include <kernel/spinlock.h> 8 #include <sm/optee_smc.h> 9 #include <sm/psci.h> 10 11 enum smcwd_call { 12 SMCWD_INIT = 0, 13 SMCWD_SET_TIMEOUT = 1, 14 SMCWD_ENABLE = 2, 15 SMCWD_PET = 3, 16 SMCWD_GET_TIMELEFT = 4, 17 }; 18 19 static unsigned long wdt_min_timeout; 20 static unsigned long wdt_max_timeout; 21 /* Lock for timeout variables */ 22 static unsigned int wdt_lock = SPINLOCK_UNLOCK; 23 __wdt_sm_handler(struct thread_smc_args * args)24enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args) 25 { 26 TEE_Result res = TEE_ERROR_GENERIC; 27 uint32_t exceptions = 0; 28 unsigned long min_timeout = 0; 29 unsigned long max_timeout = 0; 30 31 switch (args->a1) { 32 case SMCWD_INIT: 33 exceptions = cpu_spin_lock_xsave(&wdt_lock); 34 res = watchdog_init(&wdt_min_timeout, &wdt_max_timeout); 35 cpu_spin_unlock_xrestore(&wdt_lock, exceptions); 36 37 if (res) { 38 args->a0 = PSCI_RET_INTERNAL_FAILURE; 39 } else { 40 args->a0 = PSCI_RET_SUCCESS; 41 args->a1 = wdt_min_timeout; 42 args->a2 = wdt_max_timeout; 43 } 44 break; 45 case SMCWD_SET_TIMEOUT: 46 exceptions = cpu_spin_lock_xsave(&wdt_lock); 47 min_timeout = wdt_min_timeout; 48 max_timeout = wdt_max_timeout; 49 cpu_spin_unlock_xrestore(&wdt_lock, exceptions); 50 51 if (args->a2 < min_timeout || args->a2 > max_timeout) { 52 args->a0 = PSCI_RET_INVALID_PARAMETERS; 53 break; 54 } 55 56 watchdog_settimeout(args->a2); 57 args->a0 = PSCI_RET_SUCCESS; 58 break; 59 case SMCWD_ENABLE: 60 if (args->a2 == 0) { 61 watchdog_stop(); 62 args->a0 = PSCI_RET_SUCCESS; 63 } else if (args->a2 == 1) { 64 watchdog_start(); 65 args->a0 = PSCI_RET_SUCCESS; 66 } else { 67 args->a0 = PSCI_RET_INVALID_PARAMETERS; 68 } 69 break; 70 case SMCWD_PET: 71 watchdog_ping(); 72 args->a0 = PSCI_RET_SUCCESS; 73 break; 74 /* SMCWD_GET_TIMELEFT is optional */ 75 case SMCWD_GET_TIMELEFT: 76 default: 77 args->a0 = PSCI_RET_NOT_SUPPORTED; 78 } 79 80 return SM_HANDLER_SMC_HANDLED; 81 } 82