Skip to content

Commit 7820875

Browse files
author
Alain Volmat
committed
drivers: clock: stm32: add PLLSAI handling (common/F4/F7)
Add code handling the pllsai. It is similar to the pllsai1 pllsai2 which can be found on some other socs, except, depending on the socs the fact that pllsai source can be or not common with other plls and moreover it can also have additional DIV_DIVQ and DIV_DIVR additional dividers. Choice is made to add PLLSAI instead of add further support to PLLSAI1, in order to stick to the proper naming of the PLLs. Signed-off-by: Alain Volmat <[email protected]>
1 parent 3c06fbf commit 7820875

File tree

6 files changed

+264
-6
lines changed

6 files changed

+264
-6
lines changed

drivers/clock_control/clock_stm32_ll_common.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,41 @@ int enabled_clock(uint32_t src_clk)
228228
}
229229
break;
230230
#endif /* STM32_SRC_PLLI2S_R */
231+
#if defined(STM32_SRC_PLLSAI_P)
232+
case STM32_SRC_PLLSAI_P:
233+
if (!IS_ENABLED(STM32_PLLSAI_P_ENABLED)) {
234+
r = -ENOTSUP;
235+
}
236+
break;
237+
#endif /* STM32_SRC_PLLSAI_P */
238+
#if defined(STM32_SRC_PLLSAI_Q)
239+
case STM32_SRC_PLLSAI_Q:
240+
if (!IS_ENABLED(STM32_PLLSAI_Q_ENABLED)) {
241+
r = -ENOTSUP;
242+
}
243+
break;
244+
#endif /* STM32_SRC_PLLSAI_Q */
245+
#if defined(STM32_SRC_PLLSAI_DIVQ)
246+
case STM32_SRC_PLLSAI_DIVQ:
247+
if (!IS_ENABLED(STM32_PLLSAI_Q_ENABLED)) {
248+
r = -ENOTSUP;
249+
}
250+
break;
251+
#endif /* STM32_SRC_PLLSAI_DIVQ */
252+
#if defined(STM32_SRC_PLLSAI_R)
253+
case STM32_SRC_PLLSAI_R:
254+
if (!IS_ENABLED(STM32_PLLSAI_R_ENABLED)) {
255+
r = -ENOTSUP;
256+
}
257+
break;
258+
#endif /* STM32_SRC_PLLSAI_R */
259+
#if defined(STM32_SRC_PLLSAI_DIVR)
260+
case STM32_SRC_PLLSAI_DIVR:
261+
if (!IS_ENABLED(STM32_PLLSAI_R_ENABLED)) {
262+
r = -ENOTSUP;
263+
}
264+
break;
265+
#endif /* STM32_SRC_PLLSAI_DIVR */
231266
#if defined(STM32_SRC_PLLSAI1_P)
232267
case STM32_SRC_PLLSAI1_P:
233268
if (!IS_ENABLED(STM32_PLLSAI1_P_ENABLED)) {
@@ -497,6 +532,50 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
497532
STM32_PLLI2S_R_DIVISOR);
498533
break;
499534
#endif /* STM32_SRC_PLLI2S_R */
535+
#if defined(STM32_SRC_PLLSAI_P) && STM32_PLLSAI_P_ENABLED
536+
case STM32_SRC_PLLSAI_P:
537+
*rate = get_pll_div_frequency(get_pllsaisrc_frequency(),
538+
STM32_PLLSAI_M_DIVISOR,
539+
STM32_PLLSAI_N_MULTIPLIER,
540+
STM32_PLLSAI_P_DIVISOR);
541+
break;
542+
#endif /* STM32_SRC_PLLSAI_P */
543+
#if defined(STM32_SRC_PLLSAI_Q) && STM32_PLLSAI_Q_ENABLED
544+
case STM32_SRC_PLLSAI_Q:
545+
*rate = get_pll_div_frequency(get_pllsaisrc_frequency(),
546+
STM32_PLLSAI_M_DIVISOR,
547+
STM32_PLLSAI_N_MULTIPLIER,
548+
STM32_PLLSAI_Q_DIVISOR);
549+
break;
550+
#endif /* STM32_SRC_PLLSAI_Q */
551+
#if defined(STM32_SRC_PLLSAI_DIVQ) && STM32_PLLSAI_Q_ENABLED && STM32_PLLSAI_DIVQ_ENABLED && \
552+
defined(STM32_PLLSAI_DIVQ_DIVISOR)
553+
case STM32_SRC_PLLSAI_DIVQ:
554+
*rate = get_pll_div_frequency(get_pllsaisrc_frequency(),
555+
STM32_PLLSAI_M_DIVISOR,
556+
STM32_PLLSAI_N_MULTIPLIER,
557+
STM32_PLLSAI_Q_DIVISOR);
558+
*rate /= STM32_PLLSAI_DIVQ_DIVISOR;
559+
break;
560+
#endif /* STM32_SRC_PLLSAI_DIVQ */
561+
#if defined(STM32_SRC_PLLSAI_R) && STM32_PLLSAI_R_ENABLED
562+
case STM32_SRC_PLLSAI_R:
563+
*rate = get_pll_div_frequency(get_pllsaisrc_frequency(),
564+
STM32_PLLSAI_M_DIVISOR,
565+
STM32_PLLSAI_N_MULTIPLIER,
566+
STM32_PLLSAI_R_DIVISOR);
567+
break;
568+
#endif /* STM32_SRC_PLLSAI_R */
569+
#if defined(STM32_SRC_PLLSAI_DIVR) && STM32_PLLSAI_R_ENABLED && STM32_PLLSAI_DIVR_ENABLED && \
570+
defined(STM32_PLLSAI_DIVR_DIVISOR)
571+
case STM32_SRC_PLLSAI_DIVR:
572+
*rate = get_pll_div_frequency(get_pllsaisrc_frequency(),
573+
STM32_PLLSAI_M_DIVISOR,
574+
STM32_PLLSAI_N_MULTIPLIER,
575+
STM32_PLLSAI_R_DIVISOR);
576+
*rate /= STM32_PLLSAI_DIVR_DIVISOR;
577+
break;
578+
#endif /* STM32_SRC_PLLSAI_DIVR */
500579
#if defined(STM32_SRC_PLLSAI1_P) & STM32_PLLSAI1_P_ENABLED
501580
case STM32_SRC_PLLSAI1_P:
502581
*rate = get_pll_div_frequency(get_pllsai1src_frequency(),
@@ -762,6 +841,16 @@ static void set_up_plls(void)
762841
}
763842
#endif /* STM32_PLLI2S_ENABLED */
764843

