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_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_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.litex"
|
||||
source "drivers/entropy/Kconfig.gecko"
|
||||
source "drivers/entropy/Kconfig.neorv32"
|
||||
|
||||
config ENTROPY_HAS_DRIVER
|
||||
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
|
||||
depends on SERIAL
|
||||
|
||||
config ENTROPY_INIT_PRIORITY
|
||||
default 55
|
||||
depends on ENTROPY_GENERATOR
|
||||
|
||||
endif # SOC_SERIES_NEORV32
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue