Skip to content

Commit dd2ddbb

Browse files
committed
drivers/clock_control: stm32u5: Add support for optional clocks config
This change updates stm32u5 driver to support configuration of optional clocks on peripherals. Signed-off-by: Erwan Gouriou <[email protected]>
1 parent 25ddcae commit dd2ddbb

File tree

2 files changed

+139
-1
lines changed

2 files changed

+139
-1
lines changed

drivers/clock_control/clock_stm32_ll_u5.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,57 @@ static uint32_t get_startup_frequency(void)
7171
}
7272
}
7373

74+
__unused
75+
static uint32_t get_pllout_frequency(uint32_t pllsrc_freq,
76+
int pllm_div,
77+
int plln_mul,
78+
int pllout_div)
79+
{
80+
__ASSERT_NO_MSG(pllm_div && pllout_div);
81+
82+
return (pllsrc_freq * plln_mul) /
83+
(pllm_div * pllout_div);
84+
}
85+
86+
static uint32_t get_sysclk_frequency(void)
87+
{
88+
#if defined(STM32_SYSCLK_SRC_PLL)
89+
return get_pllout_frequency(get_pllsrc_frequency(),
90+
STM32_PLL_M_DIVISOR,
91+
STM32_PLL_N_MULTIPLIER,
92+
STM32_PLL_R_DIVISOR);
93+
#elif defined(STM32_SYSCLK_SRC_MSIS)
94+
return get_msis_frequency();
95+
#elif defined(STM32_SYSCLK_SRC_HSE
96+
return STM32_HSE_FREQ;
97+
#elif defined(STM32_SYSCLK_SRC_HSI)) {
98+
return STM32_HSI_FREQ;
99+
#else
100+
__ASSERT(0, "No SYSCLK Source configured");
101+
return 0;
102+
#endif
103+
104+
}
105+
106+
/** @brief Verifies clock is part of active clock configuration */
107+
static int enabled_clock(uint32_t src_clk)
108+
{
109+
if ((src_clk == STM32_SRC_SYSCLK) ||
110+
((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) ||
111+
((src_clk == STM32_SRC_HSI16) && IS_ENABLED(STM32_HSI_ENABLED)) ||
112+
((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) ||
113+
((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) ||
114+
((src_clk == STM32_SRC_MSIS) && IS_ENABLED(STM32_MSIS_ENABLED)) ||
115+
((src_clk == STM32_SRC_MSIK) && IS_ENABLED(STM32_MSIK_ENABLED)) ||
116+
((src_clk == STM32_SRC_PLL1_P) && IS_ENABLED(STM32_PLL_P_ENABLED)) ||
117+
((src_clk == STM32_SRC_PLL1_Q) && IS_ENABLED(STM32_PLL_Q_ENABLED)) ||
118+
((src_clk == STM32_SRC_PLL1_R) && IS_ENABLED(STM32_PLL_R_ENABLED))) {
119+
return 0;
120+
}
121+
122+
return -ENOTSUP;
123+
}
124+
74125
static inline int stm32_clock_control_on(const struct device *dev,
75126
clock_control_subsys_t sub_system)
76127
{
@@ -115,6 +166,35 @@ static inline int stm32_clock_control_off(const struct device *dev,
115166
return 0;
116167
}
117168

169+
static inline int stm32_clock_control_configure(const struct device *dev,
170+
clock_control_subsys_t sub_system,
171+
void *data)
172+
{
173+
struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
174+
volatile uint32_t *reg;
175+
uint32_t reg_val, dt_val;
176+
int err;
177+
178+
ARG_UNUSED(dev);
179+
ARG_UNUSED(data);
180+
181+
err = enabled_clock(pclken->bus);
182+
if (err < 0) {
183+
/* Attempt to configure a src clock not available or not valid */
184+
return err;
185+
}
186+
187+
dt_val = STM32U5_CLOCK_VAL_GET(pclken->enr) <<
188+
STM32U5_CLOCK_SHIFT_GET(pclken->enr);
189+
reg = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(rcc)) +
190+
STM32U5_CLOCK_REG_GET(pclken->enr));
191+
reg_val = *reg;
192+
reg_val |= dt_val;
193+
*reg = reg_val;
194+
195+
return 0;
196+
}
197+
118198
static int stm32_clock_control_get_subsys_rate(const struct device *dev,
119199
clock_control_subsys_t sys,
120200
uint32_t *rate)
@@ -156,6 +236,60 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev,
156236
case STM32_CLOCK_BUS_APB3:
157237
*rate = apb3_clock;
158238
break;
239+
case STM32_SRC_SYSCLK:
240+
*rate = get_sysclk_frequency();
241+
break;
242+
#if defined(STM32_HSI_ENABLED)
243+
case STM32_SRC_HSI16:
244+
*rate = STM32_HSI_FREQ;
245+
break;
246+
#endif /* STM32_HSI_ENABLED */
247+
#if defined(STM32_MSIS_ENABLED)
248+
case STM32_SRC_MSIS:
249+
*rate = get_msis_frequency();
250+
break;
251+
#endif /* STM32_MSIS_ENABLED */
252+
#if defined(STM32_MSIK_ENABLED)
253+
case STM32_SRC_MSIK:
254+
*rate = __LL_RCC_CALC_MSIK_FREQ(LL_RCC_MSIRANGESEL_RUN,
255+
STM32_MSIK_RANGE << RCC_ICSCR1_MSIKRANGE_Pos);
256+
break;
257+
#endif /* STM32_MSIK_ENABLED */
258+
#if defined(STM32_HSE_ENABLED)
259+
case STM32_SRC_HSE:
260+
*rate = STM32_HSE_FREQ;
261+
break;
262+
#endif /* STM32_HSE_ENABLED */
263+
#if defined(STM32_LSE_ENABLED)
264+
case STM32_SRC_LSE:
265+
*rate = STM32_LSE_FREQ;
266+
break;
267+
#endif /* STM32_LSE_ENABLED */
268+
#if defined(STM32_LSI_ENABLED)
269+
case STM32_SRC_LSI:
270+
*rate = STM32_LSI_FREQ;
271+
break;
272+
#endif /* STM32_LSI_ENABLED */
273+
#if defined(STM32_PLL_ENABLED)
274+
case STM32_SRC_PLL1_P:
275+
*rate = get_pllout_frequency(get_pllsrc_frequency(),
276+
STM32_PLL_M_DIVISOR,
277+
STM32_PLL_N_MULTIPLIER,
278+
STM32_PLL_P_DIVISOR);
279+
break;
280+
case STM32_SRC_PLL1_Q:
281+
*rate = get_pllout_frequency(get_pllsrc_frequency(),
282+
STM32_PLL_M_DIVISOR,
283+
STM32_PLL_N_MULTIPLIER,
284+
STM32_PLL_Q_DIVISOR);
285+
break;
286+
case STM32_SRC_PLL1_R:
287+
*rate = get_pllout_frequency(get_pllsrc_frequency(),
288+
STM32_PLL_M_DIVISOR,
289+
STM32_PLL_N_MULTIPLIER,
290+
STM32_PLL_R_DIVISOR);
291+
break;
292+
#endif /* STM32_PLL_ENABLED */
159293
default:
160294
return -ENOTSUP;
161295
}
@@ -167,6 +301,7 @@ static struct clock_control_driver_api stm32_clock_control_api = {
167301
.on = stm32_clock_control_on,
168302
.off = stm32_clock_control_off,
169303
.get_rate = stm32_clock_control_get_subsys_rate,
304+
.configure = stm32_clock_control_configure,
170305
};
171306

172307
__unused

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
#define STM32_SRC_SYSCLK 0x011
3434
/** Clock muxes */
3535
/* #define STM32_SRC_ICLK 0x012 */
36+
37+
#define STM32_SRC_CLOCK_MIN STM32_SRC_PLL1_P
38+
#define STM32_SRC_CLOCK_MAX STM32_SRC_SYSCLK
39+
3640
/** Bus clocks */
3741
#define STM32_CLOCK_BUS_AHB1 0x088
3842
#define STM32_CLOCK_BUS_AHB2 0x08C
@@ -46,7 +50,6 @@
4650
#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1
4751
#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB3
4852

49-
5053
/**
5154
* @brief STM32U5 clock configuration bit field.
5255
*

0 commit comments

Comments
 (0)