Skip to content

Commit 7d447a1

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

File tree

5 files changed

+249
-4
lines changed

5 files changed

+249
-4
lines changed

drivers/clock_control/clock_stm32_ll_common.c

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,34 @@ int enabled_clock(uint32_t src_clk)
249249
}
250250
break;
251251
#endif /* STM32_SRC_PLLSAI1_R */
252+
#if defined(STM32_SRC_PLLSAI2_P)
253+
case STM32_SRC_PLLSAI2_P:
254+
if (!IS_ENABLED(STM32_PLLSAI2_P_ENABLED)) {
255+
r = -ENOTSUP;
256+
}
257+
break;
258+
#endif /* STM32_SRC_PLLSAI2_P */
259+
#if defined(STM32_SRC_PLLSAI2_Q)
260+
case STM32_SRC_PLLSAI2_Q:
261+
if (!IS_ENABLED(STM32_PLLSAI2_Q_ENABLED)) {
262+
r = -ENOTSUP;
263+
}
264+
break;
265+
#endif /* STM32_SRC_PLLSAI2_Q */
266+
#if defined(STM32_SRC_PLLSAI2_R)
267+
case STM32_SRC_PLLSAI2_R:
268+
if (!IS_ENABLED(STM32_PLLSAI2_R_ENABLED)) {
269+
r = -ENOTSUP;
270+
}
271+
break;
272+
#endif /* STM32_SRC_PLLSAI2_R */
273+
#if defined(STM32_SRC_PLLSAI2_DIVR)
274+
case STM32_SRC_PLLSAI2_DIVR:
275+
if (!IS_ENABLED(STM32_PLLSAI2_R_ENABLED)) {
276+
r = -ENOTSUP;
277+
}
278+
break;
279+
#endif /* STM32_SRC_PLLSAI2_DIVR */
252280
#if defined(STM32_SRC_PLL2CLK)
253281
case STM32_SRC_PLL2CLK:
254282
if (!IS_ENABLED(STM32_PLL2_ENABLED)) {
@@ -486,8 +514,40 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
486514
STM32_PLLSAI1_R_DIVISOR);
487515
break;
488516
#endif /* STM32_SRC_PLLSAI1_R */
489-
490-
/* PLLSAI2x not supported yet */
517+
#if defined(STM32_SRC_PLLSAI2_P) & STM32_PLLSAI2_P_ENABLED
518+
case STM32_SRC_PLLSAI2_P:
519+
*rate = get_pll_div_frequency(get_pllsai2src_frequency(),
520+
STM32_PLLSAI2_M_DIVISOR,
521+
STM32_PLLSAI2_N_MULTIPLIER,
522+
STM32_PLLSAI2_P_DIVISOR);
523+
break;
524+
#endif /* STM32_SRC_PLLSAI2_P */
525+
#if defined(STM32_SRC_PLLSAI2_Q) & STM32_PLLSAI2_Q_ENABLED
526+
case STM32_SRC_PLLSAI2_Q:
527+
*rate = get_pll_div_frequency(get_pllsai2src_frequency(),
528+
STM32_PLLSAI2_M_DIVISOR,
529+
STM32_PLLSAI2_N_MULTIPLIER,
530+
STM32_PLLSAI2_Q_DIVISOR);
531+
break;
532+
#endif /* STM32_SRC_PLLSAI2_Q */
533+
#if defined(STM32_SRC_PLLSAI2_R) & STM32_PLLSAI2_R_ENABLED
534+
case STM32_SRC_PLLSAI2_R:
535+
*rate = get_pll_div_frequency(get_pllsai2src_frequency(),
536+
STM32_PLLSAI2_M_DIVISOR,
537+
STM32_PLLSAI2_N_MULTIPLIER,
538+
STM32_PLLSAI2_R_DIVISOR);
539+
break;
540+
#endif /* STM32_SRC_PLLSAI2_R */
541+
#if defined(STM32_SRC_PLLSAI2_DIVR) & STM32_PLLSAI2_R_ENABLED & STM32_PLLSAI2_DIVR_ENABLED \
542+
& defined(STM32_PLLSAI2_DIVR_DIVISOR)
543+
case STM32_SRC_PLLSAI2_DIVR:
544+
*rate = get_pll_div_frequency(get_pllsai2src_frequency(),
545+
STM32_PLLSAI2_M_DIVISOR,
546+
STM32_PLLSAI2_N_MULTIPLIER,
547+
STM32_PLLSAI2_R_DIVISOR);
548+
*rate /= STM32_PLLSAI2_DIVR_DIVISOR;
549+
break;
550+
#endif /* STM32_SRC_PLLSAI2_DIVR */
491551
#if defined(STM32_SRC_LSE)
492552
case STM32_SRC_LSE:
493553
*rate = STM32_LSE_FREQ;
@@ -678,6 +738,16 @@ static void set_up_plls(void)
678738
/* Wait for PLL ready */
679739
}
680740
#endif /* STM32_PLLSAI1_ENABLED */
741+
742+
#if defined(STM32_PLLSAI2_ENABLED)
743+
config_pllsai2();
744+
745+
/* Enable PLL */
746+
LL_RCC_PLLSAI2_Enable();
747+
while (LL_RCC_PLLSAI2_IsReady() != 1U) {
748+
/* Wait for PLL ready */
749+
}
750+
#endif /* STM32_PLLSAI2_ENABLED */
681751
}
682752

