41575d8e4c
This construct is quite long-winded. In earlier days it made some sense since auto-allocation was a strange concept. But with driver model now used pretty universally, we can shorten this to 'auto'. This reduces verbosity and makes it easier to read. Coincidentally it also ensures that every declaration is on one line, thus making dtoc's job easier. Signed-off-by: Simon Glass <sjg@chromium.org>
90 lines
1.7 KiB
C
90 lines
1.7 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (c) 2019, Linaro Limited
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <log.h>
|
|
#include <rng.h>
|
|
#include <virtio_types.h>
|
|
#include <virtio.h>
|
|
#include <virtio_ring.h>
|
|
|
|
#define BUFFER_SIZE 16UL
|
|
|
|
struct virtio_rng_priv {
|
|
struct virtqueue *rng_vq;
|
|
};
|
|
|
|
static int virtio_rng_read(struct udevice *dev, void *data, size_t len)
|
|
{
|
|
int ret;
|
|
unsigned int rsize;
|
|
unsigned char buf[BUFFER_SIZE] __aligned(4);
|
|
unsigned char *ptr = data;
|
|
struct virtio_sg sg;
|
|
struct virtio_sg *sgs[1];
|
|
struct virtio_rng_priv *priv = dev_get_priv(dev);
|
|
|
|
while (len) {
|
|
sg.addr = buf;
|
|
sg.length = min(len, sizeof(buf));
|
|
sgs[0] = &sg;
|
|
|
|
ret = virtqueue_add(priv->rng_vq, sgs, 0, 1);
|
|
if (ret)
|
|
return ret;
|
|
|
|
virtqueue_kick(priv->rng_vq);
|
|
|
|
while (!virtqueue_get_buf(priv->rng_vq, &rsize))
|
|
;
|
|
|
|
memcpy(ptr, buf, rsize);
|
|
len -= rsize;
|
|
ptr += rsize;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int virtio_rng_bind(struct udevice *dev)
|
|
{
|
|
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent);
|
|
|
|
/* Indicate what driver features we support */
|
|
virtio_driver_features_init(uc_priv, NULL, 0, NULL, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int virtio_rng_probe(struct udevice *dev)
|
|
{
|
|
struct virtio_rng_priv *priv = dev_get_priv(dev);
|
|
int ret;
|
|
|
|
ret = virtio_find_vqs(dev, 1, &priv->rng_vq);
|
|
if (ret < 0) {
|
|
debug("%s: virtio_find_vqs failed\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct dm_rng_ops virtio_rng_ops = {
|
|
.read = virtio_rng_read,
|
|
};
|
|
|
|
U_BOOT_DRIVER(virtio_rng) = {
|
|
.name = VIRTIO_RNG_DRV_NAME,
|
|
.id = UCLASS_RNG,
|
|
.bind = virtio_rng_bind,
|
|
.probe = virtio_rng_probe,
|
|
.remove = virtio_reset,
|
|
.ops = &virtio_rng_ops,
|
|
.priv_auto = sizeof(struct virtio_rng_priv),
|
|
.flags = DM_FLAG_ACTIVE_DMA,
|
|
};
|