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