[][Add trngv2 driver support]

[Description]
Add trngv2 driver support.

[Release-log]
N/A

Change-Id: Idc248b40b9120ff308b06247551ecd4a7c633ffb
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5379902
diff --git a/target/linux/mediatek/patches-5.4/1661-Add-trngv2-driver-support.patch b/target/linux/mediatek/patches-5.4/1661-Add-trngv2-driver-support.patch
new file mode 100644
index 0000000..7c09a71
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/1661-Add-trngv2-driver-support.patch
@@ -0,0 +1,185 @@
+From ae5611b1b7a857edb3d9c8e900b550c76f7c236e Mon Sep 17 00:00:00 2001
+From: "Mingming.Su" <Mingming.Su@mediatek.com>
+Date: Fri, 17 Dec 2021 20:27:34 +0800
+Subject: [PATCH] Add trngv2 driver support
+
+---
+ drivers/char/hw_random/mtk-rng.c | 105 +++++++++++++++++++++++--------
+ 1 file changed, 78 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
+index a8bd06da7..75fca4cef 100644
+--- a/drivers/char/hw_random/mtk-rng.c
++++ b/drivers/char/hw_random/mtk-rng.c
+@@ -6,6 +6,7 @@
+  */
+ #define MTK_RNG_DEV KBUILD_MODNAME
+ 
++#include <linux/arm-smccc.h>
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/err.h>
+@@ -15,8 +16,12 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
++#include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/soc/mediatek/mtk_sip_svc.h>
++
++#define MTK_SIP_KERNEL_GET_RND		MTK_SIP_SMC_CMD(0x550)
+ 
+ /* Runtime PM autosuspend timeout: */
+ #define RNG_AUTOSUSPEND_TIMEOUT		100
+@@ -32,10 +37,15 @@
+ 
+ #define to_mtk_rng(p)	container_of(p, struct mtk_rng, rng)
+ 
++struct mtk_rng_of_data{
++	unsigned int rng_version;
++};
++
+ struct mtk_rng {
+ 	void __iomem *base;
+ 	struct clk *clk;
+ 	struct hwrng rng;
++	const struct mtk_rng_of_data *soc;
+ };
+ 
+ static int mtk_rng_init(struct hwrng *rng)
+@@ -103,41 +113,74 @@ static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+ 	return retval || !wait ? retval : -EIO;
+ }
+ 
++static int mtk_rngv2_read(struct hwrng *rng, void *buf, size_t max, bool wait)
++{
++	struct arm_smccc_res res;
++	int retval = 0;
++
++	while (max >= sizeof(u32)) {
++		arm_smccc_smc(MTK_SIP_KERNEL_GET_RND, 0, 0, 0, 0, 0, 0, 0,
++			      &res);
++		if (res.a0)
++			break;
++
++		*(u32 *)buf = res.a1;
++		retval += sizeof(u32);
++		buf += sizeof(u32);
++		max -= sizeof(u32);
++	}
++
++	return retval || !wait ? retval : -EIO;
++}
++
+ static int mtk_rng_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res;
+ 	int ret;
+ 	struct mtk_rng *priv;
+ 
+-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-	if (!res) {
+-		dev_err(&pdev->dev, "no iomem resource\n");
+-		return -ENXIO;
+-	}
+-
+ 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv)
+ 		return -ENOMEM;
+ 
+-	priv->rng.name = pdev->name;
++	priv->soc = of_device_get_match_data(&pdev->dev);
++	if (priv->soc->rng_version == 1) {
++		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++		if (!res) {
++			dev_err(&pdev->dev, "no iomem resource\n");
++			return -ENXIO;
++		}
++
++		priv->base = devm_ioremap_resource(&pdev->dev, res);
++		if (IS_ERR(priv->base))
++			return PTR_ERR(priv->base);
++
++		priv->clk = devm_clk_get(&pdev->dev, "rng");
++		if (IS_ERR(priv->clk)) {
++			ret = PTR_ERR(priv->clk);
++			dev_err(&pdev->dev, "no clock for device: %d\n", ret);
++			return ret;
++		}
++
+ #ifndef CONFIG_PM
+-	priv->rng.init = mtk_rng_init;
+-	priv->rng.cleanup = mtk_rng_cleanup;
++		priv->rng.init = mtk_rng_init;
++		priv->rng.cleanup = mtk_rng_cleanup;
+ #endif
+-	priv->rng.read = mtk_rng_read;
++		priv->rng.read = mtk_rng_read;
++
++		pm_runtime_set_autosuspend_delay(&pdev->dev,
++						 RNG_AUTOSUSPEND_TIMEOUT);
++		pm_runtime_use_autosuspend(&pdev->dev);
++		pm_runtime_enable(&pdev->dev);
++	} else {
++		priv->rng.read = mtk_rngv2_read;
++	}
++
++	priv->rng.name = pdev->name;
+ 	priv->rng.priv = (unsigned long)&pdev->dev;
+ 	priv->rng.quality = 900;
+ 
+-	priv->clk = devm_clk_get(&pdev->dev, "rng");
+-	if (IS_ERR(priv->clk)) {
+-		ret = PTR_ERR(priv->clk);
+-		dev_err(&pdev->dev, "no clock for device: %d\n", ret);
+-		return ret;
+-	}
+-
+-	priv->base = devm_ioremap_resource(&pdev->dev, res);
+-	if (IS_ERR(priv->base))
+-		return PTR_ERR(priv->base);
++	dev_set_drvdata(&pdev->dev, priv);
+ 
+ 	ret = devm_hwrng_register(&pdev->dev, &priv->rng);
+ 	if (ret) {
+@@ -146,11 +189,6 @@ static int mtk_rng_probe(struct platform_device *pdev)
+ 		return ret;
+ 	}
+ 
+-	dev_set_drvdata(&pdev->dev, priv);
+-	pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT);
+-	pm_runtime_use_autosuspend(&pdev->dev);
+-	pm_runtime_enable(&pdev->dev);
+-
+ 	dev_info(&pdev->dev, "registered RNG driver\n");
+ 
+ 	return 0;
+@@ -185,9 +223,22 @@ static const struct dev_pm_ops mtk_rng_pm_ops = {
+ #define MTK_RNG_PM_OPS NULL
+ #endif	/* CONFIG_PM */
+ 
++static const struct mtk_rng_of_data mt7981_rng_data = {
++	.rng_version = 2,
++};
++
++static const struct mtk_rng_of_data mt7986_rng_data = {
++	.rng_version = 1,
++};
++
++static const struct mtk_rng_of_data mt7623_rng_data = {
++	.rng_version = 1,
++};
++
+ static const struct of_device_id mtk_rng_match[] = {
+-	{ .compatible = "mediatek,mt7986-rng" },
+-	{ .compatible = "mediatek,mt7623-rng" },
++	{ .compatible = "mediatek,mt7981-rng", .data = &mt7981_rng_data },
++	{ .compatible = "mediatek,mt7986-rng", .data = &mt7986_rng_data },
++	{ .compatible = "mediatek,mt7623-rng", .data = &mt7623_rng_data },
+ 	{},
+ };
+ MODULE_DEVICE_TABLE(of, mtk_rng_match);
+-- 
+2.18.0
+