blob: 38c2d4b4baed31da7a9e660270e961516a5b76bc [file] [log] [blame]
/*
* Copyright 2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/entropy.h>
#include <zephyr/sys/util_macro.h>
#define TRNG_NODE DT_INST(0, nxp_els_trng)
#define ELS_NODE DT_PARENT(TRNG_NODE)
#define CLOCK_DEV DT_CLOCKS_CTLR(ELS_NODE)
#define CLOCK_CELL DT_CLOCKS_CELL(ELS_NODE, name)
#define ELS_BASE DT_REG_ADDR(ELS_NODE)
#define ELS_STATUS (ELS_BASE + 0U)
#define ELS_STATUS_BUSY_MASK BIT(0)
#define ELS_STATUS_DRBG_ENT_LVL_MASK (BIT(9) | BIT(8))
#define ELS_CTRL (ELS_BASE + 4U)
#define ELS_CTRL_EN_MASK BIT(0)
#define ELS_PRNG_DATOUT (ELS_BASE + 0x5c)
static uint8_t els_entropy_level(volatile uint32_t *status)
{
uint32_t val = *status;
uint32_t level = (val & ELS_STATUS_DRBG_ENT_LVL_MASK) >> 8;
return (uint8_t)level;
}
static int entropy_els_get_entropy(const struct device *dev, uint8_t *buf, uint16_t len)
{
volatile uint32_t *status = (uint32_t *)ELS_STATUS;
volatile uint32_t *prng_datout = (uint32_t *)ELS_PRNG_DATOUT;
if (els_entropy_level(status) < 1) {
return -EIO;
}
uint8_t byte_cnt = 0;
uint32_t val = 0;
uint8_t num = 0;
while (len-- > 0) {
if (byte_cnt == 0) {
val = *prng_datout;
}
num = val >> (8 * byte_cnt);
byte_cnt = (byte_cnt + 1) % 4;
*buf = num;
buf++;
}
return 0;
}
static int entropy_els_init(const struct device *dev)
{
volatile uint32_t *status = (uint32_t *)ELS_STATUS;
volatile uint32_t *ctrl = (uint32_t *)ELS_CTRL;
int ret;
ret = clock_control_on(DEVICE_DT_GET(CLOCK_DEV), (clock_control_subsys_t)CLOCK_CELL);
if (ret) {
return ret;
}
*ctrl |= ELS_CTRL_EN_MASK;
while (*status & ELS_STATUS_BUSY_MASK) {
}
return 0;
}
static DEVICE_API(entropy, entropy_els_api_funcs) = {
.get_entropy = entropy_els_get_entropy
};
DEVICE_DT_DEFINE(TRNG_NODE, entropy_els_init, NULL, NULL, NULL, PRE_KERNEL_1,
CONFIG_ENTROPY_INIT_PRIORITY, &entropy_els_api_funcs);