From: David Yang <mmyangfl@gmail.com>
To: linux-crypto@vger.kernel.org
Cc: David Yang <mmyangfl@gmail.com>,
Weili Qian <qianweili@huawei.com>,
Zhou Wang <wangzhou1@hisilicon.com>,
Herbert Xu <herbert@gondor.apana.org.au>,
"David S. Miller" <davem@davemloft.net>,
linux-kernel@vger.kernel.org
Subject: [PATCH] crypto: hisilicon/trng - add support for HiSTB TRNG
Date: Sun, 26 Mar 2023 13:34:41 +0800 [thread overview]
Message-ID: <20230326053448.299008-1-mmyangfl@gmail.com> (raw)
HiSTB TRNG are found on some HiSilicon STB SoCs.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
v2: fix typo
v3: add option for post process depth, adjust timeout
drivers/crypto/hisilicon/Kconfig | 7 +
drivers/crypto/hisilicon/Makefile | 2 +-
drivers/crypto/hisilicon/trng/Makefile | 3 +
drivers/crypto/hisilicon/trng/trng-stb.c | 171 +++++++++++++++++++++++
4 files changed, 182 insertions(+), 1 deletion(-)
create mode 100644 drivers/crypto/hisilicon/trng/trng-stb.c
diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig
index 4137a8bf131f..e8690c223584 100644
--- a/drivers/crypto/hisilicon/Kconfig
+++ b/drivers/crypto/hisilicon/Kconfig
@@ -82,3 +82,10 @@ config CRYPTO_DEV_HISI_TRNG
select CRYPTO_RNG
help
Support for HiSilicon TRNG Driver.
+
+config CRYPTO_DEV_HISTB_TRNG
+ tristate "Support for HiSTB TRNG Driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ select HW_RANDOM
+ help
+ Support for HiSTB TRNG Driver.
diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile
index 8595a5a5d228..fc51e0edec69 100644
--- a/drivers/crypto/hisilicon/Makefile
+++ b/drivers/crypto/hisilicon/Makefile
@@ -5,4 +5,4 @@ obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/
obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += hisi_qm.o
hisi_qm-objs = qm.o sgl.o debugfs.o
obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += zip/
-obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += trng/
+obj-y += trng/
diff --git a/drivers/crypto/hisilicon/trng/Makefile b/drivers/crypto/hisilicon/trng/Makefile
index d909079f351c..cf20b057c66b 100644
--- a/drivers/crypto/hisilicon/trng/Makefile
+++ b/drivers/crypto/hisilicon/trng/Makefile
@@ -1,2 +1,5 @@
obj-$(CONFIG_CRYPTO_DEV_HISI_TRNG) += hisi-trng-v2.o
hisi-trng-v2-objs = trng.o
+
+obj-$(CONFIG_CRYPTO_DEV_HISTB_TRNG) += histb-trng.o
+histb-trng-objs += trng-stb.o
diff --git a/drivers/crypto/hisilicon/trng/trng-stb.c b/drivers/crypto/hisilicon/trng/trng-stb.c
new file mode 100644
index 000000000000..44ee071fd348
--- /dev/null
+++ b/drivers/crypto/hisilicon/trng/trng-stb.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Device driver for True RNG in HiSTB SoCs
+ *
+ * Copyright (c) 2023 David Yang
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/timekeeping.h>
+
+#define HISTB_TRNG_CTRL 0x0
+#define RNG_SOURCE GENMASK(1, 0)
+#define DROP_ENABLE BIT(5)
+#define POST_PROCESS_ENABLE BIT(7)
+#define POST_PROCESS_DEPTH GENMASK(15, 8)
+#define HISTB_TRNG_NUMBER 0x4
+#define HISTB_TRNG_STAT 0x8
+#define DATA_COUNT GENMASK(2, 0) /* max 4 */
+
+/*
+ * Observed:
+ * depth = 1 -> ~1ms
+ * depth = 255 -> ~16ms
+ */
+static int histb_trng_wait(struct hwrng *rng)
+{
+ void __iomem *base = (void __iomem *) rng->priv;
+ u32 val;
+
+ return readl_relaxed_poll_timeout(base + HISTB_TRNG_STAT,
+ val, val & DATA_COUNT, 1000,
+ 30 * 1000);
+}
+
+static void histb_trng_init(struct hwrng *rng, unsigned int depth)
+{
+ void __iomem *base = (void __iomem *) rng->priv;
+ u32 val;
+
+ val = readl_relaxed(base + HISTB_TRNG_CTRL);
+
+ val &= ~RNG_SOURCE;
+ val |= 2;
+
+ val &= ~POST_PROCESS_DEPTH;
+ val |= min(depth, 0xffu) << 8;
+
+ val |= POST_PROCESS_ENABLE;
+ val |= DROP_ENABLE;
+
+ writel_relaxed(val, base + HISTB_TRNG_CTRL);
+}
+
+static int histb_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+ void __iomem *base = (void __iomem *) rng->priv;
+ size_t i;
+
+ for (i = 0; i < max; i += sizeof(u32)) {
+ if (!(readl_relaxed(base + HISTB_TRNG_STAT) & DATA_COUNT)) {
+ if (!wait)
+ break;
+ if (histb_trng_wait(rng)) {
+ pr_err("failed to generate random number, generated %zu\n",
+ i);
+ if (i)
+ break;
+ return -ETIMEDOUT;
+ }
+ }
+ *(u32 *) (data + i) = readl_relaxed(base + HISTB_TRNG_NUMBER);
+ }
+
+ return i;
+}
+
+static unsigned int histb_trng_get_depth(struct hwrng *rng)
+{
+ void __iomem *base = (void __iomem *) rng->priv;
+ u32 val = readl_relaxed(base + HISTB_TRNG_CTRL);
+
+ return (val & POST_PROCESS_DEPTH) >> 8;
+}
+
+static ssize_t
+depth_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct hwrng *rng = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", histb_trng_get_depth(rng));
+}
+
+static ssize_t
+depth_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hwrng *rng = dev_get_drvdata(dev);
+ unsigned int depth;
+
+ if (kstrtouint(buf, 0, &depth))
+ return -ERANGE;
+
+ histb_trng_init(rng, depth);
+ return count;
+}
+
+static DEVICE_ATTR_RW(depth);
+
+static struct attribute *histb_trng_attrs[] = {
+ &dev_attr_depth.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(histb_trng);
+
+static int histb_trng_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct hwrng *rng;
+ int ret;
+
+ rng = devm_kzalloc(dev, sizeof(*rng), GFP_KERNEL);
+ if (!rng)
+ return -ENOMEM;
+
+ rng->priv = (unsigned long) devm_platform_ioremap_resource(pdev, 0);
+ if (rng->priv <= 0)
+ return -ENOMEM;
+
+ histb_trng_init(rng, 144);
+ if (histb_trng_wait(rng))
+ return -ENODEV;
+
+ rng->name = KBUILD_MODNAME;
+ rng->read = histb_trng_read;
+
+ ret = devm_hwrng_register(dev, rng);
+ if (ret) {
+ dev_err(dev, "failed to register %s (%d)\n", rng->name, ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, rng);
+ dev_set_drvdata(dev, rng);
+ return 0;
+}
+
+static const struct of_device_id histb_trng_of_match[] = {
+ { .compatible = "hisilicon,histb-trng", },
+ { }
+};
+
+static struct platform_driver histb_trng_driver = {
+ .probe = histb_trng_probe,
+ .driver = {
+ .name = "histb-trng",
+ .of_match_table = of_match_ptr(histb_trng_of_match),
+ .dev_groups = histb_trng_groups,
+ },
+};
+
+module_platform_driver(histb_trng_driver);
+
+MODULE_DESCRIPTION("HiSTB True RNG");
+MODULE_LICENSE("Dual MIT/GPL");
--
2.39.2
next reply other threads:[~2023-03-26 5:35 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-26 5:34 David Yang [this message]
-- strict thread matches above, loose matches on Subject: below --
2023-03-21 5:58 [PATCH] crypto: hisilicon/trng - add support for HiSTB TRNG David Yang
2023-03-21 7:56 ` kernel test robot
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=20230326053448.299008-1-mmyangfl@gmail.com \
--to=mmyangfl@gmail.com \
--cc=davem@davemloft.net \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=qianweili@huawei.com \
--cc=wangzhou1@hisilicon.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.