From: Yu'an Wang wangyuan46@huawei.com
driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4FHUR
----------------------------------------------------------
Provide kernel-side GM authentication support for the True Random Number Generator hardware found on HiSilicon KP920 SoC
Signed-off-by: Yu'an Wang wangyuan46@huawei.com Reviewed-by: Weili Qian qianweili@huawei.com Reviewed-by: Longfang Liu liulongfang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/char/hw_random/Kconfig | 13 ++++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/hisi-gm-trng.c | 99 +++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 drivers/char/hw_random/hisi-gm-trng.c
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 72676f6e2364..dda4a9dfad2e 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -348,6 +348,19 @@ config HW_RANDOM_HISI
If unsure, say Y.
+config HW_RANDOM_HISI_GM + tristate "HiSilicon GM auth True Random Number Generator support" + depends on HW_RANDOM && ARM64 && ACPI + default HW_RANDOM + help + This driver provides kernel-side gm authentication upport for the + True Random Number Generator hardware found on HiSilicon Hi1620 SoC. + + To compile this driver as a module, choose M here: the + module will be called hisi-gm-trng. + + If unsure, say Y. + config HW_RANDOM_ST tristate "ST Microelectronics HW Random Number Generator support" depends on HW_RANDOM && ARCH_STI diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 8933fada74f2..d24ec71627af 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o +obj-$(CONFIG_HW_RANDOM_HISI_GM) += hisi-gm-trng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o diff --git a/drivers/char/hw_random/hisi-gm-trng.c b/drivers/char/hw_random/hisi-gm-trng.c new file mode 100644 index 000000000000..0303cc6bfee6 --- /dev/null +++ b/drivers/char/hw_random/hisi-gm-trng.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 HiSilicon Limited. */ + +#include <linux/acpi.h> +#include <linux/err.h> +#include <linux/hw_random.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/random.h> +#include <linux/arm-smccc.h> + +#define HISI_TRNG_SMC_CMD 0x83000109 +#define HISI_TRNG_SMC_BYTES 32 +#define HISI_TRNG_QUALITY 513 + +struct hisi_gm_trng { + struct hwrng rng; + void *va; + phys_addr_t pa; +}; + +static int hisi_gm_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) +{ + struct arm_smccc_res res = {0}; + struct hisi_gm_trng *trng; + int currsize = 0; + + trng = container_of(rng, struct hisi_gm_trng, rng); + + do { + /* get gm true random number through bios */ + arm_smccc_smc(HISI_TRNG_SMC_CMD, trng->pa, 0, 0, 0, 0, 0, 0, + &res); + if (res.a0) + return currsize; + + if (max - currsize >= HISI_TRNG_SMC_BYTES) { + memcpy(buf + currsize, trng->va, HISI_TRNG_SMC_BYTES); + currsize += HISI_TRNG_SMC_BYTES; + if (currsize == max) + return currsize; + continue; + } + + memcpy(buf + currsize, trng->va, max - currsize); + currsize = max; + } while (currsize < max); + + return currsize; +} + +static int hisi_gm_trng_probe(struct platform_device *pdev) +{ + struct hisi_gm_trng *trng; + int ret; + + trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); + if (!trng) + return -ENOMEM; + + trng->rng.name = pdev->name; + trng->rng.quality = HISI_TRNG_QUALITY; + trng->rng.read = hisi_gm_trng_read; + trng->va = devm_kzalloc(&pdev->dev, HISI_TRNG_SMC_BYTES, GFP_KERNEL); + if (!trng->va) + return -ENOMEM; + + trng->pa = virt_to_phys(trng->va); + + ret = devm_hwrng_register(&pdev->dev, &trng->rng); + if (ret) + dev_err(&pdev->dev, "failed to register hwrng!\n"); + + return ret; +} + +static const struct acpi_device_id hisi_gm_trng_acpi_tbl[] = { + { "HISI02B4", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, hisi_gm_trng_acpi_tbl); + +static struct platform_driver hisi_gm_trng_driver = { + .probe = hisi_gm_trng_probe, + .driver = { + .name = "hisi-gm-trng", + .acpi_match_table = ACPI_PTR(hisi_gm_trng_acpi_tbl), + }, +}; + +module_platform_driver(hisi_gm_trng_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Yuan Wang wangyuan46@huawei.com"); +MODULE_DESCRIPTION("HiSilicon GM auth true random number generator driver"); +