[][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
+