683753
static void set_up_fixed_clock_sources(void)

drivers/clock_control/clock_stm32_ll_common.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,25 @@
5858
#define z_pllsai1_r(v) LL_RCC_PLLSAI1R_DIV_ ## v
5959
#define pllsai1r(v) z_pllsai1_r(v)
6060

61+
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
62+
#define z_pllsai2_m(v) LL_RCC_PLLSAI2M_DIV_ ## v
63+
#else
64+
#define z_pllsai2_m(v) LL_RCC_PLLM_DIV_ ## v
65+
#endif
66+
#define pllsai2m(v) z_pllsai2_m(v)
67+
68+
#define z_pllsai2_p(v) LL_RCC_PLLSAI2P_DIV_ ## v
69+
#define pllsai2p(v) z_pllsai2_p(v)
70+
71+
#define z_pllsai2_q(v) LL_RCC_PLLSAI2Q_DIV_ ## v
72+
#define pllsai2q(v) z_pllsai2_q(v)
73+
74+
#define z_pllsai2_r(v) LL_RCC_PLLSAI2R_DIV_ ## v
75+
#define pllsai2r(v) z_pllsai2_r(v)
76+
77+
#define z_pllsai2_divr(v) LL_RCC_PLLSAI2DIVR_DIV_ ## v
78+
#define pllsai2divr(v) z_pllsai2_divr(v)
79+
6180
#ifdef __cplusplus
6281
extern "C" {
6382
#endif
@@ -77,6 +96,10 @@ void config_plli2s(void);
7796
uint32_t get_pllsai1src_frequency(void);
7897
void config_pllsai1(void);
7998
#endif
99+
#if defined(STM32_PLLSAI2_ENABLED)
100+
uint32_t get_pllsai2src_frequency(void);
101+
void config_pllsai2(void);
102+
#endif
80103
void config_enable_default_clocks(void);
81104
void config_regulator_voltage(uint32_t hclk_freq);
82105
int enabled_clock(uint32_t src_clk);

drivers/clock_control/clock_stm32l4_l5_wb_wl.c

Lines changed: 108 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) || defined(STM32_PLLSAI1_ENABLED)
20+
#if defined(STM32_PLL_ENABLED) || defined(STM32_PLLSAI1_ENABLED) || defined(STM32_PLLSAI2_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, \
@@ -179,6 +179,113 @@ void config_pllsai1(void)
179179

180180
#endif /* STM32_PLLSAI1_ENABLED */
181181

