aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/hw_random/bcm2835-rng.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 14:53:12 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 14:53:12 -0700
commit797994f81a8b2bdca2eecffa415c1e7a89a4f961 (patch)
tree1383dc469c26ad37fdf960f682d9a48c782935c5 /drivers/char/hw_random/bcm2835-rng.c
parentc8d8566952fda026966784a62f324c8352f77430 (diff)
parent3862de1f6c442d53bd828d39f86d07d933a70605 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto update from Herbert Xu: - XTS mode optimisation for twofish/cast6/camellia/aes on x86 - AVX2/x86_64 implementation for blowfish/twofish/serpent/camellia - SSSE3/AVX/AVX2 optimisations for sha256/sha512 - Added driver for SAHARA2 crypto accelerator - Fix for GMAC when used in non-IPsec secnarios - Added generic CMAC implementation (including IPsec glue) - IP update for crypto/atmel - Support for more than one device in hwrng/timeriomem - Added Broadcom BCM2835 RNG driver - Misc fixes * git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (59 commits) crypto: caam - fix job ring cleanup code crypto: camellia - add AVX2/AES-NI/x86_64 assembler implementation of camellia cipher crypto: serpent - add AVX2/x86_64 assembler implementation of serpent cipher crypto: twofish - add AVX2/x86_64 assembler implementation of twofish cipher crypto: blowfish - add AVX2/x86_64 implementation of blowfish cipher crypto: tcrypt - add async cipher speed tests for blowfish crypto: testmgr - extend camellia test-vectors for camellia-aesni/avx2 crypto: aesni_intel - fix Kconfig problem with CRYPTO_GLUE_HELPER_X86 crypto: aesni_intel - add more optimized XTS mode for x86-64 crypto: x86/camellia-aesni-avx - add more optimized XTS code crypto: cast6-avx: use new optimized XTS code crypto: x86/twofish-avx - use optimized XTS code crypto: x86 - add more optimized XTS-mode for serpent-avx xfrm: add rfc4494 AES-CMAC-96 support crypto: add CMAC support to CryptoAPI crypto: testmgr - add empty test vectors for null ciphers crypto: testmgr - add AES GMAC test vectors crypto: gcm - fix rfc4543 to handle async crypto correctly crypto: gcm - make GMAC work when dst and src are different hwrng: timeriomem - added devicetree hooks ...
Diffstat (limited to 'drivers/char/hw_random/bcm2835-rng.c')
-rw-r--r--drivers/char/hw_random/bcm2835-rng.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
new file mode 100644
index 00000000000..eb7f14725eb
--- /dev/null
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ * Copyright (c) 2013 Lubomir Rintel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License ("GPL")
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/hw_random.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define RNG_CTRL 0x0
+#define RNG_STATUS 0x4
+#define RNG_DATA 0x8
+
+/* enable rng */
+#define RNG_RBGEN 0x1
+
+/* the initial numbers generated are "less random" so will be discarded */
+#define RNG_WARMUP_COUNT 0x40000
+
+static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
+ bool wait)
+{
+ void __iomem *rng_base = (void __iomem *)rng->priv;
+
+ while ((__raw_readl(rng_base + RNG_STATUS) >> 24) == 0) {
+ if (!wait)
+ return 0;
+ cpu_relax();
+ }
+
+ *(u32 *)buf = __raw_readl(rng_base + RNG_DATA);
+ return sizeof(u32);
+}
+
+static struct hwrng bcm2835_rng_ops = {
+ .name = "bcm2835",
+ .read = bcm2835_rng_read,
+};
+
+static int bcm2835_rng_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ void __iomem *rng_base;
+ int err;
+
+ /* map peripheral */
+ rng_base = of_iomap(np, 0);
+ if (!rng_base) {
+ dev_err(dev, "failed to remap rng regs");
+ return -ENODEV;
+ }
+ bcm2835_rng_ops.priv = (unsigned long)rng_base;
+
+ /* register driver */
+ err = hwrng_register(&bcm2835_rng_ops);
+ if (err) {
+ dev_err(dev, "hwrng registration failed\n");
+ iounmap(rng_base);
+ } else {
+ dev_info(dev, "hwrng registered\n");
+
+ /* set warm-up count & enable */
+ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
+ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
+ }
+ return err;
+}
+
+static int bcm2835_rng_remove(struct platform_device *pdev)
+{
+ void __iomem *rng_base = (void __iomem *)bcm2835_rng_ops.priv;
+
+ /* disable rng hardware */
+ __raw_writel(0, rng_base + RNG_CTRL);
+
+ /* unregister driver */
+ hwrng_unregister(&bcm2835_rng_ops);
+ iounmap(rng_base);
+
+ return 0;
+}
+
+static const struct of_device_id bcm2835_rng_of_match[] = {
+ { .compatible = "brcm,bcm2835-rng", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_rng_of_match);
+
+static struct platform_driver bcm2835_rng_driver = {
+ .driver = {
+ .name = "bcm2835-rng",
+ .owner = THIS_MODULE,
+ .of_match_table = bcm2835_rng_of_match,
+ },
+ .probe = bcm2835_rng_probe,
+ .remove = bcm2835_rng_remove,
+};
+module_platform_driver(bcm2835_rng_driver);
+
+MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
+MODULE_DESCRIPTION("BCM2835 Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPLv2");