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