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