Skip to content

Commit eaa7f4c

Browse files
committed
drivers/clock_control: stm32_common: Implement clock source selection
Similarly to what was done on U5 and H7 clock_control drivers, enable device clock source selection. This is done by: -providing implementation for clock_control_configure(). -updating clock_control_get_rate() to support various possible clock sources (SYSCLK, PLLCLK, LSE, LSI, HSI, HSE). -providing enable_clock() to verify requested clock source exists and is enabled. -adding LSI and LSE device tree based initialization to set_up_fixed_clock_sources(). Signed-off-by: Erwan Gouriou <[email protected]>
1 parent cb8f684 commit eaa7f4c

File tree

9 files changed

+428
-157
lines changed

9 files changed

+428
-157
lines changed

drivers/clock_control/clock_stm32_ll_common.c

Lines changed: 196 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <zephyr/sys/__assert.h>
1717
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
1818
#include "clock_stm32_ll_common.h"
19+
#include "stm32_hsem.h"
1920

2021
/* Macros to fill up prescaler values */
2122
#define fn_ahb_prescaler(v) LL_RCC_SYSCLK_DIV_ ## v
@@ -35,7 +36,6 @@
3536
#define fn_mco2_prescaler(v) LL_RCC_MCO2_DIV_ ## v
3637
#define mco2_prescaler(v) fn_mco2_prescaler(v)
3738

38-
3939
#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb4_prescaler)
4040
#define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK4_FREQ
4141
#define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHB4Prescaler
@@ -52,6 +52,84 @@ static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler)
5252
return clock / prescaler;
5353
}
5454

55+
__unused
56+
static uint32_t get_msi_frequency(void)
57+
{
58+
#if defined(STM32_MSI_ENABLED)
59+
#if !defined(LL_RCC_MSIRANGESEL_RUN)
60+
return __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
61+
#else
62+
return __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGESEL_RUN,
63+
LL_RCC_MSI_GetRange());
64+
#endif
65+
#endif
66+
return 0;
67+
}
68+
69+
/** @brief Verifies clock is part of active clock configuration */
70+
__unused
71+
static int enabled_clock(uint32_t src_clk)
72+
{
73+
int r = 0;
74+
75+
switch (src_clk) {
76+
#if defined(STM32_SRC_SYSCLK)
77+
case STM32_SRC_SYSCLK:
78+
break;
79+
#endif /* STM32_SRC_SYSCLK */
80+
#if defined(STM32_SRC_PCLK)
81+
case STM32_SRC_PCLK:
82+
break;
83+
#endif /* STM32_SRC_PCLK */
84+
#if defined(STM32_SRC_HSE)
85+
case STM32_SRC_HSE:
86+
if (!IS_ENABLED(STM32_HSE_ENABLED)) {
87+
r = -ENOTSUP;
88+
}
89+
break;
90+
#endif /* STM32_SRC_HSE */
91+
#if defined(STM32_SRC_HSI)
92+
case STM32_SRC_HSI:
93+
if (!IS_ENABLED(STM32_HSI_ENABLED)) {
94+
r = -ENOTSUP;
95+
}
96+
break;
97+
#endif /* STM32_SRC_HSI */
98+
#if defined(STM32_SRC_LSE)
99+
case STM32_SRC_LSE:
100+
if (!IS_ENABLED(STM32_LSE_ENABLED)) {
101+
r = -ENOTSUP;
102+
}
103+
break;
104+
#endif /* STM32_SRC_LSE */
105+
#if defined(STM32_SRC_LSI)
106+
case STM32_SRC_LSI:
107+
if (!IS_ENABLED(STM32_LSI_ENABLED)) {
108+
r = -ENOTSUP;
109+
}
110+
break;
111+
#endif /* STM32_SRC_LSI */
112+
#if defined(STM32_SRC_MSI)
113+
case STM32_SRC_MSI:
114+
if (!IS_ENABLED(STM32_MSI_ENABLED)) {
115+
r = -ENOTSUP;
116+
}
117+
break;
118+
#endif /* STM32_SRC_MSI */
119+
#if defined(STM32_SRC_PLLCLK)
120+
case STM32_SRC_PLLCLK:
121+
if (!IS_ENABLED(STM32_PLL_ENABLED)) {
122+
r = -ENOTSUP;
123+
}
124+
break;
125+
#endif /* STM32_SRC_PLLCLK */
126+
default:
127+
return -ENOTSUP;
128+
}
129+
130+
return r;
131+
}
132+
55133
static inline int stm32_clock_control_on(const struct device *dev,
56134
clock_control_subsys_t sub_system)
57135
{
@@ -69,7 +147,6 @@ static inline int stm32_clock_control_on(const struct device *dev,
69147
return 0;
70148
}
71149

72-
73150
static inline int stm32_clock_control_off(const struct device *dev,
74151
clock_control_subsys_t sub_system)
75152
{
@@ -92,6 +169,40 @@ static inline int stm32_clock_control_off(const struct device *dev,
92169
return 0;
93170
}
94171

172+
static inline int stm32_clock_control_configure(const struct device *dev,
173+
clock_control_subsys_t sub_system,
174+
void *data)
175+
{
176+
#if defined(STM32_SRC_CLOCK_MIN)
177+
/* At least one alt src clock available */
178+
struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
179+
volatile uint32_t *reg;
180+
uint32_t reg_val, dt_val;
181+
int err;
182+
183+
ARG_UNUSED(dev);
184+
ARG_UNUSED(data);
185+
186+
err = enabled_clock(pclken->bus);
187+
if (err < 0) {
188+
/* Attempt to configure a src clock not available or not valid */
189+
return err;
190+
}
191+
192+
dt_val = STM32_CLOCK_VAL_GET(pclken->enr) <<
193+
STM32_CLOCK_SHIFT_GET(pclken->enr);
194+
reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) +
195+
STM32_CLOCK_REG_GET(pclken->enr));
196+
reg_val = *reg;
197+
reg_val |= dt_val;
198+
*reg = reg_val;
199+
200+
return 0;
201+
#else
202+
/* No src clock available: Not supported */
203+
return -ENOTSUP;
204+
#endif
205+
}
95206

