Skip to content

Commit 92365ed

Browse files
tpamborfabiobaltieri
authored andcommitted
drivers: clock_control: stm32{h5,u5}: fix PLL rate with fractional PLL
When calculating the PLL output rate, take into account the fractional part of the PLL multiplier N. This ensures that the calculated output frequency is correct. Signed-off-by: Tim Pambor <tim.pambor@codewrights.de>
1 parent 049d368 commit 92365ed

File tree

3 files changed

+44
-12
lines changed

3 files changed

+44
-12
lines changed

‎drivers/clock_control/clock_stm32_ll_h5.c‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#define PLL2_ID 2
4141
#define PLL3_ID 3
4242

43+
#define PLL_FRACN_DIVISOR 8192
44+
4345
static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler)
4446
{
4547
return clock / prescaler;
@@ -87,13 +89,17 @@ static uint32_t get_startup_frequency(void)
8789

8890
__unused
8991
static uint32_t get_pllout_frequency(uint32_t pllsrc_freq,
90-
int pllm_div,
91-
int plln_mul,
92-
int pllout_div)
92+
unsigned int pllm_div,
93+
unsigned int plln_mul,
94+
unsigned int plln_frac,
95+
unsigned int pllout_div)
9396
{
9497
__ASSERT_NO_MSG(pllm_div && pllout_div);
9598

96-
return (pllsrc_freq / pllm_div) * plln_mul / pllout_div;
99+
uint32_t f_vco = (pllsrc_freq / pllm_div) *
100+
((uint64_t)plln_mul * PLL_FRACN_DIVISOR + plln_frac) / PLL_FRACN_DIVISOR;
101+
102+
return f_vco / pllout_div;
97103
}
98104

99105
static uint32_t get_sysclk_frequency(void)
@@ -102,6 +108,7 @@ static uint32_t get_sysclk_frequency(void)
102108
return get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
103109
STM32_PLL_M_DIVISOR,
104110
STM32_PLL_N_MULTIPLIER,
111+
STM32_PLL_FRACN_VALUE,
105112
STM32_PLL_R_DIVISOR);
106113
#elif defined(STM32_SYSCLK_SRC_CSI)
107114
return STM32_CSI_FREQ;
@@ -290,18 +297,21 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
290297
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
291298
STM32_PLL_M_DIVISOR,
292299
STM32_PLL_N_MULTIPLIER,
300+
STM32_PLL_FRACN_VALUE,
293301
STM32_PLL_P_DIVISOR);
294302
break;
295303
case STM32_SRC_PLL1_Q:
296304
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
297305
STM32_PLL_M_DIVISOR,
298306
STM32_PLL_N_MULTIPLIER,
307+
STM32_PLL_FRACN_VALUE,
299308
STM32_PLL_Q_DIVISOR);
300309
break;
301310
case STM32_SRC_PLL1_R:
302311
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
303312
STM32_PLL_M_DIVISOR,
304313
STM32_PLL_N_MULTIPLIER,
314+
STM32_PLL_FRACN_VALUE,
305315
STM32_PLL_R_DIVISOR);
306316
break;
307317
#endif /* STM32_PLL_ENABLED */
@@ -310,18 +320,21 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
310320
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL2_ID),
311321
STM32_PLL2_M_DIVISOR,
312322
STM32_PLL2_N_MULTIPLIER,
323+
STM32_PLL2_FRACN_VALUE,
313324
STM32_PLL2_P_DIVISOR);
314325
break;
315326
case STM32_SRC_PLL2_Q:
316327
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL2_ID),
317328
STM32_PLL2_M_DIVISOR,
318329
STM32_PLL2_N_MULTIPLIER,
330+
STM32_PLL2_FRACN_VALUE,
319331
STM32_PLL2_Q_DIVISOR);
320332
break;
321333
case STM32_SRC_PLL2_R:
322334
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL2_ID),
323335
STM32_PLL2_M_DIVISOR,
324336
STM32_PLL2_N_MULTIPLIER,
337+
STM32_PLL2_FRACN_VALUE,
325338
STM32_PLL2_R_DIVISOR);
326339
break;
327340
#endif /* STM32_PLL2_ENABLED */
@@ -330,18 +343,21 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
330343
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL3_ID),
331344
STM32_PLL3_M_DIVISOR,
332345
STM32_PLL3_N_MULTIPLIER,
346+
STM32_PLL3_FRACN_VALUE,
333347
STM32_PLL3_P_DIVISOR);
334348
break;
335349
case STM32_SRC_PLL3_Q:
336350
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL3_ID),
337351
STM32_PLL3_M_DIVISOR,
338352
STM32_PLL3_N_MULTIPLIER,
353+
STM32_PLL3_FRACN_VALUE,
339354
STM32_PLL3_Q_DIVISOR);
340355
break;
341356
case STM32_SRC_PLL3_R:
342357
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL3_ID),
343358
STM32_PLL3_M_DIVISOR,
344359
STM32_PLL3_N_MULTIPLIER,
360+
STM32_PLL3_FRACN_VALUE,
345361
STM32_PLL3_R_DIVISOR);
346362
break;
347363
#endif /* STM32_PLL3_ENABLED */

