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