Skip to content

Commit

Permalink
hwrng: mtk - add runtime PM support
Browse files Browse the repository at this point in the history
Add runtime PM support.  There will be the benefit on SoCs where the
clock to the RNG used can be shutdown.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Sean Wang authored and Herbert Xu committed Jun 20, 2017
1 parent 3419491 commit 81d2b34
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions drivers/char/hw_random/mtk-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
#include <linux/module.h>
#include <linux/of.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 TIMEOUT_POLL 20
Expand Down Expand Up @@ -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);
int retval = 0;

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

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

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

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->clk = devm_clk_get(&pdev->dev, "rng");
if (IS_ERR(priv->clk)) {
Expand All @@ -142,11 +154,40 @@ 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;
}

#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[] = {
{ .compatible = "mediatek,mt7623-rng" },
{},
Expand All @@ -157,6 +198,7 @@ static struct platform_driver mtk_rng_driver = {
.probe = mtk_rng_probe,
.driver = {
.name = MTK_RNG_DEV,
.pm = MTK_RNG_PM_OPS,
.of_match_table = mtk_rng_match,
},
};
Expand Down

0 comments on commit 81d2b34

Please sign in to comment.