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