diff options
Diffstat (limited to 'drivers/char/hw_random/iproc-rng200.c')
| -rw-r--r-- | drivers/char/hw_random/iproc-rng200.c | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/drivers/char/hw_random/iproc-rng200.c b/drivers/char/hw_random/iproc-rng200.c index 32d9fe61a225..440fe28bddc0 100644 --- a/drivers/char/hw_random/iproc-rng200.c +++ b/drivers/char/hw_random/iproc-rng200.c @@ -1,14 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2015 Broadcom Corporation * -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License as -* published by the Free Software Foundation version 2. -* -* This program is distributed "as is" WITHOUT ANY WARRANTY of any -* kind, whether express or implied; without even the implied warranty -* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. */ /* * DESCRIPTION: The Broadcom iProc RNG200 Driver @@ -19,8 +12,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/delay.h> @@ -28,7 +20,6 @@ #define RNG_CTRL_OFFSET 0x00 #define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF #define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001 -#define RNG_CTRL_RNG_RBGEN_DISABLE 0x00000000 #define RNG_SOFT_RESET_OFFSET 0x04 #define RNG_SOFT_RESET 0x00000001 @@ -54,15 +45,24 @@ struct iproc_rng200_dev { #define to_rng_priv(rng) container_of(rng, struct iproc_rng200_dev, rng) -static void iproc_rng200_restart(void __iomem *rng_base) +static void iproc_rng200_enable_set(void __iomem *rng_base, bool enable) { - uint32_t val; + u32 val; - /* Disable RBG */ val = ioread32(rng_base + RNG_CTRL_OFFSET); val &= ~RNG_CTRL_RNG_RBGEN_MASK; - val |= RNG_CTRL_RNG_RBGEN_DISABLE; + + if (enable) + val |= RNG_CTRL_RNG_RBGEN_ENABLE; + iowrite32(val, rng_base + RNG_CTRL_OFFSET); +} + +static void iproc_rng200_restart(void __iomem *rng_base) +{ + uint32_t val; + + iproc_rng200_enable_set(rng_base, false); /* Clear all interrupt status */ iowrite32(0xFFFFFFFFUL, rng_base + RNG_INT_STATUS_OFFSET); @@ -84,11 +84,7 @@ static void iproc_rng200_restart(void __iomem *rng_base) val &= ~RBG_SOFT_RESET; iowrite32(val, rng_base + RBG_SOFT_RESET_OFFSET); - /* Enable RBG */ - val = ioread32(rng_base + RNG_CTRL_OFFSET); - val &= ~RNG_CTRL_RNG_RBGEN_MASK; - val |= RNG_CTRL_RNG_RBGEN_ENABLE; - iowrite32(val, rng_base + RNG_CTRL_OFFSET); + iproc_rng200_enable_set(rng_base, true); } static int iproc_rng200_read(struct hwrng *rng, void *buf, size_t max, @@ -155,13 +151,8 @@ static int iproc_rng200_read(struct hwrng *rng, void *buf, size_t max, static int iproc_rng200_init(struct hwrng *rng) { struct iproc_rng200_dev *priv = to_rng_priv(rng); - uint32_t val; - /* Setup RNG. */ - val = ioread32(priv->base + RNG_CTRL_OFFSET); - val &= ~RNG_CTRL_RNG_RBGEN_MASK; - val |= RNG_CTRL_RNG_RBGEN_ENABLE; - iowrite32(val, priv->base + RNG_CTRL_OFFSET); + iproc_rng200_enable_set(priv->base, true); return 0; } @@ -169,13 +160,8 @@ static int iproc_rng200_init(struct hwrng *rng) static void iproc_rng200_cleanup(struct hwrng *rng) { struct iproc_rng200_dev *priv = to_rng_priv(rng); - uint32_t val; - /* Disable RNG hardware */ - val = ioread32(priv->base + RNG_CTRL_OFFSET); - val &= ~RNG_CTRL_RNG_RBGEN_MASK; - val |= RNG_CTRL_RNG_RBGEN_DISABLE; - iowrite32(val, priv->base + RNG_CTRL_OFFSET); + iproc_rng200_enable_set(priv->base, false); } static int iproc_rng200_probe(struct platform_device *pdev) @@ -195,10 +181,12 @@ static int iproc_rng200_probe(struct platform_device *pdev) return PTR_ERR(priv->base); } - priv->rng.name = "iproc-rng200", - priv->rng.read = iproc_rng200_read, - priv->rng.init = iproc_rng200_init, - priv->rng.cleanup = iproc_rng200_cleanup, + dev_set_drvdata(dev, priv); + + priv->rng.name = "iproc-rng200"; + priv->rng.read = iproc_rng200_read; + priv->rng.init = iproc_rng200_init; + priv->rng.cleanup = iproc_rng200_cleanup; /* Register driver */ ret = devm_hwrng_register(dev, &priv->rng); @@ -212,6 +200,28 @@ static int iproc_rng200_probe(struct platform_device *pdev) return 0; } +static int __maybe_unused iproc_rng200_suspend(struct device *dev) +{ + struct iproc_rng200_dev *priv = dev_get_drvdata(dev); + + iproc_rng200_cleanup(&priv->rng); + + return 0; +} + +static int __maybe_unused iproc_rng200_resume(struct device *dev) +{ + struct iproc_rng200_dev *priv = dev_get_drvdata(dev); + + iproc_rng200_init(&priv->rng); + + return 0; +} + +static const struct dev_pm_ops iproc_rng200_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(iproc_rng200_suspend, iproc_rng200_resume) +}; + static const struct of_device_id iproc_rng200_of_match[] = { { .compatible = "brcm,bcm2711-rng200", }, { .compatible = "brcm,bcm7211-rng200", }, @@ -225,6 +235,7 @@ static struct platform_driver iproc_rng200_driver = { .driver = { .name = "iproc-rng200", .of_match_table = iproc_rng200_of_match, + .pm = &iproc_rng200_pm_ops, }, .probe = iproc_rng200_probe, }; |