96207
static int stm32_clock_control_get_subsys_rate(const struct device *clock,
97208
clock_control_subsys_t sub_system,
@@ -120,6 +231,14 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
120231
uint32_t ahb3_clock = ahb_clock;
121232
#endif
122233

234+
#if defined(STM32_SRC_PCLK)
235+
if (pclken->bus == STM32_SRC_PCLK) {
236+
/* STM32_SRC_PCLK can't be used to request a subsys freq */
237+
/* Use STM32_CLOCK_BUS_FOO instead. */
238+
return -ENOTSUP;
239+
}
240+
#endif
241+
123242
ARG_UNUSED(clock);
124243

125244
switch (pclken->bus) {
@@ -153,6 +272,39 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
153272
/* STM32WL: AHB3 and APB3 share the same clock and prescaler. */
154273
*rate = ahb3_clock;
155274
break;
275+
#endif
276+
#if defined(STM32_SRC_SYSCLK)
277+
case STM32_SRC_SYSCLK:
278+
*rate = SystemCoreClock * STM32_CORE_PRESCALER;
279+
break;
280+
#endif
281+
#if defined(STM32_SRC_PLLCLK) & defined(STM32_SYSCLK_SRC_PLL)
282+
case STM32_SRC_PLLCLK:
283+
if (get_pllout_frequency() == 0) {
284+
return -EIO;
285+
}
286+
*rate = get_pllout_frequency();
287+
break;
288+
#endif
289+
#if defined(STM32_SRC_LSE)
290+
case STM32_SRC_LSE:
291+
*rate = STM32_LSE_FREQ;
292+
break;
293+
#endif
294+
#if defined(STM32_SRC_LSI)
295+
case STM32_SRC_LSI:
296+
*rate = STM32_LSI_FREQ;
297+
break;
298+
#endif
299+
#if defined(STM32_SRC_HSI)
300+
case STM32_SRC_HSI:
301+
*rate = STM32_HSI_FREQ;
302+
break;
303+
#endif
304+
#if defined(STM32_SRC_HSE)
305+
case STM32_SRC_HSE:
306+
*rate = STM32_HSE_FREQ;
307+
break;
156308
#endif
157309
default:
158310
return -ENOTSUP;
@@ -165,6 +317,7 @@ static struct clock_control_driver_api stm32_clock_control_api = {
165317
.on = stm32_clock_control_on,
166318
.off = stm32_clock_control_off,
167319
.get_rate = stm32_clock_control_get_subsys_rate,
320+
.configure = stm32_clock_control_configure,
168321
};
169322

170323
/*
@@ -206,10 +359,9 @@ static inline void stm32_clock_control_mco_init(void)
206359
}
207360

208361
__unused
209-
static int set_up_plls(void)
362+
static void set_up_plls(void)
210363
{
211364
#if defined(STM32_PLL_ENABLED)
212-
int r;
213365

214366
/*
215367
* Case of chain-loaded applications:
@@ -245,10 +397,7 @@ static int set_up_plls(void)
245397
<< RCC_PLLCFGR_PLLQ_Pos);
246398
#endif
247399

248-
r = config_pll_sysclock();
249-
if (r < 0) {
250-
return -ENOTSUP;
251-
}
400+
config_pll_sysclock();
252401

253402
/* Enable PLL */
254403
LL_RCC_PLL_Enable();
@@ -257,8 +406,6 @@ static int set_up_plls(void)
257406
}
258407

259408
#endif /* STM32_PLL_ENABLED */
260-
261-
return 0;
262409
}
263410

264411
static void set_up_fixed_clock_sources(void)
@@ -328,6 +475,44 @@ static void set_up_fixed_clock_sources(void)
328475
}
329476
#endif /* STM32_MSI_ENABLED */
330477

478+
if (IS_ENABLED(STM32_LSI_ENABLED)) {
479+
#if defined(CONFIG_SOC_SERIES_STM32WBX)
480+
LL_RCC_LSI1_Enable();
481+
while (LL_RCC_LSI1_IsReady() != 1) {
482+
}
483+
#else
484+
LL_RCC_LSI_Enable();
485+
while (LL_RCC_LSI_IsReady() != 1) {
486+
}
487+
#endif
488+
}
489+
490+
if (IS_ENABLED(STM32_LSE_ENABLED)) {
491+
/* LSE belongs to the back-up domain, enable access.*/
492+
493+
z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY);
494+
495+
/* Set the DBP bit in the Power control register 1 (PWR_CR1) */
496+
LL_PWR_EnableBkUpAccess();
497+
while (!LL_PWR_IsEnabledBkUpAccess()) {
498+
/* Wait for Backup domain access */
499+
}
500+
501+
#if STM32_LSE_DRIVING
502+
/* Configure driving capability */
503+
LL_RCC_LSE_SetDriveCapability(STM32_LSE_DRIVING << RCC_BDCR_LSEDRV_Pos);
504+
#endif
505+
506+
/* Enable LSE Oscillator (32.768 kHz) */
507+
LL_RCC_LSE_Enable();
508+
while (!LL_RCC_LSE_IsReady()) {
509+
/* Wait for LSE ready */
510+
}
511+
512+
LL_PWR_DisableBkUpAccess();
513+
514+
z_stm32_hsem_unlock(CFG_HW_RCC_SEMID);
515+
}
331516
}
332517

333518
/**
@@ -344,8 +529,6 @@ static void set_up_fixed_clock_sources(void)
344529
*/
345530
int stm32_clock_control_init(const struct device *dev)
346531
{
347-
int r;
348-
349532
ARG_UNUSED(dev);
350533

351534
/* Some clocks would be activated by default */
@@ -371,10 +554,7 @@ int stm32_clock_control_init(const struct device *dev)
371554
set_up_fixed_clock_sources();
372555

373556
/* Set up PLLs */
374-
r = set_up_plls();
375-
if (r < 0) {
376-
return r;
377-
}
557+
set_up_plls();
378558

379559
if (DT_PROP(DT_NODELABEL(rcc), undershoot_prevention) &&
380560
(STM32_CORE_PRESCALER == LL_RCC_SYSCLK_DIV_1) &&

drivers/clock_control/clock_stm32_ll_common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
#endif
3434

3535
#ifdef STM32_SYSCLK_SRC_PLL
36-
int config_pll_sysclock(void);
36+
void config_pll_sysclock(void);
37+
uint32_t get_pllout_frequency(void);
3738
#endif
3839
void config_enable_default_clocks(void);
3940

0 commit comments

Comments
 (0)