summaryrefslogtreecommitdiff
path: root/drivers/rng/arm_rndr.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-10-11 11:53:58 -0400
committerTom Rini <trini@konsulko.com>2023-10-11 13:22:32 -0400
commit9598cf43f946fdbc8448db218965c00d64ce3d5e (patch)
tree00230631fe97ec3effede778cc229d762c6e8778 /drivers/rng/arm_rndr.c
parent5ae883c7160cf8b0604ec6d03798dd90fc81ee38 (diff)
parent1a1d48e36a1b185884e82d72457f7a274e4d1857 (diff)
Merge branch '2023-10-11-assorted-fixes-and-updates'
- Assorted TI K3 updates, use ".dtso" for device tree overlays to match general usage, mkimage fixes/improvements, assorted platform updates/fixes, other assorted driver/platform fixes.
Diffstat (limited to 'drivers/rng/arm_rndr.c')
-rw-r--r--drivers/rng/arm_rndr.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/rng/arm_rndr.c b/drivers/rng/arm_rndr.c
new file mode 100644
index 00000000000..55989743eae
--- /dev/null
+++ b/drivers/rng/arm_rndr.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Arm Ltd.
+ *
+ * Use the (optional) ARMv8.5 RNDR register to provide random numbers to
+ * U-Boot's UCLASS_RNG users.
+ * Detection is done at runtime using the CPU ID registers.
+ */
+
+#define LOG_CATEGORY UCLASS_RNG
+
+#include <common.h>
+#include <dm.h>
+#include <linux/kernel.h>
+#include <rng.h>
+#include <asm/system.h>
+
+#define DRIVER_NAME "arm-rndr"
+
+static bool cpu_has_rndr(void)
+{
+ uint64_t reg;
+
+ __asm__ volatile("mrs %0, ID_AA64ISAR0_EL1\n" : "=r" (reg));
+ return !!(reg & ID_AA64ISAR0_EL1_RNDR);
+}
+
+/*
+ * The system register name is RNDR, but this isn't widely known among older
+ * toolchains, and also triggers errors because of it being an architecture
+ * extension. Since we check the availability of the register before, it's
+ * fine to use here, though.
+ */
+#define RNDR "S3_3_C2_C4_0"
+
+static uint64_t read_rndr(void)
+{
+ uint64_t reg;
+
+ __asm__ volatile("mrs %0, " RNDR "\n" : "=r" (reg));
+
+ return reg;
+}
+
+static int arm_rndr_read(struct udevice *dev, void *data, size_t len)
+{
+ uint64_t random;
+
+ while (len) {
+ int tocopy = min(sizeof(uint64_t), len);
+
+ random = read_rndr();
+ memcpy(data, &random, tocopy);
+ len -= tocopy;
+ data += tocopy;
+ }
+
+ return 0;
+}
+
+static const struct dm_rng_ops arm_rndr_ops = {
+ .read = arm_rndr_read,
+};
+
+static int arm_rndr_probe(struct udevice *dev)
+{
+ if (!cpu_has_rndr())
+ return -ENODEV;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(arm_rndr) = {
+ .name = DRIVER_NAME,
+ .id = UCLASS_RNG,
+ .ops = &arm_rndr_ops,
+ .probe = arm_rndr_probe,
+};
+
+U_BOOT_DRVINFO(cpu_arm_rndr) = {
+ .name = DRIVER_NAME,
+};