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 #include <string.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include "max32650.h"
25 #include "gcr_regs.h"
26 #include "mxc_sys.h"
27 #include "usbhs_regs.h"
28 #include "flc_regs.h"
29 #include "icc_regs.h"
30 #include "mxc_errors.h"
31
32 extern void (*const __isr_vector[])(void);
33 uint32_t SystemCoreClock = 0;
34 uint8_t ChipRevision = 0;
35
36 /*
37 The libc implementation from GCC 11+ depends on _getpid and _kill in some places.
38 There is no concept of processes/PIDs in the baremetal PeriphDrivers, therefore
39 we implement stub functions that return an error code to resolve linker warnings.
40 */
_getpid(void)41 __weak int _getpid(void)
42 {
43 return E_NOT_SUPPORTED;
44 }
45
_kill(void)46 __weak int _kill(void)
47 {
48 return E_NOT_SUPPORTED;
49 }
50
SystemCoreClockUpdate(void)51 __weak void SystemCoreClockUpdate(void)
52 {
53 uint32_t base_freq, div, clk_src;
54
55 // Get the clock source and frequency
56 clk_src = (MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_SYSOSC_SEL);
57 if (clk_src == MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_HFXIN) {
58 base_freq = HFX_FREQ;
59 } else if (clk_src == MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_NANORING) {
60 base_freq = NANORING_FREQ;
61 } else if (clk_src == MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_HIRC96) {
62 base_freq = HIRC96_FREQ;
63 } else if (clk_src == MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_HIRC8) {
64 base_freq = HIRC8_FREQ;
65 } else {
66 #ifndef CRYPTO_FREQ
67 if (ChipRevision > 0xA1) {
68 base_freq = CRYPTO_FREQ_A3;
69 } else {
70 base_freq = CRYPTO_FREQ_A1;
71 }
72 #else
73 base_freq = CRYPTO_FREQ;
74 #endif
75 }
76
77 // Get the clock divider
78 div = (MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_SYSCLK_PRESCALE) >>
79 MXC_F_GCR_CLK_CTRL_SYSCLK_PRESCALE_POS;
80
81 SystemCoreClock = base_freq >> div;
82 }
83
84 /* This function is called before C runtime initialization and can be
85 * implemented by the application for early initializations. If a value other
86 * than '0' is returned, the C runtime initialization will be skipped.
87 *
88 * You may over-ride this function in your program by defining a custom
89 * PreInit(), but care should be taken to reproduce the initialization steps
90 * or a non-functional system may result.
91 */
PreInit(void)92 __weak int PreInit(void)
93 {
94 /* Workaround: Write to SCON register on power up to fix trim issue for SRAM */
95 MXC_GCR->scon = (MXC_GCR->scon & ~(MXC_F_GCR_SCON_OVR)) | (MXC_S_GCR_SCON_OVR_1V1);
96 return 0;
97 }
98
99 /* This function can be implemented by the application to initialize the board */
Board_Init(void)100 __weak int Board_Init(void)
101 {
102 /* Do nothing */
103 return 0;
104 }
105
106 /* This function is called just before control is transferred to main().
107 *
108 * You may over-ride this function in your program by defining a custom
109 * SystemInit(), but care should be taken to reproduce the initialization
110 * steps or a non-functional system may result.
111 */
SystemInit(void)112 __weak void SystemInit(void)
113 {
114 ChipRevision = MXC_SYS_GetRev();
115 /* Configure the interrupt controller to use the application vector table in */
116 /* the application space */
117 SCB->VTOR = (uint32_t)__isr_vector;
118
119 /* MAX3265x ROM turns off interrupts, which is not the same as the reset state. */
120 __enable_irq();
121
122 /* Enable FPU on Cortex-M4, which occupies coprocessor slots 10 & 11 */
123 /* Grant full access, per "Table B3-24 CPACR bit assignments". */
124 /* DDI0403D "ARMv7-M Architecture Reference Manual" */
125 SCB->CPACR |= SCB_CPACR_CP10_Msk | SCB_CPACR_CP11_Msk;
126 __DSB();
127 __ISB();
128
129 /* Change system clock source to the main high-speed clock */
130 MXC_SYS_Clock_Select(MXC_SYS_CLOCK_HIRC96);
131 SystemCoreClockUpdate();
132
133 /* Erratum #?: Adjust register timing for VCORE == 1.1v, prevents USB failure. 2017-10-04 ZNM/HTN */
134 MXC_GCR->scon |= MXC_S_GCR_SCON_OVR_1V1;
135
136 // Flush and enable instruction cache
137 MXC_ICC->invalidate = 1;
138 while (!(MXC_ICC->cache_ctrl & MXC_F_ICC_CACHE_CTRL_READY)) {}
139 MXC_ICC->cache_ctrl |= MXC_F_ICC_CACHE_CTRL_ENABLE;
140 while (!(MXC_ICC->cache_ctrl & MXC_F_ICC_CACHE_CTRL_READY)) {}
141
142 /* Shutdown all peripheral clocks initially. They will be re-enabled by each periph's init function. */
143 /* GPIO Clocks are left enabled */
144 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_USB);
145 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TFT);
146 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_DMA);
147 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SPI0);
148 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SPI1);
149 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SPI2);
150 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_UART0);
151 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_UART1);
152 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_I2C0);
153 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TPU);
154 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TIMER0);
155 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TIMER1);
156 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TIMER2);
157 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TIMER3);
158 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TIMER4);
159 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TIMER5);
160 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_ADC);
161 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_I2C1);
162 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_PT);
163 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SPIXIPF);
164 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SPIXIPM);
165 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_UART2);
166 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_TRNG);
167 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_FLC);
168 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_HBC);
169 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SCACHE);
170 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SDMA);
171 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SEMA);
172 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SDHC);
173 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_ICACHE);
174 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_ICACHEXIP);
175 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_OWIRE);
176 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SPI3);
177 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_I2S);
178 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SPIXIPR);
179
180 Board_Init();
181 }
182
183 #if defined(__CC_ARM)
184 /* Function called post memory initialization (post scatter load) in the Keil Toolchain, which
185 * we are using to call the system core clock update and board initialization
186 * to prevent data corruption if they are called from SystemInit. */
187 extern void $Super$$__main_after_scatterload(void);
$Sub$$__main_after_scatterload(void)188 void $Sub$$__main_after_scatterload(void)
189 {
190 SystemInit();
191 $Super$$__main_after_scatterload();
192 }
193 #endif /* __CC_ARM */
194