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