‎drivers/clock_control/clock_stm32_ll_u5.c‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#define PLL2_ID 2
3838
#define PLL3_ID 3
3939

40+
#define PLL_FRACN_DIVISOR 8192
41+
4042
/* Shorthand for Power Controller node */
4143
#define PWR_NODE DT_NODELABEL(pwr)
4244

@@ -103,13 +105,17 @@ static uint32_t get_startup_frequency(void)
103105

104106
__unused
105107
static uint32_t get_pllout_frequency(uint32_t pllsrc_freq,
106-
int pllm_div,
107-
int plln_mul,
108-
int pllout_div)
108+
unsigned int pllm_div,
109+
unsigned int plln_mul,
110+
unsigned int plln_frac,
111+
unsigned int pllout_div)
109112
{
110113
__ASSERT_NO_MSG(pllm_div && pllout_div);
111114

112-
return (pllsrc_freq / pllm_div) * plln_mul / pllout_div;
115+
uint32_t f_vco = (pllsrc_freq / pllm_div) *
116+
((uint64_t)plln_mul * PLL_FRACN_DIVISOR + plln_frac) / PLL_FRACN_DIVISOR;
117+
118+
return f_vco / pllout_div;
113119
}
114120

115121
static uint32_t get_sysclk_frequency(void)
@@ -118,6 +124,7 @@ static uint32_t get_sysclk_frequency(void)
118124
return get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
119125
STM32_PLL_M_DIVISOR,
120126
STM32_PLL_N_MULTIPLIER,
127+
STM32_PLL_FRACN_VALUE,
121128
STM32_PLL_R_DIVISOR);
122129
#elif defined(STM32_SYSCLK_SRC_MSIS)
123130
return get_msis_frequency();
@@ -318,18 +325,21 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
318325
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
319326
STM32_PLL_M_DIVISOR,
320327
STM32_PLL_N_MULTIPLIER,
328+
STM32_PLL_FRACN_VALUE,
321329
STM32_PLL_P_DIVISOR);
322330
break;
323331
case STM32_SRC_PLL1_Q:
324332
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
325333
STM32_PLL_M_DIVISOR,
326334
STM32_PLL_N_MULTIPLIER,
335+
STM32_PLL_FRACN_VALUE,
327336
STM32_PLL_Q_DIVISOR);
328337
break;
329338
case STM32_SRC_PLL1_R:
330339
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL1_ID),
331340
STM32_PLL_M_DIVISOR,
332341
STM32_PLL_N_MULTIPLIER,
342+
STM32_PLL_FRACN_VALUE,
333343
STM32_PLL_R_DIVISOR);
334344
break;
335345
#endif /* STM32_PLL_ENABLED */
@@ -338,18 +348,21 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
338348
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL2_ID),
339349
STM32_PLL2_M_DIVISOR,
340350
STM32_PLL2_N_MULTIPLIER,
351+
STM32_PLL2_FRACN_VALUE,
341352
STM32_PLL2_P_DIVISOR);
342353
break;
343354
case STM32_SRC_PLL2_Q:
344355
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL2_ID),
345356
STM32_PLL2_M_DIVISOR,
346357
STM32_PLL2_N_MULTIPLIER,
358+
STM32_PLL2_FRACN_VALUE,
347359
STM32_PLL2_Q_DIVISOR);
348360
break;
349361
case STM32_SRC_PLL2_R:
350362
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL2_ID),
351363
STM32_PLL2_M_DIVISOR,
352364
STM32_PLL2_N_MULTIPLIER,
365+
STM32_PLL2_FRACN_VALUE,
353366
STM32_PLL2_R_DIVISOR);
354367
break;
355368
#endif /* STM32_PLL2_ENABLED */
@@ -358,18 +371,21 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
358371
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL3_ID),
359372
STM32_PLL3_M_DIVISOR,
360373
STM32_PLL3_N_MULTIPLIER,
374+
STM32_PLL3_FRACN_VALUE,
361375
STM32_PLL3_P_DIVISOR);
362376
break;
363377
case STM32_SRC_PLL3_Q:
364378
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL3_ID),
365379
STM32_PLL3_M_DIVISOR,
366380
STM32_PLL3_N_MULTIPLIER,
381+
STM32_PLL3_FRACN_VALUE,
367382
STM32_PLL3_Q_DIVISOR);
368383
break;
369384
case STM32_SRC_PLL3_R:
370385
*rate = get_pllout_frequency(get_pllsrc_frequency(PLL3_ID),
371386
STM32_PLL3_M_DIVISOR,
372387
STM32_PLL3_N_MULTIPLIER,
388+
STM32_PLL3_FRACN_VALUE,
373389
STM32_PLL3_R_DIVISOR);
374390
break;
375391
#endif /* STM32_PLL3_ENABLED */

