1 /*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 #include <lk/err.h>
9 #include <lk/debug.h>
10 #include <stdlib.h>
11 #include <lk/reg.h>
12 #include <dev/uart.h>
13 #include <platform.h>
14 #include <platform/stm32.h>
15 #include <platform/sdram.h>
16 #include <kernel/novm.h>
17 #include <arch/arm/cm.h>
18
19 uint32_t SystemCoreClock = HSI_VALUE;
20 uint32_t stm32_unique_id[3];
21
22 #if defined(ENABLE_SDRAM)
23 // target exports this with sdram configuration values
24 extern const sdram_config_t target_sdram_config;
25 #endif
26
SystemInit(void)27 void SystemInit(void) {
28 /* Reset the RCC clock configuration to the default reset state ------------*/
29 /* Set HSION bit */
30 RCC->CR |= (uint32_t)0x00000001;
31
32 /* Reset CFGR register */
33 RCC->CFGR = 0x00000000;
34
35 /* Reset HSEON, CSSON and PLLON bits */
36 RCC->CR &= (uint32_t)0xFEF6FFFF;
37
38 /* Reset PLLCFGR register */
39 RCC->PLLCFGR = 0x24003010;
40
41 /* Reset HSEBYP bit */
42 RCC->CR &= (uint32_t)0xFFFBFFFF;
43
44 /* Disable all interrupts */
45 RCC->CIR = 0x00000000;
46
47 __HAL_RCC_PWR_CLK_ENABLE();
48
49 #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
50 SystemInit_ExtMemCtl();
51 #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
52 }
53
54 /**
55 * @brief System Clock Configuration
56 * The system Clock is configured as follow :
57 * System Clock source = PLL (HSE or HSI)
58 * SYSCLK(Hz) = 216000000
59 * HCLK(Hz) = 216000000
60 * AHB Prescaler = 1
61 * APB1 Prescaler = 4
62 * APB2 Prescaler = 2
63 * HSE Frequency(Hz) = 25000000
64 * PLL_M = 25 or 16
65 * PLL_N = 432
66 * PLL_P = 2
67 * PLL_Q = 9
68 * VDD(V) = 3.3
69 * Main regulator output voltage = Scale1 mode
70 * Flash Latency(WS) = 7
71 * @param None
72 * @retval None
73 */
SystemClock_Config(void)74 static void SystemClock_Config(void) {
75 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
76 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
77 HAL_StatusTypeDef ret = HAL_OK;
78
79 #if defined(USE_HSE_XTAL)
80 /* Enable HSE Oscillator and activate PLL with HSE as source.
81 * The external XTAL is a more stable clock source.
82 */
83 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
84 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
85 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
86 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
87 RCC_OscInitStruct.PLL.PLLM = 25;
88 RCC_OscInitStruct.PLL.PLLN = 432;
89 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
90 RCC_OscInitStruct.PLL.PLLQ = 9;
91 #else
92 /* Enable HSI Oscillator and activate PLL with HSI as source.
93 * Some boards like STm32756G-EVAL2 seem to malfuction with the
94 * HSE xtal configuration.
95 */
96 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
97 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
98 RCC_OscInitStruct.HSICalibrationValue = 16;
99 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
100 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
101 RCC_OscInitStruct.PLL.PLLM = 16;
102 RCC_OscInitStruct.PLL.PLLN = 432;
103 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
104 RCC_OscInitStruct.PLL.PLLQ = 9;
105 #endif
106
107 ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
108 if (ret != HAL_OK) {
109 while (1) { ; }
110 }
111
112 /* Activate the OverDrive to reach the 216 MHz Frequency */
113 ret = HAL_PWREx_EnableOverDrive();
114 if (ret != HAL_OK) {
115 while (1) { ; }
116 }
117
118 /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
119 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
120 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
121 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
122 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
123 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
124
125 ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
126 if (ret != HAL_OK) {
127 while (1) { ; }
128 }
129 }
130
stm32_rng_init(void)131 void stm32_rng_init(void) {
132 RNG_HandleTypeDef rng_handle = { 0 };
133
134 __HAL_RCC_RNG_CLK_ENABLE();
135
136 rng_handle.Instance = RNG;
137 HAL_StatusTypeDef status = HAL_RNG_Init(&rng_handle);
138 if (status != HAL_OK) {
139 panic("error initializing random number hardware\n");
140 }
141
142 /* seed the pseudo random number generator with this */
143 #if STM32_SEED_RAND_FROM_HWRNG
144 uint32_t r;
145
146 /* discard he first result */
147 status = HAL_RNG_GenerateRandomNumber(&rng_handle, &r);
148 if (status != HAL_OK) {
149 panic("error getting random number from hardware\n");
150 }
151
152 status = HAL_RNG_GenerateRandomNumber(&rng_handle, &r);
153 if (status != HAL_OK) {
154 panic("error getting random number from hardware\n");
155 }
156
157 srand(r);
158 #endif
159 }
160
161 /* set up the mpu to enable caching in the appropriate areas */
mpu_init(void)162 static void mpu_init(void) {
163 MPU_Region_InitTypeDef MPU_InitStruct;
164 HAL_MPU_Disable();
165
166 uint region_num = 0;
167
168 /* mark the first bit of the address space as inaccessible, to catch null pointers */
169 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
170 MPU_InitStruct.BaseAddress = 0x0;
171 MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; /* 0x00200000 */
172 MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
173 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
174 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
175 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
176 MPU_InitStruct.Number = region_num++;
177 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
178 MPU_InitStruct.SubRegionDisable = 0x00;
179 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
180 HAL_MPU_ConfigRegion(&MPU_InitStruct);
181
182 #if defined(ENABLE_SDRAM)
183 /* configure SDRAM */
184 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
185 MPU_InitStruct.BaseAddress = SDRAM_BASE;
186
187 MPU_InitStruct.Size =
188 #if SDRAM_SIZE == 0x00100000
189 MPU_REGION_SIZE_1MB;
190 #elif SDRAM_SIZE == 0x00200000
191 MPU_REGION_SIZE_2MB;
192 #elif SDRAM_SIZE == 0x00400000
193 MPU_REGION_SIZE_4MB;
194 #elif SDRAM_SIZE == 0x00800000
195 MPU_REGION_SIZE_8MB;
196 #elif SDRAM_SIZE == 0x01000000
197 MPU_REGION_SIZE_16MB
198 #elif SDRAM_SIZE == 0x02000000
199 MPU_REGION_SIZE_32MB;
200 #elif SDRAM_SIZE == 0x04000000
201 MPU_REGION_SIZE_64MB;
202 #elif SDRAM_SIZE == 0x08000000
203 MPU_REGION_SIZE_128MB;
204 #else
205 #error SDRAM_SIZE not defined.
206 #endif
207
208 MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RW;
209 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
210 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
211 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
212 MPU_InitStruct.Number = region_num++;
213 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
214 MPU_InitStruct.SubRegionDisable = 0x00;
215 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
216 HAL_MPU_ConfigRegion(&MPU_InitStruct);
217 #endif
218
219 // SRAM
220 #if defined(ENABLE_EXT_SRAM)
221 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
222 MPU_InitStruct.BaseAddress = EXT_SRAM_BASE;
223 MPU_InitStruct.Size = MPU_REGION_SIZE_2MB; // XXX use max size of aperture?
224 MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RW;
225 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
226 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
227 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
228 MPU_InitStruct.Number = region_num++;
229 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
230 MPU_InitStruct.SubRegionDisable = 0x00;
231 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
232
233 HAL_MPU_ConfigRegion(&MPU_InitStruct);
234 #endif
235
236 HAL_MPU_Enable(MPU_HFNMI_PRIVDEF);
237 }
238
platform_early_init(void)239 void platform_early_init(void) {
240 // Do general system init
241 SystemInit();
242 SystemClock_Config();
243
244 // Enable the flash ART controller
245 __HAL_FLASH_ART_ENABLE();
246 __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
247
248 /* read the unique id */
249 stm32_unique_id[0] = *REG32(0x1ff0f420);
250 stm32_unique_id[1] = *REG32(0x1ff0f424);
251 stm32_unique_id[2] = *REG32(0x1ff0f428);
252
253 /* seed the random number generator based on this */
254 srand(stm32_unique_id[0] ^ stm32_unique_id[1] ^ stm32_unique_id[2]);
255
256 // Start the systick timer
257 uint32_t sysclk = HAL_RCC_GetSysClockFreq();
258 arm_cm_systick_init(sysclk);
259
260 stm32_timer_early_init();
261 stm32_gpio_early_init();
262 stm32_flash_early_init();
263 stm32_rng_init();
264 stm32_usbc_early_init();
265
266 /* clear the reboot reason */
267 RCC->CSR |= (1<<24);
268
269 #if defined(ENABLE_SDRAM)
270 /* initialize SDRAM */
271 stm32_sdram_init((sdram_config_t *)&target_sdram_config);
272
273 /* add a novm arena for it */
274 novm_add_arena("sdram", SDRAM_BASE, SDRAM_SIZE);
275 #endif
276
277 mpu_init();
278 }
279
platform_init(void)280 void platform_init(void) {
281 printf("clocks:\n");
282 printf("\tsysclk %u\n", HAL_RCC_GetSysClockFreq());
283 printf("\thclk %u\n", HAL_RCC_GetHCLKFreq());
284 printf("\tpclk1 %u\n", HAL_RCC_GetPCLK1Freq());
285 printf("\tpclk2 %u\n", HAL_RCC_GetPCLK2Freq());
286
287 printf("unique id: 0x%08x%08x%08x\n", stm32_unique_id[0], stm32_unique_id[1], stm32_unique_id[2]);
288
289 stm32_timer_init();
290
291 stm32_flash_init();
292
293 stm32_usbc_init();
294 }
295
296