1 /*
2 * Copyright (c) 2024 STMicroelectronics
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <soc.h>
8 #include <stm32_ll_bus.h>
9 #include <stm32_ll_pwr.h>
10 #include <stm32_ll_rcc.h>
11 #include <stm32_ll_radio.h>
12 #include <stm32_ll_system.h>
13 #include <stm32_ll_utils.h>
14
15 #include <zephyr/irq.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/sys/util.h>
18 #include <zephyr/toolchain.h>
19 #include <zephyr/sys/__assert.h>
20 #include <zephyr/arch/common/sys_io.h>
21 #include <zephyr/arch/common/sys_bitops.h>
22 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
23
24 /* Driver definitions */
25 #define RCC_REG(_reg_offset) (DT_REG_ADDR(STM32_CLOCK_CONTROL_NODE) + (_reg_offset))
26 #define RADIO_CTRL_IRQn 21 /* Not provided by CMSIS; must be declared manually */
27
28 #define CLOCK_FREQ_64MHZ (64000000U)
29 #define CLOCK_FREQ_32MHZ (32000000U)
30 #define CLOCK_FREQ_16MHZ (16000000U)
31
32 /* Device tree node definitions */
33 #define DT_RCC_SLOWCLK_NODE DT_PHANDLE(STM32_CLOCK_CONTROL_NODE, slow_clock)
34 #define DT_LSI_NODE DT_NODELABEL(clk_lsi)
35
36 /* Device tree properties definitions */
37 #define STM32_WB0_CLKSYS_PRESCALER \
38 DT_PROP(STM32_CLOCK_CONTROL_NODE, clksys_prescaler)
39
40 #if DT_NODE_HAS_PROP(STM32_CLOCK_CONTROL_NODE, slow_clock)
41
42 # if !DT_NODE_HAS_STATUS_OKAY(DT_RCC_SLOWCLK_NODE)
43 # error slow-clock source is not enabled
44 # endif
45
46 # if DT_SAME_NODE(DT_RCC_SLOWCLK_NODE, DT_LSI_NODE)
47 # define STM32_WB0_SLOWCLK_SRC LL_RCC_LSCO_CLKSOURCE_LSI
48 # elif DT_SAME_NODE(DT_RCC_SLOWCLK_NODE, DT_NODELABEL(clk_lse))
49 # define STM32_WB0_SLOWCLK_SRC LL_RCC_LSCO_CLKSOURCE_LSE
50 # elif DT_SAME_NODE(DT_RCC_SLOWCLK_NODE, DT_NODELABEL(clk_16mhz_div512))
51 # define STM32_WB0_SLOWCLK_SRC LL_RCC_LSCO_CLKSOURCE_HSI64M_DIV2048
52 # else
53 # error Invalid device selected as slow-clock
54 # endif
55
56 #endif /* DT_NODE_HAS_PROP(STM32_CLOCK_CONTROL_NODE, slow_clock) */
57
58 #if DT_NODE_HAS_PROP(DT_LSI_NODE, runtime_measurement_interval)
59 #define STM32_WB0_RUNTIME_LSI_CALIBRATION 1
60 #define STM32_WB0_LSI_RUNTIME_CALIB_INTERVAL \
61 DT_PROP(DT_LSI_NODE, runtime_measurement_interval)
62 #endif /* DT_NODE_HAS_PROP(clk_lsi, runtime_calibration_settings) */
63
64 /* Verify device tree properties are correct */
65 BUILD_ASSERT(!IS_ENABLED(STM32_SYSCLK_SRC_HSE) || STM32_WB0_CLKSYS_PRESCALER != 64,
66 "clksys-prescaler cannot be 64 when SYSCLK source is Direct HSE");
67
68 #if defined(STM32_LSI_ENABLED)
69 /* Check clock configuration allows MR_BLE IP to work.
70 * This IP is required to perform LSI measurements.
71 */
72 # if defined(STM32_SYSCLK_SRC_HSI)
73 /* When using HSI without PLL, the "16MHz" output is not actually 16MHz, since
74 * the RC64M generator is imprecise. In this configuration, MR_BLE is broken.
75 * The CPU and MR_BLE must be running at 32MHz for MR_BLE to work with HSI.
76 */
77 BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC >= CLOCK_FREQ_32MHZ,
78 "System clock frequency must be at least 32MHz to use LSI");
79 # else
80 /* In PLL or Direct HSE mode, the clock is stable, so 16MHz can be used. */
81 BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC >= CLOCK_FREQ_16MHZ,
82 "System clock frequency must be at least 16MHz to use LSI");
83 # endif /* STM32_SYSCLK_SRC_HSI */
84
85 /**
86 * @brief Variable holding the "current frequency of LSI", according
87 * to the measurement process. This variable is updated each time
88 * a new measurement of the LSI frequency is performed.
89 */
90 static volatile uint32_t stm32wb0_lsi_frequency = STM32_LSI_FREQ;
91
92 /**
93 * @brief Perform a measurement of the LSI frequency and updates
94 * the @p stm32wb0_lsi_frequency global variable based on the results.
95 *
96 * @param wait_event Semaphore to wait for completion of the measurement
97 * If NULL, RADIO_CONTROL registers are polled instead.
98 */
measure_lsi_frequency(struct k_sem * wait_event)99 static void measure_lsi_frequency(struct k_sem *wait_event)
100 {
101 uint32_t fast_clock_cycles_elapsed;
102
103 /* Ensure calibration flag is clear */
104 LL_RADIO_TIMER_ClearFlag_LSICalibrationEnded(RADIO_CTRL);
105
106 /* Setup the calibration parameters
107 *
108 * NOTE: (size - 1) is required to get the correct count,
109 * because the value in the register is one less than the
110 * actual number of periods requested for calibration.
111 */
112 LL_RADIO_TIMER_SetLSIWindowCalibrationLength(RADIO_CTRL,
113 (CONFIG_STM32WB0_LSI_MEASUREMENT_WINDOW - 1));
114
115 /* Start LSI calibration */
116 LL_RADIO_TIMER_StartLSICalibration(RADIO_CTRL);
117
118 if (wait_event) {
119 /* Wait for semaphore to be signaled */
120 k_sem_take(wait_event, K_FOREVER);
121 } else {
122 while (!LL_RADIO_TIMER_IsActiveFlag_LSICalibrationEnded(RADIO_CTRL)) {
123 /* Wait for calibration to finish (polling) */
124 }
125
126 /* Clear calibration complete flag / interrupt */
127 LL_RADIO_TIMER_ClearFlag_LSICalibrationEnded(RADIO_CTRL);
128 }
129
130 /* Read calibration results */
131 fast_clock_cycles_elapsed = LL_RADIO_TIMER_GetLSIPeriod(RADIO_CTRL);
132
133 /**
134 * Calculate LSI frequency from calibration results and update
135 * the corresponding global variable
136 *
137 * LSI calibration counts the amount of 16MHz clock half-periods that
138 * occur until a certain amount of slow clock cycles have been observed.
139 *
140 * @p fast_clock_cycles_elapsed is the number of 16MHz clock half-periods
141 * elapsed while waiting for @p STM32_WB0_LSI_MEASURE_WINDOW_SIZE LSI periods
142 * to occur. The LSI frequency can be calculated the following way:
143 *
144 * t = <number of periods counted> / <clock frequency>
145 *
146 * ==> Time taken for calibration:
147 *
148 * tCALIB = @p fast_clock_cycles_elapsed / (2 * 16MHz)
149 *
150 * ==> LSI period:
151 *
152 * tLSI = tCALIB / @p STM32_WB0_LSI_MEASURE_WINDOW_SIZE
153 *
154 * ( @p fast_clock_cycles_elapsed / (2 * 16MHz) )
155 * = ------------------------------------------------
156 * @p STM32_WB0_LSI_MEASURE_WINDOW_SIZE
157 *
158 * ==> LSI frequency:
159 *
160 * fLSI = (1 / tLSI)
161 *
162 * @p STM32_WB0_LSI_MEASURE_WINDOW_SIZE
163 * = ------------------------------------------------
164 * ( @p fast_clock_cycles_elapsed / (2 * 16MHz) )
165 *
166 * (2 * 16MHz) * @p STM32_WB0_LSI_MEASURE_WINDOW_SIZE
167 * = -----------------------------------------------------
168 * @p fast_clock_cycles_elapsed
169 *
170 * NOTE: The division must be performed first to avoid 32-bit overflow.
171 */
172 stm32wb0_lsi_frequency =
173 (CLOCK_FREQ_32MHZ / fast_clock_cycles_elapsed)
174 * CONFIG_STM32WB0_LSI_MEASUREMENT_WINDOW;
175 }
176 #endif /* STM32_LSI_ENABLED */
177
178 /** @brief Verifies if provided domain / bus clock is currently active */
enabled_clock(uint32_t src_clk)179 int enabled_clock(uint32_t src_clk)
180 {
181 int r = 0;
182
183 switch (src_clk) {
184 case STM32_SRC_SYSCLK:
185 break;
186 case STM32_SRC_LSE:
187 if (!IS_ENABLED(STM32_LSE_ENABLED)) {
188 r = -ENOTSUP;
189 }
190 break;
191 case STM32_SRC_LSI:
192 if (!IS_ENABLED(STM32_LSI_ENABLED)) {
193 r = -ENOTSUP;
194 }
195 break;
196 case STM32_SRC_CLKSLOWMUX:
197 break;
198 case STM32_SRC_CLK16MHZ:
199 break;
200 case STM32_SRC_CLK32MHZ:
201 break;
202 default:
203 return -ENOTSUP;
204 }
205
206 return r;
207 }
208
stm32_clock_control_on(const struct device * dev,clock_control_subsys_t sub_system)209 static inline int stm32_clock_control_on(const struct device *dev,
210 clock_control_subsys_t sub_system)
211 {
212 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
213 const mem_addr_t reg = RCC_REG(pclken->bus);
214 volatile uint32_t temp;
215
216 ARG_UNUSED(dev);
217 if (!IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX)) {
218 /* Attempting to change domain clock */
219 return -ENOTSUP;
220 }
221
222 sys_set_bits(reg, pclken->enr);
223
224 /* Read back register to be blocked by RCC
225 * until peripheral clock enabling is complete
226 */
227 temp = sys_read32(reg);
228 UNUSED(temp);
229
230 return 0;
231 }
232
stm32_clock_control_off(const struct device * dev,clock_control_subsys_t sub_system)233 static inline int stm32_clock_control_off(const struct device *dev,
234 clock_control_subsys_t sub_system)
235 {
236 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
237 const mem_addr_t reg = RCC_REG(pclken->bus);
238
239 ARG_UNUSED(dev);
240 if (!IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX)) {
241 /* Attempting to change domain clock */
242 return -ENOTSUP;
243 }
244
245 sys_clear_bits(reg, pclken->enr);
246
247 return 0;
248 }
249
stm32_clock_control_configure(const struct device * dev,clock_control_subsys_t sub_system,void * data)250 static inline int stm32_clock_control_configure(const struct device *dev,
251 clock_control_subsys_t sub_system,
252 void *data)
253 {
254 struct stm32_pclken *pclken = (struct stm32_pclken *)sub_system;
255 const uint32_t shift = STM32_CLOCK_SHIFT_GET(pclken->enr);
256 mem_addr_t reg = RCC_REG(STM32_CLOCK_REG_GET(pclken->enr));
257 int err;
258
259 ARG_UNUSED(dev);
260 ARG_UNUSED(data);
261
262 err = enabled_clock(pclken->bus);
263 if (err < 0) {
264 /* Attempting to configure an unavailable or invalid clock */
265 return err;
266 }
267
268 sys_clear_bits(reg, STM32_CLOCK_MASK_GET(pclken->enr) << shift);
269 sys_set_bits(reg, STM32_CLOCK_VAL_GET(pclken->enr) << shift);
270
271 return 0;
272 }
273
get_apb0_periph_clkrate(struct stm32_pclken * pclken,uint32_t * rate,uint32_t slow_clock,uint32_t sysclk,uint32_t clk_sys)274 static inline int get_apb0_periph_clkrate(struct stm32_pclken *pclken,
275 uint32_t *rate, uint32_t slow_clock, uint32_t sysclk, uint32_t clk_sys)
276 {
277 switch (pclken->enr) {
278 /* Slow clock peripherals: RTC & IWDG */
279 case LL_APB0_GRP1_PERIPH_RTC:
280 case LL_APB0_GRP1_PERIPH_WDG:
281 *rate = slow_clock;
282 break;
283
284 /* SYSCLK peripherals: all timers */
285 #if defined(TIM1)
286 case LL_APB0_GRP1_PERIPH_TIM1:
287 #endif
288 #if defined(TIM2)
289 case LL_APB0_GRP1_PERIPH_TIM2:
290 #endif
291 #if defined(TIM16)
292 case LL_APB0_GRP1_PERIPH_TIM16:
293 #endif
294 #if defined(TIM17)
295 case LL_APB0_GRP1_PERIPH_TIM17:
296 #endif
297 *rate = sysclk;
298 break;
299
300 /* CLK_SYS peripherals: SYSCFG */
301 case LL_APB0_GRP1_PERIPH_SYSCFG:
302 *rate = clk_sys;
303 break;
304 default:
305 return -ENOTSUP;
306 }
307
308 if (pclken->div) {
309 *rate /= (pclken->div + 1);
310 }
311
312 return 0;
313 }
314
get_apb1_periph_clkrate(struct stm32_pclken * pclken,uint32_t * rate,uint32_t clk_sys)315 static inline int get_apb1_periph_clkrate(struct stm32_pclken *pclken,
316 uint32_t *rate, uint32_t clk_sys)
317 {
318 switch (pclken->enr) {
319 #if defined(SPI1)
320 case LL_APB1_GRP1_PERIPH_SPI1:
321 *rate = clk_sys;
322 break;
323 #endif
324 #if defined(SPI2)
325 case LL_APB1_GRP1_PERIPH_SPI2:
326 switch (LL_RCC_GetSPI2I2SClockSource()) {
327 case LL_RCC_SPI2_I2S_CLK16M:
328 *rate = CLOCK_FREQ_16MHZ;
329 break;
330 case LL_RCC_SPI2_I2S_CLK32M:
331 *rate = CLOCK_FREQ_32MHZ;
332 break;
333 default:
334 CODE_UNREACHABLE;
335 }
336 break;
337 #endif
338 case LL_APB1_GRP1_PERIPH_SPI3:
339 switch (LL_RCC_GetSPI3I2SClockSource()) {
340 case LL_RCC_SPI3_I2S_CLK16M:
341 *rate = CLOCK_FREQ_16MHZ;
342 break;
343 case LL_RCC_SPI3_I2S_CLK32M:
344 *rate = CLOCK_FREQ_32MHZ;
345 break;
346 #if defined(LL_RCC_SPI3_I2S_CLK64M)
347 case LL_RCC_SPI3_I2S_CLK64M:
348 *rate = CLOCK_FREQ_64MHZ;
349 break;
350 #endif
351 default:
352 CODE_UNREACHABLE;
353 }
354 break;
355
356 case LL_APB1_GRP1_PERIPH_I2C1:
357 #if defined(I2C2)
358 case LL_APB1_GRP1_PERIPH_I2C2:
359 #endif
360 *rate = CLOCK_FREQ_16MHZ;
361 break;
362
363 case LL_APB1_GRP1_PERIPH_ADCDIG:
364 case LL_APB1_GRP1_PERIPH_ADCANA:
365 case (LL_APB1_GRP1_PERIPH_ADCDIG | LL_APB1_GRP1_PERIPH_ADCANA):
366 /* ADC has two enable bits - accept all combinations. */
367 *rate = CLOCK_FREQ_16MHZ;
368 break;
369
370 case LL_APB1_GRP1_PERIPH_USART1:
371 *rate = CLOCK_FREQ_16MHZ;
372 break;
373
374 case LL_APB1_GRP1_PERIPH_LPUART1:
375 #if !defined(RCC_CFGR_LPUCLKSEL)
376 *rate = CLOCK_FREQ_16MHZ;
377 #else
378 switch (LL_RCC_GetLPUARTClockSource()) {
379 case LL_RCC_LPUCLKSEL_CLK16M:
380 *rate = CLOCK_FREQ_16MHZ;
381 break;
382 case LL_RCC_LPUCLKSEL_CLKLSE:
383 *rate = STM32_LSE_FREQ;
384 break;
385 default:
386 CODE_UNREACHABLE;
387 }
388 #endif
389 break;
390 default:
391 return -ENOTSUP;
392 }
393
394 if (pclken->div) {
395 *rate /= (pclken->div + 1);
396 }
397
398 return 0;
399 }
400
stm32_clock_control_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)401 static int stm32_clock_control_get_subsys_rate(const struct device *dev,
402 clock_control_subsys_t sub_system,
403 uint32_t *rate)
404 {
405
406 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
407 uint32_t sysclk, slow_clock, clk_sys;
408 #if defined(STM32_LSI_ENABLED)
409 const uint32_t clk_lsi = stm32wb0_lsi_frequency;
410 #else
411 const uint32_t clk_lsi = 0;
412 #endif
413
414
415 ARG_UNUSED(dev);
416
417 /* Obtain SYSCLK frequency by checking which source drives high-speed clock tree.
418 * If Direct HSE is enabled, the high-speed tree is clocked by HSE @ 32MHz.
419 * Otherwise, the high-speed tree is clocked by the RC64MPLL clock @ 64MHz.
420 *
421 * NOTE: it is NOT possible to use the usual 'SystemCoreClock * Prescaler' approach on
422 * STM32WB0 because the prescaler configuration is not affected by input clock variation:
423 * setting CLKSYSDIV = 1 results in 32MHz CLK_SYS, regardless of SYSCLK being 32 or 64MHZ.
424 */
425 if (LL_RCC_DIRECT_HSE_IsEnabled()) {
426 sysclk = STM32_HSE_FREQ;
427 } else {
428 sysclk = STM32_HSI_FREQ;
429 }
430
431 /* Obtain CLK_SYS (AHB0) frequency by using the CLKSYSDIV prescaler value.
432 *
433 * NOTE: LL_RCC_GetRC64MPLLPrescaler is strictly identical to LL_RCC_GetDirectHSEPrescaler
434 * and can be used regardless of which source is driving the high-speed clock tree.
435 *
436 * NOTE: the prescaler value must be interpreted as if source clock is 64MHz, regardless
437 * of which source is actually driving the high-speed clock tree. This allows using the
438 * following formula for calculations.
439 *
440 * NOTE: (x >> y) is equivalent to (x / 2^y) or (x / (1 << y)).
441 */
442 clk_sys = CLOCK_FREQ_64MHZ >> LL_RCC_GetRC64MPLLPrescaler();
443
444 /* Obtain slow clock tree source by reading RCC_CFGR->LCOSEL.
445 * From this, we can deduce at which frequency the slow clock tree is running.
446 */
447 switch (LL_RCC_LSCO_GetSource()) {
448 case LL_RCC_LSCO_CLKSOURCE_LSE:
449 slow_clock = STM32_LSE_FREQ;
450 break;
451 case LL_RCC_LSCO_CLKSOURCE_LSI:
452 slow_clock = clk_lsi;
453 break;
454 case LL_RCC_LSCO_CLKSOURCE_HSI64M_DIV2048:
455 slow_clock = CLOCK_FREQ_64MHZ / 2048;
456 break;
457 default:
458 __ASSERT(0, "Illegal slow clock source!");
459 CODE_UNREACHABLE;
460 }
461
462 switch (pclken->bus) {
463 case STM32_CLOCK_BUS_AHB0:
464 /* All peripherals on AHB0 are clocked by CLK_SYS. */
465 *rate = clk_sys;
466 break;
467 case STM32_CLOCK_BUS_APB0:
468 return get_apb0_periph_clkrate(pclken, rate, slow_clock,
469 sysclk, clk_sys);
470 case STM32_CLOCK_BUS_APB1:
471 return get_apb1_periph_clkrate(pclken, rate, clk_sys);
472 case STM32_SRC_SYSCLK:
473 *rate = sysclk;
474 break;
475 case STM32_SRC_LSE:
476 *rate = STM32_LSE_FREQ;
477 break;
478 case STM32_SRC_LSI:
479 *rate = clk_lsi;
480 break;
481 case STM32_SRC_CLKSLOWMUX:
482 *rate = slow_clock;
483 break;
484 case STM32_SRC_CLK16MHZ:
485 *rate = CLOCK_FREQ_16MHZ;
486 break;
487 case STM32_SRC_CLK32MHZ:
488 *rate = CLOCK_FREQ_32MHZ;
489 break;
490 default:
491 case STM32_CLOCK_BUS_APB2:
492 /* The only periperhal on APB2 is the MR_BLE radio. However,
493 * it is clocked by two sources that run at different frequencies,
494 * and we are unable to determine which one this API's caller cares
495 * about. For this reason, return ENOTSUP anyways.
496 *
497 * Note that since the only driver that might call this API is the
498 * Bluetooth driver, and since it can already determine both frequencies
499 * very easily, this should not pose any problem.
500 */
501 return -ENOTSUP;
502 }
503
504 if (pclken->div) {
505 *rate /= (pclken->div + 1);
506 }
507
508 return 0;
509 }
510
stm32_clock_control_get_status(const struct device * dev,clock_control_subsys_t sub_system)511 static enum clock_control_status stm32_clock_control_get_status(const struct device *dev,
512 clock_control_subsys_t sub_system)
513 {
514 struct stm32_pclken *pclken = (struct stm32_pclken *)sub_system;
515
516 ARG_UNUSED(dev);
517
518 if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX)) {
519 /* Bus / gated clock */
520 if ((sys_read32(RCC_REG(pclken->bus)) & pclken->enr) == pclken->enr) {
521 return CLOCK_CONTROL_STATUS_ON;
522 } else {
523 return CLOCK_CONTROL_STATUS_OFF;
524 }
525 } else {
526 /* Domain clock */
527 if (enabled_clock(pclken->bus) == 0) {
528 return CLOCK_CONTROL_STATUS_ON;
529 } else {
530 return CLOCK_CONTROL_STATUS_OFF;
531 }
532 }
533 }
534
535 static DEVICE_API(clock_control, stm32_clock_control_api) = {
536 .on = stm32_clock_control_on,
537 .off = stm32_clock_control_off,
538 .get_rate = stm32_clock_control_get_subsys_rate,
539 .get_status = stm32_clock_control_get_status,
540 .configure = stm32_clock_control_configure,
541 };
542
set_up_fixed_clock_sources(void)543 static void set_up_fixed_clock_sources(void)
544 {
545 if (IS_ENABLED(STM32_HSE_ENABLED)) {
546 /* Enable HSE */
547 LL_RCC_HSE_Enable();
548 while (LL_RCC_HSE_IsReady() != 1) {
549 /* Wait for HSE ready */
550 }
551 }
552
553 if (IS_ENABLED(STM32_HSI_ENABLED)) {
554 /* Enable HSI if not enabled */
555 if (LL_RCC_HSI_IsReady() != 1) {
556 /* Enable HSI */
557 LL_RCC_HSI_Enable();
558 while (LL_RCC_HSI_IsReady() != 1) {
559 /* Wait for HSI ready */
560 }
561 }
562 }
563
564 if (IS_ENABLED(STM32_LSI_ENABLED)) {
565 LL_RCC_LSI_Enable();
566 while (LL_RCC_LSI_IsReady() != 1) {
567 /* Wait for LSI ready */
568 }
569 }
570
571 if (IS_ENABLED(STM32_LSE_ENABLED)) {
572 #if STM32_LSE_DRIVING
573 /* Configure driving capability */
574 LL_RCC_LSE_SetDriveCapability(STM32_LSE_DRIVING << RCC_CSSWCR_LSEDRV_Pos);
575 #endif
576 /* Unconditionally disable pull-up & pull-down on LSE pins */
577 LL_PWR_SetNoPullB(LL_PWR_GPIO_BIT_12 | LL_PWR_GPIO_BIT_13);
578
579 if (IS_ENABLED(STM32_LSE_BYPASS)) {
580 /* Configure LSE bypass */
581 LL_RCC_LSE_EnableBypass();
582 }
583
584 /* Enable LSE Oscillator (32.768 kHz) */
585 LL_RCC_LSE_Enable();
586 while (!LL_RCC_LSE_IsReady()) {
587 /* Wait for LSE ready */
588 }
589 }
590 }
591
592 /* The STM32WB0 prescaler division factor defines vary depending on
593 * whether SYSCLK runs at 32MHz (Direct HSE) or 64MHz (RC64MPLL).
594 * The following helper macro wraps this difference.
595 */
596 #if defined(STM32_SYSCLK_SRC_HSE)
597 #define LL_PRESCALER(x) LL_RCC_DIRECT_HSE_DIV_ ##x
598 #else
599 #define LL_PRESCALER(x) LL_RCC_RC64MPLL_DIV_ ##x
600 #endif
601
602 /**
603 * @brief Converts the Kconfig STM32_WB0_CLKSYS_PRESCALER option
604 * to a LL_RCC_RC64MPLL_DIV_x value understandable by the LL.
605 */
kconfig_to_ll_prescaler(uint32_t kcfg_pre)606 static inline uint32_t kconfig_to_ll_prescaler(uint32_t kcfg_pre)
607 {
608 switch (kcfg_pre) {
609 case 1:
610 return LL_PRESCALER(1);
611 case 2:
612 return LL_PRESCALER(2);
613 case 4:
614 return LL_PRESCALER(4);
615 case 8:
616 return LL_PRESCALER(8);
617 case 16:
618 return LL_PRESCALER(16);
619 case 32:
620 return LL_PRESCALER(32);
621 #if !defined(STM32_SYSCLK_SRC_HSE)
622 /* A prescaler value of 64 is only valid when running
623 * off RC64MPLL because CLK_SYS must be at least 1MHz
624 */
625 case 64:
626 return LL_RCC_RC64MPLL_DIV_64;
627 #endif
628 }
629 CODE_UNREACHABLE;
630 }
631 #undef LL_PRESCALER /* Undefine helper macro */
632
633 #if CONFIG_STM32WB0_LSI_RUNTIME_MEASUREMENT_INTERVAL != 0
634 K_SEM_DEFINE(lsi_measurement_sema, 0, 1);
635
636 #define NUM_SLOW_CLOCK_PERIPHERALS 3
637
638 /**
639 * Reserve one slot for each slow clock peripheral to ensure each
640 * peripheral's driver can register a callback to cope with clock drift.
641 */
642 static lsi_update_cb_t lsi_update_callbacks[NUM_SLOW_CLOCK_PERIPHERALS];
643
stm32wb0_register_lsi_update_callback(lsi_update_cb_t cb)644 int stm32wb0_register_lsi_update_callback(lsi_update_cb_t cb)
645 {
646 for (size_t i = 0; i < ARRAY_SIZE(lsi_update_callbacks); i++) {
647 if (lsi_update_callbacks[i] == NULL) {
648 lsi_update_callbacks[i] = cb;
649 return 0;
650 }
651 }
652 return -ENOMEM;
653 }
654
radio_ctrl_isr(void)655 static void radio_ctrl_isr(void)
656 {
657 /* Clear calibration complete flag / interrupt */
658 LL_RADIO_TIMER_ClearFlag_LSICalibrationEnded(RADIO_CTRL);
659
660 /* Release the measurement thread */
661 k_sem_give(&lsi_measurement_sema);
662 }
663
lsi_rt_measure_loop(void)664 static void lsi_rt_measure_loop(void)
665 {
666 uint32_t old, new;
667
668 while (1) {
669 /* Sleep until calibration interval elapses */
670 k_sleep(K_MSEC(CONFIG_STM32WB0_LSI_RUNTIME_MEASUREMENT_INTERVAL));
671
672 old = stm32wb0_lsi_frequency;
673
674 /* Ensure the MR_BLE IP clock is enabled. */
675 if (!LL_APB2_GRP1_IsEnabledClock(LL_APB2_GRP1_PERIPH_MRBLE)) {
676 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_MRBLE);
677 }
678
679 /* Perform measurement, making sure we sleep on the semaphore
680 * signaled by the "measurement complete" interrupt handler
681 */
682 measure_lsi_frequency(&lsi_measurement_sema);
683
684 new = stm32wb0_lsi_frequency;
685
686 /* If LSI frequency changed, invoke all registered callbacks */
687 if (new != old) {
688 for (size_t i = 0; i < ARRAY_SIZE(lsi_update_callbacks); i++) {
689 if (lsi_update_callbacks[i]) {
690 lsi_update_callbacks[i](stm32wb0_lsi_frequency);
691 }
692 }
693 }
694 }
695 }
696
697 #define LSI_RTM_THREAD_STACK_SIZE 512
698 #define LSI_RTM_THREAD_PRIORITY K_LOWEST_APPLICATION_THREAD_PRIO
699
700 K_KERNEL_THREAD_DEFINE(lsi_rt_measurement_thread,
701 LSI_RTM_THREAD_STACK_SIZE,
702 lsi_rt_measure_loop,
703 NULL, NULL, NULL,
704 LSI_RTM_THREAD_PRIORITY, /* No options */ 0,
705 /* No delay (automatic start by kernel) */ 0);
706 #endif
707
stm32_clock_control_init(const struct device * dev)708 int stm32_clock_control_init(const struct device *dev)
709 {
710 ARG_UNUSED(dev);
711
712 /* Set flash latency according to target CLK_SYS frequency:
713 * - 1 wait state when CLK_SYS > 32MHz (i.e., 64MHz configuration)
714 * - 0 wait states otherwise (CLK_SYS <= 32MHz)
715 */
716 LL_FLASH_SetLatency(
717 (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC >= CLOCK_FREQ_32MHZ)
718 ? LL_FLASH_LATENCY_1
719 : LL_FLASH_LATENCY_0
720 );
721
722 /* Unconditionally enable SYSCFG clock for other drivers */
723 LL_APB0_GRP1_EnableClock(LL_APB0_GRP1_PERIPH_SYSCFG);
724
725 /* Set up indiviual enabled clocks */
726 set_up_fixed_clock_sources();
727
728 /* Set up the slow clock mux */
729 #if defined(STM32_WB0_SLOWCLK_SRC)
730 LL_RCC_LSCO_SetSource(STM32_WB0_SLOWCLK_SRC);
731 #endif
732
733 #if defined(STM32_SYSCLK_SRC_HSE)
734 /* Select Direct HSE as SYSCLK source */
735 LL_RCC_DIRECT_HSE_Enable();
736
737 while (LL_RCC_DIRECT_HSE_IsEnabled() == 0) {
738 /* Wait until Direct HSE is ready */
739 }
740 #elif defined(STM32_SYSCLK_SRC_HSI) || defined(STM32_SYSCLK_SRC_PLL)
741 /* Select RC64MPLL (HSI/PLL) block as SYSCLK source. */
742 LL_RCC_DIRECT_HSE_Disable();
743
744 # if defined(STM32_SYSCLK_SRC_PLL)
745 BUILD_ASSERT(IS_ENABLED(STM32_HSE_ENABLED),
746 "STM32WB0 PLL requires HSE to be enabled!");
747
748 /* Turn on the PLL part of RC64MPLL block */
749 LL_RCC_RC64MPLL_Enable();
750 while (LL_RCC_RC64MPLL_IsReady() == 0) {
751 /* Wait until PLL is ready */
752 }
753
754 # endif /* STM32_SYSCLK_SRC_PLL */
755 #endif /* STM32_SYSCLK_SRC_* */
756
757 /* Set CLK_SYS prescaler */
758 LL_RCC_SetRC64MPLLPrescaler(
759 kconfig_to_ll_prescaler(STM32_WB0_CLKSYS_PRESCALER));
760
761 SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
762
763 #if defined(STM32_LSI_ENABLED)
764 /* Enable MR_BLE clock for LSI measurement.
765 * This is needed because we use part of the MR_BLE hardware
766 * to perform this measurement.
767 */
768 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_MRBLE);
769
770 /* Perform a measure of the LSI frequency */
771 measure_lsi_frequency(NULL);
772
773 #if CONFIG_STM32WB0_LSI_RUNTIME_MEASUREMENT_INTERVAL == 0
774 /* Disable the MR_BLE clock after the measurement */
775 LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_MRBLE);
776 #else
777 /* MR_BLE clock must not be disabled, as we're
778 * about to access registers of the IP again.
779 */
780
781 /* Enable LSI measurement complete IRQ at NVIC level */
782 IRQ_CONNECT(RADIO_CTRL_IRQn, IRQ_PRIO_LOWEST,
783 radio_ctrl_isr, NULL, 0);
784 irq_enable(RADIO_CTRL_IRQn);
785
786 /* Unmask IRQ at peripheral level */
787 LL_RADIO_TIMER_EnableLSICalibrationIT(RADIO_CTRL);
788 #endif /* CONFIG_STM32WB0_LSI_RUNTIME_MEASUREMENT_INTERVAL == 0 */
789 #endif /* STM32_LSI_ENABLED*/
790 return 0;
791 }
792
793 /**
794 * @brief Reset & Clock Controller device
795 * Note that priority is intentionally set to 1,
796 * so that RCC init runs just after SoC init.
797 */
798 DEVICE_DT_DEFINE(STM32_CLOCK_CONTROL_NODE,
799 &stm32_clock_control_init,
800 NULL, NULL, NULL,
801 PRE_KERNEL_1,
802 CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
803 &stm32_clock_control_api);
804