You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.4 KiB
121 lines
3.4 KiB
/* |
|
* Copyright (c) 2025 STMicroelectronics |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
#include <zephyr/kernel.h> |
|
#include <zephyr/device.h> |
|
#include <stm32_ll_rng.h> |
|
|
|
/** |
|
* This driver supports two compatibles: |
|
* - "st,stm32-rng" for TRNG with IRQ lines |
|
* - "st,stm32-rng-noirq" for TRNG without IRQ lines |
|
*/ |
|
#define IRQLESS_TRNG DT_HAS_COMPAT_STATUS_OKAY(st_stm32_rng_noirq) |
|
|
|
#if IRQLESS_TRNG |
|
#define DT_DRV_COMPAT st_stm32_rng_noirq |
|
#define TRNG_GENERATION_DELAY K_NSEC(DT_INST_PROP_OR(0, generation_delay_ns, 0)) |
|
#else /* !IRQLESS_TRNG */ |
|
#define DT_DRV_COMPAT st_stm32_rng |
|
#define IRQN DT_INST_IRQN(0) |
|
#define IRQ_PRIO DT_INST_IRQ(0, priority) |
|
#endif /* IRQLESS_TRNG */ |
|
|
|
/* Cross-series LL compatibility wrappers */ |
|
static inline void ll_rng_enable_it(RNG_TypeDef *RNGx) |
|
{ |
|
/* Silence "unused" warning on IRQ-less hardware*/ |
|
ARG_UNUSED(RNGx); |
|
#if !IRQLESS_TRNG |
|
# if defined(CONFIG_SOC_STM32WB09XX) |
|
LL_RNG_EnableEnErrorIrq(RNGx); |
|
LL_RNG_EnableEnFfFullIrq(RNGx); |
|
# else |
|
LL_RNG_EnableIT(RNGx); |
|
# endif |
|
#endif /* !IRQLESS_TRNG */ |
|
} |
|
|
|
static inline uint32_t ll_rng_is_active_seis(RNG_TypeDef *RNGx) |
|
{ |
|
#if defined(CONFIG_SOC_STM32WB09XX) |
|
return LL_RNG_IsActiveFlag_ENTROPY_ERR(RNGx); |
|
#elif defined(CONFIG_SOC_SERIES_STM32WB0X) |
|
/* STM32WB05 / STM32WB06 / STM32WB07 */ |
|
return LL_RNG_IsActiveFlag_FAULT(RNGx); |
|
#else |
|
return LL_RNG_IsActiveFlag_SEIS(RNGx); |
|
#endif /* CONFIG_SOC_SERIES_STM32WB0X */ |
|
} |
|
|
|
static inline void ll_rng_clear_seis(RNG_TypeDef *RNGx) |
|
{ |
|
#if defined(CONFIG_SOC_STM32WB09XX) |
|
LL_RNG_SetResetHealthErrorFlags(RNGx, 1); |
|
#elif defined(CONFIG_SOC_SERIES_STM32WB0X) |
|
/* STM32WB05 / STM32WB06 / STM32WB07 */ |
|
LL_RNG_ClearFlag_FAULT(RNGx); |
|
#else |
|
LL_RNG_ClearFlag_SEIS(RNGx); |
|
#endif /* CONFIG_SOC_SERIES_STM32WB0X */ |
|
} |
|
|
|
static inline uint32_t ll_rng_is_active_secs(RNG_TypeDef *RNGx) |
|
{ |
|
#if !defined(CONFIG_SOC_SERIES_STM32WB0X) |
|
return LL_RNG_IsActiveFlag_SECS(RNGx); |
|
#else |
|
/** |
|
* STM32WB0x RNG has no equivalent of SECS. |
|
* Since this flag is always checked in conjunction |
|
* with FAULT (the SEIS equivalent), returning 0 is OK. |
|
*/ |
|
return 0; |
|
#endif /* !CONFIG_SOC_SERIES_STM32WB0X */ |
|
} |
|
|
|
static inline uint32_t ll_rng_is_active_drdy(RNG_TypeDef *RNGx) |
|
{ |
|
#if defined(CONFIG_SOC_STM32WB09XX) |
|
return LL_RNG_IsActiveFlag_VAL_READY(RNGx); |
|
#elif defined(CONFIG_SOC_SERIES_STM32WB0X) |
|
/* STM32WB05 / STM32WB06 / STM32WB07 */ |
|
return LL_RNG_IsActiveFlag_RNGRDY(RNGx); |
|
#else |
|
return LL_RNG_IsActiveFlag_DRDY(RNGx); |
|
#endif /* CONFIG_SOC_SERIES_STM32WB0X */ |
|
} |
|
|
|
#if defined(CONFIG_SOC_SERIES_STM32WB0X) && !defined(CONFIG_SOC_STM32WB09XX) |
|
/* STM32WB05, STM32WB06 and STM32WB07 have 16-bit data register */ |
|
typedef uint16_t rng_sample_t; |
|
#else |
|
/* All other TRNG IPs have 32-bit data register */ |
|
typedef uint32_t rng_sample_t; |
|
#endif |
|
|
|
static inline rng_sample_t ll_rng_read_rand_data(RNG_TypeDef *RNGx) |
|
{ |
|
#if defined(CONFIG_SOC_STM32WB09XX) |
|
rng_sample_t rnd = LL_RNG_GetRndVal(RNGx); |
|
|
|
/** |
|
* STM32WB09 TRNG does not clear IRQ flags in hardware. |
|
* We must clear the "FIFO full" flag now that we consumed data |
|
* from it to ensure the TRNG's IRQ line goes back to low state. |
|
* |
|
* Raw register access is performed because STM32CubeWB0 v1.0.0 |
|
* package is lacking the LL function to clear IRQ flags. |
|
*/ |
|
WRITE_REG(RNG->IRQ_SR, RNG_IRQ_SR_FF_FULL_IRQ); |
|
|
|
return rnd; |
|
#elif defined(CONFIG_SOC_SERIES_STM32WB0X) |
|
/* STM32WB05 / STM32WB06 / STM32WB07 */ |
|
return LL_RNG_ReadRandData16(RNGx); |
|
#else |
|
return LL_RNG_ReadRandData32(RNGx); |
|
#endif /* CONFIG_SOC_SERIES_STM32WB0X */ |
|
}
|
|
|