From bc40eb278b0c14b990556eab34a57b2b8ed598f4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Feb 2020 19:52:04 +0100 Subject: [PATCH] drivers/rng: add Amlogic hardware RNG driver Add support for the hardware random number generator of Amlogic SOCs. Signed-off-by: Heinrich Schuchardt Reviewed-by: Neil Armstrong Reviewed-by: Sughosh Ganu --- drivers/rng/Kconfig | 8 +++ drivers/rng/Makefile | 1 + drivers/rng/meson-rng.c | 120 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 drivers/rng/meson-rng.c diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index c1aa43b823..edb6152bb9 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -8,6 +8,14 @@ config DM_RNG if DM_RNG +config RNG_MESON + bool "Amlogic Meson Random Number Generator support" + depends on ARCH_MESON + default y + help + Enable support for hardware random number generator + of Amlogic Meson SoCs. + config RNG_SANDBOX bool "Sandbox random number generator" depends on SANDBOX diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 3517005541..6a8a66779b 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -4,5 +4,6 @@ # obj-$(CONFIG_DM_RNG) += rng-uclass.o +obj-$(CONFIG_RNG_MESON) += meson-rng.o obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o diff --git a/drivers/rng/meson-rng.c b/drivers/rng/meson-rng.c new file mode 100644 index 0000000000..4b81a62353 --- /dev/null +++ b/drivers/rng/meson-rng.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2020, Heinrich Schuchardt + * + * Driver for Amlogic hardware random number generator + */ + +#include +#include +#include +#include +#include + +struct meson_rng_platdata { + fdt_addr_t base; + struct clk clk; +}; + +/** + * meson_rng_read() - fill buffer with random bytes + * + * @buffer: buffer to receive data + * @size: size of buffer + * + * Return: 0 + */ +static int meson_rng_read(struct udevice *dev, void *data, size_t len) +{ + struct meson_rng_platdata *pdata = dev_get_platdata(dev); + char *buffer = (char *)data; + + while (len) { + u32 rand = readl(pdata->base); + size_t step; + + if (len >= 4) + step = 4; + else + step = len; + memcpy(buffer, &rand, step); + buffer += step; + len -= step; + } + return 0; +} + +/** + * meson_rng_probe() - probe rng device + * + * @dev: device + * Return: 0 if ok + */ +static int meson_rng_probe(struct udevice *dev) +{ + struct meson_rng_platdata *pdata = dev_get_platdata(dev); + int err; + + err = clk_enable(&pdata->clk); + if (err) + return err; + + return 0; +} + +/** + * meson_rng_remove() - deinitialize rng device + * + * @dev: device + * Return: 0 if ok + */ +static int meson_rng_remove(struct udevice *dev) +{ + struct meson_rng_platdata *pdata = dev_get_platdata(dev); + + return clk_disable(&pdata->clk); +} + +/** + * meson_rng_ofdata_to_platdata() - transfer device tree data to plaform data + * + * @dev: device + * Return: 0 if ok + */ +static int meson_rng_ofdata_to_platdata(struct udevice *dev) +{ + struct meson_rng_platdata *pdata = dev_get_platdata(dev); + int err; + + pdata->base = dev_read_addr(dev); + if (!pdata->base) + return -ENODEV; + + err = clk_get_by_name(dev, "core", &pdata->clk); + if (err) + return err; + + return 0; +} + +static const struct dm_rng_ops meson_rng_ops = { + .read = meson_rng_read, +}; + +static const struct udevice_id meson_rng_match[] = { + { + .compatible = "amlogic,meson-rng", + }, + {}, +}; + +U_BOOT_DRIVER(meson_rng) = { + .name = "meson-rng", + .id = UCLASS_RNG, + .of_match = meson_rng_match, + .ops = &meson_rng_ops, + .probe = meson_rng_probe, + .remove = meson_rng_remove, + .platdata_auto_alloc_size = sizeof(struct meson_rng_platdata), + .ofdata_to_platdata = meson_rng_ofdata_to_platdata, +}; -- 2.25.1