From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 11/12] hw_random: add timeriomem_rng driver
Date: Wed, 13 Mar 2024 11:56:30 +0100 [thread overview]
Message-ID: <20240313105631.686778-12-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20240313105631.686778-1-a.fatoum@pengutronix.de>
To enable proper hardening with stack protector, add support for the
RNGs with the interface of a single memory mapped 32-bit register.
This can possibly come in handy for the web demo.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/hw_random/Kconfig | 7 ++
drivers/hw_random/Makefile | 1 +
drivers/hw_random/timeriomem-rng.c | 145 +++++++++++++++++++++++++++++
3 files changed, 153 insertions(+)
create mode 100644 drivers/hw_random/timeriomem-rng.c
diff --git a/drivers/hw_random/Kconfig b/drivers/hw_random/Kconfig
index 58df6a75443c..bd1ac89ad37d 100644
--- a/drivers/hw_random/Kconfig
+++ b/drivers/hw_random/Kconfig
@@ -8,6 +8,13 @@ menuconfig HWRNG
if HWRNG
+config HW_RANDOM_TIMERIOMEM
+ tristate "Timer IOMEM HW Random Number Generator support"
+ help
+ This driver provides barebox support for a generic Random
+ Number Generator used by reading a 'dumb' iomem address that
+ is to be read no faster than, for example, once a second.
+
config HWRNG_MXC_RNGC
tristate "Freescale i.MX RNGC Random Number Generator"
depends on ARCH_IMX25 || ARCH_IMX35 || ARCH_IMX53 || COMPILE_TEST
diff --git a/drivers/hw_random/Makefile b/drivers/hw_random/Makefile
index 8658d4e52521..32b02fa211ac 100644
--- a/drivers/hw_random/Makefile
+++ b/drivers/hw_random/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o
+obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
diff --git a/drivers/hw_random/timeriomem-rng.c b/drivers/hw_random/timeriomem-rng.c
new file mode 100644
index 000000000000..8d4705830653
--- /dev/null
+++ b/drivers/hw_random/timeriomem-rng.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * drivers/char/hw_random/timeriomem-rng.c
+ *
+ * Copyright (C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *
+ * Derived from drivers/char/hw_random/omap-rng.c
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Overview:
+ * This driver is useful for platforms that have an IO range that provides
+ * periodic random data from a single IO memory address. All the platform
+ * has to do is provide the address and 'wait time' that new data becomes
+ * available.
+ *
+ * TODO: add support for reading sizes other than 32bits and masking
+ */
+
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/ktime.h>
+#include <of.h>
+#include <linux/device.h>
+#include <linux/time.h>
+
+struct timeriomem_rng_private {
+ void __iomem *io_base;
+
+ ktime_t period;
+ ktime_t next_read;
+
+ struct hwrng rng_ops;
+};
+
+static int timeriomem_rng_read(struct hwrng *hwrng, void *data,
+ size_t max, bool wait)
+{
+ struct timeriomem_rng_private *priv =
+ container_of(hwrng, struct timeriomem_rng_private, rng_ops);
+ int retval = 0;
+ int period_us = ktime_to_us(priv->period);
+ ktime_t now = ktime_get();
+
+ /*
+ * There may not have been enough time for new data to be generated
+ * since the last request. If the caller doesn't want to wait, let them
+ * bail out. Otherwise, wait for the completion. If the new data has
+ * already been generated, the completion should already be available.
+ */
+ if (ktime_before(now, priv->next_read)) {
+ if (!wait)
+ return 0;
+
+ udelay(ktime_to_us(ktime_sub(priv->next_read, now)));
+ }
+
+ do {
+ /*
+ * After the first read, all additional reads will need to wait
+ * for the RNG to generate new data. Since the period can have
+ * a wide range of values (1us to 1s have been observed), allow
+ * for 1% tolerance in the sleep time rather than a fixed value.
+ */
+ if (retval > 0)
+ udelay(period_us);
+
+ *(u32 *)data = readl(priv->io_base);
+ retval += sizeof(u32);
+ data += sizeof(u32);
+ max -= sizeof(u32);
+ } while (wait && max > sizeof(u32));
+
+ /*
+ * Block any new callers until the RNG has had time to generate new
+ * data.
+ */
+ priv->next_read = ktime_add(ktime_get(), priv->period);
+
+ return retval;
+}
+
+static int timeriomem_rng_probe(struct device *dev)
+{
+ struct timeriomem_rng_private *priv;
+ struct resource *res;
+ int err = 0;
+ int period;
+
+ /* Allocate memory for the device structure (and zero it) */
+ priv = devm_kzalloc(dev,
+ sizeof(struct timeriomem_rng_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->io_base = dev_platform_get_and_ioremap_resource(dev, 0, &res);
+ if (IS_ERR(priv->io_base))
+ return PTR_ERR(priv->io_base);
+
+ if (res->start % 4 != 0 || resource_size(res) < 4) {
+ dev_err(dev,
+ "address must be at least four bytes wide and 32-bit aligned\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(dev->of_node, "period", &period))
+ return dev_err_probe(dev, -EINVAL, "missing period\n");
+
+ priv->period = ns_to_ktime(period * NSEC_PER_USEC);
+
+ priv->rng_ops.name = dev_name(dev);
+ priv->rng_ops.read = timeriomem_rng_read;
+
+ /* Assume random data is already available. */
+ priv->next_read = ktime_get();
+
+ err = hwrng_register(dev, &priv->rng_ops);
+ if (err) {
+ dev_err(dev, "problem registering\n");
+ return err;
+ }
+
+ dev_info(dev, "32bits from 0x%p @ %dus\n",
+ priv->io_base, period);
+
+ return 0;
+}
+
+static const struct of_device_id timeriomem_rng_match[] = {
+ { .compatible = "timeriomem_rng" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, timeriomem_rng_match);
+
+static struct driver timeriomem_rng_driver = {
+ .name = "timeriomem_rng",
+ .of_match_table = timeriomem_rng_match,
+ .probe = timeriomem_rng_probe,
+};
+
+device_platform_driver(timeriomem_rng_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
+MODULE_DESCRIPTION("Timer IOMEM H/W RNG driver");
--
2.39.2
next prev parent reply other threads:[~2024-03-13 11:05 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-13 10:56 [PATCH 00/12] hw_random: add 6 more RNG drivers Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 01/12] hw_random: support ctrlc() Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 02/12] ARM: io: read 32 bits at once for aligned I/O memcpy/memset Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 03/12] driver: implement dev_platform_get_and_ioremap_resource Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 04/12] hw_random: add struct hwrng::priv member Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 05/12] hw_random: remove confusing left-overs from kernel help texts Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 06/12] hw_random: remove reference to undefined CONFIG_HW_RANDOM Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 07/12] hw_random: add Atmel RNG driver Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 08/12] hw_random: add BCM2835 " Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 09/12] hw_random: add IPROC RNG200 driver for BCM2711 Ahmad Fatoum
2024-03-13 10:56 ` [PATCH 10/12] hw_random: add Rockchip RNG support Ahmad Fatoum
2024-03-13 10:56 ` Ahmad Fatoum [this message]
2024-03-13 10:56 ` [PATCH 12/12] hw_random: add OMAP RNG driver Ahmad Fatoum
2024-03-15 7:07 ` [PATCH 00/12] hw_random: add 6 more RNG drivers Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240313105631.686778-12-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox