1 /*
2  * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * \file sam_drv.h
19  * \brief Driver for Arm Security Alarm Manager (SAM).
20  */
21 
22 #ifndef __SAM_DRV_H__
23 #define __SAM_DRV_H__
24 
25 #include <stdbool.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /**
34  * \brief SAM Event IDs.
35  */
36 enum sam_event_id_t {
37     SAM_EVENT_CONFIG_INTEGRITY_ERROR = 0UL,
38     SAM_EVENT_WATCHDOG_TIMER,
39     SAM_EVENT_DUPLICATION_ERROR,
40     SAM_EVENT_LCM_FATAL_ERROR,
41     SAM_EVENT_CPU_LOCKUP,
42     SAM_EVENT_ATU_ERROR,
43     SAM_EVENT_KMU_PARITY_ERROR,
44     SAM_EVENT_CRYPTO_PARITY_ERROR,
45     SAM_EVENT_SIC_PARITY_ERROR,
46     SAM_EVENT_AES_DFA_ERROR,
47     SAM_EVENT_AES_PARITY_ERROR,
48     SAM_EVENT_DMA_DCLS_ERROR,
49     SAM_EVENT_PSI_PARITY_ERROR,
50     SAM_EVENT_BUS_PARITY_ERROR,
51     SAM_EVENT_PROCESSOR_DCLS_ERROR,
52     SAM_EVENT_PROCESSOR_RAS_SET_0,
53     SAM_EVENT_PROCESSOR_RAS_SET_1,
54     SAM_EVENT_PROCESSOR_RAS_SET_2,
55     SAM_EVENT_SRAM_PARTIAL_WRITE,
56     SAM_EVENT_VM0_SINGLE_ECC_ERROR,
57     SAM_EVENT_VM1_SINGLE_ECC_ERROR,
58     SAM_EVENT_VM2_SINGLE_ECC_ERROR,
59     SAM_EVENT_VM3_SINGLE_ECC_ERROR,
60     SAM_EVENT_VM0_DOUBLE_ECC_ERROR,
61     SAM_EVENT_VM1_DOUBLE_ECC_ERROR,
62     SAM_EVENT_VM2_DOUBLE_ECC_ERROR,
63     SAM_EVENT_VM3_DOUBLE_ECC_ERROR,
64     SAM_EVENT_SRAM_MPC_PARITY_ERROR,
65     SAM_EVENT_SIC_MPC_PARITY_ERROR,
66     SAM_EVENT_ATU_PARITY_ERROR,
67     SAM_EVENT_PPR_PARITY_ERROR,
68     SAM_EVENT_SYSCTRL_PARITY_ERROR,
69     SAM_EVENT_CPU_PPB_PARITY_ERROR,
70     SAM_EVENT_SACFG_PARITY_ERROR,
71     SAM_EVENT_NSACFG_PARITY_ERROR,
72     SAM_EVENT_INTEGRITY_CHECKER_ALARM,
73     SAM_EVENT_TRAM_PARITY_ERROR,
74     /* Reserved 37-47 */
75     SAM_EVENT_EXTERNAL_SENSOR_0 = 48UL,
76     SAM_EVENT_EXTERNAL_SENSOR_1,
77     SAM_EVENT_EXTERNAL_SENSOR_2,
78     SAM_EVENT_EXTERNAL_SENSOR_3,
79     SAM_EVENT_EXTERNAL_SENSOR_4,
80     SAM_EVENT_EXTERNAL_SENSOR_5,
81     SAM_EVENT_EXTERNAL_SENSOR_6,
82     SAM_EVENT_EXTERNAL_SENSOR_7,
83     SAM_EVENT_EXTERNAL_SENSOR_8,
84     SAM_EVENT_EXTERNAL_SENSOR_9,
85     SAM_EVENT_EXTERNAL_SENSOR_10,
86     SAM_EVENT_EXTERNAL_SENSOR_11,
87     SAM_EVENT_EXTERNAL_SENSOR_12,
88     SAM_EVENT_EXTERNAL_SENSOR_13,
89     SAM_EVENT_EXTERNAL_SENSOR_14,
90     SAM_EVENT_EXTERNAL_SENSOR_15,
91 
92     /* Maximum permitted event ID */
93     SAM_MAX_EVENT_ID = SAM_EVENT_EXTERNAL_SENSOR_15,
94 };
95 
96 /**
97  * \brief SAM response action IDs.
98  */
99 enum sam_response_t {
100     SAM_RESPONSE_NONE = 0UL,
101     SAM_RESPONSE_COLD_RESET = 1UL,
102     SAM_RESPONSE_WARM_RESET = 1UL << 1,
103     SAM_RESPONSE_NMI = 1UL << 2,
104     SAM_RESPONSE_CRITICAL_FAULT_INTERRUPT = 1UL << 3,
105     SAM_RESPONSE_FAULT_INTERRUPT = 1UL << 4,
106     SAM_RESPONSE_ACTION_5 = 1UL << 5,
107     SAM_RESPONSE_ACTION_6 = 1UL << 6,
108     SAM_RESPONSE_ACTION_7 = 1UL << 7,
109 
110     SAM_MAX_RESPONSE_ACTION = SAM_RESPONSE_ACTION_7,
111 };
112 
113 /**
114  * \brief SAM error type.
115  */
116 enum sam_error_t {
117     SAM_ERROR_NONE = 0,
118     SAM_ERROR_INVALID_ARGUMENT,
119 };
120 
121 /**
122  * \brief SAM event handler function type.
123  */
124 typedef void (*sam_event_handler_t)(void);
125 
126 /* SAM config covers 24 registers: samem to samicv */
127 #define SAM_CONFIG_LEN 24
128 
129 /**
130  * \brief SAM device configuration structure.
131  */
132 struct sam_dev_cfg_t {
133     const uintptr_t base; /**< SAM base address */
134     const uint32_t default_config[SAM_CONFIG_LEN];  /**< Default SAM config */
135 };
136 
137 /**
138  * \brief SAM device structure.
139  */
140 struct sam_dev_t {
141     const struct sam_dev_cfg_t *const cfg; /**< SAM configuration */
142     sam_event_handler_t event_handlers[SAM_MAX_EVENT_ID + 1]; /**< SAM event handlers */
143 };
144 
145 /**
146  * \brief Initialize SAM device.
147  *
148  * \param[in] dev  Pointer to SAM device struct.
149  *
150  * \return Error code of enum sam_error_t type.
151  */
152 enum sam_error_t sam_init(const struct sam_dev_t *dev);
153 
154 /**
155  * \brief Enable a SAM event.
156  *
157  * \param[in] dev       Pointer to SAM device struct.
158  * \param[in] event_id  Event ID to enable.
159  *
160  * \return Error code of enum sam_error_t type.
161  */
162 enum sam_error_t sam_enable_event(const struct sam_dev_t *dev,
163                                   enum sam_event_id_t event_id);
164 
165 /**
166  * \brief Disable a SAM event.
167  *
168  * \param[in] dev       Pointer to SAM device struct.
169  * \param[in] event_id  Event ID to disable.
170  *
171  * \return Error code of enum sam_error_t type.
172  */
173 enum sam_error_t sam_disable_event(const struct sam_dev_t *dev,
174                                    enum sam_event_id_t event_id);
175 
176 /**
177  * \brief Set the response action for a SAM event.
178  *
179  * \param[in] dev              Pointer to SAM device struct.
180  * \param[in] event_id         Event ID for which to set response.
181  * \param[in] response         Response action to set.
182  * \param[in] enable_response  Enable or disable the response.
183  *
184  * \return Error code of enum sam_error_t type.
185  */
186 enum sam_error_t sam_set_event_response(const struct sam_dev_t *dev,
187                                         enum sam_event_id_t event_id,
188                                         enum sam_response_t response,
189                                         bool enable_response);
190 
191 /**
192  * \brief Set the SAM watchdog counter initial value.
193  *
194  * \param[in] dev          Pointer to SAM device struct.
195  * \param[in] count_value  Number of cycles to count after a SAM event before
196  *                         asserting the watchdog event:
197  *                         0: watchdog count down disabled,
198  *                         1 to (2^26)-1: valid initial count values.
199  * \param[in] responses    Bitwise OR of response actions that trigger the
200  *                         watchdog counter. SAM_RESPONSE_COLD_RESET and
201  *                         SAM_RESPONSE_WARM_RESET are ignored.
202  */
203 void sam_set_watchdog_counter_initial_value(const struct sam_dev_t *dev,
204                                             uint32_t count_value,
205                                             enum sam_response_t responses);
206 
207 /**
208  * \brief Register a handler function for a SAM event.
209  *
210  * \param[in] dev            Pointer to SAM device struct.
211  * \param[in] event_id       Event ID to handle.
212  * \param[in] event_handler  Pointer to event handler function.
213  *
214  * \return Error code of enum sam_error_t type.
215  */
216 enum sam_error_t sam_register_event_handler(struct sam_dev_t *dev,
217                                             enum sam_event_id_t event_id,
218                                             sam_event_handler_t event_handler);
219 
220 /**
221  * \brief Handle any outstanding SAM events by calling the corresponding
222  *        registered event handler functions.
223  *
224  * \note This function is intended to be called from an interrupt handler.
225  *
226  * \param[in] dev  Pointer to SAM device struct.
227  */
228 void sam_handle_event(const struct sam_dev_t *dev);
229 
230 /**
231  * \brief Handle an SRAM partial write event.
232  *
233  * \note This function is intended to be called from an interrupt handler.
234  *
235  * \param[in] dev  Pointer to SAM device struct.
236  */
237 void sam_handle_partial_write(const struct sam_dev_t *dev);
238 
239 /**
240  * \brief Handle an SRAM single ECC error event.
241  *
242  * \note This function is intended to be called from an interrupt handler.
243  *
244  * \param[in] dev  Pointer to SAM device struct.
245  */
246 void sam_handle_single_ecc_error(const struct sam_dev_t *dev);
247 
248 #ifdef __cplusplus
249 }
250 #endif
251 
252 #endif /* __SAM_DRV_H__ */
253