1 /*
2 *
3 * Copyright (c) 2019 Linaro Limited.
4 * Copyright (c) 2020 Jeremy LOCHE
5 * Copyright (c) 2021 Electrolance Solutions
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <soc.h>
11 #include <stm32_ll_bus.h>
12 #include <stm32_ll_pwr.h>
13 #include <stm32_ll_rcc.h>
14 #include <stm32_ll_utils.h>
15 #include <zephyr/arch/cpu.h>
16 #include <zephyr/drivers/clock_control.h>
17 #include <zephyr/sys/util.h>
18 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
19 #include "stm32_hsem.h"
20
21
22 /* Macros to fill up prescaler values */
23 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
24 #define z_hsi_divider(v) LL_RCC_HSI_DIV_ ## v
25 #else
26 #define z_hsi_divider(v) LL_RCC_HSI_DIV ## v
27 #endif
28 #define hsi_divider(v) z_hsi_divider(v)
29
30 #define z_sysclk_prescaler(v) LL_RCC_SYSCLK_DIV_ ## v
31 #define sysclk_prescaler(v) z_sysclk_prescaler(v)
32
33 #define z_ahb_prescaler(v) LL_RCC_AHB_DIV_ ## v
34 #define ahb_prescaler(v) z_ahb_prescaler(v)
35
36 #define z_apb1_prescaler(v) LL_RCC_APB1_DIV_ ## v
37 #define apb1_prescaler(v) z_apb1_prescaler(v)
38
39 #define z_apb2_prescaler(v) LL_RCC_APB2_DIV_ ## v
40 #define apb2_prescaler(v) z_apb2_prescaler(v)
41
42 #define z_apb3_prescaler(v) LL_RCC_APB3_DIV_ ## v
43 #define apb3_prescaler(v) z_apb3_prescaler(v)
44
45 #define z_apb4_prescaler(v) LL_RCC_APB4_DIV_ ## v
46 #define apb4_prescaler(v) z_apb4_prescaler(v)
47
48 #define z_apb5_prescaler(v) LL_RCC_APB5_DIV_ ## v
49 #define apb5_prescaler(v) z_apb5_prescaler(v)
50
51 /* Macro to check for clock feasibility */
52 /* It is Cortex M7's responsibility to setup clock tree */
53 /* This check should only be performed for the M7 core code */
54 #ifdef CONFIG_CPU_CORTEX_M7
55
56 /* Choose PLL SRC */
57 #if defined(STM32_PLL_SRC_HSI)
58 #define PLLSRC_FREQ ((STM32_HSI_FREQ)/(STM32_HSI_DIVISOR))
59 #elif defined(STM32_PLL_SRC_CSI)
60 #define PLLSRC_FREQ STM32_CSI_FREQ
61 #elif defined(STM32_PLL_SRC_HSE)
62 #define PLLSRC_FREQ STM32_HSE_FREQ
63 #else
64 #define PLLSRC_FREQ 0
65 #endif
66
67 /* Given source clock and dividers, computed the output frequency of PLLP */
68 #define PLLP_FREQ(pllsrc_freq, divm, divn, divp) (((pllsrc_freq)*\
69 (divn))/((divm)*(divp)))
70
71 /* PLL P output frequency value */
72 #define PLLP_VALUE PLLP_FREQ(\
73 PLLSRC_FREQ,\
74 STM32_PLL_M_DIVISOR,\
75 STM32_PLL_N_MULTIPLIER,\
76 STM32_PLL_P_DIVISOR)
77
78 /* SYSCLKSRC before the D1CPRE prescaler */
79 #if defined(STM32_SYSCLK_SRC_PLL)
80 #define SYSCLKSRC_FREQ PLLP_VALUE
81 #elif defined(STM32_SYSCLK_SRC_HSI)
82 #define SYSCLKSRC_FREQ ((STM32_HSI_FREQ)/(STM32_HSI_DIVISOR))
83 #elif defined(STM32_SYSCLK_SRC_CSI)
84 #define SYSCLKSRC_FREQ STM32_CSI_FREQ
85 #elif defined(STM32_SYSCLK_SRC_HSE)
86 #define SYSCLKSRC_FREQ STM32_HSE_FREQ
87 #endif
88
89 /* ARM Sys CPU Clock before HPRE prescaler */
90 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
91 #define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE))
92 #define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE))
93 #define APB1_FREQ ((AHB_FREQ)/(STM32_PPRE1))
94 #define APB2_FREQ ((AHB_FREQ)/(STM32_PPRE2))
95 #define APB4_FREQ ((AHB_FREQ)/(STM32_PPRE4))
96 #define APB5_FREQ ((AHB_FREQ)/(STM32_PPRE5))
97 #else
98 #define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE))
99 #define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE))
100 #define APB1_FREQ ((AHB_FREQ)/(STM32_D2PPRE1))
101 #define APB2_FREQ ((AHB_FREQ)/(STM32_D2PPRE2))
102 #define APB3_FREQ ((AHB_FREQ)/(STM32_D1PPRE))
103 #define APB4_FREQ ((AHB_FREQ)/(STM32_D3PPRE))
104 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
105
106 /* Datasheet maximum frequency definitions */
107 #if defined(CONFIG_SOC_STM32H743XX) ||\
108 defined(CONFIG_SOC_STM32H745XX_M7) || defined(CONFIG_SOC_STM32H745XX_M4) ||\
109 defined(CONFIG_SOC_STM32H747XX_M7) || defined(CONFIG_SOC_STM32H747XX_M4) ||\
110 defined(CONFIG_SOC_STM32H750XX) ||\
111 defined(CONFIG_SOC_STM32H753XX) ||\
112 defined(CONFIG_SOC_STM32H755XX_M7) || defined(CONFIG_SOC_STM32H755XX_M4) ||\
113 defined(CONFIG_SOC_STM32H757XX_M7) || defined(CONFIG_SOC_STM32H757XX_M4)
114 /* All h7 SoC with maximum 480MHz SYSCLK */
115 #define SYSCLK_FREQ_MAX 480000000UL
116 #define AHB_FREQ_MAX 240000000UL
117 #define APBx_FREQ_MAX 120000000UL
118 #elif defined(CONFIG_SOC_STM32H723XX) ||\
119 defined(CONFIG_SOC_STM32H725XX) ||\
120 defined(CONFIG_SOC_STM32H730XX) || defined(CONFIG_SOC_STM32H730XXQ) ||\
121 defined(CONFIG_SOC_STM32H735XX)
122 /* All h7 SoC with maximum 550MHz SYSCLK */
123 #define SYSCLK_FREQ_MAX 550000000UL
124 #define AHB_FREQ_MAX 275000000UL
125 #define APBx_FREQ_MAX 137500000UL
126 #elif defined(CONFIG_SOC_STM32H7A3XX) || defined(CONFIG_SOC_STM32H7A3XXQ) ||\
127 defined(CONFIG_SOC_STM32H7B0XX) || defined(CONFIG_SOC_STM32H7B0XXQ) ||\
128 defined(CONFIG_SOC_STM32H7B3XX) || defined(CONFIG_SOC_STM32H7B3XXQ)
129 #define SYSCLK_FREQ_MAX 280000000UL
130 #define AHB_FREQ_MAX 280000000UL
131 #define APBx_FREQ_MAX 140000000UL
132 #elif defined(CONFIG_SOC_SERIES_STM32H7RSX)
133 /* All h7RS SoC with maximum 500MHz SYSCLK (refer to Datasheet DS14359 rev 1) */
134 #define SYSCLK_FREQ_MAX 500000000UL
135 #define AHB_FREQ_MAX 250000000UL
136 #define APBx_FREQ_MAX 125000000UL
137 #else
138 /* Default: All h7 SoC with maximum 280MHz SYSCLK */
139 #define SYSCLK_FREQ_MAX 280000000UL
140 #define AHB_FREQ_MAX 140000000UL
141 #define APBx_FREQ_MAX 70000000UL
142 #endif
143
144 #if SYSCLK_FREQ > SYSCLK_FREQ_MAX
145 #error "SYSCLK frequency is too high!"
146 #endif
147 #if AHB_FREQ > AHB_FREQ_MAX
148 #error "AHB frequency is too high!"
149 #endif
150 #if APB1_FREQ > APBx_FREQ_MAX
151 #error "APB1 frequency is too high!"
152 #endif
153 #if APB2_FREQ > APBx_FREQ_MAX
154 #error "APB2 frequency is too high!"
155 #endif
156 #if APB3_FREQ > APBx_FREQ_MAX
157 #error "APB3 frequency is too high!"
158 #endif
159 #if APB4_FREQ > APBx_FREQ_MAX
160 #error "APB4 frequency is too high!"
161 #endif
162
163 /* end of clock feasibility check */
164 #endif /* CONFIG_CPU_CORTEX_M7 */
165
166
167 #if defined(CONFIG_CPU_CORTEX_M7)
168 #if STM32_D1CPRE > 1
169 /*
170 * D1CPRE prescaler allows to set a HCLK frequency lower than SYSCLK frequency.
171 * Though, zephyr doesn't make a difference today between these two clocks.
172 * So, changing this prescaler is not allowed until it is made possible to
173 * use them independently in zephyr clock subsystem.
174 */
175 #error "D1CPRE prescaler can't be higher than 1"
176 #endif
177 #endif /* CONFIG_CPU_CORTEX_M7 */
178
179 #if defined(CONFIG_CPU_CORTEX_M7)
180 /* Offset to access bus clock registers from M7 (or only) core */
181 #define STM32H7_BUS_CLK_REG DT_REG_ADDR(DT_NODELABEL(rcc))
182 #elif defined(CONFIG_CPU_CORTEX_M4)
183 /* Offset to access bus clock registers from M4 core */
184 #define STM32H7_BUS_CLK_REG DT_REG_ADDR(DT_NODELABEL(rcc)) + 0x60
185 #endif
186
get_bus_clock(uint32_t clock,uint32_t prescaler)187 static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler)
188 {
189 return clock / prescaler;
190 }
191
192 __unused
get_pllout_frequency(uint32_t pllsrc_freq,int pllm_div,int plln_mul,int pllout_div)193 static uint32_t get_pllout_frequency(uint32_t pllsrc_freq,
194 int pllm_div,
195 int plln_mul,
196 int pllout_div)
197 {
198 __ASSERT_NO_MSG(pllm_div && pllout_div);
199
200 return (pllsrc_freq / pllm_div) * plln_mul / pllout_div;
201 }
202
203 __unused
get_pllsrc_frequency(void)204 static uint32_t get_pllsrc_frequency(void)
205 {
206 switch (LL_RCC_PLL_GetSource()) {
207 case LL_RCC_PLLSOURCE_HSI:
208 return STM32_HSI_FREQ;
209 case LL_RCC_PLLSOURCE_CSI:
210 return STM32_CSI_FREQ;
211 case LL_RCC_PLLSOURCE_HSE:
212 return STM32_HSE_FREQ;
213 case LL_RCC_PLLSOURCE_NONE:
214 default:
215 return 0;
216 }
217 }
218
219 __unused
get_hclk_frequency(void)220 static uint32_t get_hclk_frequency(void)
221 {
222 uint32_t sysclk = 0;
223
224 /* Get the current system clock source */
225 switch (LL_RCC_GetSysClkSource()) {
226 case LL_RCC_SYS_CLKSOURCE_STATUS_HSI:
227 sysclk = STM32_HSI_FREQ/STM32_HSI_DIVISOR;
228 break;
229 case LL_RCC_SYS_CLKSOURCE_STATUS_CSI:
230 sysclk = STM32_CSI_FREQ;
231 break;
232 case LL_RCC_SYS_CLKSOURCE_STATUS_HSE:
233 sysclk = STM32_HSE_FREQ;
234 break;
235 #if defined(STM32_PLL_ENABLED)
236 case LL_RCC_SYS_CLKSOURCE_STATUS_PLL1:
237 sysclk = get_pllout_frequency(get_pllsrc_frequency(),
238 STM32_PLL_M_DIVISOR,
239 STM32_PLL_N_MULTIPLIER,
240 STM32_PLL_P_DIVISOR);
241 break;
242 #endif /* STM32_PLL_ENABLED */
243 }
244
245 return get_bus_clock(sysclk, STM32_HPRE);
246 }
247
248 #if !defined(CONFIG_CPU_CORTEX_M4)
249
prepare_regulator_voltage_scale(void)250 static int32_t prepare_regulator_voltage_scale(void)
251 {
252 /* Apply system power supply configuration */
253 #if defined(SMPS) && defined(CONFIG_POWER_SUPPLY_DIRECT_SMPS)
254 LL_PWR_ConfigSupply(LL_PWR_DIRECT_SMPS_SUPPLY);
255 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_LDO)
256 LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_LDO);
257 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_LDO)
258 LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_LDO);
259 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT_AND_LDO)
260 LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO);
261 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT_AND_LDO)
262 LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO);
263 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT)
264 LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_EXT);
265 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT)
266 LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_EXT);
267 #elif defined(CONFIG_POWER_SUPPLY_EXTERNAL_SOURCE)
268 LL_PWR_ConfigSupply(LL_PWR_EXTERNAL_SOURCE_SUPPLY);
269 #else
270 LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
271 #endif
272
273 /* Make sure to put the CPU in highest Voltage scale during clock configuration */
274 /* Highest voltage is SCALE0 */
275 LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
276 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
277 while (LL_PWR_IsActiveFlag_VOSRDY() == 0) {
278 #else
279 while (LL_PWR_IsActiveFlag_VOS() == 0) {
280 #endif
281 }
282 return 0;
283 }
284
285 static int32_t optimize_regulator_voltage_scale(uint32_t sysclk_freq)
286 {
287
288 /* After sysclock is configured, tweak the voltage scale down */
289 /* to reduce power consumption */
290
291 /* Needs some smart work to configure properly */
292 /* LL_PWR_REGULATOR_SCALE3 is lowest power consumption */
293 /* Must be done in accordance to the Maximum allowed frequency vs VOS*/
294 /* See RM0433 page 352 for more details */
295 #if defined(SMPS) && defined(CONFIG_POWER_SUPPLY_DIRECT_SMPS)
296 LL_PWR_ConfigSupply(LL_PWR_DIRECT_SMPS_SUPPLY);
297 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_LDO)
298 LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_LDO);
299 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_LDO)
300 LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_LDO);
301 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT_AND_LDO)
302 LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO);
303 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT_AND_LDO)
304 LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO);
305 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT)
306 LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_EXT);
307 #elif defined(SMPS) && defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT)
308 LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_EXT);
309 #elif defined(CONFIG_POWER_SUPPLY_EXTERNAL_SOURCE)
310 LL_PWR_ConfigSupply(LL_PWR_EXTERNAL_SOURCE_SUPPLY);
311 #else
312 LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
313 #endif
314 LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
315 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
316 while (LL_PWR_IsActiveFlag_VOSRDY() == 0) {
317 #else
318 while (LL_PWR_IsActiveFlag_VOS() == 0) {
319 #endif
320 };
321 return 0;
322 }
323
324 __unused
325 static int get_vco_input_range(uint32_t m_div, uint32_t *range)
326 {
327 uint32_t vco_freq;
328
329 vco_freq = PLLSRC_FREQ / m_div;
330
331 if (MHZ(1) <= vco_freq && vco_freq <= MHZ(2)) {
332 *range = LL_RCC_PLLINPUTRANGE_1_2;
333 } else if (MHZ(2) < vco_freq && vco_freq <= MHZ(4)) {
334 *range = LL_RCC_PLLINPUTRANGE_2_4;
335 } else if (MHZ(4) < vco_freq && vco_freq <= MHZ(8)) {
336 *range = LL_RCC_PLLINPUTRANGE_4_8;
337 } else if (MHZ(8) < vco_freq && vco_freq <= MHZ(16)) {
338 *range = LL_RCC_PLLINPUTRANGE_8_16;
339 } else {
340 return -ERANGE;
341 }
342
343 return 0;
344 }
345
346 __unused
347 static uint32_t get_vco_output_range(uint32_t vco_input_range)
348 {
349 if (vco_input_range == LL_RCC_PLLINPUTRANGE_1_2) {
350 return LL_RCC_PLLVCORANGE_MEDIUM;
351 }
352
353 return LL_RCC_PLLVCORANGE_WIDE;
354 }
355
356 #endif /* ! CONFIG_CPU_CORTEX_M4 */
357
358 /** @brief Verifies clock is part of active clock configuration */
359 int enabled_clock(uint32_t src_clk)
360 {
361
362 if ((src_clk == STM32_SRC_SYSCLK) ||
363 ((src_clk == STM32_SRC_CKPER) && IS_ENABLED(STM32_CKPER_ENABLED)) ||
364 ((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) ||
365 ((src_clk == STM32_SRC_HSI_KER) && IS_ENABLED(STM32_HSI_ENABLED)) ||
366 ((src_clk == STM32_SRC_CSI_KER) && IS_ENABLED(STM32_CSI_ENABLED)) ||
367 ((src_clk == STM32_SRC_HSI48) && IS_ENABLED(STM32_HSI48_ENABLED)) ||
368 ((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) ||
369 ((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) ||
370 ((src_clk == STM32_SRC_PLL1_P) && IS_ENABLED(STM32_PLL_P_ENABLED)) ||
371 ((src_clk == STM32_SRC_PLL1_Q) && IS_ENABLED(STM32_PLL_Q_ENABLED)) ||
372 ((src_clk == STM32_SRC_PLL1_R) && IS_ENABLED(STM32_PLL_R_ENABLED)) ||
373 ((src_clk == STM32_SRC_PLL2_P) && IS_ENABLED(STM32_PLL2_P_ENABLED)) ||
374 ((src_clk == STM32_SRC_PLL2_Q) && IS_ENABLED(STM32_PLL2_Q_ENABLED)) ||
375 ((src_clk == STM32_SRC_PLL2_R) && IS_ENABLED(STM32_PLL2_R_ENABLED)) ||
376 ((src_clk == STM32_SRC_PLL3_P) && IS_ENABLED(STM32_PLL3_P_ENABLED)) ||
377 ((src_clk == STM32_SRC_PLL3_Q) && IS_ENABLED(STM32_PLL3_Q_ENABLED)) ||
378 ((src_clk == STM32_SRC_PLL3_R) && IS_ENABLED(STM32_PLL3_R_ENABLED))) {
379 return 0;
380 }
381
382 return -ENOTSUP;
383 }
384
385 static inline int stm32_clock_control_on(const struct device *dev,
386 clock_control_subsys_t sub_system)
387 {
388 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
389 volatile int temp;
390
391 ARG_UNUSED(dev);
392
393 if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) {
394 /* Attempt to toggle a wrong periph clock bit */
395 return -ENOTSUP;
396 }
397
398 z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
399
400 sys_set_bits(STM32H7_BUS_CLK_REG + pclken->bus, pclken->enr);
401 /* Delay after enabling the clock, to allow it to become active.
402 * See RM0433 8.5.10 "Clock enabling delays"
403 */
404 temp = sys_read32(STM32H7_BUS_CLK_REG + pclken->bus);
405 UNUSED(temp);
406
407 z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
408
409 return 0;
410 }
411
412 static inline int stm32_clock_control_off(const struct device *dev,
413 clock_control_subsys_t sub_system)
414 {
415 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
416
417 ARG_UNUSED(dev);
418
419 if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) {
420 /* Attempt to toggle a wrong periph clock bit */
421 return -ENOTSUP;
422 }
423
424 z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
425
426 sys_clear_bits(STM32H7_BUS_CLK_REG + pclken->bus, pclken->enr);
427
428 z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
429
430 return 0;
431 }
432
433 static inline int stm32_clock_control_configure(const struct device *dev,
434 clock_control_subsys_t sub_system,
435 void *data)
436 {
437 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
438 int err;
439
440 ARG_UNUSED(dev);
441 ARG_UNUSED(data);
442
443 err = enabled_clock(pclken->bus);
444 if (err < 0) {
445 /* Attempt to configure a src clock not available or not valid */
446 return err;
447 }
448
449 z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
450
451 sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_DT_CLKSEL_REG_GET(pclken->enr),
452 STM32_DT_CLKSEL_MASK_GET(pclken->enr) <<
453 STM32_DT_CLKSEL_SHIFT_GET(pclken->enr));
454 sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_DT_CLKSEL_REG_GET(pclken->enr),
455 STM32_DT_CLKSEL_VAL_GET(pclken->enr) <<
456 STM32_DT_CLKSEL_SHIFT_GET(pclken->enr));
457
458 z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
459
460 return 0;
461 }
462
463 static int stm32_clock_control_get_subsys_rate(const struct device *clock,
464 clock_control_subsys_t sub_system,
465 uint32_t *rate)
466 {
467 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
468 /*
469 * Get AHB Clock (= SystemCoreClock = SYSCLK/prescaler)
470 * SystemCoreClock is preferred to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC
471 * since it will be updated after clock configuration and hence
472 * more likely to contain actual clock speed
473 */
474 #if defined(CONFIG_CPU_CORTEX_M4)
475 uint32_t ahb_clock = SystemCoreClock;
476 #else
477 uint32_t ahb_clock = get_bus_clock(SystemCoreClock, STM32_HPRE);
478 #endif
479 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
480 uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_PPRE1);
481 uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_PPRE2);
482 uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_PPRE4);
483 uint32_t apb5_clock = get_bus_clock(ahb_clock, STM32_PPRE5);
484 #else
485 uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_D2PPRE1);
486 uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_D2PPRE2);
487 uint32_t apb3_clock = get_bus_clock(ahb_clock, STM32_D1PPRE);
488 uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_D3PPRE);
489 #endif
490
491 ARG_UNUSED(clock);
492
493 switch (pclken->bus) {
494 case STM32_CLOCK_BUS_AHB1:
495 case STM32_CLOCK_BUS_AHB2:
496 case STM32_CLOCK_BUS_AHB3:
497 case STM32_CLOCK_BUS_AHB4:
498 *rate = ahb_clock;
499 break;
500 case STM32_CLOCK_BUS_APB1:
501 case STM32_CLOCK_BUS_APB1_2:
502 *rate = apb1_clock;
503 break;
504 case STM32_CLOCK_BUS_APB2:
505 *rate = apb2_clock;
506 break;
507 #if !defined(CONFIG_SOC_SERIES_STM32H7RSX)
508 case STM32_CLOCK_BUS_APB3:
509 *rate = apb3_clock;
510 break;
511 #endif /* !CONFIG_SOC_SERIES_STM32H7RSX */
512 case STM32_CLOCK_BUS_APB4:
513 *rate = apb4_clock;
514 break;
515 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
516 case STM32_CLOCK_BUS_APB5:
517 *rate = apb5_clock;
518 break;
519 case STM32_CLOCK_BUS_AHB5:
520 *rate = ahb_clock;
521 break;
522 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
523 case STM32_SRC_SYSCLK:
524 *rate = get_hclk_frequency();
525 break;
526 #if defined(STM32_CKPER_ENABLED)
527 case STM32_SRC_CKPER:
528 *rate = LL_RCC_GetCLKPClockFreq(LL_RCC_CLKP_CLKSOURCE);
529 break;
530 #endif /* STM32_CKPER_ENABLED */
531 #if defined(STM32_HSE_ENABLED)
532 case STM32_SRC_HSE:
533 *rate = STM32_HSE_FREQ;
534 break;
535 #endif /* STM32_HSE_ENABLED */
536 #if defined(STM32_LSE_ENABLED)
537 case STM32_SRC_LSE:
538 *rate = STM32_LSE_FREQ;
539 break;
540 #endif /* STM32_LSE_ENABLED */
541 #if defined(STM32_LSI_ENABLED)
542 case STM32_SRC_LSI:
543 *rate = STM32_LSI_FREQ;
544 break;
545 #endif /* STM32_LSI_ENABLED */
546 #if defined(STM32_HSI_ENABLED)
547 case STM32_SRC_HSI_KER:
548 *rate = STM32_HSI_FREQ/STM32_HSI_DIVISOR;
549 break;
550 #endif /* STM32_HSI_ENABLED */
551 #if defined(STM32_HSI48_ENABLED)
552 case STM32_SRC_HSI48:
553 *rate = STM32_HSI48_FREQ;
554 break;
555 #endif /* STM32_HSI48_ENABLED */
556 #if defined(STM32_PLL_ENABLED)
557 case STM32_SRC_PLL1_P:
558 *rate = get_pllout_frequency(get_pllsrc_frequency(),
559 STM32_PLL_M_DIVISOR,
560 STM32_PLL_N_MULTIPLIER,
561 STM32_PLL_P_DIVISOR);
562 break;
563 case STM32_SRC_PLL1_Q:
564 *rate = get_pllout_frequency(get_pllsrc_frequency(),
565 STM32_PLL_M_DIVISOR,
566 STM32_PLL_N_MULTIPLIER,
567 STM32_PLL_Q_DIVISOR);
568 break;
569 case STM32_SRC_PLL1_R:
570 *rate = get_pllout_frequency(get_pllsrc_frequency(),
571 STM32_PLL_M_DIVISOR,
572 STM32_PLL_N_MULTIPLIER,
573 STM32_PLL_R_DIVISOR);
574 break;
575 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
576 case STM32_SRC_PLL1_S:
577 *rate = get_pllout_frequency(get_pllsrc_frequency(),
578 STM32_PLL_M_DIVISOR,
579 STM32_PLL_N_MULTIPLIER,
580 STM32_PLL_S_DIVISOR);
581 break;
582 /* PLL 1 has no T-divider */
583 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
584 #endif /* STM32_PLL_ENABLED */
585 #if defined(STM32_PLL2_ENABLED)
586 case STM32_SRC_PLL2_P:
587 *rate = get_pllout_frequency(get_pllsrc_frequency(),
588 STM32_PLL2_M_DIVISOR,
589 STM32_PLL2_N_MULTIPLIER,
590 STM32_PLL2_P_DIVISOR);
591 break;
592 case STM32_SRC_PLL2_Q:
593 *rate = get_pllout_frequency(get_pllsrc_frequency(),
594 STM32_PLL2_M_DIVISOR,
595 STM32_PLL2_N_MULTIPLIER,
596 STM32_PLL2_Q_DIVISOR);
597 break;
598 case STM32_SRC_PLL2_R:
599 *rate = get_pllout_frequency(get_pllsrc_frequency(),
600 STM32_PLL2_M_DIVISOR,
601 STM32_PLL2_N_MULTIPLIER,
602 STM32_PLL2_R_DIVISOR);
603 break;
604 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
605 case STM32_SRC_PLL2_S:
606 *rate = get_pllout_frequency(get_pllsrc_frequency(),
607 STM32_PLL2_M_DIVISOR,
608 STM32_PLL2_N_MULTIPLIER,
609 STM32_PLL2_S_DIVISOR);
610 break;
611 case STM32_SRC_PLL2_T:
612 *rate = get_pllout_frequency(get_pllsrc_frequency(),
613 STM32_PLL2_M_DIVISOR,
614 STM32_PLL2_N_MULTIPLIER,
615 STM32_PLL2_T_DIVISOR);
616 break;
617 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
618 #endif /* STM32_PLL2_ENABLED */
619 #if defined(STM32_PLL3_ENABLED)
620 case STM32_SRC_PLL3_P:
621 *rate = get_pllout_frequency(get_pllsrc_frequency(),
622 STM32_PLL3_M_DIVISOR,
623 STM32_PLL3_N_MULTIPLIER,
624 STM32_PLL3_P_DIVISOR);
625 break;
626 case STM32_SRC_PLL3_Q:
627 *rate = get_pllout_frequency(get_pllsrc_frequency(),
628 STM32_PLL3_M_DIVISOR,
629 STM32_PLL3_N_MULTIPLIER,
630 STM32_PLL3_Q_DIVISOR);
631 break;
632 case STM32_SRC_PLL3_R:
633 *rate = get_pllout_frequency(get_pllsrc_frequency(),
634 STM32_PLL3_M_DIVISOR,
635 STM32_PLL3_N_MULTIPLIER,
636 STM32_PLL3_R_DIVISOR);
637 break;
638 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
639 case STM32_SRC_PLL3_S:
640 *rate = get_pllout_frequency(get_pllsrc_frequency(),
641 STM32_PLL3_M_DIVISOR,
642 STM32_PLL3_N_MULTIPLIER,
643 STM32_PLL3_S_DIVISOR);
644 break;
645 /* PLL 3 has no T-divider */
646 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
647 #endif /* STM32_PLL3_ENABLED */
648 default:
649 return -ENOTSUP;
650 }
651
652 if (pclken->div) {
653 *rate /= (pclken->div + 1);
654 }
655
656 return 0;
657 }
658
659 static DEVICE_API(clock_control, stm32_clock_control_api) = {
660 .on = stm32_clock_control_on,
661 .off = stm32_clock_control_off,
662 .get_rate = stm32_clock_control_get_subsys_rate,
663 .configure = stm32_clock_control_configure,
664 };
665
666 __unused
667 static void set_up_fixed_clock_sources(void)
668 {
669
670 if (IS_ENABLED(STM32_HSE_ENABLED)) {
671 /* Enable HSE oscillator */
672 if (IS_ENABLED(STM32_HSE_BYPASS)) {
673 LL_RCC_HSE_EnableBypass();
674 } else {
675 LL_RCC_HSE_DisableBypass();
676 }
677
678 LL_RCC_HSE_Enable();
679 while (LL_RCC_HSE_IsReady() != 1) {
680 }
681 /* Check if we need to enable HSE clock security system or not */
682 #if STM32_HSE_CSS
683 z_arm_nmi_set_handler(HAL_RCC_NMI_IRQHandler);
684 LL_RCC_HSE_EnableCSS();
685 #endif /* STM32_HSE_CSS */
686 }
687
688 if (IS_ENABLED(STM32_HSI_ENABLED)) {
689 if (IS_ENABLED(STM32_PLL_SRC_HSI) || IS_ENABLED(STM32_PLL2_SRC_HSI) ||
690 + IS_ENABLED(STM32_PLL3_SRC_HSI)) {
691 /* HSI calibration */
692 LL_RCC_HSI_SetCalibTrimming(RCC_HSICALIBRATION_DEFAULT);
693 }
694 /* Enable HSI if not enabled */
695 if (LL_RCC_HSI_IsReady() != 1) {
696 /* Enable HSI oscillator */
697 LL_RCC_HSI_Enable();
698 while (LL_RCC_HSI_IsReady() != 1) {
699 /* Wait for HSI ready */
700 }
701 }
702 /* HSI divider configuration */
703 LL_RCC_HSI_SetDivider(hsi_divider(STM32_HSI_DIVISOR));
704 }
705
706 if (IS_ENABLED(STM32_CSI_ENABLED)) {
707 /* Enable CSI oscillator */
708 LL_RCC_CSI_Enable();
709 while (LL_RCC_CSI_IsReady() != 1) {
710 }
711 }
712
713 if (IS_ENABLED(STM32_LSI_ENABLED)) {
714 /* Enable LSI oscillator */
715 LL_RCC_LSI_Enable();
716 while (LL_RCC_LSI_IsReady() != 1) {
717 }
718 }
719
720 if (IS_ENABLED(STM32_LSE_ENABLED)) {
721 /* Enable backup domain */
722 LL_PWR_EnableBkUpAccess();
723
724 /* Configure driving capability */
725 LL_RCC_LSE_SetDriveCapability(STM32_LSE_DRIVING << RCC_BDCR_LSEDRV_Pos);
726
727 if (IS_ENABLED(STM32_LSE_BYPASS)) {
728 /* Configure LSE bypass */
729 LL_RCC_LSE_EnableBypass();
730 }
731
732 /* Enable LSE oscillator */
733 LL_RCC_LSE_Enable();
734 while (LL_RCC_LSE_IsReady() != 1) {
735 }
736 }
737
738 if (IS_ENABLED(STM32_HSI48_ENABLED)) {
739 LL_RCC_HSI48_Enable();
740 while (LL_RCC_HSI48_IsReady() != 1) {
741 }
742 }
743 }
744
745 /*
746 * Unconditionally switch the system clock source to HSI.
747 */
748 __unused
749 static void stm32_clock_switch_to_hsi(void)
750 {
751 /* Enable HSI if not enabled */
752 if (LL_RCC_HSI_IsReady() != 1) {
753 /* Enable HSI */
754 LL_RCC_HSI_Enable();
755 while (LL_RCC_HSI_IsReady() != 1) {
756 /* Wait for HSI ready */
757 }
758 }
759
760 /* Set HSI as SYSCLCK source */
761 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
762 while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {
763 }
764 }
765
766 __unused
767 static int set_up_plls(void)
768 {
769 #if defined(STM32_PLL_ENABLED) || defined(STM32_PLL2_ENABLED) || defined(STM32_PLL3_ENABLED)
770 int r;
771 uint32_t vco_input_range;
772 uint32_t vco_output_range;
773
774 /*
775 * Case of chain-loaded applications:
776 * Switch to HSI and disable the PLL before configuration.
777 * (Switching to HSI makes sure we have a SYSCLK source in
778 * case we're currently running from the PLL we're about to
779 * turn off and reconfigure.)
780 *
781 */
782 if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) {
783 stm32_clock_switch_to_hsi();
784 LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
785 }
786
787 #if defined(CONFIG_STM32_MEMMAP) && defined(CONFIG_BOOTLOADER_MCUBOOT)
788 /*
789 * Don't disable PLL during application initialization
790 * that runs in memmap mode when (Q/O)SPI uses PLL
791 * as its clock source.
792 */
793 #if defined(OCTOSPI1) || defined(OCTOSPI2)
794 if (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) != LL_RCC_OSPI_CLKSOURCE_PLL1Q) {
795 LL_RCC_PLL1_Disable();
796 }
797 if (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) != LL_RCC_OSPI_CLKSOURCE_PLL2R) {
798 LL_RCC_PLL2_Disable();
799 }
800 #elif defined(QUADSPI)
801 if (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) != LL_RCC_QSPI_CLKSOURCE_PLL1Q) {
802 LL_RCC_PLL1_Disable();
803 }
804 if (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) != LL_RCC_QSPI_CLKSOURCE_PLL2R) {
805 LL_RCC_PLL2_Disable();
806 }
807 #else
808 LL_RCC_PLL1_Disable();
809 LL_RCC_PLL2_Disable();
810 #endif
811 #else
812 LL_RCC_PLL1_Disable();
813 LL_RCC_PLL2_Disable();
814 #endif
815 LL_RCC_PLL3_Disable();
816
817 /* Configure PLL source */
818
819 /* Can be HSE , HSI 64Mhz/HSIDIV, CSI 4MHz*/
820 if (IS_ENABLED(STM32_PLL_SRC_HSE)) {
821 /* Main PLL configuration and activation */
822 LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
823 } else if (IS_ENABLED(STM32_PLL_SRC_CSI)) {
824 /* Main PLL configuration and activation */
825 LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_CSI);
826 } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) {
827 /* Main PLL configuration and activation */
828 LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
829 } else {
830 return -ENOTSUP;
831 }
832
833 #if defined(STM32_PLL_ENABLED)
834 r = get_vco_input_range(STM32_PLL_M_DIVISOR, &vco_input_range);
835 if (r < 0) {
836 return r;
837 }
838
839 vco_output_range = get_vco_output_range(vco_input_range);
840
841 LL_RCC_PLL1_SetM(STM32_PLL_M_DIVISOR);
842
843 LL_RCC_PLL1_SetVCOInputRange(vco_input_range);
844 LL_RCC_PLL1_SetVCOOutputRange(vco_output_range);
845
846 LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER);
847
848 LL_RCC_PLL1FRACN_Disable();
849 if (IS_ENABLED(STM32_PLL_FRACN_ENABLED)) {
850 LL_RCC_PLL1_SetFRACN(STM32_PLL_FRACN_VALUE);
851 LL_RCC_PLL1FRACN_Enable();
852 }
853
854 if (IS_ENABLED(STM32_PLL_P_ENABLED)) {
855 LL_RCC_PLL1_SetP(STM32_PLL_P_DIVISOR);
856 LL_RCC_PLL1P_Enable();
857 }
858
859 if (IS_ENABLED(STM32_PLL_Q_ENABLED)) {
860 LL_RCC_PLL1_SetQ(STM32_PLL_Q_DIVISOR);
861 LL_RCC_PLL1Q_Enable();
862 }
863
864 if (IS_ENABLED(STM32_PLL_R_ENABLED)) {
865 LL_RCC_PLL1_SetR(STM32_PLL_R_DIVISOR);
866 LL_RCC_PLL1R_Enable();
867 }
868
869 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
870 if (IS_ENABLED(STM32_PLL_S_ENABLED)) {
871 LL_RCC_PLL1_SetS(STM32_PLL_S_DIVISOR);
872 LL_RCC_PLL1S_Enable();
873 }
874 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
875 LL_RCC_PLL1_Enable();
876 while (LL_RCC_PLL1_IsReady() != 1U) {
877 }
878
879 #endif /* STM32_PLL_ENABLED */
880
881 #if defined(STM32_PLL2_ENABLED)
882 r = get_vco_input_range(STM32_PLL2_M_DIVISOR, &vco_input_range);
883 if (r < 0) {
884 return r;
885 }
886
887 vco_output_range = get_vco_output_range(vco_input_range);
888
889 LL_RCC_PLL2_SetM(STM32_PLL2_M_DIVISOR);
890
891 LL_RCC_PLL2_SetVCOInputRange(vco_input_range);
892 LL_RCC_PLL2_SetVCOOutputRange(vco_output_range);
893
894 LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER);
895
896 LL_RCC_PLL2FRACN_Disable();
897 if (IS_ENABLED(STM32_PLL2_FRACN_ENABLED)) {
898 LL_RCC_PLL2_SetFRACN(STM32_PLL2_FRACN_VALUE);
899 LL_RCC_PLL2FRACN_Enable();
900 }
901
902 if (IS_ENABLED(STM32_PLL2_P_ENABLED)) {
903 LL_RCC_PLL2_SetP(STM32_PLL2_P_DIVISOR);
904 LL_RCC_PLL2P_Enable();
905 }
906
907 if (IS_ENABLED(STM32_PLL2_Q_ENABLED)) {
908 LL_RCC_PLL2_SetQ(STM32_PLL2_Q_DIVISOR);
909 LL_RCC_PLL2Q_Enable();
910 }
911
912 if (IS_ENABLED(STM32_PLL2_R_ENABLED)) {
913 LL_RCC_PLL2_SetR(STM32_PLL2_R_DIVISOR);
914 LL_RCC_PLL2R_Enable();
915 }
916
917 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
918 if (IS_ENABLED(STM32_PLL2_S_ENABLED)) {
919 LL_RCC_PLL2_SetS(STM32_PLL2_S_DIVISOR);
920 LL_RCC_PLL2S_Enable();
921 }
922
923 if (IS_ENABLED(STM32_PLL2_T_ENABLED)) {
924 LL_RCC_PLL2_SetT(STM32_PLL2_T_DIVISOR);
925 LL_RCC_PLL2T_Enable();
926 }
927
928 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
929 LL_RCC_PLL2_Enable();
930 while (LL_RCC_PLL2_IsReady() != 1U) {
931 }
932
933 #endif /* STM32_PLL2_ENABLED */
934
935 #if defined(STM32_PLL3_ENABLED)
936 r = get_vco_input_range(STM32_PLL3_M_DIVISOR, &vco_input_range);
937 if (r < 0) {
938 return r;
939 }
940
941 vco_output_range = get_vco_output_range(vco_input_range);
942
943 LL_RCC_PLL3_SetM(STM32_PLL3_M_DIVISOR);
944
945 LL_RCC_PLL3_SetVCOInputRange(vco_input_range);
946 LL_RCC_PLL3_SetVCOOutputRange(vco_output_range);
947
948 LL_RCC_PLL3_SetN(STM32_PLL3_N_MULTIPLIER);
949
950 LL_RCC_PLL3FRACN_Disable();
951 if (IS_ENABLED(STM32_PLL3_FRACN_ENABLED)) {
952 LL_RCC_PLL3_SetFRACN(STM32_PLL3_FRACN_VALUE);
953 LL_RCC_PLL3FRACN_Enable();
954 }
955
956 if (IS_ENABLED(STM32_PLL3_P_ENABLED)) {
957 LL_RCC_PLL3_SetP(STM32_PLL3_P_DIVISOR);
958 LL_RCC_PLL3P_Enable();
959 }
960
961 if (IS_ENABLED(STM32_PLL3_Q_ENABLED)) {
962 LL_RCC_PLL3_SetQ(STM32_PLL3_Q_DIVISOR);
963 LL_RCC_PLL3Q_Enable();
964 }
965
966 if (IS_ENABLED(STM32_PLL3_R_ENABLED)) {
967 LL_RCC_PLL3_SetR(STM32_PLL3_R_DIVISOR);
968 LL_RCC_PLL3R_Enable();
969 }
970
971 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
972 if (IS_ENABLED(STM32_PLL3_S_ENABLED)) {
973 LL_RCC_PLL3_SetS(STM32_PLL3_S_DIVISOR);
974 LL_RCC_PLL3S_Enable();
975 }
976
977 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
978 LL_RCC_PLL3_Enable();
979 while (LL_RCC_PLL3_IsReady() != 1U) {
980 }
981
982 #endif /* STM32_PLL3_ENABLED */
983
984 #else
985 /* Init PLL source to None */
986 LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_NONE);
987
988 #endif /* STM32_PLL_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED */
989
990 return 0;
991 }
992
993 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
994 /* adapted from the stm32cube SystemCoreClockUpdate*/
995 void stm32_system_clock_update(void)
996 {
997 uint32_t sysclk, hsivalue, pllsource, pllm, pllp, core_presc;
998 float_t pllfracn, pllvco;
999
1000 /* Get SYSCLK source */
1001 switch (RCC->CFGR & RCC_CFGR_SWS) {
1002 case 0x00: /* HSI used as system clock source (default after reset) */
1003 sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)
1004 >> RCC_CR_HSIDIV_Pos));
1005 break;
1006
1007 case 0x08: /* CSI used as system clock source */
1008 sysclk = CSI_VALUE;
1009 break;
1010
1011 case 0x10: /* HSE used as system clock source */
1012 sysclk = HSE_VALUE;
1013 break;
1014
1015 case 0x18: /* PLL1 used as system clock source */
1016 /*
1017 * PLL1_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
1018 * SYSCLK = PLL1_VCO / PLL1R
1019 */
1020 pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
1021 pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos);
1022
1023 if ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN) != 0U) {
1024 pllfracn = (float_t)(uint32_t)(((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN)
1025 >> RCC_PLL1FRACR_FRACN_Pos));
1026 } else {
1027 pllfracn = (float_t)0U;
1028 }
1029
1030 if (pllm != 0U) {
1031 switch (pllsource) {
1032 case 0x02: /* HSE used as PLL1 clock source */
1033 pllvco = ((float_t)HSE_VALUE / (float_t)pllm) *
1034 ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) +
1035 (pllfracn/(float_t)0x2000) + (float_t)1);
1036 break;
1037
1038 case 0x01: /* CSI used as PLL1 clock source */
1039 pllvco = ((float_t)CSI_VALUE / (float_t)pllm) *
1040 ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) +
1041 (pllfracn/(float_t)0x2000) + (float_t)1);
1042 break;
1043
1044 case 0x00: /* HSI used as PLL1 clock source */
1045 default:
1046 hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >>
1047 RCC_CR_HSIDIV_Pos));
1048 pllvco = ((float_t)hsivalue / (float_t)pllm) *
1049 ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) +
1050 (pllfracn/(float_t)0x2000) + (float_t)1);
1051 break;
1052 }
1053
1054 pllp = (((RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVP) >>
1055 RCC_PLL1DIVR1_DIVP_Pos) + 1U);
1056 sysclk = (uint32_t)(float_t)(pllvco/(float_t)pllp);
1057 } else {
1058 sysclk = 0U;
1059 }
1060 break;
1061
1062 default: /* Unexpected, default to HSI used as system clk source (default after reset) */
1063 sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos));
1064 break;
1065 }
1066
1067 /* system clock frequency : CM7 CPU frequency */
1068 core_presc = (RCC->CDCFGR & RCC_CDCFGR_CPRE);
1069
1070 if (core_presc >= 8U) {
1071 SystemCoreClock = (sysclk >> (core_presc - RCC_CDCFGR_CPRE_3 + 1U));
1072 } else {
1073 SystemCoreClock = sysclk;
1074 }
1075 }
1076 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
1077
1078 int stm32_clock_control_init(const struct device *dev)
1079 {
1080 int r = 0;
1081
1082 #if defined(CONFIG_CPU_CORTEX_M7)
1083 uint32_t old_hclk_freq;
1084 uint32_t new_hclk_freq;
1085
1086 /* HW semaphore Clock enable */
1087 #if defined(CONFIG_SOC_STM32H7A3XX) || defined(CONFIG_SOC_STM32H7A3XXQ) || \
1088 defined(CONFIG_SOC_STM32H7B0XX) || defined(CONFIG_SOC_STM32H7B0XXQ) || \
1089 defined(CONFIG_SOC_STM32H7B3XX) || defined(CONFIG_SOC_STM32H7B3XXQ)
1090 LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_HSEM);
1091 #elif !defined(CONFIG_SOC_SERIES_STM32H7RSX)
1092 /* The stm32h7RS serie has no HSEM peripheral */
1093 LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM);
1094 #endif
1095 z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
1096
1097 /* Set up individual enabled clocks */
1098 set_up_fixed_clock_sources();
1099
1100 /* Set up PLLs */
1101 r = set_up_plls();
1102 if (r < 0) {
1103 return r;
1104 }
1105
1106 /* Configure Voltage scale to comply with the desired system frequency */
1107 prepare_regulator_voltage_scale();
1108
1109 /* Current hclk value */
1110 old_hclk_freq = get_hclk_frequency();
1111 /* AHB is HCLK clock to configure */
1112 new_hclk_freq = get_bus_clock(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC,
1113 STM32_HPRE);
1114
1115 /* Set flash latency */
1116
1117 /* AHB/AXI/HCLK clock is SYSCLK / HPRE */
1118 /* If freq increases, set flash latency before any clock setting */
1119 if (new_hclk_freq > old_hclk_freq) {
1120 LL_SetFlashLatency(new_hclk_freq);
1121 }
1122 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
1123 /*
1124 * The default Flash latency is 3 WS which is not enough,
1125 * set higher and correct later if needed
1126 */
1127 LL_FLASH_SetLatency(LL_FLASH_LATENCY_6);
1128 #endif /* CONFIG_SOC_SERIES_STM32H7RSX */
1129
1130 /* Preset the prescalers prior to choosing SYSCLK */
1131 /* Prevents APB clock to go over limits */
1132 /* Set buses (Sys,AHB, APB1, APB2 & APB4) prescalers */
1133 LL_RCC_SetSysPrescaler(sysclk_prescaler(STM32_D1CPRE));
1134 LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_HPRE));
1135 #if defined(CONFIG_SOC_SERIES_STM32H7RSX)
1136 LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_PPRE1));
1137 LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_PPRE2));
1138 LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_PPRE4));
1139 LL_RCC_SetAPB5Prescaler(apb5_prescaler(STM32_PPRE5));
1140
1141 #else
1142 LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_D2PPRE1));
1143 LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_D2PPRE2));
1144 LL_RCC_SetAPB3Prescaler(apb3_prescaler(STM32_D1PPRE));
1145 LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_D3PPRE));
1146
1147 #endif
1148 /* Set up sys clock */
1149 if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) {
1150 /* Set PLL1 as System Clock Source */
1151 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
1152 while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) {
1153 }
1154 } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSE)) {
1155 /* Set sysclk source to HSE */
1156 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
1157 while (LL_RCC_GetSysClkSource() !=
1158 LL_RCC_SYS_CLKSOURCE_STATUS_HSE) {
1159 }
1160 } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSI)) {
1161 /* Set sysclk source to HSI */
1162 stm32_clock_switch_to_hsi();
1163 } else if (IS_ENABLED(STM32_SYSCLK_SRC_CSI)) {
1164 /* Set sysclk source to CSI */
1165 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_CSI);
1166 while (LL_RCC_GetSysClkSource() !=
1167 LL_RCC_SYS_CLKSOURCE_STATUS_CSI) {
1168 }
1169 } else {
1170 return -ENOTSUP;
1171 }
1172
1173 /* Set FLASH latency */
1174 /* AHB/AXI/HCLK clock is SYSCLK / HPRE */
1175 /* If freq not increased, set flash latency after all clock setting */
1176 if (new_hclk_freq <= old_hclk_freq) {
1177 LL_SetFlashLatency(new_hclk_freq);
1178 }
1179
1180 optimize_regulator_voltage_scale(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
1181
1182 z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
1183 #endif /* CONFIG_CPU_CORTEX_M7 */
1184
1185 ARG_UNUSED(dev);
1186
1187 /* Update CMSIS variable */
1188 SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
1189
1190 return r;
1191 }
1192
1193 #if defined(STM32_HSE_CSS)
1194 void __weak stm32_hse_css_callback(void) {}
1195
1196 /* Called by the HAL in response to an HSE CSS interrupt */
1197 void HAL_RCC_CSSCallback(void)
1198 {
1199 stm32_hse_css_callback();
1200 }
1201 #endif
1202
1203 /**
1204 * @brief RCC device, note that priority is intentionally set to 1 so
1205 * that the device init runs just after SOC init
1206 */
1207 DEVICE_DT_DEFINE(DT_NODELABEL(rcc),
1208 stm32_clock_control_init,
1209 NULL,
1210 NULL, NULL,
1211 PRE_KERNEL_1,
1212 CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
1213 &stm32_clock_control_api);
1214