182+
#if defined(STM32_PLLSAI2_ENABLED)
183+
#if defined(RCC_PLLSAI2_SUPPORT)
184+
185+
/**
186+
* @brief Return PLLSAI2 source
187+
*/
188+
__unused
189+
static uint32_t get_pllsai2_source(void)
190+
{
191+
/* Configure PLL source */
192+
if (IS_ENABLED(STM32_PLLSAI2_SRC_HSI)) {
193+
return LL_RCC_PLLSOURCE_HSI;
194+
} else if (IS_ENABLED(STM32_PLLSAI2_SRC_HSE)) {
195+
return LL_RCC_PLLSOURCE_HSE;
196+
} else if (IS_ENABLED(STM32_PLLSAI2_SRC_MSI)) {
197+
return LL_RCC_PLLSOURCE_MSI;
198+
}
199+
200+
__ASSERT(0, "Invalid source");
201+
return 0;
202+
}
203+
204+
/**
205+
* @brief Get the PLLSAI2 source frequency
206+
*/
207+
__unused
208+
uint32_t get_pllsai2src_frequency(void)
209+
{
210+
if (IS_ENABLED(STM32_PLLSAI2_SRC_HSI)) {
211+
return STM32_HSI_FREQ;
212+
} else if (IS_ENABLED(STM32_PLLSAI2_SRC_HSE)) {
213+
return STM32_HSE_FREQ;
214+
#if defined(STM32_MSI_ENABLED)
215+
} else if (IS_ENABLED(STM32_PLLSAI2_SRC_MSI)) {
216+
return CALC_RUN_MSI_FREQ(STM32_MSI_RANGE);
217+
#endif
218+
}
219+
220+
__ASSERT(0, "Invalid source");
221+
return 0;
222+
}
223+
224+
/**
225+
* @brief Set up PLLSAI2 configuration
226+
*/
227+
__unused
228+
void config_pllsai2(void)
229+
{
230+
#ifndef RCC_PLLSAI2M_DIV_1_16_SUPPORT
231+
/*
232+
* On some L4 series, there is no dedicated M_DIVISOR for PLLSAIs
233+
* and it is shared with PLL and other PLLSAIs. Ensure that if they
234+
* exist, they have the same value
235+
*/
236+
#if defined(STM32_PLL_M_DIVISOR) && (STM32_PLL_M_DIVISOR != STM32_PLLSAI2_M_DIVISOR)
237+
#error "PLLSAI2 M divisor must have same value as PLL M divisor"
238+
#elif defined(STM32_PLLSAI1_M_DIVISOR) && (STM32_PLLSAI1_M_DIVISOR != STM32_PLLSAI2_M_DIVISOR)
239+
#error "PLLSAI2 M divisor must have same value as PLLSAI1 M divisor"
240+
#endif
241+
#endif
242+
#if STM32_PLLSAI2_P_ENABLED
243+
LL_RCC_PLLSAI2_ConfigDomain_SAI(get_pllsai2_source(),
244+
pllsai2m(STM32_PLLSAI2_M_DIVISOR),
245+
STM32_PLLSAI2_N_MULTIPLIER,
246+
pllsai2p(STM32_PLLSAI2_P_DIVISOR));
247+
248+
LL_RCC_PLLSAI2_EnableDomain_SAI();
249+
#endif /* STM32_PLLSAI2_P_ENABLED */
250+
251+
#if STM32_PLLSAI2_Q_ENABLED && defined(RCC_PLLSAI2Q_DIV_SUPPORT)
252+
LL_RCC_PLLSAI2_ConfigDomain_DSI(get_pllsai2_source(),
253+
pllsai2m(STM32_PLLSAI2_M_DIVISOR),
254+
STM32_PLLSAI2_N_MULTIPLIER,
255+
pllsai2q(STM32_PLLSAI2_Q_DIVISOR));
256+
257+
LL_RCC_PLLSAI2_EnableDomain_DSI();
258+
#endif /* STM32_PLLSAI2_Q_ENABLED */
259+
260+
#if STM32_PLLSAI2_R_ENABLED
261+
#if defined(RCC_CCIPR2_PLLSAI2DIVR)
262+
#if STM32_PLLSAI2_DIVR_ENABLED
263+
LL_RCC_PLLSAI2_ConfigDomain_LTDC(get_pllsai2_source(),
264+
pllsai2m(STM32_PLLSAI2_M_DIVISOR),
265+
STM32_PLLSAI2_N_MULTIPLIER,
266+
pllsai2r(STM32_PLLSAI2_R_DIVISOR),
267+
pllsai2divr(STM32_PLLSAI2_DIVR_DIVISOR));
268+
269+
LL_RCC_PLLSAI2_EnableDomain_LTDC();
270+
#else
271+
#error "On PLLSAI2, div_divr device-tree properties is needed"
272+
#endif
273+
#else
274+
LL_RCC_PLLSAI2_ConfigDomain_ADC(get_pllsai2_source(),
275+
pllsai2m(STM32_PLLSAI2_M_DIVISOR),
276+
STM32_PLLSAI2_N_MULTIPLIER,
277+
pllsai2r(STM32_PLLSAI2_R_DIVISOR));
278+
279+
LL_RCC_PLLSAI2_EnableDomain_ADC();
280+
#endif
281+
#endif /* STM32_PLLSAI2_R_ENABLED */
282+
}
283+
#else
284+
#error "PLLSAI2 is not available in this platform"
285+
#endif
286+
287+
#endif /* STM32_PLLSAI2_ENABLED */
288+
182289
/**
183290
* @brief Activate default clocks
184291
*/

include/zephyr/drivers/clock_control/stm32_clock_control.h

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,20 @@
230230
#define STM32_PLLSAI1_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai1), div_r, 1)
231231
#endif
232232

