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