summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kaiser <martin@kaiser.cx>2023-07-04 19:32:03 +0200
committerHerbert Xu <herbert@gondor.apana.org.au>2023-07-20 22:16:24 +1200
commitac0042fa5aa5ac7929d95f4bf9185429ccdb70cb (patch)
tree538386be1f5e5368bb90f5684d0b09d4e9047105
parent97c63a9dea2929fc4fd42f1d4446d97b6c011a1f (diff)
hwrng: pic32 - enable TRNG only while it's used
The probe function enables the TRNG hardware before registering the driver. If registration fails, probe returns an error, but the TRNG remains enabled. Define init and cleanup functions, enable and disable the hardware there. Signed-off-by: Martin Kaiser <martin@kaiser.cx> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/char/hw_random/pic32-rng.c41
1 files changed, 19 insertions, 22 deletions
diff --git a/drivers/char/hw_random/pic32-rng.c b/drivers/char/hw_random/pic32-rng.c
index c1b3f5915f03..1902f4389a3f 100644
--- a/drivers/char/hw_random/pic32-rng.c
+++ b/drivers/char/hw_random/pic32-rng.c
@@ -38,6 +38,15 @@ struct pic32_rng {
*/
#define RNG_TIMEOUT 500
+static int pic32_rng_init(struct hwrng *rng)
+{
+ struct pic32_rng *priv = container_of(rng, struct pic32_rng, rng);
+
+ /* enable TRNG in enhanced mode */
+ writel(TRNGEN | TRNGMOD, priv->base + RNGCON);
+ return 0;
+}
+
static int pic32_rng_read(struct hwrng *rng, void *buf, size_t max,
bool wait)
{
@@ -59,12 +68,17 @@ static int pic32_rng_read(struct hwrng *rng, void *buf, size_t max,
return -EIO;
}
+static void pic32_rng_cleanup(struct hwrng *rng)
+{
+ struct pic32_rng *priv = container_of(rng, struct pic32_rng, rng);
+
+ writel(0, priv->base + RNGCON);
+}
+
static int pic32_rng_probe(struct platform_device *pdev)
{
struct pic32_rng *priv;
struct clk *clk;
- u32 v;
- int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -78,28 +92,12 @@ static int pic32_rng_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return PTR_ERR(clk);
- /* enable TRNG in enhanced mode */
- v = TRNGEN | TRNGMOD;
- writel(v, priv->base + RNGCON);
-
priv->rng.name = pdev->name;
+ priv->rng.init = pic32_rng_init;
priv->rng.read = pic32_rng_read;
+ priv->rng.cleanup = pic32_rng_cleanup;
- ret = devm_hwrng_register(&pdev->dev, &priv->rng);
- if (ret)
- return ret;
-
- platform_set_drvdata(pdev, priv);
-
- return 0;
-}
-
-static int pic32_rng_remove(struct platform_device *pdev)
-{
- struct pic32_rng *rng = platform_get_drvdata(pdev);
-
- writel(0, rng->base + RNGCON);
- return 0;
+ return devm_hwrng_register(&pdev->dev, &priv->rng);
}
static const struct of_device_id pic32_rng_of_match[] __maybe_unused = {
@@ -110,7 +108,6 @@ MODULE_DEVICE_TABLE(of, pic32_rng_of_match);
static struct platform_driver pic32_rng_driver = {
.probe = pic32_rng_probe,
- .remove = pic32_rng_remove,
.driver = {
.name = "pic32-rng",
.of_match_table = of_match_ptr(pic32_rng_of_match),