844+
#if defined(STM32_PLLSAI_ENABLED)
845+
config_pllsai();
846+
847+
/* Enable PLL */
848+
LL_RCC_PLLSAI_Enable();
849+
while (LL_RCC_PLLSAI_IsReady() != 1U) {
850+
/* Wait for PLL ready */
851+
}
852+
#endif /* STM32_PLLSAI_ENABLED */
853+
765854
#if defined(STM32_PLLSAI1_ENABLED)
766855
config_pllsai1();
767856

drivers/clock_control/clock_stm32_ll_common.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,23 @@
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)
45+
#define z_pllsai_m(v) LL_RCC_PLLM_DIV_ ## v
46+
#define pllsaim(v) z_pllsai_m(v)
47+
48+
#define z_pllsai_p(v) LL_RCC_PLLSAIP_DIV_ ## v
49+
#define pllsaip(v) z_pllsai_p(v)
50+
51+
#define z_pllsai_q(v) LL_RCC_PLLSAIQ_DIV_ ## v
52+
#define pllsaiq(v) z_pllsai_q(v)
53+
54+
#define z_pllsai_divq(v) LL_RCC_PLLSAIDIVQ_DIV_ ## v
55+
#define pllsaidivq(v) z_pllsai_divq(v)
56+
57+
#define z_pllsai_r(v) LL_RCC_PLLSAIR_DIV_ ## v
58+
#define pllsair(v) z_pllsai_r(v)
59+
60+
#define z_pllsai_divr(v) LL_RCC_PLLSAIDIVR_DIV_ ## v
61+
#define pllsaidivr(v) z_pllsai_divr(v)
5162

