Skip to content

Commit bae6615

Browse files
committed
drivers: entropy: add driver for VirtIO Entropy device
Add VirtIO Entropy driver. The `virtio,device4` is a somewhat unfamiliar naming convention, but it follows the convention used in Linux. Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent ad3df1d commit bae6615

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed

drivers/entropy/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_SMARTBOND_TRNG entropy_smartbon
4343
zephyr_library_sources_ifdef(CONFIG_ENTROPY_STM32_RNG entropy_stm32.c)
4444
zephyr_library_sources_ifdef(CONFIG_ENTROPY_SY1XX_TRNG entropy_sy1xx_trng.c)
4545
zephyr_library_sources_ifdef(CONFIG_ENTROPY_TELINK_B91_TRNG entropy_b91_trng.c)
46+
zephyr_library_sources_ifdef(CONFIG_ENTROPY_VIRTIO entropy_virtio.c)
4647
# zephyr-keep-sorted-stop
4748

4849
zephyr_library_link_libraries_ifdef(CONFIG_BUILD_WITH_TFM tfm_api)

drivers/entropy/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ source "drivers/entropy/Kconfig.siwx91x"
4545
source "drivers/entropy/Kconfig.smartbond"
4646
source "drivers/entropy/Kconfig.stm32"
4747
source "drivers/entropy/Kconfig.sy1xx"
48+
source "drivers/entropy/Kconfig.virtio"
4849
# zephyr-keep-sorted-stop
4950

5051
config ENTROPY_HAS_DRIVER

drivers/entropy/Kconfig.virtio

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) 2025 TOKITA Hiroshi
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config ENTROPY_VIRTIO
5+
bool "Driver for VirtIO Entropy device"
6+
depends on DT_HAS_VIRTIO_DEVICE4_ENABLED
7+
depends on VIRTIO
8+
select ENTROPY_HAS_DRIVER
9+
default y
10+
help
11+
Enable driver for the VirtIO Entropy device.

drivers/entropy/entropy_virtio.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
* Copyright (c) 2025 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/entropy.h>
8+
#include <zephyr/virtio/virtio.h>
9+
#include <zephyr/virtio/virtqueue.h>
10+
#include <zephyr/logging/log.h>
11+
12+
#define VIRTIO_ENTROPY_QUEUE_IDX 0
13+
14+
#define DT_DRV_COMPAT virtio_device4
15+
16+
LOG_MODULE_REGISTER(virtio_entropy, CONFIG_ENTROPY_LOG_LEVEL);
17+
18+
struct entropy_virtio_config {
19+
const struct device *vdev;
20+
};
21+
22+
struct entropy_virtio_data {
23+
struct k_sem sem;
24+
uint32_t received_len;
25+
};
26+
27+
static void entropy_virtio_virtq_recv_cb(void *priv, uint32_t len)
28+
{
29+
struct entropy_virtio_data *data = priv;
30+
31+
data->received_len = len;
32+
k_sem_give(&data->sem);
33+
}
34+
35+
static uint16_t entropy_virtio_enum_queues_cb(uint16_t q_index, uint16_t q_size_max, void *unused)
36+
{
37+
if (q_index == VIRTIO_ENTROPY_QUEUE_IDX) {
38+
return MIN(1, q_size_max);
39+
}
40+
41+
return 0;
42+
}
43+
44+
static int entropy_virtio_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t length)
45+
{
46+
struct virtq_buf buf[] = {{.addr = buffer, .len = length}};
47+
const struct entropy_virtio_config *cfg = dev->config;
48+
struct entropy_virtio_data *data = dev->data;
49+
struct virtq *vq = virtio_get_virtqueue(cfg->vdev, VIRTIO_ENTROPY_QUEUE_IDX);
50+
int ret;
51+
52+
if (!vq) {
53+
LOG_ERR("failed to get virtqueue %d", VIRTIO_ENTROPY_QUEUE_IDX);
54+
return -ENODEV;
55+
}
56+
57+
data->received_len = 0;
58+
ret = virtq_add_buffer_chain(vq, buf, 1, 0, entropy_virtio_virtq_recv_cb, data, K_FOREVER);
59+
if (ret) {
60+
LOG_ERR("virtq_add_buffer_chain failed: %d", ret);
61+
return -EIO;
62+
}
63+
64+
virtio_notify_virtqueue(cfg->vdev, VIRTIO_ENTROPY_QUEUE_IDX);
65+
66+
k_sem_take(&data->sem, K_FOREVER);
67+
68+
if (data->received_len != length) {
69+
LOG_ERR("insufficient number of values: %d/%d", data->received_len, length);
70+
return -EIO;
71+
}
72+
73+
return 0;
74+
}
75+
76+
static DEVICE_API(entropy, entropy_virtio_api) = {
77+
.get_entropy = entropy_virtio_get_entropy,
78+
};
79+
80+
static int entropy_virtio_init(const struct device *dev)
81+
{
82+
const struct entropy_virtio_config *cfg = dev->config;
83+
struct entropy_virtio_data *data = dev->data;
84+
int ret;
85+
86+
ret = virtio_commit_feature_bits(cfg->vdev);
87+
if (ret != 0) {
88+
return ret;
89+
}
90+
91+
ret = virtio_init_virtqueues(cfg->vdev, 1, entropy_virtio_enum_queues_cb, NULL);
92+
if (ret) {
93+
LOG_ERR("virtio_init_virtqueues failed: %d", ret);
94+
return ret;
95+
}
96+
97+
virtio_finalize_init(cfg->vdev);
98+
99+
k_sem_init(&data->sem, 0, 1);
100+
101+
LOG_DBG("VirtIO entropy driver initialized");
102+
return 0;
103+
}
104+
105+
#define ENTROPY_VIRTIO_INST(n) \
106+
static struct entropy_virtio_data entropy_virtio_data_##n; \
107+
static const struct entropy_virtio_config entropy_virtio_config_##n = { \
108+
.vdev = DEVICE_DT_GET(DT_PARENT(DT_DRV_INST(n))), \
109+
}; \
110+
DEVICE_DT_INST_DEFINE(n, entropy_virtio_init, NULL, &entropy_virtio_data_##n, \
111+
&entropy_virtio_config_##n, POST_KERNEL, \
112+
CONFIG_ENTROPY_INIT_PRIORITY, &entropy_virtio_api);
113+
114+
DT_INST_FOREACH_STATUS_OKAY(ENTROPY_VIRTIO_INST);

dts/bindings/rng/virtio,device4.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2025 TOKITA Hiroshi
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: VirtIO Entropy device (ID:4)
5+
6+
compatible: "virtio,device4"
7+
8+
include: base.yaml

0 commit comments

Comments
 (0)