1 /*
2 * Copyright (c) 2017 Linaro Limited.
3 * Copyright (c) 2017 RnDity Sp. z o.o.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <soc.h>
9 #include <stm32_ll_bus.h>
10 #include <stm32_ll_pwr.h>
11 #include <stm32_ll_rcc.h>
12 #include <stm32_ll_system.h>
13 #include <stm32_ll_utils.h>
14 #include <drivers/clock_control.h>
15 #include <sys/util.h>
16 #include <sys/__assert.h>
17 #include <drivers/clock_control/stm32_clock_control.h>
18 #include "clock_stm32_ll_common.h"
19
20 /* Macros to fill up prescaler values */
21 #define fn_ahb_prescaler(v) LL_RCC_SYSCLK_DIV_ ## v
22 #define ahb_prescaler(v) fn_ahb_prescaler(v)
23
24 #define fn_apb1_prescaler(v) LL_RCC_APB1_DIV_ ## v
25 #define apb1_prescaler(v) fn_apb1_prescaler(v)
26
27 #ifndef CONFIG_SOC_SERIES_STM32F0X
28 #define fn_apb2_prescaler(v) LL_RCC_APB2_DIV_ ## v
29 #define apb2_prescaler(v) fn_apb2_prescaler(v)
30 #endif /* CONFIG_SOC_SERIES_STM32F0X */
31
32 #define fn_mco1_prescaler(v) LL_RCC_MCO1_DIV_ ## v
33 #define mco1_prescaler(v) fn_mco1_prescaler(v)
34
35 #define fn_mco2_prescaler(v) LL_RCC_MCO2_DIV_ ## v
36 #define mco2_prescaler(v) fn_mco2_prescaler(v)
37
38 /* Calculate MSI freq for the given range(at RUN range, not after standby) */
39 #if defined(CONFIG_SOC_SERIES_STM32WBX)
40 #define RCC_CALC_MSI_RUN_FREQ(range) __LL_RCC_CALC_MSI_FREQ( \
41 range << RCC_CR_MSIRANGE_Pos)
42 #else
43 #define RCC_CALC_MSI_RUN_FREQ(range) __LL_RCC_CALC_MSI_FREQ( \
44 LL_RCC_MSIRANGESEL_RUN, range << RCC_CR_MSIRANGE_Pos)
45 #endif
46
47 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_SOC_SERIES_STM32WLX)
48 #define __LL_RCC_CALC_HCLK_FREQ __LL_RCC_CALC_HCLK1_FREQ
49 #endif
50
51 #if defined(CONFIG_SOC_SERIES_STM32WBX)
52 #define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK4_FREQ
53 #define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHB4Prescaler
54 #elif defined(CONFIG_SOC_SERIES_STM32WLX)
55 #define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK3_FREQ
56 #define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHB3Prescaler
57 #else
58 #define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK_FREQ
59 #define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHBPrescaler
60 #endif
61
62 /* Identify stm32wl dual-core socs by symbol defined in CMSIS dev header file */
63 #if (defined(CONFIG_SOC_SERIES_STM32WLX) && defined(DUAL_CORE))
64 #define STM32WL_DUAL_CORE
65 #endif
66
67 #if STM32_AHB_PRESCALER > 1
68 /*
69 * AHB prescaler allows to set a HCLK frequency (feeding cortex systick)
70 * lower than SYSCLK frequency (actual core frequency).
71 * Though, zephyr doesn't make a difference today between these two clocks.
72 * So, changing this prescaler is not allowed until it is made possible to
73 * use them independently in zephyr clock subsystem.
74 */
75 #error "AHB prescaler can't be higher than 1"
76 #endif
77
78 /**
79 * @brief fill in AHB/APB buses configuration structure
80 */
config_bus_clk_init(LL_UTILS_ClkInitTypeDef * clk_init)81 static void config_bus_clk_init(LL_UTILS_ClkInitTypeDef *clk_init)
82 {
83 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE)
84 clk_init->CPU2CLKDivider = ahb_prescaler(STM32_CPU2_PRESCALER);
85 #endif
86 #if defined(CONFIG_SOC_SERIES_STM32WBX)
87 clk_init->CPU1CLKDivider = ahb_prescaler(STM32_CPU1_PRESCALER);
88 clk_init->AHB4CLKDivider = ahb_prescaler(STM32_AHB4_PRESCALER);
89 #elif defined(CONFIG_SOC_SERIES_STM32WLX)
90 clk_init->CPU1CLKDivider = ahb_prescaler(STM32_CPU1_PRESCALER);
91 clk_init->AHB3CLKDivider = ahb_prescaler(STM32_AHB3_PRESCALER);
92 #else
93 clk_init->AHBCLKDivider = ahb_prescaler(STM32_AHB_PRESCALER);
94 #endif /* CONFIG_SOC_SERIES_STM32WBX */
95
96 clk_init->APB1CLKDivider = apb1_prescaler(STM32_APB1_PRESCALER);
97
98 #if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
99 !defined (CONFIG_SOC_SERIES_STM32G0X)
100 clk_init->APB2CLKDivider = apb2_prescaler(STM32_APB2_PRESCALER);
101 #endif
102 }
103
get_bus_clock(uint32_t clock,uint32_t prescaler)104 static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler)
105 {
106 return clock / prescaler;
107 }
108
stm32_clock_control_on(const struct device * dev,clock_control_subsys_t sub_system)109 static inline int stm32_clock_control_on(const struct device *dev,
110 clock_control_subsys_t sub_system)
111 {
112 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
113
114 ARG_UNUSED(dev);
115
116 switch (pclken->bus) {
117 case STM32_CLOCK_BUS_AHB1:
118 LL_AHB1_GRP1_EnableClock(pclken->enr);
119 break;
120 #if defined(CONFIG_SOC_SERIES_STM32L4X) || \
121 defined(CONFIG_SOC_SERIES_STM32L5X) || \
122 defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB2_SUPPORT) || \
123 defined(CONFIG_SOC_SERIES_STM32F7X) || \
124 defined(CONFIG_SOC_SERIES_STM32F2X) || \
125 defined(CONFIG_SOC_SERIES_STM32WBX) || \
126 defined(CONFIG_SOC_SERIES_STM32WLX) || \
127 defined(CONFIG_SOC_SERIES_STM32G4X)
128 case STM32_CLOCK_BUS_AHB2:
129 LL_AHB2_GRP1_EnableClock(pclken->enr);
130 break;
131 #endif /* CONFIG_SOC_SERIES_STM32_* */
132 #if defined(CONFIG_SOC_SERIES_STM32L4X) || \
133 defined(CONFIG_SOC_SERIES_STM32L5X) || \
134 defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB3_SUPPORT) || \
135 defined(CONFIG_SOC_SERIES_STM32F7X) || \
136 defined(CONFIG_SOC_SERIES_STM32F2X) || \
137 defined(CONFIG_SOC_SERIES_STM32WBX) || \
138 defined(CONFIG_SOC_SERIES_STM32WLX) || \
139 defined(CONFIG_SOC_SERIES_STM32G4X)
140 case STM32_CLOCK_BUS_AHB3:
141 LL_AHB3_GRP1_EnableClock(pclken->enr);
142 break;
143 #endif /* CONFIG_SOC_SERIES_STM32_* */
144 case STM32_CLOCK_BUS_APB1:
145 LL_APB1_GRP1_EnableClock(pclken->enr);
146 break;
147 #if defined(CONFIG_SOC_SERIES_STM32L4X) || \
148 defined(CONFIG_SOC_SERIES_STM32L5X) || \
149 defined(CONFIG_SOC_SERIES_STM32F0X) || \
150 defined(CONFIG_SOC_SERIES_STM32WBX) || \
151 defined(CONFIG_SOC_SERIES_STM32WLX) || \
152 defined(CONFIG_SOC_SERIES_STM32G4X)
153 case STM32_CLOCK_BUS_APB1_2:
154 LL_APB1_GRP2_EnableClock(pclken->enr);
155 break;
156 #endif /* CONFIG_SOC_SERIES_STM32_* */
157 #if !defined(CONFIG_SOC_SERIES_STM32F0X)
158 case STM32_CLOCK_BUS_APB2:
159 LL_APB2_GRP1_EnableClock(pclken->enr);
160 break;
161 #endif
162 #if defined(CONFIG_SOC_SERIES_STM32WLX)
163 case STM32_CLOCK_BUS_APB3:
164 LL_APB3_GRP1_EnableClock(pclken->enr);
165 break;
166 #endif
167 #if defined (CONFIG_SOC_SERIES_STM32L0X) || \
168 defined (CONFIG_SOC_SERIES_STM32G0X)
169 case STM32_CLOCK_BUS_IOP:
170 LL_IOP_GRP1_EnableClock(pclken->enr);
171 break;
172 #endif
173 default:
174 return -ENOTSUP;
175 }
176
177 return 0;
178 }
179
180
stm32_clock_control_off(const struct device * dev,clock_control_subsys_t sub_system)181 static inline int stm32_clock_control_off(const struct device *dev,
182 clock_control_subsys_t sub_system)
183 {
184 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
185
186 ARG_UNUSED(dev);
187
188 switch (pclken->bus) {
189 case STM32_CLOCK_BUS_AHB1:
190 LL_AHB1_GRP1_DisableClock(pclken->enr);
191 break;
192 #if defined(CONFIG_SOC_SERIES_STM32L4X) || \
193 defined(CONFIG_SOC_SERIES_STM32L5X) || \
194 defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB2_SUPPORT) || \
195 defined(CONFIG_SOC_SERIES_STM32F7X) || \
196 defined(CONFIG_SOC_SERIES_STM32F2X) || \
197 defined(CONFIG_SOC_SERIES_STM32WBX) || \
198 defined(CONFIG_SOC_SERIES_STM32WLX) || \
199 defined(CONFIG_SOC_SERIES_STM32G4X)
200 case STM32_CLOCK_BUS_AHB2:
201 LL_AHB2_GRP1_DisableClock(pclken->enr);
202 break;
203 #endif /* CONFIG_SOC_SERIES_STM32_* */
204 #if defined(CONFIG_SOC_SERIES_STM32L4X) || \
205 defined(CONFIG_SOC_SERIES_STM32L5X) || \
206 defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB3_SUPPORT) || \
207 defined(CONFIG_SOC_SERIES_STM32F7X) || \
208 defined(CONFIG_SOC_SERIES_STM32F2X) || \
209 defined(CONFIG_SOC_SERIES_STM32WBX) || \
210 defined(CONFIG_SOC_SERIES_STM32WLX) || \
211 defined(CONFIG_SOC_SERIES_STM32G4X)
212 case STM32_CLOCK_BUS_AHB3:
213 LL_AHB3_GRP1_DisableClock(pclken->enr);
214 break;
215 #endif /* CONFIG_SOC_SERIES_STM32_* */
216 case STM32_CLOCK_BUS_APB1:
217 LL_APB1_GRP1_DisableClock(pclken->enr);
218 break;
219 #if defined(CONFIG_SOC_SERIES_STM32L4X) || \
220 defined(CONFIG_SOC_SERIES_STM32L5X) || \
221 defined(CONFIG_SOC_SERIES_STM32F0X) || \
222 defined(CONFIG_SOC_SERIES_STM32WBX) || \
223 defined(CONFIG_SOC_SERIES_STM32WLX) || \
224 defined(CONFIG_SOC_SERIES_STM32G4X)
225 case STM32_CLOCK_BUS_APB1_2:
226 LL_APB1_GRP2_DisableClock(pclken->enr);
227 break;
228 #endif /* CONFIG_SOC_SERIES_STM32_* */
229 #if !defined(CONFIG_SOC_SERIES_STM32F0X)
230 case STM32_CLOCK_BUS_APB2:
231 LL_APB2_GRP1_DisableClock(pclken->enr);
232 break;
233 #endif
234 #if defined(CONFIG_SOC_SERIES_STM32WLX)
235 case STM32_CLOCK_BUS_APB3:
236 LL_APB3_GRP1_DisableClock(pclken->enr);
237 break;
238 #endif
239 #if defined (CONFIG_SOC_SERIES_STM32L0X) || \
240 defined (CONFIG_SOC_SERIES_STM32G0X)
241 case STM32_CLOCK_BUS_IOP:
242 LL_IOP_GRP1_DisableClock(pclken->enr);
243 break;
244 #endif
245 default:
246 return -ENOTSUP;
247 }
248
249 return 0;
250 }
251
252
stm32_clock_control_get_subsys_rate(const struct device * clock,clock_control_subsys_t sub_system,uint32_t * rate)253 static int stm32_clock_control_get_subsys_rate(const struct device *clock,
254 clock_control_subsys_t sub_system,
255 uint32_t *rate)
256 {
257 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
258 /*
259 * Get AHB Clock (= SystemCoreClock = SYSCLK/prescaler)
260 * SystemCoreClock is preferred to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC
261 * since it will be updated after clock configuration and hence
262 * more likely to contain actual clock speed
263 */
264 uint32_t ahb_clock = SystemCoreClock;
265 uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_APB1_PRESCALER);
266 #if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
267 !defined (CONFIG_SOC_SERIES_STM32G0X)
268 uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_APB2_PRESCALER);
269 #endif
270 #if defined(CONFIG_SOC_SERIES_STM32WLX)
271 uint32_t ahb3_clock = get_bus_clock(ahb_clock * STM32_CPU1_PRESCALER,
272 STM32_AHB3_PRESCALER);
273 #endif
274
275 ARG_UNUSED(clock);
276
277 switch (pclken->bus) {
278 case STM32_CLOCK_BUS_AHB1:
279 case STM32_CLOCK_BUS_AHB2:
280 #if !defined(CONFIG_SOC_SERIES_STM32WLX)
281 case STM32_CLOCK_BUS_AHB3:
282 #endif
283 #if defined (CONFIG_SOC_SERIES_STM32L0X) || \
284 defined (CONFIG_SOC_SERIES_STM32G0X)
285 case STM32_CLOCK_BUS_IOP:
286 #endif
287 *rate = ahb_clock;
288 break;
289 case STM32_CLOCK_BUS_APB1:
290 #if defined(CONFIG_SOC_SERIES_STM32L4X) || \
291 defined(CONFIG_SOC_SERIES_STM32L5X) || \
292 defined(CONFIG_SOC_SERIES_STM32F0X) || \
293 defined(CONFIG_SOC_SERIES_STM32WBX) || \
294 defined(CONFIG_SOC_SERIES_STM32WLX) || \
295 defined(CONFIG_SOC_SERIES_STM32G4X)
296 case STM32_CLOCK_BUS_APB1_2:
297 #endif /* CONFIG_SOC_SERIES_STM32_* */
298 #if defined(CONFIG_SOC_SERIES_STM32G0X)
299 case STM32_CLOCK_BUS_APB2:
300 /*
301 * STM32G0x only has one APB, but two reset/clock enable
302 * registers for peripherals, so return the APB1 clock rate here
303 */
304 #endif /* CONFIG_SOC_SERIES_STM32G0X */
305 *rate = apb1_clock;
306 break;
307 #if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
308 !defined (CONFIG_SOC_SERIES_STM32G0X)
309 case STM32_CLOCK_BUS_APB2:
310 *rate = apb2_clock;
311 break;
312 #endif
313 #if defined(CONFIG_SOC_SERIES_STM32WLX)
314 case STM32_CLOCK_BUS_AHB3:
315 case STM32_CLOCK_BUS_APB3:
316 /* AHB3 and APB3 share the same clock and prescaler. */
317 *rate = ahb3_clock;
318 break;
319 #endif
320 default:
321 return -ENOTSUP;
322 }
323
324 return 0;
325 }
326
327 static struct clock_control_driver_api stm32_clock_control_api = {
328 .on = stm32_clock_control_on,
329 .off = stm32_clock_control_off,
330 .get_rate = stm32_clock_control_get_subsys_rate,
331 };
332
333 /*
334 * Unconditionally switch the system clock source to HSI.
335 */
336 __unused
stm32_clock_switch_to_hsi(uint32_t new_ahb_prescaler)337 static void stm32_clock_switch_to_hsi(uint32_t new_ahb_prescaler)
338 {
339 /* Enable HSI if not enabled */
340 if (LL_RCC_HSI_IsReady() != 1) {
341 /* Enable HSI */
342 LL_RCC_HSI_Enable();
343 while (LL_RCC_HSI_IsReady() != 1) {
344 /* Wait for HSI ready */
345 }
346 }
347
348 /* Set HSI as SYSCLCK source */
349 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
350 LL_RCC_SetAHBPrescaler(new_ahb_prescaler);
351 while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {
352 }
353 }
354
355 /*
356 * MCO configure doesn't active requested clock source,
357 * so please make sure the clock source was enabled.
358 */
stm32_clock_control_mco_init(void)359 static inline void stm32_clock_control_mco_init(void)
360 {
361 #ifndef CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK
362 LL_RCC_ConfigMCO(MCO1_SOURCE,
363 mco1_prescaler(CONFIG_CLOCK_STM32_MCO1_DIV));
364 #endif /* CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK */
365
366 #ifndef CONFIG_CLOCK_STM32_MCO2_SRC_NOCLOCK
367 LL_RCC_ConfigMCO(MCO2_SOURCE,
368 mco2_prescaler(CONFIG_CLOCK_STM32_MCO2_DIV));
369 #endif /* CONFIG_CLOCK_STM32_MCO2_SRC_NOCLOCK */
370 }
371
372
373 /**
374 * @brief Initialize clocks for the stm32
375 *
376 * This routine is called to enable and configure the clocks and PLL
377 * of the soc on the board. It depends on the board definition.
378 * This function is called on the startup and also to restore the config
379 * when exiting for low power mode.
380 *
381 * @param dev clock device struct
382 *
383 * @return 0
384 */
stm32_clock_control_init(const struct device * dev)385 int stm32_clock_control_init(const struct device *dev)
386 {
387 LL_UTILS_ClkInitTypeDef s_ClkInitStruct;
388 uint32_t hclk_prescaler;
389 uint32_t flash_prescaler;
390 #if STM32_SYSCLK_SRC_HSE || STM32_SYSCLK_SRC_MSI
391 uint32_t new_hclk_freq;
392 uint32_t old_flash_freq;
393 uint32_t new_flash_freq;
394 #endif
395
396 ARG_UNUSED(dev);
397
398 /* configure clock for AHB/APB buses */
399 config_bus_clk_init((LL_UTILS_ClkInitTypeDef *)&s_ClkInitStruct);
400
401 /* update local hclk and flash-clk prescaler variable */
402 #if defined(CONFIG_SOC_SERIES_STM32WBX)
403 hclk_prescaler = s_ClkInitStruct.CPU1CLKDivider;
404 flash_prescaler = s_ClkInitStruct.AHB4CLKDivider;
405 #elif defined(CONFIG_SOC_SERIES_STM32WLX)
406 hclk_prescaler = s_ClkInitStruct.CPU1CLKDivider;
407 flash_prescaler = s_ClkInitStruct.AHB3CLKDivider;
408 #else
409 hclk_prescaler = s_ClkInitStruct.AHBCLKDivider;
410 flash_prescaler = hclk_prescaler;
411 #endif
412
413 /* Some clocks would be activated by default */
414 config_enable_default_clocks();
415
416 #if STM32_SYSCLK_SRC_PLL
417 LL_UTILS_PLLInitTypeDef s_PLLInitStruct;
418
419 /* configure PLL input settings */
420 config_pll_init(&s_PLLInitStruct);
421
422 /*
423 * Switch to HSI and disable the PLL before configuration.
424 * (Switching to HSI makes sure we have a SYSCLK source in
425 * case we're currently running from the PLL we're about to
426 * turn off and reconfigure.)
427 *
428 * Don't use s_ClkInitStruct.AHBCLKDivider as the AHB
429 * prescaler here. In this configuration, that's the value to
430 * use when the SYSCLK source is the PLL, not HSI.
431 */
432 stm32_clock_switch_to_hsi(LL_RCC_SYSCLK_DIV_1);
433 LL_RCC_PLL_Disable();
434
435 #ifdef CONFIG_SOC_SERIES_STM32F7X
436 /* Assuming we stay on Power Scale default value: Power Scale 1 */
437 if (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC > 180000000) {
438 LL_PWR_EnableOverDriveMode();
439 while (LL_PWR_IsActiveFlag_OD() != 1) {
440 /* Wait for OverDrive mode ready */
441 }
442 LL_PWR_EnableOverDriveSwitching();
443 while (LL_PWR_IsActiveFlag_ODSW() != 1) {
444 /* Wait for OverDrive switch ready */
445 }
446 }
447 #endif
448
449 #if STM32_PLL_Q_DIVISOR
450 MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ,
451 STM32_PLL_Q_DIVISOR
452 << RCC_PLLCFGR_PLLQ_Pos);
453 #endif /* STM32_PLL_Q_DIVISOR */
454
455 #if STM32_PLL_SRC_MSI
456
457 /* Set MSI Range */
458 #if !defined(CONFIG_SOC_SERIES_STM32WBX)
459 LL_RCC_MSI_EnableRangeSelection();
460 #endif
461 LL_RCC_MSI_SetRange(STM32_MSI_RANGE << RCC_CR_MSIRANGE_Pos);
462 LL_RCC_MSI_SetCalibTrimming(0);
463
464 #if STM32_MSI_PLL_MODE
465
466 #ifndef STM32_LSE_CLOCK
467 #error "MSI Hardware auto calibration requires LSE clock activation"
468 #endif
469 /* Enable MSI hardware auto calibration */
470 LL_RCC_MSI_EnablePLLMode();
471 #endif
472
473 /* Switch to PLL with MSI as clock source */
474 LL_PLL_ConfigSystemClock_MSI(&s_PLLInitStruct, &s_ClkInitStruct);
475
476 /* Disable other clocks */
477 LL_RCC_HSI_Disable();
478 LL_RCC_HSE_Disable();
479
480 #elif STM32_PLL_SRC_HSI
481 /* Switch to PLL with HSI as clock source */
482 LL_PLL_ConfigSystemClock_HSI(&s_PLLInitStruct, &s_ClkInitStruct);
483
484 /* Disable other clocks */
485 LL_RCC_HSE_Disable();
486 LL_RCC_MSI_Disable();
487
488 #elif STM32_PLL_SRC_HSE
489
490 #ifndef CONFIG_SOC_SERIES_STM32WLX
491 int hse_bypass;
492 if (IS_ENABLED(STM32_HSE_BYPASS)) {
493 hse_bypass = LL_UTILS_HSEBYPASS_ON;
494 } else {
495 hse_bypass = LL_UTILS_HSEBYPASS_OFF;
496 }
497 #else
498 if (IS_ENABLED(STM32_HSE_TCXO)) {
499 LL_RCC_HSE_EnableTcxo();
500 }
501 if (IS_ENABLED(STM32_HSE_DIV2)) {
502 LL_RCC_HSE_EnableDiv2();
503 }
504 #endif
505
506 /* Switch to PLL with HSE as clock source */
507 LL_PLL_ConfigSystemClock_HSE(
508 #if !defined(CONFIG_SOC_SERIES_STM32WBX) && !defined(CONFIG_SOC_SERIES_STM32WLX)
509 CONFIG_CLOCK_STM32_HSE_CLOCK,
510 #endif
511 #ifndef CONFIG_SOC_SERIES_STM32WLX
512 hse_bypass,
513 #endif
514 &s_PLLInitStruct,
515 &s_ClkInitStruct);
516
517 /* Disable other clocks */
518 LL_RCC_HSI_Disable();
519 LL_RCC_MSI_Disable();
520
521 #endif /* STM32_PLL_SRC_* */
522
523 #elif STM32_SYSCLK_SRC_HSE
524
525 old_flash_freq = RCC_CALC_FLASH_FREQ(HAL_RCC_GetSysClockFreq(),
526 GET_CURRENT_FLASH_PRESCALER());
527
528 /* Calculate new SystemCoreClock variable based on HSE freq */
529 uint32_t hse_freq;
530 if (IS_ENABLED(STM32_HSE_DIV2)) {
531 hse_freq = CONFIG_CLOCK_STM32_HSE_CLOCK / 2;
532 } else {
533 hse_freq = CONFIG_CLOCK_STM32_HSE_CLOCK;
534 }
535 new_hclk_freq = __LL_RCC_CALC_HCLK_FREQ(hse_freq, hclk_prescaler);
536
537 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_SOC_SERIES_STM32WLX)
538 new_flash_freq = RCC_CALC_FLASH_FREQ(CONFIG_CLOCK_STM32_HSE_CLOCK,
539 flash_prescaler);
540 #else
541 new_flash_freq = new_hclk_freq;
542 #endif
543
544 #if defined(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC)
545 __ASSERT(new_hclk_freq == CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC,
546 "Config mismatch HCLK frequency %u %u",
547 CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, new_hclk_freq);
548 #endif
549
550 /* If freq increases, set flash latency before any clock setting */
551 if (new_flash_freq > old_flash_freq) {
552 LL_SetFlashLatency(new_flash_freq);
553 }
554
555 /* Enable HSE if not enabled */
556 if (LL_RCC_HSE_IsReady() != 1) {
557 #ifdef CONFIG_SOC_SERIES_STM32WLX
558 if (IS_ENABLED(STM32_HSE_TCXO)) {
559 LL_RCC_HSE_EnableTcxo();
560 }
561 #elif !defined(CONFIG_SOC_SERIES_STM32WBX)
562 /* Check if need to enable HSE bypass feature or not */
563 if (IS_ENABLED(STM32_HSE_BYPASS)) {
564 LL_RCC_HSE_EnableBypass();
565 } else {
566 LL_RCC_HSE_DisableBypass();
567 }
568 #endif
569
570 /* Enable HSE */
571 LL_RCC_HSE_Enable();
572 while (LL_RCC_HSE_IsReady() != 1) {
573 /* Wait for HSE ready */
574 }
575 }
576
577 /* Set HSE as SYSCLCK source */
578 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
579 LL_RCC_SetAHBPrescaler(hclk_prescaler);
580 while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) {
581 }
582
583 /* Update SystemCoreClock variable */
584 LL_SetSystemCoreClock(new_hclk_freq);
585
586 /* Set APB1 & APB2 prescaler*/
587 LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
588 #if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
589 !defined (CONFIG_SOC_SERIES_STM32G0X)
590 LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider);
591 #endif
592 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE)
593 LL_C2_RCC_SetAHBPrescaler(s_ClkInitStruct.CPU2CLKDivider);
594 #endif
595 #ifdef CONFIG_SOC_SERIES_STM32WBX
596 LL_RCC_SetAHB4Prescaler(s_ClkInitStruct.AHB4CLKDivider);
597 #endif /* CONFIG_SOC_SERIES_STM32WBX */
598 #ifdef CONFIG_SOC_SERIES_STM32WLX
599 LL_RCC_SetAHB3Prescaler(s_ClkInitStruct.AHB3CLKDivider);
600 #endif /* CONFIG_SOC_SERIES_STM32WLX */
601
602 /* If freq not increased, set flash latency after all clock setting */
603 if (new_flash_freq <= old_flash_freq) {
604 LL_SetFlashLatency(new_flash_freq);
605 }
606
607 /* Disable other clocks */
608 LL_RCC_HSI_Disable();
609 LL_RCC_MSI_Disable();
610 LL_RCC_PLL_Disable();
611
612 #elif STM32_SYSCLK_SRC_MSI
613
614 old_flash_freq = RCC_CALC_FLASH_FREQ(HAL_RCC_GetSysClockFreq(),
615 GET_CURRENT_FLASH_PRESCALER());
616
617 new_hclk_freq = __LL_RCC_CALC_HCLK_FREQ(
618 RCC_CALC_MSI_RUN_FREQ(STM32_MSI_RANGE),
619 hclk_prescaler);
620 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_SOC_SERIES_STM32WLX)
621 new_flash_freq = RCC_CALC_FLASH_FREQ(
622 RCC_CALC_MSI_RUN_FREQ(STM32_MSI_RANGE),
623 flash_prescaler);
624 #else
625 new_flash_freq = new_hclk_freq;
626 #endif
627
628 #if defined(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC)
629 __ASSERT(new_hclk_freq == CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC,
630 "Config mismatch HCLK frequency %u %u",
631 CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, new_hclk_freq);
632 #endif
633
634 /* If freq increases, set flash latency before any clock setting */
635 if (new_flash_freq > old_flash_freq) {
636 LL_SetFlashLatency(new_flash_freq);
637 }
638
639 /* Set MSI Range */
640 #if !defined(CONFIG_SOC_SERIES_STM32WBX)
641 LL_RCC_MSI_EnableRangeSelection();
642 #endif
643 LL_RCC_MSI_SetRange(STM32_MSI_RANGE << RCC_CR_MSIRANGE_Pos);
644
645 #if STM32_MSI_PLL_MODE
646 /* Enable MSI hardware auto calibration */
647 LL_RCC_MSI_EnablePLLMode();
648 #endif
649
650 /* Enable MSI if not enabled */
651 if (LL_RCC_MSI_IsReady() != 1) {
652 /* Enable MSI */
653 LL_RCC_MSI_Enable();
654 while (LL_RCC_MSI_IsReady() != 1) {
655 /* Wait for HSI ready */
656 }
657 }
658
659 /* Set MSI as SYSCLCK source */
660 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI);
661 LL_RCC_SetAHBPrescaler(hclk_prescaler);
662 while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) {
663 }
664
665 /* Update SystemCoreClock variable */
666 LL_SetSystemCoreClock(new_hclk_freq);
667
668 /* Set APB1 & APB2 prescaler*/
669 LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
670 LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider);
671 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE)
672 LL_C2_RCC_SetAHBPrescaler(s_ClkInitStruct.CPU2CLKDivider);
673 #endif
674 #ifdef CONFIG_SOC_SERIES_STM32WBX
675 LL_RCC_SetAHB4Prescaler(s_ClkInitStruct.AHB4CLKDivider);
676 #endif
677 #ifdef CONFIG_SOC_SERIES_STM32WLX
678 LL_RCC_SetAHB3Prescaler(s_ClkInitStruct.AHB3CLKDivider);
679 #endif
680 /* If freq not increased, set flash latency after all clock setting */
681 if (new_flash_freq <= old_flash_freq) {
682 LL_SetFlashLatency(new_flash_freq);
683 }
684
685 /* Disable other clocks */
686 LL_RCC_HSE_Disable();
687 LL_RCC_HSI_Disable();
688 LL_RCC_PLL_Disable();
689
690 #elif STM32_SYSCLK_SRC_HSI
691
692 stm32_clock_switch_to_hsi(hclk_prescaler);
693
694 /* Update SystemCoreClock variable */
695 LL_SetSystemCoreClock(__LL_RCC_CALC_HCLK_FREQ(HSI_VALUE,
696 hclk_prescaler));
697
698 /* Set APB1 & APB2 prescaler*/
699 LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
700 #if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
701 !defined (CONFIG_SOC_SERIES_STM32G0X)
702 LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider);
703 #endif /* CONFIG_SOC_SERIES_STM32F0X && CONFIG_SOC_SERIES_STM32G0X */
704 #if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(STM32WL_DUAL_CORE)
705 LL_C2_RCC_SetAHBPrescaler(s_ClkInitStruct.CPU2CLKDivider);
706 #endif
707 #ifdef CONFIG_SOC_SERIES_STM32WBX
708 LL_RCC_SetAHB4Prescaler(s_ClkInitStruct.AHB4CLKDivider);
709 #endif /* CONFIG_SOC_SERIES_STM32WBX */
710 #ifdef CONFIG_SOC_SERIES_STM32WLX
711 LL_RCC_SetAHB3Prescaler(s_ClkInitStruct.AHB3CLKDivider);
712 #endif /* CONFIG_SOC_SERIES_STM32WLX */
713
714 /* Set flash latency */
715 /* HSI used as SYSCLK, set latency to 0 */
716 LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
717
718 /* Disable other clocks */
719 LL_RCC_HSE_Disable();
720 LL_RCC_MSI_Disable();
721 LL_RCC_PLL_Disable();
722
723 #endif /* STM32_SYSCLK_SRC_... */
724
725 /* configure MCO1/MCO2 based on Kconfig */
726 stm32_clock_control_mco_init();
727
728 return 0;
729 }
730
731 /**
732 * @brief RCC device, note that priority is intentionally set to 1 so
733 * that the device init runs just after SOC init
734 */
735 DEVICE_DT_DEFINE(DT_NODELABEL(rcc),
736 &stm32_clock_control_init,
737 NULL,
738 NULL, NULL,
739 PRE_KERNEL_1,
740 CONFIG_CLOCK_CONTROL_STM32_DEVICE_INIT_PRIORITY,
741 &stm32_clock_control_api);
742