1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 /**
22  * @file mxc_sys.c
23  * @brief      System layer driver.
24  * @details    This driver is used to control the system layer of the device.
25  */
26 
27 /* **** Includes **** */
28 #include <stddef.h>
29 #include <string.h>
30 #include "mxc_device.h"
31 #include "mxc_assert.h"
32 #include "mxc_sys.h"
33 #include "mxc_delay.h"
34 #include "aes.h"
35 #include "flc.h"
36 #include "lpgcr_regs.h"
37 #include "gcr_regs.h"
38 #include "fcr_regs.h"
39 #include "mcr_regs.h"
40 #include "pwrseq_regs.h"
41 
42 /**
43  * @ingroup mxc_sys
44  * @{
45  */
46 
47 /* **** Definitions **** */
48 #define MXC_SYS_CLOCK_TIMEOUT MSEC(5)
49 
50 // DAP Lock macros
51 #define INFOBLOCK_DAP_LOCK_OFFSET 0x30
52 #define DAP_LOCK_SEQUENCE_01 0x5A5AA5A5
53 #define DAP_LOCK_SEQUENCE_23 0xFFFFFFFF
54 
55 /* **** Globals **** */
56 
57 /* Symbol defined by the build system when loading RISCV image */
58 extern volatile void const *_riscv_boot; // Defined in linker file
59 
60 /* **** Functions **** */
61 
62 /* ************************************************************************** */
MXC_SYS_GetUSN(uint8_t * usn,uint8_t * checksum)63 int MXC_SYS_GetUSN(uint8_t *usn, uint8_t *checksum)
64 {
65     int err = E_NO_ERROR;
66     uint32_t *infoblock = (uint32_t *)MXC_INFO0_MEM_BASE;
67 
68     if (usn == NULL) {
69         return E_NULL_PTR;
70     }
71 
72     /* Read the USN from the info block */
73     MXC_FLC_UnlockInfoBlock(MXC_INFO0_MEM_BASE);
74 
75     uint32_t _usn_32[MXC_SYS_USN_CHECKSUM_LEN / 4];
76     // ^ Declare as uint32_t to preserve mem alignment
77     uint8_t *_usn_8 = (uint8_t *)_usn_32;
78     memset(_usn_8, 0, MXC_SYS_USN_CHECKSUM_LEN);
79 
80     _usn_8[0] = (infoblock[0] & 0x007F8000) >> 15;
81     _usn_8[1] = (infoblock[0] & 0x7F800000) >> 23;
82     _usn_8[2] = (infoblock[1] & 0x0000007F) << 1;
83     _usn_8[2] |= (infoblock[0] & 0x80000000) >> 31;
84     _usn_8[3] = (infoblock[1] & 0x00007F80) >> 7;
85     _usn_8[4] = (infoblock[1] & 0x007F8000) >> 15;
86     _usn_8[5] = (infoblock[1] & 0x7F800000) >> 23;
87     _usn_8[6] = (infoblock[2] & 0x007F8000) >> 15;
88     _usn_8[7] = (infoblock[2] & 0x7F800000) >> 23;
89     _usn_8[8] = (infoblock[3] & 0x0000007F) << 1;
90     _usn_8[8] |= (infoblock[2] & 0x80000000) >> 31;
91     _usn_8[9] = (infoblock[3] & 0x00007F80) >> 7;
92     _usn_8[10] = (infoblock[3] & 0x007F8000) >> 15;
93 
94     /* If requested, verify and return the checksum */
95     if (checksum != NULL) {
96         uint32_t _check_csum_32[MXC_SYS_USN_CHECKSUM_LEN / 4];
97         // ^ Declare as uint32_t to preserve mem alignment
98         uint8_t *check_csum = (uint8_t *)_check_csum_32;
99         memset(check_csum, 0, MXC_SYS_USN_CHECKSUM_LEN);
100         uint8_t aes_key[MXC_SYS_USN_CHECKSUM_LEN] = { 0 }; // NULL Key (per checksum spec)
101 
102         // Read Checksum from the infoblock
103         checksum[0] = ((infoblock[3] & 0x7F800000) >> 23);
104         checksum[1] = ((infoblock[4] & 0x007F8000) >> 15);
105 
106         err = MXC_AES_Init();
107         if (err) {
108             MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
109             return err;
110         }
111 
112         // Set NULL Key
113         MXC_AES_SetExtKey((const void *)aes_key, MXC_AES_128BITS);
114 
115         // Compute Checksum
116         mxc_aes_req_t aes_req;
117         aes_req.length = MXC_SYS_USN_CHECKSUM_LEN / 4;
118         aes_req.inputData = _usn_32;
119         aes_req.resultData = _check_csum_32;
120         aes_req.keySize = MXC_AES_128BITS;
121         aes_req.encryption = MXC_AES_ENCRYPT_EXT_KEY;
122         aes_req.callback = NULL;
123 
124         err = MXC_AES_Generic(&aes_req);
125         if (err) {
126             MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
127             return err;
128         }
129 
130         MXC_AES_Shutdown();
131 
132         // Verify Checksum
133         if (check_csum[0] != checksum[1] || check_csum[1] != checksum[0]) {
134             MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
135             return E_INVALID;
136         }
137     }
138 
139     /* Add the info block checksum to the USN */
140     _usn_8[11] = ((infoblock[3] & 0x7F800000) >> 23);
141     _usn_8[12] = ((infoblock[4] & 0x007F8000) >> 15);
142 
143     MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
144 
145     memcpy(usn, _usn_8, MXC_SYS_USN_LEN);
146 
147     return err;
148 }
149 
150 /* ************************************************************************** */
MXC_SYS_IsClockEnabled(mxc_sys_periph_clock_t clock)151 int MXC_SYS_IsClockEnabled(mxc_sys_periph_clock_t clock)
152 {
153     /* The mxc_sys_periph_clock_t enum uses enum values that are the offset by 32 and 64 for the perckcn1 register. */
154     if (clock > 63) {
155         clock -= 64;
156         return !(MXC_LPGCR->pclkdis & (0x1 << clock));
157     } else if (clock > 31) {
158         clock -= 32;
159         return !(MXC_GCR->pclkdis1 & (0x1 << clock));
160     } else {
161         return !(MXC_GCR->pclkdis0 & (0x1 << clock));
162     }
163 }
164 
165 /* ************************************************************************** */
MXC_SYS_ClockDisable(mxc_sys_periph_clock_t clock)166 void MXC_SYS_ClockDisable(mxc_sys_periph_clock_t clock)
167 {
168     /* The mxc_sys_periph_clock_t enum uses enum values that are the offset by 32 and 64 for the perckcn1 register. */
169     if (clock > 63) {
170         clock -= 64;
171         MXC_LPGCR->pclkdis |= (0x1 << clock);
172     } else if (clock > 31) {
173         clock -= 32;
174         MXC_GCR->pclkdis1 |= (0x1 << clock);
175     } else {
176         MXC_GCR->pclkdis0 |= (0x1 << clock);
177     }
178 }
179 
180 /* ************************************************************************** */
MXC_SYS_ClockEnable(mxc_sys_periph_clock_t clock)181 void MXC_SYS_ClockEnable(mxc_sys_periph_clock_t clock)
182 {
183     /* The mxc_sys_periph_clock_t enum uses enum values that are the offset by 32 and 64 for the perckcn1 register. */
184     if (clock > 63) {
185         clock -= 64;
186         MXC_LPGCR->pclkdis &= ~(0x1 << clock);
187     } else if (clock > 31) {
188         clock -= 32;
189         MXC_GCR->pclkdis1 &= ~(0x1 << clock);
190     } else {
191         MXC_GCR->pclkdis0 &= ~(0x1 << clock);
192     }
193 }
194 /* ************************************************************************** */
MXC_SYS_RTCClockEnable()195 void MXC_SYS_RTCClockEnable()
196 {
197     MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN;
198 }
199 
200 /* ************************************************************************** */
MXC_SYS_RTCClockDisable(void)201 int MXC_SYS_RTCClockDisable(void)
202 {
203     /* Check that the RTC is not the system clock source */
204     if ((MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL) != MXC_S_GCR_CLKCTRL_SYSCLK_SEL_ERTCO) {
205         MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_ERTCO_EN;
206         return E_NO_ERROR;
207     } else {
208         return E_BAD_STATE;
209     }
210 }
211 
212 /******************************************************************************/
MXC_SYS_ClockSourceEnable(mxc_sys_system_clock_t clock)213 int MXC_SYS_ClockSourceEnable(mxc_sys_system_clock_t clock)
214 {
215     int err = E_NO_ERROR;
216 
217     switch (clock) {
218     case MXC_SYS_CLOCK_IPO:
219         MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IPO_EN;
220         return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IPO_RDY);
221         break;
222 
223     case MXC_SYS_CLOCK_IBRO:
224         MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN;
225         return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IBRO_RDY);
226         break;
227 
228     case MXC_SYS_CLOCK_ISO:
229         MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ISO_EN;
230         return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ISO_RDY);
231         break;
232 
233     case MXC_SYS_CLOCK_EXTCLK:
234         // No EXT_CLK "RDY" bit for AI87 so we enable every time
235         err = MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_EXTCLK);
236         if (err)
237             return err;
238 
239         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
240                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_EXTCLK);
241         break;
242 
243     case MXC_SYS_CLOCK_INRO:
244         // The 80k clock is always enabled
245         return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_INRO_RDY);
246         break;
247 
248     case MXC_SYS_CLOCK_EBO:
249         MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_EBO_EN;
250         return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_EBO_RDY);
251         break;
252 
253     case MXC_SYS_CLOCK_ERTCO:
254         MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN;
255         return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ERTCO_RDY);
256         break;
257 
258     case MXC_SYS_CLOCK_IPLL:
259         MXC_GCR->ipll_ctrl |= MXC_F_GCR_IPLL_CTRL_EN;
260         return MXC_SYS_Clock_Timeout(MXC_F_GCR_IPLL_CTRL_RDY);
261         break;
262 
263     default:
264         return E_BAD_PARAM;
265         break;
266     }
267 
268     return err;
269 }
270 
271 /******************************************************************************/
MXC_SYS_ClockSourceDisable(mxc_sys_system_clock_t clock)272 int MXC_SYS_ClockSourceDisable(mxc_sys_system_clock_t clock)
273 {
274     uint32_t current_clock;
275 
276     current_clock = MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL;
277 
278     // Don't turn off the clock we're running on
279     if (clock == current_clock) {
280         return E_BAD_PARAM;
281     }
282 
283     switch (clock) {
284     case MXC_SYS_CLOCK_IPO:
285         MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_IPO_EN;
286         break;
287 
288     case MXC_SYS_CLOCK_ISO:
289         MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_ISO_EN;
290         break;
291 
292     case MXC_SYS_CLOCK_IBRO:
293         MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_IBRO_EN;
294         break;
295 
296     case MXC_SYS_CLOCK_EXTCLK:
297         // MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_EXTCLK_EN;
298         break;
299 
300     case MXC_SYS_CLOCK_INRO:
301         // The 80k clock is always enabled
302         break;
303 
304     case MXC_SYS_CLOCK_EBO:
305         MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_EBO_EN;
306         break;
307 
308     case MXC_SYS_CLOCK_ERTCO:
309         MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_ERTCO_EN;
310         break;
311 
312     case MXC_SYS_CLOCK_IPLL:
313         MXC_GCR->ipll_ctrl &= ~MXC_F_GCR_IPLL_CTRL_EN;
314         break;
315 
316     default:
317         return E_BAD_PARAM;
318     }
319 
320     return E_NO_ERROR;
321 }
322 
323 /* ************************************************************************** */
MXC_SYS_Clock_Timeout(uint32_t ready)324 int MXC_SYS_Clock_Timeout(uint32_t ready)
325 {
326     volatile uint32_t *ready_reg;
327 
328     if (ready == MXC_F_GCR_IPLL_CTRL_RDY) {
329         ready_reg = &(MXC_GCR->ipll_ctrl);
330     } else {
331         ready_reg = &(MXC_GCR->clkctrl);
332     }
333 
334 #ifdef __riscv
335     // The current RISC-V implementation is to block until the clock is ready.
336     // We do not have access to a system tick in the RV core.
337     while (!(*ready_reg & ready)) {}
338     return E_NO_ERROR;
339 #else
340     // Start timeout, wait for ready
341     MXC_DelayAsync(MXC_SYS_CLOCK_TIMEOUT, NULL);
342 
343     do {
344         if (*ready_reg & ready) {
345             MXC_DelayAbort();
346             return E_NO_ERROR;
347         }
348     } while (MXC_DelayCheck() == E_BUSY);
349 
350     return E_TIME_OUT;
351 #endif // __riscv
352 }
353 
354 /* ************************************************************************** */
MXC_SYS_Clock_Select(mxc_sys_system_clock_t clock)355 int MXC_SYS_Clock_Select(mxc_sys_system_clock_t clock)
356 {
357     uint32_t current_clock;
358     int err = E_NO_ERROR;
359 
360     // Save the current system clock
361     current_clock = MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL;
362 
363     switch (clock) {
364     case MXC_SYS_CLOCK_IPO:
365 
366         // Enable IPO clock
367         if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_IPO_EN)) {
368             MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IPO_EN;
369 
370             // Check if IPO clock is ready
371             if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IPO_RDY) != E_NO_ERROR) {
372                 return E_TIME_OUT;
373             }
374         }
375 
376         // Set IPO clock as System Clock
377         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
378                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_IPO);
379 
380         break;
381 
382     case MXC_SYS_CLOCK_ISO:
383         // Enable ISO clock
384         if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_ISO_EN)) {
385             MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ISO_EN;
386 
387             // Check if ISO clock is ready
388             if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ISO_RDY) != E_NO_ERROR) {
389                 return E_TIME_OUT;
390             }
391         }
392 
393         // Set ISO clock as System Clock
394         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
395                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_ISO);
396 
397         break;
398 
399     case MXC_SYS_CLOCK_IPLL:
400         // Enable IPLL clock
401         if (!(MXC_GCR->ipll_ctrl & MXC_F_GCR_IPLL_CTRL_EN)) {
402             MXC_GCR->ipll_ctrl |= MXC_F_GCR_IPLL_CTRL_EN;
403 
404             // Check if IPLL clock is ready
405             if (MXC_SYS_Clock_Timeout(MXC_F_GCR_IPLL_CTRL_RDY) != E_NO_ERROR) {
406                 return E_TIME_OUT;
407             }
408         }
409 
410         // Set IPLL clock as System Clock
411         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
412                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_IPLL);
413 
414         break;
415 
416     case MXC_SYS_CLOCK_EBO:
417         // Enable EBO clock
418         if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_EBO_EN)) {
419             MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_EBO_EN;
420 
421             // Check if ISO clock is ready
422             if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_EBO_RDY) != E_NO_ERROR) {
423                 return E_TIME_OUT;
424             }
425         }
426 
427         // Set ISO clock as System Clock
428         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
429                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_EBO);
430 
431         break;
432 
433     case MXC_SYS_CLOCK_IBRO:
434 
435         // Enable IBRO clock
436         if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_IBRO_EN)) {
437             MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN;
438 
439             // Check if IBRO clock is ready
440             if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IBRO_RDY) != E_NO_ERROR) {
441                 return E_TIME_OUT;
442             }
443         }
444 
445         // Set IBRO clock as System Clock
446         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
447                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_IBRO);
448 
449         break;
450 
451     case MXC_SYS_CLOCK_EXTCLK:
452         // No EXT_CLK "RDY" bit for AI85 so we enable every time
453         err = MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_EXTCLK);
454         if (err)
455             return err;
456 
457         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
458                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_EXTCLK);
459 
460         break;
461 
462     case MXC_SYS_CLOCK_INRO:
463         // Set INRO clock as System Clock
464         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
465                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_INRO);
466 
467         break;
468 
469     case MXC_SYS_CLOCK_ERTCO:
470 
471         // Enable ERTCO clock
472         if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_ERTCO_EN)) {
473             MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN;
474 
475             // Check if ERTCO clock is ready
476             if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ERTCO_RDY) != E_NO_ERROR) {
477                 return E_TIME_OUT;
478             }
479         }
480 
481         // Set ERTCO clock as System Clock
482         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
483                      MXC_S_GCR_CLKCTRL_SYSCLK_SEL_ERTCO);
484 
485         break;
486 
487     default:
488         return E_BAD_PARAM;
489     }
490 
491     // Wait for system clock to be ready
492     if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_SYSCLK_RDY) != E_NO_ERROR) {
493         // Restore the old system clock if timeout
494         MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL, current_clock);
495 
496         return E_TIME_OUT;
497     }
498 
499     // Update the system core clock
500     SystemCoreClockUpdate();
501 
502     return E_NO_ERROR;
503 }
504 
505 /* ************************************************************************** */
MXC_SYS_SetClockDiv(mxc_sys_system_clock_div_t div)506 void MXC_SYS_SetClockDiv(mxc_sys_system_clock_div_t div)
507 {
508     /* Return if this setting is already current */
509     if (div == MXC_SYS_GetClockDiv()) {
510         return;
511     }
512 
513     MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_DIV, div);
514 
515     SystemCoreClockUpdate();
516 }
517 
518 /* ************************************************************************** */
MXC_SYS_GetClockDiv(void)519 mxc_sys_system_clock_div_t MXC_SYS_GetClockDiv(void)
520 {
521     return (MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_DIV);
522 }
523 
524 /* ************************************************************************** */
MXC_SYS_Reset_Periph(mxc_sys_reset_t reset)525 void MXC_SYS_Reset_Periph(mxc_sys_reset_t reset)
526 {
527     /* The mxc_sys_reset_t enum uses enum values that are the offset by 32 and 64 for the rst register. */
528     if (reset > 63) {
529         reset -= 64;
530         MXC_LPGCR->rst = (0x1 << reset);
531         while (MXC_LPGCR->rst & (0x1 << reset)) {}
532     } else if (reset > 31) {
533         reset -= 32;
534         MXC_GCR->rst1 = (0x1 << reset);
535         while (MXC_GCR->rst1 & (0x1 << reset)) {}
536     } else {
537         MXC_GCR->rst0 = (0x1 << reset);
538         while (MXC_GCR->rst0 & (0x1 << reset)) {}
539     }
540 }
541 
542 /* ************************************************************************** */
MXC_SYS_RISCVRun(void)543 void MXC_SYS_RISCVRun(void)
544 {
545     MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_CPU1);
546 
547     /* Disable the the RSCV */
548     MXC_GCR->pclkdis1 |= MXC_F_GCR_PCLKDIS1_CPU1;
549 
550     /* Set the interrupt vector base address */
551     MXC_FCR->urvbootaddr = (uint32_t)&_riscv_boot;
552 
553     /* Power up the RSCV */
554     MXC_GCR->pclkdis1 &= ~(MXC_F_GCR_PCLKDIS1_CPU1);
555 
556     /* CPU1 reset */
557     MXC_GCR->rst1 |= MXC_F_GCR_RST1_CPU1;
558 }
559 
560 /* ************************************************************************** */
MXC_SYS_RISCVShutdown(void)561 void MXC_SYS_RISCVShutdown(void)
562 {
563     /* Disable the the RSCV */
564     MXC_GCR->pclkdis1 |= MXC_F_GCR_PCLKDIS1_CPU1;
565 }
566 
567 // AI87-TODO: Neede to verify these changes
568 /* ************************************************************************** */
MXC_SYS_RiscVClockRate(void)569 uint32_t MXC_SYS_RiscVClockRate(void)
570 {
571     // If in LPM mode and the PCLK is selected as the RV32 clock source,
572     if (((MXC_GCR->pm & MXC_F_GCR_PM_MODE) == MXC_S_GCR_PM_MODE_LPM) &&
573         ((MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_ISOCLK_SELECT) == 0)) {
574         return SystemCoreClock / 2;
575     } else {
576         return ISO_FREQ;
577     }
578 }
579 
580 /* ************************************************************************** */
MXC_SYS_LockDAP_Permanent(void)581 int MXC_SYS_LockDAP_Permanent(void)
582 {
583 #ifdef DEBUG
584     // Locking the DAP is not supported while in DEBUG.
585     // To use this function, build for release ("make release")
586     // or set DEBUG = 0
587     // (see https://analogdevicesinc.github.io/msdk/USERGUIDE/#build-tables)
588     return E_NOT_SUPPORTED;
589 #else
590     int err;
591     uint32_t info_blk_addr;
592     uint32_t lock_sequence[4];
593 
594     // Infoblock address to write lock sequence to
595     info_blk_addr = MXC_INFO_MEM_BASE + INFOBLOCK_DAP_LOCK_OFFSET;
596 
597     // Set lock sequence
598     lock_sequence[0] = DAP_LOCK_SEQUENCE_01;
599     lock_sequence[1] = DAP_LOCK_SEQUENCE_01;
600     lock_sequence[2] = DAP_LOCK_SEQUENCE_23;
601     lock_sequence[3] = DAP_LOCK_SEQUENCE_23;
602 
603     // Initialize FLC
604     MXC_FLC_Init();
605 
606     // Unlock infoblock
607     MXC_FLC_UnlockInfoBlock(info_blk_addr);
608 
609     // Write DAP lock sequence to infoblock
610     err = MXC_FLC_Write128(info_blk_addr, lock_sequence);
611 
612     // Re-lock infoblock
613     MXC_FLC_LockInfoBlock(info_blk_addr);
614 
615     return err;
616 #endif
617 }
618 
619 /**@} end of mxc_sys */
620