1 /*
2 * Copyright 2020-2022 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_cdog.h"
9
10 /*******************************************************************************
11 * Definitions
12 *******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.cdog"
17 #endif
18
19 /* Reset CONTROL mask */
20 #define RESERVED_CTRL_MASK 0x800u
21
22 #if defined(CDOG_IRQS)
23 /* Array of IRQs */
24 static const IRQn_Type s_CdogIrqs[] = CDOG_IRQS;
25 #endif /* CDOG_IRQS */
26
27 #ifdef CDOG_CLOCKS
28 static const clock_ip_name_t s_CdogClocks[] = CDOG_CLOCKS;
29 #endif /* CDOG_CLOCKS */
30
31 #ifdef CDOG_BASE_PTRS
32 static const CDOG_Type* s_cdogBases[] = CDOG_BASE_PTRS;
33 #endif /* CDOG_BASE_PTRS */
34
35 /*******************************************************************************
36 * Prototypes
37 ******************************************************************************/
38
39 /*******************************************************************************
40 * Code
41 ******************************************************************************/
42
CDOG_GetInstance(CDOG_Type * base)43 static uint32_t CDOG_GetInstance(CDOG_Type *base)
44 {
45 uint32_t instance;
46
47 /* Find the instance index from base address mappings. */
48 for (instance = 0; instance < ARRAY_SIZE(s_cdogBases); instance++)
49 {
50 if (s_cdogBases[instance] == base)
51 {
52 break;
53 }
54 }
55
56 assert(instance < ARRAY_SIZE(s_cdogBases));
57
58 return instance;
59 }
60
61 /*!
62 * brief Sets the default configuration of CDOG
63 *
64 * This function initialize CDOG config structure to default values.
65 *
66 * param conf CDOG configuration structure
67 */
CDOG_GetDefaultConfig(cdog_config_t * conf)68 void CDOG_GetDefaultConfig(cdog_config_t *conf)
69 {
70 /* Default configuration after reset */
71 conf->lock = (uint8_t)kCDOG_LockCtrl_Unlock; /* Lock control */
72 conf->timeout = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Timeout control */
73 conf->miscompare = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Miscompare control */
74 conf->sequence = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Sequence control */
75 conf->state = (uint8_t)kCDOG_FaultCtrl_NoAction; /* State control */
76 conf->address = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Address control */
77 conf->irq_pause = (uint8_t)kCDOG_IrqPauseCtrl_Run; /* IRQ pause control */
78 conf->debug_halt = (uint8_t)kCDOG_DebugHaltCtrl_Run; /* Debug halt control */
79 return;
80 }
81
82 /*!
83 * brief Sets secure counter and instruction timer values
84 *
85 * This function sets value in RELOAD and START registers for instruction timer.
86 *
87 * param base CDOG peripheral base address
88 * param reload reload value
89 * param start start value
90 */
CDOG_Start(CDOG_Type * base,uint32_t reload,uint32_t start)91 void CDOG_Start(CDOG_Type *base, uint32_t reload, uint32_t start)
92 {
93 base->RELOAD = reload;
94 base->START = start;
95 }
96
97 /*!
98 * brief Stops secure counter and instruction timer
99 *
100 * This function stops instruction timer and secure counter.
101 * This also change state of CDOG to IDLE.
102 *
103 * param base CDOG peripheral base address
104 * param stop expected value which will be compared with value of secure counter
105 */
CDOG_Stop(CDOG_Type * base,uint32_t stop)106 void CDOG_Stop(CDOG_Type *base, uint32_t stop)
107 {
108 base->STOP = stop;
109 }
110
111 /*!
112 * brief Sets secure counter and instruction timer values
113 *
114 * This function sets value in STOP, RELOAD and START registers
115 * for instruction timer and secure counter.
116 *
117 * param base CDOG peripheral base address
118 * param stop expected value which will be compared with value of secure counter
119 * param reload reload value for instruction timer
120 * param start start value for secure timer
121 */
CDOG_Set(CDOG_Type * base,uint32_t stop,uint32_t reload,uint32_t start)122 void CDOG_Set(CDOG_Type *base, uint32_t stop, uint32_t reload, uint32_t start)
123 {
124 base->STOP = stop;
125 base->RELOAD = reload;
126 base->START = start;
127 }
128
129 /*!
130 * brief Add value to secure counter
131 *
132 * This function add specified value to secure counter.
133 *
134 * param base CDOG peripheral base address.
135 * param add Value to be added.
136 */
CDOG_Add(CDOG_Type * base,uint32_t add)137 void CDOG_Add(CDOG_Type *base, uint32_t add)
138 {
139 base->ADD = (secure_counter_t)add;
140 }
141
142 /*!
143 * brief Add 1 to secure counter
144 *
145 * This function add 1 to secure counter.
146 *
147 * param base CDOG peripheral base address.
148 * param add Value to be added.
149 */
CDOG_Add1(CDOG_Type * base)150 void CDOG_Add1(CDOG_Type *base)
151 {
152 base->ADD1 = (secure_counter_t)0x1U;
153 }
154
155 /*!
156 * brief Add 16 to secure counter
157 *
158 * This function add 16 to secure counter.
159 *
160 * param base CDOG peripheral base address.
161 * param add Value to be added.
162 */
CDOG_Add16(CDOG_Type * base)163 void CDOG_Add16(CDOG_Type *base)
164 {
165 base->ADD16 = (secure_counter_t)0x1U;
166 }
167
168 /*!
169 * brief Add 256 to secure counter
170 *
171 * This function add 256 to secure counter.
172 *
173 * param base CDOG peripheral base address.
174 * param add Value to be added.
175 */
CDOG_Add256(CDOG_Type * base)176 void CDOG_Add256(CDOG_Type *base)
177 {
178 base->ADD256 = (secure_counter_t)0x1U;
179 }
180
181 /*!
182 * brief Substract value to secure counter
183 *
184 * This function substract specified value to secure counter.
185 *
186 * param base CDOG peripheral base address.
187 * param sub Value to be substracted.
188 */
CDOG_Sub(CDOG_Type * base,uint32_t sub)189 void CDOG_Sub(CDOG_Type *base, uint32_t sub)
190 {
191 base->SUB = (secure_counter_t)sub;
192 }
193
194 /*!
195 * brief Substract 1 from secure counter
196 *
197 * This function substract specified 1 from secure counter.
198 *
199 * param base CDOG peripheral base address.
200 */
CDOG_Sub1(CDOG_Type * base)201 void CDOG_Sub1(CDOG_Type *base)
202 {
203 base->SUB1 = (secure_counter_t)0x1U;
204 }
205
206 /*!
207 * brief Substract 16 from secure counter
208 *
209 * This function substract specified 16 from secure counter.
210 *
211 * param base CDOG peripheral base address.
212 */
CDOG_Sub16(CDOG_Type * base)213 void CDOG_Sub16(CDOG_Type *base)
214 {
215 base->SUB16 = (secure_counter_t)0x1U;
216 }
217
218 /*!
219 * brief Substract 256 from secure counter
220 *
221 * This function substract specified 256 from secure counter.
222 *
223 * param base CDOG peripheral base address.
224 */
CDOG_Sub256(CDOG_Type * base)225 void CDOG_Sub256(CDOG_Type *base)
226 {
227 base->SUB256 = (secure_counter_t)0x1U;
228 }
229
230 /*!
231 * brief Checks secure counter.
232 *
233 * This function compares stop value with secure counter value
234 * by writting to RELOAD refister.
235 *
236 * param base CDOG peripheral base address
237 * param check expected (stop) value.
238 */
CDOG_Check(CDOG_Type * base,uint32_t check)239 void CDOG_Check(CDOG_Type *base, uint32_t check)
240 {
241 #if defined(FLS_FEATURE_CDOG_USE_RESTART)
242 base->RESTART = check;
243 #else
244 base->STOP = check;
245 base->RELOAD = base->RELOAD;
246 base->START= check;
247 #endif
248 }
249
250 /*!
251 * brief Set the CDOG persistent word.
252 *
253 * param base CDOG peripheral base address.
254 * param value The value to be written.
255 */
CDOG_WritePersistent(CDOG_Type * base,uint32_t value)256 void CDOG_WritePersistent(CDOG_Type *base, uint32_t value)
257 {
258 base->PERSISTENT = value;
259 }
260
261 /*!
262 * brief Get the CDOG persistent word.
263 *
264 * param base CDOG peripheral base address.
265 * return The persistent word.
266 */
CDOG_ReadPersistent(CDOG_Type * base)267 uint32_t CDOG_ReadPersistent(CDOG_Type *base)
268 {
269 return base->PERSISTENT;
270 }
271
272 /*!
273 * brief Initialize CDOG
274 *
275 * This function initializes CDOG setting and enable all interrupts.
276 *
277 * param base CDOG peripheral base address
278 * param conf CDOG configuration structure
279 * return Status of the init operation
280 */
CDOG_Init(CDOG_Type * base,cdog_config_t * conf)281 status_t CDOG_Init(CDOG_Type *base, cdog_config_t *conf)
282 {
283 /* Ungate clock to CDOG engine and reset it */
284 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
285 #ifdef CDOG_CLOCKS
286 CLOCK_EnableClock(s_CdogClocks[CDOG_GetInstance(base)]);
287 #endif /* CDOG_CLOCKS */
288 #endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
289
290 #if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
291 RESET_PeripheralReset(kCDOG_RST_SHIFT_RSTn);
292 #endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
293
294 if (base->CONTROL == 0x0U)
295 {
296 /* CDOG is not in IDLE mode, which may be cause after SW reset. */
297 /* Writing to CONTROL register will trigger fault. */
298 return kStatus_Fail;
299 }
300
301 /* Clear pending errors, otherwise the device will reset */
302 /* itself immediately after enable Code Watchdog */
303 if ((uint32_t)kCDOG_LockCtrl_Lock ==
304 ((base->CONTROL & CDOG_CONTROL_LOCK_CTRL_MASK) >> CDOG_CONTROL_LOCK_CTRL_SHIFT))
305
306 {
307 base->FLAGS = CDOG_FLAGS_TO_FLAG(1U) | CDOG_FLAGS_MISCOM_FLAG(1U) | CDOG_FLAGS_SEQ_FLAG(1U) |
308 CDOG_FLAGS_CNT_FLAG(1U) | CDOG_FLAGS_STATE_FLAG(1U) | CDOG_FLAGS_ADDR_FLAG(1U) |
309 CDOG_FLAGS_POR_FLAG(1U);
310 }
311 else
312 {
313 /* load default values for CDOG->CONTROL before flags clear */
314 #if defined(FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF) && (FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF > 0)
315 cdog_config_t default_conf;
316
317 /* Initialize CDOG */
318 CDOG_GetDefaultConfig(&default_conf);
319
320 /* Write default value to CDOG->CONTROL*/
321 base->CONTROL =
322 CDOG_CONTROL_TIMEOUT_CTRL(default_conf.timeout) | /* Action if the timeout event is triggered */
323 CDOG_CONTROL_MISCOMPARE_CTRL(default_conf.miscompare) | /* Action if the miscompare error event is triggered */
324 CDOG_CONTROL_SEQUENCE_CTRL(default_conf.sequence) | /* Action if the sequence error event is triggered */
325 CDOG_CONTROL_STATE_CTRL(default_conf.state) | /* Action if the state error event is triggered */
326 CDOG_CONTROL_ADDRESS_CTRL(default_conf.address) | /* Action if the address error event is triggered */
327 CDOG_CONTROL_IRQ_PAUSE(default_conf.irq_pause) | /* Pause running during interrupts setup */
328 CDOG_CONTROL_DEBUG_HALT_CTRL(default_conf.debug_halt) | /* Halt CDOG timer during debug */
329 CDOG_CONTROL_LOCK_CTRL(default_conf.lock) | RESERVED_CTRL_MASK; /* Lock control register, RESERVED */
330 #endif /* FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF */
331
332 base->FLAGS = CDOG_FLAGS_TO_FLAG(0U) | CDOG_FLAGS_MISCOM_FLAG(0U) | CDOG_FLAGS_SEQ_FLAG(0U) |
333 CDOG_FLAGS_CNT_FLAG(0U) | CDOG_FLAGS_STATE_FLAG(0U) | CDOG_FLAGS_ADDR_FLAG(0U) |
334 CDOG_FLAGS_POR_FLAG(0U);
335 }
336
337 base->CONTROL =
338 CDOG_CONTROL_TIMEOUT_CTRL(conf->timeout) | /* Action if the timeout event is triggered */
339 CDOG_CONTROL_MISCOMPARE_CTRL(conf->miscompare) | /* Action if the miscompare error event is triggered */
340 CDOG_CONTROL_SEQUENCE_CTRL(conf->sequence) | /* Action if the sequence error event is triggered */
341 CDOG_CONTROL_STATE_CTRL(conf->state) | /* Action if the state error event is triggered */
342 CDOG_CONTROL_ADDRESS_CTRL(conf->address) | /* Action if the address error event is triggered */
343 CDOG_CONTROL_IRQ_PAUSE(conf->irq_pause) | /* Pause running during interrupts setup */
344 CDOG_CONTROL_DEBUG_HALT_CTRL(conf->debug_halt) | /* Halt CDOG timer during debug */
345 CDOG_CONTROL_LOCK_CTRL(conf->lock) | RESERVED_CTRL_MASK; /* Lock control register, RESERVED */
346
347 #if defined(CDOG_IRQS)
348 /* Enable peripheral IRQ */
349 NVIC_EnableIRQ(s_CdogIrqs[CDOG_GetInstance(base)]);
350 #endif /* CDOG_IRQS */
351
352 return kStatus_Success;
353 }
354
355 /*!
356 * brief Deinitialize CDOG
357 *
358 * This function stops CDOG secure counter.
359 *
360 * param base CDOG peripheral base address
361 */
CDOG_Deinit(CDOG_Type * base)362 void CDOG_Deinit(CDOG_Type *base)
363 {
364 #if defined(CDOG_IRQS)
365 /* Disable peripheral IRQ */
366 NVIC_DisableIRQ(s_CdogIrqs[CDOG_GetInstance(base)]);
367 #endif /* CDOG_IRQS */
368
369 #if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
370 RESET_SetPeripheralReset(kCDOG_RST_SHIFT_RSTn);
371 #endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
372
373 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
374 #ifdef CDOG_CLOCKS
375 CLOCK_DisableClock(s_CdogClocks[CDOG_GetInstance(base)]);
376 #endif /* CDOG_CLOCKS */
377 #endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
378 }
379