3fd269e74f
All amba drivers return 0 in their remove callback. Together with the driver core ignoring the return value anyhow, it doesn't make sense to return a value here. Change the remove prototype to return void, which makes it explicit that returning an error value doesn't work as expected. This simplifies changing the core remove callback to return void, too. Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Acked-by: Krzysztof Kozlowski <krzk@kernel.org> # for drivers/memory Acked-by: Mark Brown <broonie@kernel.org> Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Suzuki K Poulose <suzuki.poulose@arm.com> # for hwtracing/coresight Acked-By: Vinod Koul <vkoul@kernel.org> # for dmaengine Acked-by: Guenter Roeck <linux@roeck-us.net> # for watchdog Acked-by: Wolfram Sang <wsa@kernel.org> # for I2C Acked-by: Takashi Iwai <tiwai@suse.de> # for sound Acked-by: Vladimir Zapolskiy <vz@mleia.com> # for memory/pl172 Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Link: https://lore.kernel.org/r/20210126165835.687514-5-u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
101 lines
2.1 KiB
C
101 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Nomadik RNG support
|
|
* Copyright 2009 Alessandro Rubini
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/device.h>
|
|
#include <linux/amba/bus.h>
|
|
#include <linux/hw_random.h>
|
|
#include <linux/io.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/err.h>
|
|
|
|
static struct clk *rng_clk;
|
|
|
|
static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
|
|
{
|
|
void __iomem *base = (void __iomem *)rng->priv;
|
|
|
|
/*
|
|
* The register is 32 bits and gives 16 random bits (low half).
|
|
* A subsequent read will delay the core for 400ns, so we just read
|
|
* once and accept the very unlikely very small delay, even if wait==0.
|
|
*/
|
|
*(u16 *)data = __raw_readl(base + 8) & 0xffff;
|
|
return 2;
|
|
}
|
|
|
|
/* we have at most one RNG per machine, granted */
|
|
static struct hwrng nmk_rng = {
|
|
.name = "nomadik",
|
|
.read = nmk_rng_read,
|
|
};
|
|
|
|
static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
|
|
{
|
|
void __iomem *base;
|
|
int ret;
|
|
|
|
rng_clk = devm_clk_get(&dev->dev, NULL);
|
|
if (IS_ERR(rng_clk)) {
|
|
dev_err(&dev->dev, "could not get rng clock\n");
|
|
ret = PTR_ERR(rng_clk);
|
|
return ret;
|
|
}
|
|
|
|
clk_prepare_enable(rng_clk);
|
|
|
|
ret = amba_request_regions(dev, dev->dev.init_name);
|
|
if (ret)
|
|
goto out_clk;
|
|
ret = -ENOMEM;
|
|
base = devm_ioremap(&dev->dev, dev->res.start,
|
|
resource_size(&dev->res));
|
|
if (!base)
|
|
goto out_release;
|
|
nmk_rng.priv = (unsigned long)base;
|
|
ret = devm_hwrng_register(&dev->dev, &nmk_rng);
|
|
if (ret)
|
|
goto out_release;
|
|
return 0;
|
|
|
|
out_release:
|
|
amba_release_regions(dev);
|
|
out_clk:
|
|
clk_disable(rng_clk);
|
|
return ret;
|
|
}
|
|
|
|
static void nmk_rng_remove(struct amba_device *dev)
|
|
{
|
|
amba_release_regions(dev);
|
|
clk_disable(rng_clk);
|
|
}
|
|
|
|
static const struct amba_id nmk_rng_ids[] = {
|
|
{
|
|
.id = 0x000805e1,
|
|
.mask = 0x000fffff, /* top bits are rev and cfg: accept all */
|
|
},
|
|
{0, 0},
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(amba, nmk_rng_ids);
|
|
|
|
static struct amba_driver nmk_rng_driver = {
|
|
.drv = {
|
|
.owner = THIS_MODULE,
|
|
.name = "rng",
|
|
},
|
|
.probe = nmk_rng_probe,
|
|
.remove = nmk_rng_remove,
|
|
.id_table = nmk_rng_ids,
|
|
};
|
|
|
|
module_amba_driver(nmk_rng_driver);
|
|
|
|
MODULE_LICENSE("GPL");
|