Skip to content

Commit 0abbc2f

Browse files
Alain Volmatkartben
authored andcommitted
drivers: clock: stm32: add PLLSAI1 support (common + L4)
Add stm32 common clock handling for the SAI1 PLL. Signed-off-by: Alain Volmat <[email protected]>
1 parent f5ff9fd commit 0abbc2f

File tree

5 files changed

+206
-3
lines changed

5 files changed

+206
-3
lines changed

drivers/clock_control/clock_stm32_ll_common.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,27 @@ int enabled_clock(uint32_t src_clk)
228228
}
229229
break;
230230
#endif /* STM32_SRC_PLLI2S_R */
231+
#if defined(STM32_SRC_PLLSAI1_P)
232+
case STM32_SRC_PLLSAI1_P:
233+
if (!IS_ENABLED(STM32_PLLSAI1_P_ENABLED)) {
234+
r = -ENOTSUP;
235+
}
236+
break;
237+
#endif /* STM32_SRC_PLLSAI1_P */
238+
#if defined(STM32_SRC_PLLSAI1_Q)
239+
case STM32_SRC_PLLSAI1_Q:
240+
if (!IS_ENABLED(STM32_PLLSAI1_Q_ENABLED)) {
241+
r = -ENOTSUP;
242+
}
243+
break;
244+
#endif /* STM32_SRC_PLLSAI1_Q */
245+
#if defined(STM32_SRC_PLLSAI1_R)
246+
case STM32_SRC_PLLSAI1_R:
247+
if (!IS_ENABLED(STM32_PLLSAI1_R_ENABLED)) {
248+
r = -ENOTSUP;
249+
}
250+
break;
251+
#endif /* STM32_SRC_PLLSAI1_R */
231252
#if defined(STM32_SRC_PLL2CLK)
232253
case STM32_SRC_PLL2CLK:
233254
if (!IS_ENABLED(STM32_PLL2_ENABLED)) {
@@ -441,8 +462,31 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
441462
STM32_PLLI2S_R_DIVISOR);
442463
break;
443464
#endif /* STM32_SRC_PLLI2S_R */
465+
#if defined(STM32_SRC_PLLSAI1_P) & STM32_PLLSAI1_P_ENABLED
466+
case STM32_SRC_PLLSAI1_P:
467+
*rate = get_pll_div_frequency(get_pllsai1src_frequency(),
468+
STM32_PLLSAI1_M_DIVISOR,
469+
STM32_PLLSAI1_N_MULTIPLIER,
470+
STM32_PLLSAI1_P_DIVISOR);
471+
break;
472+
#endif /* STM32_SRC_PLLSAI1_P */
473+
#if defined(STM32_SRC_PLLSAI1_Q) & STM32_PLLSAI1_Q_ENABLED
474+
case STM32_SRC_PLLSAI1_Q:
475+
*rate = get_pll_div_frequency(get_pllsai1src_frequency(),
476+
STM32_PLLSAI1_M_DIVISOR,
477+
STM32_PLLSAI1_N_MULTIPLIER,
478+
STM32_PLLSAI1_Q_DIVISOR);
479+
break;
480+
#endif /* STM32_SRC_PLLSAI1_Q */
481+
#if defined(STM32_SRC_PLLSAI1_R) & STM32_PLLSAI1_R_ENABLED
482+
case STM32_SRC_PLLSAI1_R:
483+
*rate = get_pll_div_frequency(get_pllsai1src_frequency(),
484+
STM32_PLLSAI1_M_DIVISOR,
485+
STM32_PLLSAI1_N_MULTIPLIER,
486+
STM32_PLLSAI1_R_DIVISOR);
487+
break;
488+
#endif /* STM32_SRC_PLLSAI1_R */
444489