‎include/zephyr/drivers/clock_control/stm32_clock_control.h‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@
204204
#define STM32_PLL_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_s)
205205
#define STM32_PLL_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_s, 1)
206206
#define STM32_PLL_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), fracn)
207-
#define STM32_PLL_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll), fracn, 1)
207+
#define STM32_PLL_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll), fracn, 0)
208208
#endif
209209

210210
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(plli2s), st_stm32f4_plli2s_clock, okay)
@@ -293,7 +293,7 @@
293293
#define STM32_PLL2_T_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_t)
294294
#define STM32_PLL2_T_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_t, 1)
295295
#define STM32_PLL2_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), fracn)
296-
#define STM32_PLL2_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll2), fracn, 1)
296+
#define STM32_PLL2_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll2), fracn, 0)
297297
#endif
298298

299299
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7_pll_clock, okay) || \
@@ -312,7 +312,7 @@
312312
#define STM32_PLL3_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_s)
313313
#define STM32_PLL3_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_s, 1)
314314
#define STM32_PLL3_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), fracn)
315-
#define STM32_PLL3_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll3), fracn, 1)
315+
#define STM32_PLL3_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll3), fracn, 0)
316316
#endif
317317

318318
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll4), st_stm32mp13_pll_clock, okay)
@@ -326,7 +326,7 @@
326326
#define STM32_PLL4_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll4), div_r)
327327
#define STM32_PLL4_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll4), div_r, 1)
328328
#define STM32_PLL4_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll4), fracn)
329-
#define STM32_PLL4_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll4), fracn, 1)
329+
#define STM32_PLL4_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll4), fracn, 0)
330330
#endif
331331

332332
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f1_pll_clock, okay)

0 commit comments

Comments
 (0)