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