233+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai2), st_stm32l4_pllsai_clock, okay)
234+
#define STM32_PLLSAI2_ENABLED 1
235+
#define STM32_PLLSAI2_M_DIVISOR DT_PROP(DT_NODELABEL(pllsai2), div_m)
236+
#define STM32_PLLSAI2_N_MULTIPLIER DT_PROP(DT_NODELABEL(pllsai2), mul_n)
237+
#define STM32_PLLSAI2_P_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai2), div_p)
238+
#define STM32_PLLSAI2_P_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai2), div_p, 1)
239+
#define STM32_PLLSAI2_Q_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai2), div_q)
240+
#define STM32_PLLSAI2_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai2), div_q, 1)
241+
#define STM32_PLLSAI2_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai2), div_r)
242+
#define STM32_PLLSAI2_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai2), div_r, 1)
243+
#define STM32_PLLSAI2_DIVR_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai2), div_divr)
244+
#define STM32_PLLSAI2_DIVR_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai2), div_divr, 1)
245+
#endif
246+
233247
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32u5_pll_clock, okay) || \
234248
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) || \
235249
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7rs_pll_clock, okay) || \
@@ -435,12 +449,38 @@
435449

436450
#endif
437451

438-
/* On STM32L4 series - PLL / PLLSAI1 shared same source */
452+
/** PLLSAI2 clock source */
453+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pllsai2), okay) && \
454+
DT_NODE_HAS_PROP(DT_NODELABEL(pllsai2), clocks)
455+
#define DT_PLLSAI2_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pllsai2))
456+
#if DT_SAME_NODE(DT_PLLSAI2_CLOCKS_CTRL, DT_NODELABEL(clk_msi))
457+
#define STM32_PLLSAI2_SRC_MSI 1
458+
#endif
459+
#if DT_SAME_NODE(DT_PLLSAI2_CLOCKS_CTRL, DT_NODELABEL(clk_hsi))
460+
#define STM32_PLLSAI2_SRC_HSI 1
461+
#endif
462+
#if DT_SAME_NODE(DT_PLLSAI2_CLOCKS_CTRL, DT_NODELABEL(clk_hse))
463+
#define STM32_PLLSAI2_SRC_HSE 1
464+
#endif
465+
466+
#endif
467+
468+
/* On STM32L4 series - PLL / PLLSAI1 and PLLSAI2 shared same source */
439469
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l4_pll_clock, okay) && \
440470
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay) && \
441471
!DT_SAME_NODE(DT_PLL_CLOCKS_CTRL, DT_PLLSAI1_CLOCKS_CTRL)
442472
#error "On STM32L4 series, PLL / PLLSAI1 must have the same source"
443473
#endif
474+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l4_pll_clock, okay) && \
475+
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai2), st_stm32l4_pllsai_clock, okay) && \
476+
!DT_SAME_NODE(DT_PLL_CLOCKS_CTRL, DT_PLLSAI2_CLOCKS_CTRL)
477+
#error "On STM32L4 series, PLL / PLLSAI2 must have the same source"
478+
#endif
479+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay) && \
480+
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai2), st_stm32l4_pllsai_clock, okay) && \
481+
!DT_SAME_NODE(DT_PLLSAI1_CLOCKS_CTRL, DT_PLLSAI2_CLOCKS_CTRL)
482+
#error "On STM32L4 series, PLLSAI1 / PLLSAI2 must have the same source"
483+
#endif
444484

445485
/** Fixed clocks related symbols */
446486

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
#define STM32_SRC_PLLSAI1_P (STM32_SRC_PLL_R + 1)
4040
#define STM32_SRC_PLLSAI1_Q (STM32_SRC_PLLSAI1_P + 1)
4141
#define STM32_SRC_PLLSAI1_R (STM32_SRC_PLLSAI1_Q + 1)
42+
/* PLLSAI2 clocks */
43+
#define STM32_SRC_PLLSAI2_P (STM32_SRC_PLLSAI1_R + 1)
44+
#define STM32_SRC_PLLSAI2_Q (STM32_SRC_PLLSAI2_P + 1)
45+
#define STM32_SRC_PLLSAI2_R (STM32_SRC_PLLSAI2_Q + 1)
46+
#define STM32_SRC_PLLSAI2_DIVR (STM32_SRC_PLLSAI2_R + 1)
4247

4348
/** @brief RCC_CCIPR register offset */
4449
#define CCIPR_REG 0x88

0 commit comments

Comments
 (0)