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