diff options
author | Tom Rini <trini@konsulko.com> | 2023-10-11 11:53:58 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-10-11 13:22:32 -0400 |
commit | 9598cf43f946fdbc8448db218965c00d64ce3d5e (patch) | |
tree | 00230631fe97ec3effede778cc229d762c6e8778 /drivers/rng/arm_rndr.c | |
parent | 5ae883c7160cf8b0604ec6d03798dd90fc81ee38 (diff) | |
parent | 1a1d48e36a1b185884e82d72457f7a274e4d1857 (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.c | 82 |
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, +}; |