445-
/* PLLSAI1x not supported yet */
446490
/* PLLSAI2x not supported yet */
447491
#if defined(STM32_SRC_LSE)
448492
case STM32_SRC_LSE:
@@ -624,6 +668,16 @@ static void set_up_plls(void)
624668
/* Wait for PLL ready */
625669
}
626670
#endif /* STM32_PLLI2S_ENABLED */
671+
672+
#if defined(STM32_PLLSAI1_ENABLED)
673+
config_pllsai1();
674+
675+
/* Enable PLL */
676+
LL_RCC_PLLSAI1_Enable();
677+
while (LL_RCC_PLLSAI1_IsReady() != 1U) {
678+
/* Wait for PLL ready */
679+
}
680+
#endif /* STM32_PLLSAI1_ENABLED */
627681
}
628682

629683
static void set_up_fixed_clock_sources(void)

drivers/clock_control/clock_stm32_ll_common.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@
4242
#define z_plli2s_r(v) LL_RCC_PLLI2SR_DIV_ ## v
4343
#define plli2sr(v) z_plli2s_r(v)
4444

45+
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
46+
#define z_pllsai1_m(v) LL_RCC_PLLSAI1M_DIV_ ## v
47+
#else
48+
#define z_pllsai1_m(v) LL_RCC_PLLM_DIV_ ## v
49+
#endif
50+
#define pllsai1m(v) z_pllsai1_m(v)
51+
52+
#define z_pllsai1_p(v) LL_RCC_PLLSAI1P_DIV_ ## v
53+
#define pllsai1p(v) z_pllsai1_p(v)
54+
55+
#define z_pllsai1_q(v) LL_RCC_PLLSAI1Q_DIV_ ## v
56+
#define pllsai1q(v) z_pllsai1_q(v)
57+
58+
#define z_pllsai1_r(v) LL_RCC_PLLSAI1R_DIV_ ## v
59+
#define pllsai1r(v) z_pllsai1_r(v)
60+
4561
#ifdef __cplusplus
4662
extern "C" {
4763
#endif
@@ -57,6 +73,10 @@ void config_pll2(void);
5773
#if defined(STM32_PLLI2S_ENABLED)
5874
void config_plli2s(void);
5975
#endif
76+
#if defined(STM32_PLLSAI1_ENABLED)
77+
uint32_t get_pllsai1src_frequency(void);
78+
void config_pllsai1(void);
79+
#endif
6080
void config_enable_default_clocks(void);
6181
void config_regulator_voltage(uint32_t hclk_freq);
6282
int enabled_clock(uint32_t src_clk);

drivers/clock_control/clock_stm32l4_l5_wb_wl.c

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <zephyr/sys/time_units.h>
1818
#include "clock_stm32_ll_common.h"
1919

20-
#if defined(STM32_PLL_ENABLED)
20+
#if defined(STM32_PLL_ENABLED) || defined(STM32_PLLSAI1_ENABLED)
2121

2222
#if defined(LL_RCC_MSIRANGESEL_RUN)
2323
#define CALC_RUN_MSI_FREQ(range) __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGESEL_RUN, \
@@ -26,6 +26,9 @@
2626
#define CALC_RUN_MSI_FREQ(range) __LL_RCC_CALC_MSI_FREQ(range << RCC_CR_MSIRANGE_Pos);
2727
#endif
2828

29+
#endif
30+
31+
#if defined(STM32_PLL_ENABLED)
2932
/**
3033
* @brief Return PLL source
3134
*/
@@ -87,6 +90,95 @@ void config_pll_sysclock(void)
8790

8891
#endif /* defined(STM32_PLL_ENABLED) */
8992

93+
#if defined(STM32_PLLSAI1_ENABLED)
94+
95+
/**
96+
* @brief Return PLLSAI1 source
97+
*/
98+
__unused
99+
static uint32_t get_pllsai1_source(void)
100+
{
101+
/* Configure PLL source */
102+
if (IS_ENABLED(STM32_PLLSAI1_SRC_HSI)) {
103+
return LL_RCC_PLLSOURCE_HSI;
104+
} else if (IS_ENABLED(STM32_PLLSAI1_SRC_HSE)) {
105+
return LL_RCC_PLLSOURCE_HSE;
106+
} else if (IS_ENABLED(STM32_PLLSAI1_SRC_MSI)) {
107+
return LL_RCC_PLLSOURCE_MSI;
108+
}
109+
110+
__ASSERT(0, "Invalid source");
111+
return 0;
112+
}
113+
114+
/**
115+
* @brief Get the PLLSAI1 source frequency
116+
*/
117+
__unused
118+
uint32_t get_pllsai1src_frequency(void)
119+
{
120+
if (IS_ENABLED(STM32_PLLSAI1_SRC_HSI)) {
121+
return STM32_HSI_FREQ;
122+
} else if (IS_ENABLED(STM32_PLLSAI1_SRC_HSE)) {
123+
return STM32_HSE_FREQ;
124+
#if defined(STM32_MSI_ENABLED)
125+
} else if (IS_ENABLED(STM32_PLLSAI1_SRC_MSI)) {
126+
return CALC_RUN_MSI_FREQ(STM32_MSI_RANGE);
127+
#endif
128+
}
129+
130+
__ASSERT(0, "Invalid source");
131+
return 0;
132+
}
133+
134+
/**
135+
* @brief Set up PLLSAI1 configuration
136+
*/
137+
__unused
138+
void config_pllsai1(void)
139+
{
140+
#ifndef RCC_PLLSAI1M_DIV_1_16_SUPPORT
141+
/*
142+
* On some L4 series, there is no dedicated M_DIVISOR for PLLSAIs
143+
* and it is shared with PLL and other PLLSAIs. Ensure that if they
144+
* exist, they have the same value
145+
*/
146+
#if defined(STM32_PLL_M_DIVISOR) && (STM32_PLL_M_DIVISOR != STM32_PLLSAI1_M_DIVISOR)
147+
#error "PLLSAI1 M divisor must have same value as PLL M divisor"
148+
#elif defined(STM32_PLLSAI2_M_DIVISOR) && (STM32_PLLSAI2_M_DIVISOR != STM32_PLLSAI1_M_DIVISOR)
149+
#error "PLLSAI1 M divisor must have same value as PLLSAI2 M divisor"
150+
#endif
151+
#endif
152+
#if STM32_PLLSAI1_P_ENABLED
153+
LL_RCC_PLLSAI1_ConfigDomain_SAI(get_pllsai1_source(),
154+
pllsai1m(STM32_PLLSAI1_M_DIVISOR),
155+
STM32_PLLSAI1_N_MULTIPLIER,
156+
pllsai1p(STM32_PLLSAI1_P_DIVISOR));
157+
158+
LL_RCC_PLLSAI1_EnableDomain_SAI();
159+
#endif /* STM32_PLLSAI1_P_ENABLED */
160+
161+
#if STM32_PLLSAI1_Q_ENABLED
162+
LL_RCC_PLLSAI1_ConfigDomain_48M(get_pllsai1_source(),
163+
pllsai1m(STM32_PLLSAI1_M_DIVISOR),
164+
STM32_PLLSAI1_N_MULTIPLIER,
165+
pllsai1q(STM32_PLLSAI1_Q_DIVISOR));
166+
167+
LL_RCC_PLLSAI1_EnableDomain_48M();
168+
#endif /* STM32_PLLSAI1_Q_ENABLED */
169+
170+
#if STM32_PLLSAI1_R_ENABLED
171+
LL_RCC_PLLSAI1_ConfigDomain_ADC(get_pllsai1_source(),
172+
pllsai1m(STM32_PLLSAI1_M_DIVISOR),
173+
STM32_PLLSAI1_N_MULTIPLIER,
174+
pllsai1r(STM32_PLLSAI1_R_DIVISOR));
175+
176+
LL_RCC_PLLSAI1_EnableDomain_ADC();
177+
#endif /* STM32_PLLSAI1_R_ENABLED */
178+
}
179+
180+
#endif /* STM32_PLLSAI1_ENABLED */
181+
90182
/**
91183
* @brief Activate default clocks
92184
*/

include/zephyr/drivers/clock_control/stm32_clock_control.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,18 @@
218218
#define STM32_PLLI2S_R_DIVISOR DT_PROP_OR(DT_NODELABEL(plli2s), div_r, 1)
219219
#endif
220220

221+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay)
222+
#define STM32_PLLSAI1_ENABLED 1
223+
#define STM32_PLLSAI1_M_DIVISOR DT_PROP(DT_NODELABEL(pllsai1), div_m)
224+
#define STM32_PLLSAI1_N_MULTIPLIER DT_PROP(DT_NODELABEL(pllsai1), mul_n)
225+
#define STM32_PLLSAI1_P_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), div_p)
226+
#define STM32_PLLSAI1_P_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai1), div_p, 1)
227+
#define STM32_PLLSAI1_Q_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), div_q)
228+
#define STM32_PLLSAI1_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai1), div_q, 1)
229+
#define STM32_PLLSAI1_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), div_r)
230+
#define STM32_PLLSAI1_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai1), div_r, 1)
231+
#endif
232+
221233
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32u5_pll_clock, okay) || \
222234
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) || \
223235
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7rs_pll_clock, okay) || \
@@ -407,6 +419,28 @@
407419

