--- /dev/null
+From f9c0c36eefaa8c6ee224634bf9c0b8b4ed87b43a Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+Date: Thu, 10 Apr 2025 18:22:38 +0300
+Subject: [PATCH] hwrng: mtk - Add struct device pointer to device context struct
+
+Add a struct device pointer field to the device's context struct. This
+makes using the unsigned long priv pointer in struct hwrng unnecessary, so
+remove that one as well.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/char/hw_random/mtk-rng.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/char/hw_random/mtk-rng.c
++++ b/drivers/char/hw_random/mtk-rng.c
+@@ -36,6 +36,7 @@ struct mtk_rng {
+ void __iomem *base;
+ struct clk *clk;
+ struct hwrng rng;
++ struct device *dev;
+ };
+
+ static int mtk_rng_init(struct hwrng *rng)
+@@ -85,7 +86,7 @@ static int mtk_rng_read(struct hwrng *rn
+ struct mtk_rng *priv = to_mtk_rng(rng);
+ int retval = 0;
+
+- pm_runtime_get_sync((struct device *)priv->rng.priv);
++ pm_runtime_get_sync(priv->dev);
+
+ while (max >= sizeof(u32)) {
+ if (!mtk_rng_wait_ready(rng, wait))
+@@ -97,8 +98,8 @@ static int mtk_rng_read(struct hwrng *rn
+ max -= sizeof(u32);
+ }
+
+- pm_runtime_mark_last_busy((struct device *)priv->rng.priv);
+- pm_runtime_put_sync_autosuspend((struct device *)priv->rng.priv);
++ pm_runtime_mark_last_busy(priv->dev);
++ pm_runtime_put_sync_autosuspend(priv->dev);
+
+ return retval || !wait ? retval : -EIO;
+ }
+@@ -112,13 +113,13 @@ static int mtk_rng_probe(struct platform
+ if (!priv)
+ return -ENOMEM;
+
++ priv->dev = &pdev->dev;
+ priv->rng.name = pdev->name;
+ #ifndef CONFIG_PM
+ priv->rng.init = mtk_rng_init;
+ priv->rng.cleanup = mtk_rng_cleanup;
+ #endif
+ priv->rng.read = mtk_rng_read;
+- priv->rng.priv = (unsigned long)&pdev->dev;
+ priv->rng.quality = 900;
+
+ priv->clk = devm_clk_get(&pdev->dev, "rng");
+++ /dev/null
-From 9837930d6738e9fdc323ad887ace7c236a61d70c Mon Sep 17 00:00:00 2001
-From: Daniel Golle <daniel@makrotopia.org>
-Date: Wed, 25 Jan 2023 00:27:49 +0000
-Subject: [PATCH] hwrng: add driver for MediaTek TRNG SMC
-
-Add driver providing kernel-side support for the Random Number
-Generator hardware found on Mediatek SoCs which have a driver in ARM
-TrustedFirmware-A allowing Linux to read random numbers using a
-non-standard vendor-defined Secure Monitor Call.
-
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
- drivers/char/hw_random/Kconfig | 16 +++++++
- drivers/char/hw_random/Makefile | 1 +
- drivers/char/hw_random/mtk-rng-v2.c | 74 +++++++++++++++++++++++++++++
- 3 files changed, 91 insertions(+)
- create mode 100644 drivers/char/hw_random/mtk-rng-v2.c
-
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -452,6 +452,23 @@ config HW_RANDOM_MTK
-
- If unsure, say Y.
-
-+config HW_RANDOM_MTK_V2
-+ tristate "Mediatek Random Number Generator support (v2/SMC)"
-+ depends on HAVE_ARM_SMCCC
-+ depends on HW_RANDOM
-+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
-+ default y
-+ help
-+ This driver provides kernel-side support for the Random Number
-+ Generator hardware found on Mediatek SoCs which have a driver
-+ in ARM TrustedFirmware-A allowing Linux to read using a non-
-+ standard vendor-defined Secure Monitor Call.
-+
-+ To compile this driver as a module, choose M here. the
-+ module will be called mtk-rng-v2.
-+
-+ If unsure, say Y.
-+
- config HW_RANDOM_S390
- tristate "S390 True Random Number Generator support"
- depends on S390
---- a/drivers/char/hw_random/Makefile
-+++ b/drivers/char/hw_random/Makefile
-@@ -39,6 +39,7 @@ obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-r
- obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
- obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
- obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
-+obj-$(CONFIG_HW_RANDOM_MTK_V2) += mtk-rng-v2.o
- obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o
- obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o
- obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o
---- /dev/null
-+++ b/drivers/char/hw_random/mtk-rng-v2.c
-@@ -0,0 +1,76 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Driver for Mediatek Hardware Random Number Generator (v2/SMCC)
-+ *
-+ * Copyright (C) 2023 Daniel Golle <daniel@makrotopia.org>
-+ * based on patch from Mingming Su <Mingming.Su@mediatek.com>
-+ */
-+#define MTK_RNG_DEV KBUILD_MODNAME
-+
-+#include <linux/arm-smccc.h>
-+#include <linux/err.h>
-+#include <linux/hw_random.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/soc/mediatek/mtk_sip_svc.h>
-+
-+#define MTK_SIP_KERNEL_GET_RND MTK_SIP_SMC_CMD(0x550)
-+
-+static int mtk_rng_v2_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_v2_probe(struct platform_device *pdev)
-+{
-+ struct hwrng *trng;
-+
-+ trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
-+ if (!trng)
-+ return -ENOMEM;
-+
-+ trng->name = pdev->name;
-+ trng->read = mtk_rng_v2_read;
-+ trng->quality = 900;
-+
-+ return devm_hwrng_register(&pdev->dev, trng);
-+}
-+
-+static const struct of_device_id mtk_rng_v2_match[] = {
-+ { .compatible = "mediatek,mt7981-rng" },
-+ { .compatible = "mediatek,mt7987-rng" },
-+ { .compatible = "mediatek,mt7988-rng" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, mtk_rng_v2_match);
-+
-+static struct platform_driver mtk_rng_v2_driver = {
-+ .probe = mtk_rng_v2_probe,
-+ .driver = {
-+ .name = KBUILD_MODNAME,
-+ .of_match_table = mtk_rng_v2_match,
-+ },
-+};
-+module_platform_driver(mtk_rng_v2_driver);
-+
-+MODULE_DESCRIPTION("Mediatek Random Number Generator Driver (v2/SMC)");
-+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
-+MODULE_LICENSE("GPL");
--- /dev/null
+From d211e2184d820207d14f5e8f84938c639875bf0d Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Tue, 3 Mar 2026 23:45:46 +0000
+Subject: [PATCH] hwrng: mtk - add support for hw access via SMCC
+
+Newer versions of ARM TrustedFirmware-A on MediaTek's ARMv8 SoCs no longer
+allow accessing the TRNG from outside of the trusted firmware.
+Instead, a vendor-defined custom Secure Monitor Call can be used to
+acquire random bytes.
+Add support for newer SoCs (MT7981, MT7987, MT7988). On MT7986 the best bet
+is to test if firmware blocks direct access to the hwrng and if so, expect
+the SMCC interface to be usable.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ drivers/char/hw_random/mtk-rng.c | 128 ++++++++++++++++++++++++++-----
+ 1 file changed, 107 insertions(+), 21 deletions(-)
+
+--- a/drivers/char/hw_random/mtk-rng.c
++++ b/drivers/char/hw_random/mtk-rng.c
+@@ -3,6 +3,7 @@
+ * Driver for Mediatek Hardware Random Number Generator
+ *
+ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
++ * Copyright (C) 2026 Daniel Golle <daniel@makrotopia.org>
+ */
+ #define MTK_RNG_DEV KBUILD_MODNAME
+
+@@ -17,6 +18,8 @@
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/arm-smccc.h>
++#include <linux/soc/mediatek/mtk_sip_svc.h>
+
+ /* Runtime PM autosuspend timeout: */
+ #define RNG_AUTOSUSPEND_TIMEOUT 100
+@@ -30,6 +33,11 @@
+
+ #define RNG_DATA 0x08
+
++/* Driver feature flags */
++#define MTK_RNG_SMC BIT(0)
++
++#define MTK_SIP_KERNEL_GET_RND MTK_SIP_SMC_CMD(0x550)
++
+ #define to_mtk_rng(p) container_of(p, struct mtk_rng, rng)
+
+ struct mtk_rng {
+@@ -37,6 +45,7 @@ struct mtk_rng {
+ struct clk *clk;
+ struct hwrng rng;
+ struct device *dev;
++ unsigned long flags;
+ };
+
+ static int mtk_rng_init(struct hwrng *rng)
+@@ -104,6 +113,56 @@ static int mtk_rng_read(struct hwrng *rn
+ return retval || !wait ? retval : -EIO;
+ }
+
++static int mtk_rng_read_smc(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 bool mtk_rng_hw_accessible(struct mtk_rng *priv)
++{
++ u32 val;
++ int err;
++
++ err = clk_prepare_enable(priv->clk);
++ if (err)
++ return false;
++
++ val = readl(priv->base + RNG_CTRL);
++ val |= RNG_EN;
++ writel(val, priv->base + RNG_CTRL);
++
++ val = readl(priv->base + RNG_CTRL);
++
++ if (val & RNG_EN) {
++ /* HW is accessible, clean up: disable RNG and clock */
++ writel(val & ~RNG_EN, priv->base + RNG_CTRL);
++ clk_disable_unprepare(priv->clk);
++ return true;
++ }
++
++ /*
++ * If TF-A blocks direct access, the register reads back as 0.
++ * Leave the clock enabled as TF-A's SMC handler needs it.
++ */
++ return false;
++}
++
+ static int mtk_rng_probe(struct platform_device *pdev)
+ {
+ int ret;
+@@ -115,23 +174,42 @@ static int mtk_rng_probe(struct platform
+
+ priv->dev = &pdev->dev;
+ priv->rng.name = pdev->name;
+-#ifndef CONFIG_PM
+- priv->rng.init = mtk_rng_init;
+- priv->rng.cleanup = mtk_rng_cleanup;
+-#endif
+- priv->rng.read = mtk_rng_read;
+ priv->rng.quality = 900;
++ priv->flags = (unsigned long)device_get_match_data(&pdev->dev);
+
+- 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;
++ if (!(priv->flags & MTK_RNG_SMC)) {
++ 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_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(priv->base))
++ return PTR_ERR(priv->base);
++
++ if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) &&
++ of_device_is_compatible(pdev->dev.of_node,
++ "mediatek,mt7986-rng") &&
++ !mtk_rng_hw_accessible(priv)) {
++ priv->flags |= MTK_RNG_SMC;
++ dev_info(&pdev->dev,
++ "HW RNG not MMIO accessible, using SMC\n");
++ }
+ }
+
+- priv->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(priv->base))
+- return PTR_ERR(priv->base);
++ if (priv->flags & MTK_RNG_SMC) {
++ if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC))
++ return -ENODEV;
++ priv->rng.read = mtk_rng_read_smc;
++ } else {
++#ifndef CONFIG_PM
++ priv->rng.init = mtk_rng_init;
++ priv->rng.cleanup = mtk_rng_cleanup;
++#endif
++ priv->rng.read = mtk_rng_read;
++ }
+
+ ret = devm_hwrng_register(&pdev->dev, &priv->rng);
+ if (ret) {
+@@ -140,12 +218,15 @@ static int mtk_rng_probe(struct platform
+ return ret;
+ }
+
+- dev_set_drvdata(&pdev->dev, priv);
+- pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT);
+- pm_runtime_use_autosuspend(&pdev->dev);
+- ret = devm_pm_runtime_enable(&pdev->dev);
+- if (ret)
+- return ret;
++ if (!(priv->flags & MTK_RNG_SMC)) {
++ dev_set_drvdata(&pdev->dev, priv);
++ pm_runtime_set_autosuspend_delay(&pdev->dev,
++ RNG_AUTOSUSPEND_TIMEOUT);
++ pm_runtime_use_autosuspend(&pdev->dev);
++ ret = devm_pm_runtime_enable(&pdev->dev);
++ if (ret)
++ return ret;
++ }
+
+ dev_info(&pdev->dev, "registered RNG driver\n");
+
+@@ -182,8 +263,12 @@ static const struct dev_pm_ops mtk_rng_p
+ #endif /* CONFIG_PM */
+
+ static const struct of_device_id mtk_rng_match[] = {
+- { .compatible = "mediatek,mt7986-rng" },
+ { .compatible = "mediatek,mt7623-rng" },
++ { .compatible = "mediatek,mt7622-rng" },
++ { .compatible = "mediatek,mt7981-rng", .data = (void *)MTK_RNG_SMC },
++ { .compatible = "mediatek,mt7986-rng" },
++ { .compatible = "mediatek,mt7987-rng", .data = (void *)MTK_RNG_SMC },
++ { .compatible = "mediatek,mt7988-rng", .data = (void *)MTK_RNG_SMC },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, mtk_rng_match);
+@@ -201,4 +286,5 @@ module_platform_driver(mtk_rng_driver);
+
+ MODULE_DESCRIPTION("Mediatek Random Number Generator Driver");
+ MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
++MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+ MODULE_LICENSE("GPL");