Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81d2b345 authored by Sean Wang's avatar Sean Wang Committed by Herbert Xu
Browse files

hwrng: mtk - add runtime PM support



Add runtime PM support.  There will be the benefit on SoCs where the
clock to the RNG used can be shutdown.

Signed-off-by: default avatarSean Wang <sean.wang@mediatek.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 34194913
Loading
Loading
Loading
Loading
+42 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,10 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>

/* Runtime PM autosuspend timeout: */
#define RNG_AUTOSUSPEND_TIMEOUT		100


#define USEC_POLL			2
#define USEC_POLL			2
#define TIMEOUT_POLL			20
#define TIMEOUT_POLL			20
@@ -90,6 +94,8 @@ static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
	struct mtk_rng *priv = to_mtk_rng(rng);
	struct mtk_rng *priv = to_mtk_rng(rng);
	int retval = 0;
	int retval = 0;


	pm_runtime_get_sync((struct device *)priv->rng.priv);

	while (max >= sizeof(u32)) {
	while (max >= sizeof(u32)) {
		if (!mtk_rng_wait_ready(rng, wait))
		if (!mtk_rng_wait_ready(rng, wait))
			break;
			break;
@@ -100,6 +106,9 @@ static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
		max -= sizeof(u32);
		max -= sizeof(u32);
	}
	}


	pm_runtime_mark_last_busy((struct device *)priv->rng.priv);
	pm_runtime_put_sync_autosuspend((struct device *)priv->rng.priv);

	return retval || !wait ? retval : -EIO;
	return retval || !wait ? retval : -EIO;
}
}


@@ -120,9 +129,12 @@ static int mtk_rng_probe(struct platform_device *pdev)
		return -ENOMEM;
		return -ENOMEM;


	priv->rng.name = pdev->name;
	priv->rng.name = pdev->name;
#ifndef CONFIG_PM
	priv->rng.init = mtk_rng_init;
	priv->rng.init = mtk_rng_init;
	priv->rng.cleanup = mtk_rng_cleanup;
	priv->rng.cleanup = mtk_rng_cleanup;
#endif
	priv->rng.read = mtk_rng_read;
	priv->rng.read = mtk_rng_read;
	priv->rng.priv = (unsigned long)&pdev->dev;


	priv->clk = devm_clk_get(&pdev->dev, "rng");
	priv->clk = devm_clk_get(&pdev->dev, "rng");
	if (IS_ERR(priv->clk)) {
	if (IS_ERR(priv->clk)) {
@@ -142,11 +154,40 @@ static int mtk_rng_probe(struct platform_device *pdev)
		return ret;
		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");
	dev_info(&pdev->dev, "registered RNG driver\n");


	return 0;
	return 0;
}
}


#ifdef CONFIG_PM
static int mtk_rng_runtime_suspend(struct device *dev)
{
	struct mtk_rng *priv = dev_get_drvdata(dev);

	mtk_rng_cleanup(&priv->rng);

	return 0;
}

static int mtk_rng_runtime_resume(struct device *dev)
{
	struct mtk_rng *priv = dev_get_drvdata(dev);

	return mtk_rng_init(&priv->rng);
}

static UNIVERSAL_DEV_PM_OPS(mtk_rng_pm_ops, mtk_rng_runtime_suspend,
			    mtk_rng_runtime_resume, NULL);
#define MTK_RNG_PM_OPS (&mtk_rng_pm_ops)
#else	/* CONFIG_PM */
#define MTK_RNG_PM_OPS NULL
#endif	/* CONFIG_PM */

static const struct of_device_id mtk_rng_match[] = {
static const struct of_device_id mtk_rng_match[] = {
	{ .compatible = "mediatek,mt7623-rng" },
	{ .compatible = "mediatek,mt7623-rng" },
	{},
	{},
@@ -157,6 +198,7 @@ static struct platform_driver mtk_rng_driver = {
	.probe          = mtk_rng_probe,
	.probe          = mtk_rng_probe,
	.driver = {
	.driver = {
		.name = MTK_RNG_DEV,
		.name = MTK_RNG_DEV,
		.pm = MTK_RNG_PM_OPS,
		.of_match_table = mtk_rng_match,
		.of_match_table = mtk_rng_match,
	},
	},
};
};