Commit bc85b25e5de17d714e8001cb3dc0feb66eac2750

Authored by Alessandro Rubini
Committed by Herbert Xu
1 parent 55639353a0

hwrng: nomadik - Add hardware RNG driver

The hardware random number generator by ST is used in both the Nomadik
8815 SoC and the U8500. It returns 16 bits every 400ns with automatic
delay if a read is issued too early. It depends on PLAT_NOMADIK.

Signed-off-by: Alessandro Rubini <rubini@unipv.it>
Acked-by: Andrea Gallo <andrea.gallo@stericsson.com>
Acked-by: Matt Mackall <mpm@selenic.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Showing 3 changed files with 116 additions and 0 deletions Side-by-side Diff

drivers/char/hw_random/Kconfig
... ... @@ -186,4 +186,16 @@
186 186 module will be called mxc-rnga.
187 187  
188 188 If unsure, say Y.
  189 +
  190 +config HW_RANDOM_NOMADIK
  191 + tristate "ST-Ericsson Nomadik Random Number Generator support"
  192 + depends on HW_RANDOM && PLAT_NOMADIK
  193 + ---help---
  194 + This driver provides kernel-side support for the Random Number
  195 + Generator hardware found on ST-Ericsson SoCs (8815 and 8500).
  196 +
  197 + To compile this driver as a module, choose M here: the
  198 + module will be called nomadik-rng.
  199 +
  200 + If unsure, say Y.
drivers/char/hw_random/Makefile
... ... @@ -18,4 +18,5 @@
18 18 obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
19 19 obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
20 20 obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
  21 +obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
drivers/char/hw_random/nomadik-rng.c
  1 +/*
  2 + * Nomadik RNG support
  3 + * Copyright 2009 Alessandro Rubini
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify
  6 + * it under the terms of the GNU General Public License as published by
  7 + * the Free Software Foundation; either version 2 of the License, or
  8 + * (at your option) any later version.
  9 + */
  10 +
  11 +#include <linux/kernel.h>
  12 +#include <linux/module.h>
  13 +#include <linux/init.h>
  14 +#include <linux/device.h>
  15 +#include <linux/amba/bus.h>
  16 +#include <linux/hw_random.h>
  17 +#include <linux/io.h>
  18 +
  19 +static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
  20 +{
  21 + void __iomem *base = (void __iomem *)rng->priv;
  22 +
  23 + /*
  24 + * The register is 32 bits and gives 16 random bits (low half).
  25 + * A subsequent read will delay the core for 400ns, so we just read
  26 + * once and accept the very unlikely very small delay, even if wait==0.
  27 + */
  28 + *(u16 *)data = __raw_readl(base + 8) & 0xffff;
  29 + return 2;
  30 +}
  31 +
  32 +/* we have at most one RNG per machine, granted */
  33 +static struct hwrng nmk_rng = {
  34 + .name = "nomadik",
  35 + .read = nmk_rng_read,
  36 +};
  37 +
  38 +static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id)
  39 +{
  40 + void __iomem *base;
  41 + int ret;
  42 +
  43 + ret = amba_request_regions(dev, dev->dev.init_name);
  44 + if (ret)
  45 + return ret;
  46 + ret = -ENOMEM;
  47 + base = ioremap(dev->res.start, resource_size(&dev->res));
  48 + if (!base)
  49 + goto out_release;
  50 + nmk_rng.priv = (unsigned long)base;
  51 + ret = hwrng_register(&nmk_rng);
  52 + if (ret)
  53 + goto out_unmap;
  54 + return 0;
  55 +
  56 +out_unmap:
  57 + iounmap(base);
  58 +out_release:
  59 + amba_release_regions(dev);
  60 + return ret;
  61 +}
  62 +
  63 +static int nmk_rng_remove(struct amba_device *dev)
  64 +{
  65 + void __iomem *base = (void __iomem *)nmk_rng.priv;
  66 + hwrng_unregister(&nmk_rng);
  67 + iounmap(base);
  68 + amba_release_regions(dev);
  69 + return 0;
  70 +}
  71 +
  72 +static struct amba_id nmk_rng_ids[] = {
  73 + {
  74 + .id = 0x000805e1,
  75 + .mask = 0x000fffff, /* top bits are rev and cfg: accept all */
  76 + },
  77 + {0, 0},
  78 +};
  79 +
  80 +static struct amba_driver nmk_rng_driver = {
  81 + .drv = {
  82 + .owner = THIS_MODULE,
  83 + .name = "rng",
  84 + },
  85 + .probe = nmk_rng_probe,
  86 + .remove = nmk_rng_remove,
  87 + .id_table = nmk_rng_ids,
  88 +};
  89 +
  90 +static int __init nmk_rng_init(void)
  91 +{
  92 + return amba_driver_register(&nmk_rng_driver);
  93 +}
  94 +
  95 +static void __devexit nmk_rng_exit(void)
  96 +{
  97 + amba_driver_unregister(&nmk_rng_driver);
  98 +}
  99 +
  100 +module_init(nmk_rng_init);
  101 +module_exit(nmk_rng_exit);
  102 +
  103 +MODULE_LICENSE("GPL");