xref: /optee_os/core/drivers/wdt/watchdog_sm.c (revision a7f2d4bd86327253733ce88d2160e4d02b8349b7)
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éger enum 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