Commit 8116aced authored by Yu'an Wang's avatar Yu'an Wang Committed by Zheng Zengkai
Browse files

hwrng: add hisilicon GM auth trng driver

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: default avatarYu'an Wang <wangyuan46@huawei.com>
Reviewed-by: default avatarWeili Qian <qianweili@huawei.com>
Reviewed-by: default avatarLongfang Liu <liulongfang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 26ba3a84
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
+99 −0
Original line number Diff line number Diff line
// 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");