408420
#endif
409421

422+
/** PLLSAI1 clock source */
423+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pllsai1), okay) && \
424+
DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), clocks)
425+
#define DT_PLLSAI1_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pllsai1))
426+
#if DT_SAME_NODE(DT_PLLSAI1_CLOCKS_CTRL, DT_NODELABEL(clk_msi))
427+
#define STM32_PLLSAI1_SRC_MSI 1
428+
#endif
429+
#if DT_SAME_NODE(DT_PLLSAI1_CLOCKS_CTRL, DT_NODELABEL(clk_hsi))
430+
#define STM32_PLLSAI1_SRC_HSI 1
431+
#endif
432+
#if DT_SAME_NODE(DT_PLLSAI1_CLOCKS_CTRL, DT_NODELABEL(clk_hse))
433+
#define STM32_PLLSAI1_SRC_HSE 1
434+
#endif
435+
436+
#endif
437+
438+
/* On STM32L4 series - PLL / PLLSAI1 shared same source */
439+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l4_pll_clock, okay) && \
440+
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay) && \
441+
!DT_SAME_NODE(DT_PLL_CLOCKS_CTRL, DT_PLLSAI1_CLOCKS_CTRL)
442+
#error "On STM32L4 series, PLL / PLLSAI1 must have the same source"
443+
#endif
410444

411445
/** Fixed clocks related symbols */
412446

include/zephyr/dt-bindings/clock/stm32l4_clock.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@
3535
#define STM32_SRC_PLL_P (STM32_SRC_PCLK + 1)
3636
#define STM32_SRC_PLL_Q (STM32_SRC_PLL_P + 1)
3737
#define STM32_SRC_PLL_R (STM32_SRC_PLL_Q + 1)
38-
/* TODO: PLLSAI clocks */
38+
/* PLLSAI1 clocks */
39+
#define STM32_SRC_PLLSAI1_P (STM32_SRC_PLL_R + 1)
40+
#define STM32_SRC_PLLSAI1_Q (STM32_SRC_PLLSAI1_P + 1)
41+
#define STM32_SRC_PLLSAI1_R (STM32_SRC_PLLSAI1_Q + 1)
3942

4043
/** @brief RCC_CCIPR register offset */
4144
#define CCIPR_REG 0x88

0 commit comments

Comments
 (0)