cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nomadik-rng.c (2178B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Nomadik RNG support
      4 *  Copyright 2009 Alessandro Rubini
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/device.h>
     10#include <linux/amba/bus.h>
     11#include <linux/hw_random.h>
     12#include <linux/io.h>
     13#include <linux/clk.h>
     14#include <linux/err.h>
     15
     16static struct clk *rng_clk;
     17
     18static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
     19{
     20	void __iomem *base = (void __iomem *)rng->priv;
     21
     22	/*
     23	 * The register is 32 bits and gives 16 random bits (low half).
     24	 * A subsequent read will delay the core for 400ns, so we just read
     25	 * once and accept the very unlikely very small delay, even if wait==0.
     26	 */
     27	*(u16 *)data = __raw_readl(base + 8) & 0xffff;
     28	return 2;
     29}
     30
     31/* we have at most one RNG per machine, granted */
     32static struct hwrng nmk_rng = {
     33	.name		= "nomadik",
     34	.read		= nmk_rng_read,
     35};
     36
     37static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
     38{
     39	void __iomem *base;
     40	int ret;
     41
     42	rng_clk = devm_clk_get(&dev->dev, NULL);
     43	if (IS_ERR(rng_clk)) {
     44		dev_err(&dev->dev, "could not get rng clock\n");
     45		ret = PTR_ERR(rng_clk);
     46		return ret;
     47	}
     48
     49	clk_prepare_enable(rng_clk);
     50
     51	ret = amba_request_regions(dev, dev->dev.init_name);
     52	if (ret)
     53		goto out_clk;
     54	ret = -ENOMEM;
     55	base = devm_ioremap(&dev->dev, dev->res.start,
     56			    resource_size(&dev->res));
     57	if (!base)
     58		goto out_release;
     59	nmk_rng.priv = (unsigned long)base;
     60	ret = devm_hwrng_register(&dev->dev, &nmk_rng);
     61	if (ret)
     62		goto out_release;
     63	return 0;
     64
     65out_release:
     66	amba_release_regions(dev);
     67out_clk:
     68	clk_disable_unprepare(rng_clk);
     69	return ret;
     70}
     71
     72static void nmk_rng_remove(struct amba_device *dev)
     73{
     74	amba_release_regions(dev);
     75	clk_disable_unprepare(rng_clk);
     76}
     77
     78static const struct amba_id nmk_rng_ids[] = {
     79	{
     80		.id	= 0x000805e1,
     81		.mask	= 0x000fffff, /* top bits are rev and cfg: accept all */
     82	},
     83	{0, 0},
     84};
     85
     86MODULE_DEVICE_TABLE(amba, nmk_rng_ids);
     87
     88static struct amba_driver nmk_rng_driver = {
     89	.drv = {
     90		.owner = THIS_MODULE,
     91		.name = "rng",
     92		},
     93	.probe = nmk_rng_probe,
     94	.remove = nmk_rng_remove,
     95	.id_table = nmk_rng_ids,
     96};
     97
     98module_amba_driver(nmk_rng_driver);
     99
    100MODULE_LICENSE("GPL");