From 91233dba709e9c0965e6e5ab6d4bd227571534ae Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 6 Oct 2021 22:10:36 +0200 Subject: [PATCH] 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 --- drivers/entropy/CMakeLists.txt | 1 + drivers/entropy/Kconfig | 1 + drivers/entropy/Kconfig.neorv32 | 13 ++ drivers/entropy/entropy_neorv32_trng.c | 152 ++++++++++++++++++ .../neorv32/Kconfig.defconfig.series | 4 + 5 files changed, 171 insertions(+) create mode 100644 drivers/entropy/Kconfig.neorv32 create mode 100644 drivers/entropy/entropy_neorv32_trng.c diff --git a/drivers/entropy/CMakeLists.txt b/drivers/entropy/CMakeLists.txt index 526a91a9b4b..ecedc7eb8be 100644 --- a/drivers/entropy/CMakeLists.txt +++ b/drivers/entropy/CMakeLists.txt @@ -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) diff --git a/drivers/entropy/Kconfig b/drivers/entropy/Kconfig index f1e1255b19d..3418edb08b5 100644 --- a/drivers/entropy/Kconfig +++ b/drivers/entropy/Kconfig @@ -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 diff --git a/drivers/entropy/Kconfig.neorv32 b/drivers/entropy/Kconfig.neorv32 new file mode 100644 index 00000000000..8a6ec54443e --- /dev/null +++ b/drivers/entropy/Kconfig.neorv32 @@ -0,0 +1,13 @@ +# NEORV32 TRNG configuration + +# Copyright (c) 2021 Henrik Brix Andersen +# 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. diff --git a/drivers/entropy/entropy_neorv32_trng.c b/drivers/entropy/entropy_neorv32_trng.c new file mode 100644 index 00000000000..7f7f0b1d4d6 --- /dev/null +++ b/drivers/entropy/entropy_neorv32_trng.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT neorv32_trng + +#include +#include +#include +#include + +#include +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) diff --git a/soc/riscv/riscv-privilege/neorv32/Kconfig.defconfig.series b/soc/riscv/riscv-privilege/neorv32/Kconfig.defconfig.series index 4a93142a14d..11bd7ef7d33 100644 --- a/soc/riscv/riscv-privilege/neorv32/Kconfig.defconfig.series +++ b/soc/riscv/riscv-privilege/neorv32/Kconfig.defconfig.series @@ -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