5263
#define z_pllsai1_p(v) LL_RCC_PLLSAI1P_DIV_ ## v
5364
#define pllsai1p(v) z_pllsai1_p(v)
@@ -92,6 +103,10 @@ void config_pll2(void);
92103
#if defined(STM32_PLLI2S_ENABLED)
93104
void config_plli2s(void);
94105
#endif
106+
#if defined(STM32_PLLSAI_ENABLED)
107+
uint32_t get_pllsaisrc_frequency(void);
108+
void config_pllsai(void);
109+
#endif
95110
#if defined(STM32_PLLSAI1_ENABLED)
96111
uint32_t get_pllsai1src_frequency(void);
97112
void config_pllsai1(void);

drivers/clock_control/clock_stm32f2_f4_f7.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,95 @@ void config_plli2s(void)
169169

170170
#endif /* STM32_PLLI2S_ENABLED */
171171

172+
#if defined(STM32_PLLSAI_ENABLED)
173+
174+
/**
175+
* @brief Return PLLSAI source
176+
*/
177+
__unused
178+
static uint32_t get_pllsai_source(void)
179+
{
180+
/* Configure PLL source */
181+
if (IS_ENABLED(STM32_PLLSAI_SRC_HSI)) {
182+
return LL_RCC_PLLSOURCE_HSI;
183+
} else if (IS_ENABLED(STM32_PLLSAI_SRC_HSE)) {
184+
return LL_RCC_PLLSOURCE_HSE;
185+
}
186+
187+
__ASSERT(0, "Invalid source");
188+
return 0;
189+
}
190+
191+
/**
192+
* @brief Get the PLLSAI source frequency
193+
*/
194+
__unused
195+
uint32_t get_pllsaisrc_frequency(void)
196+
{
197+
if (IS_ENABLED(STM32_PLLSAI_SRC_HSI)) {
198+
return STM32_HSI_FREQ;
199+
} else if (IS_ENABLED(STM32_PLLSAI_SRC_HSE)) {
200+
return STM32_HSE_FREQ;
201+
}
202+
203+
__ASSERT(0, "Invalid source");
204+
return 0;
205+
}
206+
207+
/**
208+
* @brief Set up PLLSAI configuration
209+
*/
210+
__unused
211+
void config_pllsai(void)
212+
{
213+
/*
214+
* In case there is no dedicated M_DIVISOR for PLLSAI, the input is shared
215+
* with PLL and PLLI2S. Ensure that if they exist, they have the same value
216+
*/
217+
#if !defined(RCC_PLLSAICFGR_PLLSAIM)
218+
#if defined(STM32_PLL_M_DIVISOR) && (STM32_PLL_M_DIVISOR != STM32_PLLSAI_M_DIVISOR)
219+
#error "PLLSAI M divisor must have same value as PLL M divisor"
220+
#endif
221+
#endif
222+
223+
#if STM32_PLLSAI_P_ENABLED
224+
#if defined(RCC_PLLSAICFGR_PLLSAIP)
225+
LL_RCC_PLLSAI_ConfigDomain_48M(get_pllsai_source(),
226+
pllsaim(STM32_PLLSAI_M_DIVISOR),
227+
STM32_PLLSAI_N_MULTIPLIER,
228+
pllsaip(STM32_PLLSAI_P_DIVISOR));
229+
#else
230+
#error "PLLSAI do not have P output on this SOC"
231+
#endif
232+
#endif /* STM32_PLLSAI_P_ENABLED */
233+
234+
#if STM32_PLLSAI_Q_ENABLED && STM32_PLLSAI_DIVQ_ENABLED
235+
#if defined(RCC_PLLSAICFGR_PLLSAIQ)
236+
LL_RCC_PLLSAI_ConfigDomain_SAI(get_pllsai_source(),
237+
pllsaim(STM32_PLLSAI_M_DIVISOR),
238+
STM32_PLLSAI_N_MULTIPLIER,
239+
pllsaiq(STM32_PLLSAI_Q_DIVISOR),
240+
pllsaidivq(STM32_PLLSAI_DIVQ_DIVISOR));
241+
#else
242+
#error "PLLSAI do not have Q output on this SOC"
243+
#endif
244+
#endif /* STM32_PLLSAI_Q_ENABLED && STM32_PLLSAI_DIVQ_ENABLED */
245+
246+
#if STM32_PLLSAI_R_ENABLED && STM32_PLLSAI_DIVR_ENABLED
247+
#if defined(RCC_PLLSAICFGR_PLLSAIR)
248+
LL_RCC_PLLSAI_ConfigDomain_LTDC(get_pllsai_source(),
249+
pllsaim(STM32_PLLSAI_M_DIVISOR),
250+
STM32_PLLSAI_N_MULTIPLIER,
251+
pllsair(STM32_PLLSAI_R_DIVISOR),
252+
pllsaidivr(STM32_PLLSAI_DIVR_DIVISOR));
253+
#else
254+
#error "PLLSAI do not have R output on this SOC"
255+
#endif
256+
#endif /* STM32_PLLSAI_R_ENABLED && STM32_PLLSAI_DIVR_ENABLED */
257+
}
258+
259+
#endif /* STM32_PLLSAI_ENABLED */
260+
172261
/**
173262
* @brief Activate default clocks
174263
*/

include/zephyr/drivers/clock_control/stm32_clock_control.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,30 @@
220220
#define STM32_PLLI2S_R_DIVISOR DT_PROP_OR(DT_NODELABEL(plli2s), div_r, 1)
221221
#endif
222222

223+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai), st_stm32fx_pllsai_clock, okay)
224+
#define STM32_PLLSAI_ENABLED 1
225+
#define STM32_PLLSAI_M_DIVISOR DT_PROP(DT_NODELABEL(pllsai), div_m)
226+
#define STM32_PLLSAI_N_MULTIPLIER DT_PROP(DT_NODELABEL(pllsai), mul_n)
227+
#define STM32_PLLSAI_P_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai), div_p)
228+
#define STM32_PLLSAI_P_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai), div_p, 1)
229+
#define STM32_PLLSAI_Q_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai), div_q)
230+
#define STM32_PLLSAI_DIVQ_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai), div_divq)
231+
#if (STM32_PLLSAI_Q_ENABLED && !STM32_PLLSAI_DIVQ_ENABLED) || \
232+
(!STM32_PLLSAI_Q_ENABLED && STM32_PLLSAI_DIVQ_ENABLED)
233+
#error "On STM32F4/STM32F7, both div_q and div_divq must be present if one of them is present"
234+
#endif
235+
#define STM32_PLLSAI_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai), div_q, 1)
236+
#define STM32_PLLSAI_DIVQ_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai), div_divq, 1)
237+
#define STM32_PLLSAI_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai), div_r)
238+
#define STM32_PLLSAI_DIVR_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pllsai), div_divr)
239+
#if (STM32_PLLSAI_R_ENABLED && !STM32_PLLSAI_DIVR_ENABLED) || \
240+
(!STM32_PLLSAI_R_ENABLED && STM32_PLLSAI_DIVR_ENABLED)
241+
#error "On STM32F4/STM32F7, both div_r and div_divr must be present if one of them is present"
242+
#endif
243+
#define STM32_PLLSAI_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai), div_r, 1)
244+
#define STM32_PLLSAI_DIVR_DIVISOR DT_PROP_OR(DT_NODELABEL(pllsai), div_divr, 1)
245+
#endif
246+
223247
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay)
224248
#define STM32_PLLSAI1_ENABLED 1
225249
#define STM32_PLLSAI1_M_DIVISOR DT_PROP(DT_NODELABEL(pllsai1), div_m)
@@ -435,6 +459,19 @@
435459

436460
#endif
437461

