blob: 7c09a7102b0f8580cf980ddde4963f8be58ca208 [file] [log] [blame]
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