// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip */ #include #include #include #include enum smcwd_call { SMCWD_INIT = 0, SMCWD_SET_TIMEOUT = 1, SMCWD_ENABLE = 2, SMCWD_PET = 3, SMCWD_GET_TIMELEFT = 4, }; static unsigned long wdt_min_timeout; static unsigned long wdt_max_timeout; /* Lock for timeout variables */ static unsigned int wdt_lock = SPINLOCK_UNLOCK; enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t exceptions = 0; unsigned long min_timeout = 0; unsigned long max_timeout = 0; switch (args->a1) { case SMCWD_INIT: exceptions = cpu_spin_lock_xsave(&wdt_lock); res = watchdog_init(&wdt_min_timeout, &wdt_max_timeout); cpu_spin_unlock_xrestore(&wdt_lock, exceptions); if (res) { args->a0 = PSCI_RET_INTERNAL_FAILURE; } else { args->a0 = PSCI_RET_SUCCESS; args->a1 = wdt_min_timeout; args->a2 = wdt_max_timeout; } break; case SMCWD_SET_TIMEOUT: exceptions = cpu_spin_lock_xsave(&wdt_lock); min_timeout = wdt_min_timeout; max_timeout = wdt_max_timeout; cpu_spin_unlock_xrestore(&wdt_lock, exceptions); if (args->a2 < min_timeout || args->a2 > max_timeout) { args->a0 = PSCI_RET_INVALID_PARAMETERS; break; } watchdog_settimeout(args->a2); args->a0 = PSCI_RET_SUCCESS; break; case SMCWD_ENABLE: if (args->a2 == 0) { watchdog_stop(); args->a0 = PSCI_RET_SUCCESS; } else if (args->a2 == 1) { watchdog_start(); args->a0 = PSCI_RET_SUCCESS; } else { args->a0 = PSCI_RET_INVALID_PARAMETERS; } break; case SMCWD_PET: watchdog_ping(); args->a0 = PSCI_RET_SUCCESS; break; /* SMCWD_GET_TIMELEFT is optional */ case SMCWD_GET_TIMELEFT: default: args->a0 = PSCI_RET_NOT_SUPPORTED; } return SM_HANDLER_SMC_HANDLED; }