From ae5611b1b7a857edb3d9c8e900b550c76f7c236e Mon Sep 17 00:00:00 2001 From: "Mingming.Su" 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 #include #include #include @@ -15,8 +16,12 @@ #include #include #include +#include #include #include +#include + +#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,13 +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); - ret = devm_pm_runtime_enable(&pdev->dev); - if (ret) - return ret; - dev_info(&pdev->dev, "registered RNG driver\n"); return 0; @@ -185,9 +221,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