summaryrefslogtreecommitdiffstats
path: root/drivers/char/hw_random/atmel-rng.c
diff options
context:
space:
mode:
authorClaudiu Beznea <claudiu.beznea@microchip.com>2022-02-21 09:59:25 +0200
committerHerbert Xu <herbert@gondor.apana.org.au>2022-03-03 10:46:19 +1200
commit9fbd8b306fcb8d1f1294972f26a3e4d57134c4ad (patch)
treed0d4991ce97645238895cc4249f27a3f6e84e651 /drivers/char/hw_random/atmel-rng.c
parentf14b02088fb8b6633bc32b052e0d66308f191cc8 (diff)
downloadlinux-stable-9fbd8b306fcb8d1f1294972f26a3e4d57134c4ad.tar.gz
linux-stable-9fbd8b306fcb8d1f1294972f26a3e4d57134c4ad.tar.bz2
linux-stable-9fbd8b306fcb8d1f1294972f26a3e4d57134c4ad.zip
hwrng: atmel - move set of TRNG_HALFR in atmel_trng_init()
Move set of TRNG_HALFR in atmel_trng_init() as this function is also called on resume path. In case of SAMA7G5 where backup and self-refresh PM mode is available most of the SoC parts are powered of (including TRNG) when entering suspend. In that case on resuming path TRNG_HALFR should also be re-configured. Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/char/hw_random/atmel-rng.c')
-rw-r--r--drivers/char/hw_random/atmel-rng.c49
1 files changed, 25 insertions, 24 deletions
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index 17f02049c112..ef49dbe681cf 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -36,6 +36,7 @@ struct atmel_trng {
struct clk *clk;
void __iomem *base;
struct hwrng rng;
+ bool has_half_rate;
};
static bool atmel_trng_wait_ready(struct atmel_trng *trng, bool wait)
@@ -74,14 +75,32 @@ out:
return ret;
}
-static void atmel_trng_init(struct atmel_trng *trng)
+static int atmel_trng_init(struct atmel_trng *trng)
{
+ unsigned long rate;
+ int ret;
+
+ ret = clk_prepare_enable(trng->clk);
+ if (ret)
+ return ret;
+
+ if (trng->has_half_rate) {
+ rate = clk_get_rate(trng->clk);
+
+ /* if peripheral clk is above 100MHz, set HALFR */
+ if (rate > 100000000)
+ writel(TRNG_HALFR, trng->base + TRNG_MR);
+ }
+
writel(TRNG_KEY | 1, trng->base + TRNG_CR);
+
+ return 0;
}
static void atmel_trng_cleanup(struct atmel_trng *trng)
{
writel(TRNG_KEY, trng->base + TRNG_CR);
+ clk_disable_unprepare(trng->clk);
}
static int atmel_trng_probe(struct platform_device *pdev)
@@ -105,22 +124,14 @@ static int atmel_trng_probe(struct platform_device *pdev)
if (!data)
return -ENODEV;
- if (data->has_half_rate) {
- unsigned long rate = clk_get_rate(trng->clk);
-
- /* if peripheral clk is above 100MHz, set HALFR */
- if (rate > 100000000)
- writel(TRNG_HALFR, trng->base + TRNG_MR);
- }
+ trng->has_half_rate = data->has_half_rate;
+ trng->rng.name = pdev->name;
+ trng->rng.read = atmel_trng_read;
- ret = clk_prepare_enable(trng->clk);
+ ret = atmel_trng_init(trng);
if (ret)
return ret;
- atmel_trng_init(trng);
- trng->rng.name = pdev->name;
- trng->rng.read = atmel_trng_read;
-
ret = devm_hwrng_register(&pdev->dev, &trng->rng);
if (ret)
goto err_register;
@@ -130,7 +141,6 @@ static int atmel_trng_probe(struct platform_device *pdev)
return 0;
err_register:
- clk_disable_unprepare(trng->clk);
atmel_trng_cleanup(trng);
return ret;
}
@@ -141,7 +151,6 @@ static int atmel_trng_remove(struct platform_device *pdev)
atmel_trng_cleanup(trng);
- clk_disable_unprepare(trng->clk);
return 0;
}
@@ -152,7 +161,6 @@ static int atmel_trng_suspend(struct device *dev)
struct atmel_trng *trng = dev_get_drvdata(dev);
atmel_trng_cleanup(trng);
- clk_disable_unprepare(trng->clk);
return 0;
}
@@ -160,15 +168,8 @@ static int atmel_trng_suspend(struct device *dev)
static int atmel_trng_resume(struct device *dev)
{
struct atmel_trng *trng = dev_get_drvdata(dev);
- int ret;
- ret = clk_prepare_enable(trng->clk);
- if (ret)
- return ret;
-
- atmel_trng_init(trng);
-
- return 0;
+ return atmel_trng_init(trng);
}
static const struct dev_pm_ops atmel_trng_pm_ops = {