drivers: entropy: add driver for the neorv32 trng
Add entropy driver for the NEORV32 True Random Number Generator (TRNG). Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
This commit is contained in:
parent
ed041e30e7
commit
91233dba70
5 changed files with 171 additions and 0 deletions
|
@ -16,3 +16,4 @@ zephyr_library_sources_ifdef(CONFIG_FAKE_ENTROPY_NATIVE_POSIX fake_entropy_nati
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE entropy_handlers.c)
|
zephyr_library_sources_ifdef(CONFIG_USERSPACE entropy_handlers.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_ENTROPY_RV32M1_TRNG entropy_rv32m1_trng.c)
|
zephyr_library_sources_ifdef(CONFIG_ENTROPY_RV32M1_TRNG entropy_rv32m1_trng.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_ENTROPY_GECKO_TRNG entropy_gecko_trng.c)
|
zephyr_library_sources_ifdef(CONFIG_ENTROPY_GECKO_TRNG entropy_gecko_trng.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_ENTROPY_NEORV32_TRNG entropy_neorv32_trng.c)
|
||||||
|
|
|
@ -31,6 +31,7 @@ source "drivers/entropy/Kconfig.native_posix"
|
||||||
source "drivers/entropy/Kconfig.rv32m1"
|
source "drivers/entropy/Kconfig.rv32m1"
|
||||||
source "drivers/entropy/Kconfig.litex"
|
source "drivers/entropy/Kconfig.litex"
|
||||||
source "drivers/entropy/Kconfig.gecko"
|
source "drivers/entropy/Kconfig.gecko"
|
||||||
|
source "drivers/entropy/Kconfig.neorv32"
|
||||||
|
|
||||||
config ENTROPY_HAS_DRIVER
|
config ENTROPY_HAS_DRIVER
|
||||||
bool
|
bool
|
||||||
|
|
13
drivers/entropy/Kconfig.neorv32
Normal file
13
drivers/entropy/Kconfig.neorv32
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# NEORV32 TRNG configuration
|
||||||
|
|
||||||
|
# Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config ENTROPY_NEORV32_TRNG
|
||||||
|
bool "NEORV32 TRNG"
|
||||||
|
default $(dt_compat_enabled,neorv32-trng)
|
||||||
|
depends on SOC_SERIES_NEORV32 && SYSCON
|
||||||
|
select ENTROPY_HAS_DRIVER
|
||||||
|
help
|
||||||
|
This option enables the True Random Number Generator (TRNG) driver for
|
||||||
|
the NEORV32.
|
152
drivers/entropy/entropy_neorv32_trng.c
Normal file
152
drivers/entropy/entropy_neorv32_trng.c
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Henrik Brix Andersen <henrik@brixandersen.dk>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT neorv32_trng
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/syscon.h>
|
||||||
|
#include <drivers/entropy.h>
|
||||||
|
#include <sys/sys_io.h>
|
||||||
|
|
||||||
|
#include <logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(neorv32_trng, CONFIG_ENTROPY_LOG_LEVEL);
|
||||||
|
|
||||||
|
/* TRNG CTRL register bits */
|
||||||
|
#define NEORV32_TRNG_CTRL_DATA_MASK BIT_MASK(8)
|
||||||
|
#define NEORV32_TRNG_CTRL_EN BIT(30)
|
||||||
|
#define NEORV32_TRNG_CTRL_VALID BIT(31)
|
||||||
|
|
||||||
|
struct neorv32_trng_config {
|
||||||
|
const struct device *syscon;
|
||||||
|
mm_reg_t base;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint32_t neorv32_trng_read_ctrl(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct neorv32_trng_config *config = dev->config;
|
||||||
|
|
||||||
|
return sys_read32(config->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void neorv32_trng_write_ctrl(const struct device *dev, uint32_t ctrl)
|
||||||
|
{
|
||||||
|
const struct neorv32_trng_config *config = dev->config;
|
||||||
|
|
||||||
|
sys_write32(ctrl, config->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int neorv32_trng_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t len)
|
||||||
|
{
|
||||||
|
uint32_t ctrl;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
ctrl = neorv32_trng_read_ctrl(dev);
|
||||||
|
|
||||||
|
if ((ctrl & NEORV32_TRNG_CTRL_VALID) != 0) {
|
||||||
|
*buffer++ = ctrl & NEORV32_TRNG_CTRL_DATA_MASK;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int neorv32_trng_get_entropy_isr(const struct device *dev, uint8_t *buffer,
|
||||||
|
uint16_t len, uint32_t flags)
|
||||||
|
{
|
||||||
|
uint32_t ctrl;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((flags & ENTROPY_BUSYWAIT) == 0) {
|
||||||
|
ctrl = neorv32_trng_read_ctrl(dev);
|
||||||
|
if ((ctrl & NEORV32_TRNG_CTRL_VALID) != 0) {
|
||||||
|
*buffer = ctrl & NEORV32_TRNG_CTRL_DATA_MASK;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No entropy available */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = neorv32_trng_get_entropy(dev, buffer, len);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int neorv32_trng_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct neorv32_trng_config *config = dev->config;
|
||||||
|
uint32_t features;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!device_is_ready(config->syscon)) {
|
||||||
|
LOG_ERR("syscon device not ready");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = syscon_read_reg(config->syscon, NEORV32_SYSINFO_FEATURES, &features);
|
||||||
|
if (err < 0) {
|
||||||
|
LOG_ERR("failed to determine implemented features (err %d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((features & NEORV32_SYSINFO_FEATURES_IO_TRNG) == 0) {
|
||||||
|
LOG_ERR("neorv32 trng not supported");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
neorv32_trng_write_ctrl(dev, NEORV32_TRNG_CTRL_EN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_DEVICE
|
||||||
|
static int neorv32_trng_pm_action(const struct device *dev, enum pm_device_action action)
|
||||||
|
{
|
||||||
|
switch (action) {
|
||||||
|
case PM_DEVICE_ACTION_SUSPEND:
|
||||||
|
neorv32_trng_write_ctrl(dev, 0);
|
||||||
|
break;
|
||||||
|
case PM_DEVICE_ACTION_RESUME:
|
||||||
|
neorv32_trng_write_ctrl(dev, NEORV32_TRNG_CTRL_EN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PM_DEVICE */
|
||||||
|
|
||||||
|
static const struct entropy_driver_api neorv32_trng_driver_api = {
|
||||||
|
.get_entropy = neorv32_trng_get_entropy,
|
||||||
|
.get_entropy_isr = neorv32_trng_get_entropy_isr,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_DEVICE
|
||||||
|
#define NEORV32_TRNG_PM_ACTION_CB neorv32_trng_pm_action
|
||||||
|
#else /* CONFIG_PM_DEVICE */
|
||||||
|
#define NEORV32_TRNG_PM_ACTION_CB NULL
|
||||||
|
#endif /* ! CONFIG_PM_DEVICE */
|
||||||
|
|
||||||
|
#define NEORV32_TRNG_INIT(n) \
|
||||||
|
static const struct neorv32_trng_config neorv32_trng_##n##_config = { \
|
||||||
|
.syscon = DEVICE_DT_GET(DT_INST_PHANDLE(n, syscon)), \
|
||||||
|
.base = DT_INST_REG_ADDR(n), \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(n, &neorv32_trng_init, \
|
||||||
|
NEORV32_TRNG_PM_ACTION_CB, \
|
||||||
|
NULL, \
|
||||||
|
&neorv32_trng_##n##_config, \
|
||||||
|
PRE_KERNEL_1, \
|
||||||
|
CONFIG_ENTROPY_INIT_PRIORITY, \
|
||||||
|
&neorv32_trng_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(NEORV32_TRNG_INIT)
|
|
@ -25,4 +25,8 @@ config SERIAL_INIT_PRIORITY
|
||||||
default 55
|
default 55
|
||||||
depends on SERIAL
|
depends on SERIAL
|
||||||
|
|
||||||
|
config ENTROPY_INIT_PRIORITY
|
||||||
|
default 55
|
||||||
|
depends on ENTROPY_GENERATOR
|
||||||
|
|
||||||
endif # SOC_SERIES_NEORV32
|
endif # SOC_SERIES_NEORV32
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue