| // SPDX-License-Identifier: BSD-2-Clause |
| /* |
| * Copyright 2022 Microchip |
| */ |
| |
| #include <drivers/wdt.h> |
| #include <kernel/spinlock.h> |
| #include <sm/optee_smc.h> |
| #include <sm/psci.h> |
| |
| 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; |
| } |