462+
/** PLLSAI clock source */
463+
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pllsai), okay) && \
464+
DT_NODE_HAS_PROP(DT_NODELABEL(pllsai), clocks)
465+
#define DT_PLLSAI_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(pllsai))
466+
#if DT_SAME_NODE(DT_PLLSAI_CLOCKS_CTRL, DT_NODELABEL(clk_hsi))
467+
#define STM32_PLLSAI_SRC_HSI 1
468+
#endif
469+
#if DT_SAME_NODE(DT_PLLSAI_CLOCKS_CTRL, DT_NODELABEL(clk_hse))
470+
#define STM32_PLLSAI_SRC_HSE 1
471+
#endif
472+
473+
#endif
474+
438475
/** PLLSAI1 clock source */
439476
#if DT_NODE_HAS_STATUS(DT_NODELABEL(pllsai1), okay) && \
440477
DT_NODE_HAS_PROP(DT_NODELABEL(pllsai1), clocks)
@@ -467,6 +504,20 @@
467504

468505
#endif
469506

507+
/* On STM32F4 series - PLL and PLLSAI share the same source */
508+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f4_pll_clock, okay) && \
509+
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai), st_stm32fx_pllsai_clock, okay) && \
510+
!DT_SAME_NODE(DT_PLL_CLOCKS_CTRL, DT_PLLSAI_CLOCKS_CTRL)
511+
#error "On STM32F4 series, PLL and PLLSAI must have the same source"
512+
#endif
513+
514+
/* On STM32F7 series - PLL and PLLSAI share the same source */
515+
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f7_pll_clock, okay) && \
516+
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai), st_stm32fx_pllsai_clock, okay) && \
517+
!DT_SAME_NODE(DT_PLL_CLOCKS_CTRL, DT_PLLSAI_CLOCKS_CTRL)
518+
#error "On STM32F7 series, PLL and PLLSAI must have the same source"
519+
#endif
520+
470521
/* On STM32L4 series - PLL / PLLSAI1 and PLLSAI2 shared same source */
471522
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l4_pll_clock, okay) && \
472523
DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pllsai1), st_stm32l4_pllsai_clock, okay) && \

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@
4343
#define STM32_SRC_TIMPCLK1 (STM32_SRC_CK48 + 1)
4444
#define STM32_SRC_TIMPCLK2 (STM32_SRC_TIMPCLK1 + 1)
4545

46+
/* PLLSAI clocks */
47+
#define STM32_SRC_PLLSAI_P (STM32_SRC_TIMPCLK2 + 1)
48+
#define STM32_SRC_PLLSAI_Q (STM32_SRC_PLLSAI_P + 1)
49+
#define STM32_SRC_PLLSAI_DIVQ (STM32_SRC_PLLSAI_Q + 1)
50+
#define STM32_SRC_PLLSAI_R (STM32_SRC_PLLSAI_DIVQ + 1)
51+
#define STM32_SRC_PLLSAI_DIVR (STM32_SRC_PLLSAI_R + 1)
52+
4653
/* I2S_CKIN not supported yet */
4754
/* #define STM32_SRC_I2S_CKIN TBD */
4855

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@
4242

4343
#define STM32_SRC_PLLI2S_R (STM32_SRC_TIMPCLK2 + 1)
4444

45+
/* PLLSAI clocks */
46+
#define STM32_SRC_PLLSAI_P (STM32_SRC_PLLI2S_R + 1)
47+
#define STM32_SRC_PLLSAI_Q (STM32_SRC_PLLSAI_P + 1)
48+
#define STM32_SRC_PLLSAI_DIVQ (STM32_SRC_PLLSAI_Q + 1)
49+
#define STM32_SRC_PLLSAI_R (STM32_SRC_PLLSAI_DIVQ + 1)
50+
#define STM32_SRC_PLLSAI_DIVR (STM32_SRC_PLLSAI_R + 1)
51+
4552
/** @brief RCC_CFGRx register offset */
4653
#define CFGR_REG 0x08
4754

0 commit comments

Comments
 (0)