1 /*
2  * Copyright (c) 2025 STMicroelectronics
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/kernel.h>
7 #include <zephyr/device.h>
8 #include <stm32_ll_rng.h>
9 
10 /**
11  * This driver supports two compatibles:
12  *	- "st,stm32-rng" for TRNG with IRQ lines
13  *	- "st,stm32-rng-noirq" for TRNG without IRQ lines
14  */
15 #define IRQLESS_TRNG DT_HAS_COMPAT_STATUS_OKAY(st_stm32_rng_noirq)
16 
17 #if IRQLESS_TRNG
18 #define DT_DRV_COMPAT st_stm32_rng_noirq
19 #define TRNG_GENERATION_DELAY	K_NSEC(DT_INST_PROP_OR(0, generation_delay_ns, 0))
20 #else /* !IRQLESS_TRNG */
21 #define DT_DRV_COMPAT st_stm32_rng
22 #define IRQN		DT_INST_IRQN(0)
23 #define IRQ_PRIO	DT_INST_IRQ(0, priority)
24 #endif /* IRQLESS_TRNG */
25 
26 /* Cross-series LL compatibility wrappers */
ll_rng_enable_it(RNG_TypeDef * RNGx)27 static inline void ll_rng_enable_it(RNG_TypeDef *RNGx)
28 {
29 	/* Silence "unused" warning on IRQ-less hardware*/
30 	ARG_UNUSED(RNGx);
31 #if !IRQLESS_TRNG
32 #	if defined(CONFIG_SOC_STM32WB09XX)
33 		LL_RNG_EnableEnErrorIrq(RNGx);
34 		LL_RNG_EnableEnFfFullIrq(RNGx);
35 #	else
36 		LL_RNG_EnableIT(RNGx);
37 #	endif
38 #endif /* !IRQLESS_TRNG */
39 }
40 
ll_rng_is_active_seis(RNG_TypeDef * RNGx)41 static inline uint32_t ll_rng_is_active_seis(RNG_TypeDef *RNGx)
42 {
43 #if defined(CONFIG_SOC_SERIES_STM32WB0X)
44 #	if defined(CONFIG_SOC_STM32WB09XX)
45 		return LL_RNG_IsActiveFlag_ENTROPY_ERR(RNGx);
46 #	else
47 		return LL_RNG_IsActiveFlag_FAULT(RNGx);
48 #	endif
49 #else
50 	return LL_RNG_IsActiveFlag_SEIS(RNGx);
51 #endif /* CONFIG_SOC_SERIES_STM32WB0X */
52 }
53 
ll_rng_clear_seis(RNG_TypeDef * RNGx)54 static inline void ll_rng_clear_seis(RNG_TypeDef *RNGx)
55 {
56 #if defined(CONFIG_SOC_SERIES_STM32WB0X)
57 #	if defined(CONFIG_SOC_STM32WB09XX)
58 		LL_RNG_SetResetHealthErrorFlags(RNGx, 1);
59 #	else
60 		LL_RNG_ClearFlag_FAULT(RNGx);
61 #	endif
62 #else
63 	LL_RNG_ClearFlag_SEIS(RNGx);
64 #endif /* CONFIG_SOC_SERIES_STM32WB0X */
65 }
66 
ll_rng_is_active_secs(RNG_TypeDef * RNGx)67 static inline uint32_t ll_rng_is_active_secs(RNG_TypeDef *RNGx)
68 {
69 #if !defined(CONFIG_SOC_SERIES_STM32WB0X)
70 	return LL_RNG_IsActiveFlag_SECS(RNGx);
71 #else
72 	/**
73 	 * STM32WB0x RNG has no equivalent of SECS.
74 	 * Since this flag is always checked in conjunction
75 	 * with FAULT (the SEIS equivalent), returning 0 is OK.
76 	 */
77 	return 0;
78 #endif /* !CONFIG_SOC_SERIES_STM32WB0X */
79 }
80 
ll_rng_is_active_drdy(RNG_TypeDef * RNGx)81 static inline uint32_t ll_rng_is_active_drdy(RNG_TypeDef *RNGx)
82 {
83 #if defined(CONFIG_SOC_SERIES_STM32WB0X)
84 #	if defined(CONFIG_SOC_STM32WB09XX)
85 		return LL_RNG_IsActiveFlag_VAL_READY(RNGx);
86 #	else
87 		return LL_RNG_IsActiveFlag_RNGRDY(RNGx);
88 #	endif
89 #else
90 	return LL_RNG_IsActiveFlag_DRDY(RNGx);
91 #endif /* CONFIG_SOC_SERIES_STM32WB0X */
92 }
93 
ll_rng_read_rand_data(RNG_TypeDef * RNGx)94 static inline uint16_t ll_rng_read_rand_data(RNG_TypeDef *RNGx)
95 {
96 #if defined(CONFIG_SOC_SERIES_STM32WB0X)
97 #	if defined(CONFIG_SOC_STM32WB09XX)
98 		return (uint16_t)LL_RNG_GetRndVal(RNGx);
99 #	else
100 		return LL_RNG_ReadRandData16(RNGx);
101 #	endif
102 #else
103 	return (uint16_t)LL_RNG_ReadRandData32(RNGx);
104 #endif /* CONFIG_SOC_SERIES_STM32WB0X */
105 }
106