1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2019, Broadcom
4  */
5 
6 #include <drivers/gic.h>
7 #include <drivers/sp805_wdt.h>
8 #include <io.h>
9 #include <kernel/interrupt.h>
10 #include <kernel/misc.h>
11 #include <kernel/pseudo_ta.h>
12 #include <trace.h>
13 
14 #define SEC_WD_SERVICE_UUID \
15 		{ 0x6272636D, 0x2019, 0x0801,  \
16 		{ 0x42, 0x43, 0x4D, 0x5F, 0x57, 0x44, 0x54, 0x30 } }
17 
18 #define PTA_BCM_SEC_WD_CMD_CONFIG	0
19 #define PTA_BCM_SEC_WD_CMD_START	1
20 #define PTA_BCM_SEC_WD_CMD_PING		2
21 #define PTA_BCM_SEC_WD_CMD_STOP		3
22 #define PTA_BCM_SEC_WD_CMD_SET_TIMEOUT	4
23 
24 #define SEC_WD_TA_NAME		"pta_bcm_sec_wd.ta"
25 
26 static struct sp805_wdt_data wd_pd;
27 
wd_isr_handler(struct wdt_chip * chip __unused)28 static void wd_isr_handler(struct wdt_chip *chip __unused)
29 {
30 	/* Do nothing */
31 	DMSG("Watchdog ISR handler !!!");
32 }
33 
pta_wd_config(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])34 static TEE_Result pta_wd_config(uint32_t param_types,
35 				TEE_Param params[TEE_NUM_PARAMS])
36 {
37 	uint32_t timeout = 0;
38 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
39 						   TEE_PARAM_TYPE_NONE,
40 						   TEE_PARAM_TYPE_NONE,
41 						   TEE_PARAM_TYPE_NONE);
42 
43 	if (exp_param_types != param_types) {
44 		EMSG("Invalid Param types");
45 		return TEE_ERROR_BAD_PARAMETERS;
46 	}
47 
48 	timeout = params[0].value.a;
49 
50 	sp805_wdt_init(&wd_pd, SEC_WDT_BASE, SEC_WDT_CLK_HZ, timeout);
51 
52 	sp805_register_itr_handler(&wd_pd, GIC_SPI(SEC_WDT_INTR),
53 				   ITRF_TRIGGER_LEVEL, wd_isr_handler);
54 	wd_pd.chip.ops->start(&wd_pd.chip);
55 
56 	return TEE_SUCCESS;
57 }
58 
pta_wd_start(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS]__unused)59 static TEE_Result pta_wd_start(uint32_t param_types,
60 			       TEE_Param params[TEE_NUM_PARAMS] __unused)
61 {
62 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
63 						   TEE_PARAM_TYPE_NONE,
64 						   TEE_PARAM_TYPE_NONE,
65 						   TEE_PARAM_TYPE_NONE);
66 
67 	if (exp_param_types != param_types) {
68 		EMSG("Invalid Param types");
69 		return TEE_ERROR_BAD_PARAMETERS;
70 	}
71 
72 	wd_pd.chip.ops->start(&wd_pd.chip);
73 
74 	return TEE_SUCCESS;
75 }
76 
pta_wd_ping(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS]__unused)77 static TEE_Result pta_wd_ping(uint32_t param_types,
78 			      TEE_Param params[TEE_NUM_PARAMS] __unused)
79 {
80 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
81 						   TEE_PARAM_TYPE_NONE,
82 						   TEE_PARAM_TYPE_NONE,
83 						   TEE_PARAM_TYPE_NONE);
84 
85 	if (exp_param_types != param_types) {
86 		EMSG("Invalid Param types");
87 		return TEE_ERROR_BAD_PARAMETERS;
88 	}
89 
90 	wd_pd.chip.ops->ping(&wd_pd.chip);
91 
92 	return TEE_SUCCESS;
93 }
94 
pta_wd_stop(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS]__unused)95 static TEE_Result pta_wd_stop(uint32_t param_types,
96 			      TEE_Param params[TEE_NUM_PARAMS] __unused)
97 {
98 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
99 						   TEE_PARAM_TYPE_NONE,
100 						   TEE_PARAM_TYPE_NONE,
101 						   TEE_PARAM_TYPE_NONE);
102 
103 	if (exp_param_types != param_types) {
104 		EMSG("Invalid Param types");
105 		return TEE_ERROR_BAD_PARAMETERS;
106 	}
107 
108 	wd_pd.chip.ops->stop(&wd_pd.chip);
109 
110 	return TEE_SUCCESS;
111 }
112 
pta_wd_set_timeout(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])113 static TEE_Result pta_wd_set_timeout(uint32_t param_types,
114 				     TEE_Param params[TEE_NUM_PARAMS])
115 {
116 	uint32_t timeout = 0;
117 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
118 						   TEE_PARAM_TYPE_NONE,
119 						   TEE_PARAM_TYPE_NONE,
120 						   TEE_PARAM_TYPE_NONE);
121 
122 	if (exp_param_types != param_types) {
123 		EMSG("Invalid Param types");
124 		return TEE_ERROR_BAD_PARAMETERS;
125 	}
126 
127 	timeout = params[0].value.a;
128 
129 	wd_pd.chip.ops->set_timeout(&wd_pd.chip, timeout);
130 
131 	return TEE_SUCCESS;
132 }
133 
invoke_command(void * session_context __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])134 static TEE_Result invoke_command(void *session_context __unused,
135 				 uint32_t cmd_id,
136 				 uint32_t param_types,
137 				 TEE_Param params[TEE_NUM_PARAMS])
138 {
139 	TEE_Result res = TEE_SUCCESS;
140 
141 	DMSG("command entry point[%d] for \"%s\"", cmd_id, SEC_WD_TA_NAME);
142 
143 	switch (cmd_id) {
144 	case PTA_BCM_SEC_WD_CMD_CONFIG:
145 		res = pta_wd_config(param_types, params);
146 		break;
147 	case PTA_BCM_SEC_WD_CMD_START:
148 		res = pta_wd_start(param_types, params);
149 		break;
150 	case PTA_BCM_SEC_WD_CMD_PING:
151 		res = pta_wd_ping(param_types, params);
152 		break;
153 	case PTA_BCM_SEC_WD_CMD_STOP:
154 		res = pta_wd_stop(param_types, params);
155 		break;
156 	case PTA_BCM_SEC_WD_CMD_SET_TIMEOUT:
157 		res = pta_wd_set_timeout(param_types, params);
158 		break;
159 	default:
160 		EMSG("cmd: %d Not supported %s", cmd_id, SEC_WD_TA_NAME);
161 		res = TEE_ERROR_NOT_SUPPORTED;
162 		break;
163 	}
164 
165 	return res;
166 }
167 
168 pseudo_ta_register(.uuid = SEC_WD_SERVICE_UUID,
169 		   .name = SEC_WD_TA_NAME,
170 		   .flags = PTA_DEFAULT_FLAGS,
171 		   .invoke_command_entry_point = invoke_command);
172