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