mail archive of the barebox mailing list
 help / color / mirror / Atom feed
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




  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