aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hw_random
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-15 13:42:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-15 13:42:15 -0400
commitcb906953d2c3fd450655d9fa833f03690ad50c23 (patch)
tree06c5665afb24baee3ac49f62db61ca97918079b4 /drivers/char/hw_random
parent6c373ca89399c5a3f7ef210ad8f63dc3437da345 (diff)
parent3abafaf2192b1712079edfd4232b19877d6f41a5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto update from Herbert Xu: "Here is the crypto update for 4.1: New interfaces: - user-space interface for AEAD - user-space interface for RNG (i.e., pseudo RNG) New hashes: - ARMv8 SHA1/256 - ARMv8 AES - ARMv8 GHASH - ARM assembler and NEON SHA256 - MIPS OCTEON SHA1/256/512 - MIPS img-hash SHA1/256 and MD5 - Power 8 VMX AES/CBC/CTR/GHASH - PPC assembler AES, SHA1/256 and MD5 - Broadcom IPROC RNG driver Cleanups/fixes: - prevent internal helper algos from being exposed to user-space - merge common code from assembly/C SHA implementations - misc fixes" * git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (169 commits) crypto: arm - workaround for building with old binutils crypto: arm/sha256 - avoid sha256 code on ARMv7-M crypto: x86/sha512_ssse3 - move SHA-384/512 SSSE3 implementation to base layer crypto: x86/sha256_ssse3 - move SHA-224/256 SSSE3 implementation to base layer crypto: x86/sha1_ssse3 - move SHA-1 SSSE3 implementation to base layer crypto: arm64/sha2-ce - move SHA-224/256 ARMv8 implementation to base layer crypto: arm64/sha1-ce - move SHA-1 ARMv8 implementation to base layer crypto: arm/sha2-ce - move SHA-224/256 ARMv8 implementation to base layer crypto: arm/sha256 - move SHA-224/256 ASM/NEON implementation to base layer crypto: arm/sha1-ce - move SHA-1 ARMv8 implementation to base layer crypto: arm/sha1_neon - move SHA-1 NEON implementation to base layer crypto: arm/sha1 - move SHA-1 ARM asm implementation to base layer crypto: sha512-generic - move to generic glue implementation crypto: sha256-generic - move to generic glue implementation crypto: sha1-generic - move to generic glue implementation crypto: sha512 - implement base layer for SHA-512 crypto: sha256 - implement base layer for SHA-256 crypto: sha1 - implement base layer for SHA-1 crypto: api - remove instance when test failed crypto: api - Move alg ref count init to crypto_check_alg ...
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r--drivers/char/hw_random/Kconfig13
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/bcm63xx-rng.c120
-rw-r--r--drivers/char/hw_random/core.c45
-rw-r--r--drivers/char/hw_random/exynos-rng.c12
-rw-r--r--drivers/char/hw_random/iproc-rng200.c239
-rw-r--r--drivers/char/hw_random/msm-rng.c11
-rw-r--r--drivers/char/hw_random/octeon-rng.c4
-rw-r--r--drivers/char/hw_random/omap-rng.c23
-rw-r--r--drivers/char/hw_random/pseries-rng.c4
-rw-r--r--drivers/char/hw_random/xgene-rng.c10
11 files changed, 367 insertions, 115 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index de57b38809c7..f48cf11c655e 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -101,6 +101,19 @@ config HW_RANDOM_BCM2835
101 101
102 If unsure, say Y. 102 If unsure, say Y.
103 103
104config HW_RANDOM_IPROC_RNG200
105 tristate "Broadcom iProc RNG200 support"
106 depends on ARCH_BCM_IPROC
107 default HW_RANDOM
108 ---help---
109 This driver provides kernel-side support for the RNG200
110 hardware found on the Broadcom iProc SoCs.
111
112 To compile this driver as a module, choose M here: the
113 module will be called iproc-rng200
114
115 If unsure, say Y.
116
104config HW_RANDOM_GEODE 117config HW_RANDOM_GEODE
105 tristate "AMD Geode HW Random Number Generator support" 118 tristate "AMD Geode HW Random Number Generator support"
106 depends on X86_32 && PCI 119 depends on X86_32 && PCI
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 0b4cd57f4e24..055bb01510ad 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -28,5 +28,6 @@ obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
28obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o 28obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
29obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o 29obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
30obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o 30obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
31obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
31obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o 32obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o
32obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o 33obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c
index ba6a65ac023b..d1494ecd9e11 100644
--- a/drivers/char/hw_random/bcm63xx-rng.c
+++ b/drivers/char/hw_random/bcm63xx-rng.c
@@ -13,24 +13,37 @@
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/hw_random.h> 14#include <linux/hw_random.h>
15 15
16#include <bcm63xx_io.h> 16#define RNG_CTRL 0x00
17#include <bcm63xx_regs.h> 17#define RNG_EN (1 << 0)
18
19#define RNG_STAT 0x04
20#define RNG_AVAIL_MASK (0xff000000)
21
22#define RNG_DATA 0x08
23#define RNG_THRES 0x0c
24#define RNG_MASK 0x10
18 25
19struct bcm63xx_rng_priv { 26struct bcm63xx_rng_priv {
27 struct hwrng rng;
20 struct clk *clk; 28 struct clk *clk;
21 void __iomem *regs; 29 void __iomem *regs;
22}; 30};
23 31
24#define to_rng_priv(rng) ((struct bcm63xx_rng_priv *)rng->priv) 32#define to_rng_priv(rng) container_of(rng, struct bcm63xx_rng_priv, rng)
25 33
26static int bcm63xx_rng_init(struct hwrng *rng) 34static int bcm63xx_rng_init(struct hwrng *rng)
27{ 35{
28 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 36 struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
29 u32 val; 37 u32 val;
38 int error;
39
40 error = clk_prepare_enable(priv->clk);
41 if (error)
42 return error;
30 43
31 val = bcm_readl(priv->regs + RNG_CTRL); 44 val = __raw_readl(priv->regs + RNG_CTRL);
32 val |= RNG_EN; 45 val |= RNG_EN;
33 bcm_writel(val, priv->regs + RNG_CTRL); 46 __raw_writel(val, priv->regs + RNG_CTRL);
34 47
35 return 0; 48 return 0;
36} 49}
@@ -40,23 +53,25 @@ static void bcm63xx_rng_cleanup(struct hwrng *rng)
40 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 53 struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
41 u32 val; 54 u32 val;
42 55
43 val = bcm_readl(priv->regs + RNG_CTRL); 56 val = __raw_readl(priv->regs + RNG_CTRL);
44 val &= ~RNG_EN; 57 val &= ~RNG_EN;
45 bcm_writel(val, priv->regs + RNG_CTRL); 58 __raw_writel(val, priv->regs + RNG_CTRL);
59
60 clk_didsable_unprepare(prov->clk);
46} 61}
47 62
48static int bcm63xx_rng_data_present(struct hwrng *rng, int wait) 63static int bcm63xx_rng_data_present(struct hwrng *rng, int wait)
49{ 64{
50 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 65 struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
51 66
52 return bcm_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK; 67 return __raw_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK;
53} 68}
54 69
55static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) 70static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data)
56{ 71{
57 struct bcm63xx_rng_priv *priv = to_rng_priv(rng); 72 struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
58 73
59 *data = bcm_readl(priv->regs + RNG_DATA); 74 *data = __raw_readl(priv->regs + RNG_DATA);
60 75
61 return 4; 76 return 4;
62} 77}
@@ -72,94 +87,53 @@ static int bcm63xx_rng_probe(struct platform_device *pdev)
72 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 87 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
73 if (!r) { 88 if (!r) {
74 dev_err(&pdev->dev, "no iomem resource\n"); 89 dev_err(&pdev->dev, "no iomem resource\n");
75 ret = -ENXIO; 90 return -ENXIO;
76 goto out;
77 } 91 }
78 92
79 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 93 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
80 if (!priv) { 94 if (!priv)
81 dev_err(&pdev->dev, "no memory for private structure\n"); 95 return -ENOMEM;
82 ret = -ENOMEM; 96
83 goto out; 97 priv->rng.name = pdev->name;
98 priv->rng.init = bcm63xx_rng_init;
99 priv->rng.cleanup = bcm63xx_rng_cleanup;
100 prov->rng.data_present = bcm63xx_rng_data_present;
101 priv->rng.data_read = bcm63xx_rng_data_read;
102
103 priv->clk = devm_clk_get(&pdev->dev, "ipsec");
104 if (IS_ERR(priv->clk)) {
105 error = PTR_ERR(priv->clk);
106 dev_err(&pdev->dev, "no clock for device: %d\n", error);
107 return error;
84 } 108 }
85 109
86 rng = kzalloc(sizeof(*rng), GFP_KERNEL);
87 if (!rng) {
88 dev_err(&pdev->dev, "no memory for rng structure\n");
89 ret = -ENOMEM;
90 goto out_free_priv;
91 }
92
93 platform_set_drvdata(pdev, rng);
94 rng->priv = (unsigned long)priv;
95 rng->name = pdev->name;
96 rng->init = bcm63xx_rng_init;
97 rng->cleanup = bcm63xx_rng_cleanup;
98 rng->data_present = bcm63xx_rng_data_present;
99 rng->data_read = bcm63xx_rng_data_read;
100
101 clk = clk_get(&pdev->dev, "ipsec");
102 if (IS_ERR(clk)) {
103 dev_err(&pdev->dev, "no clock for device\n");
104 ret = PTR_ERR(clk);
105 goto out_free_rng;
106 }
107
108 priv->clk = clk;
109
110 if (!devm_request_mem_region(&pdev->dev, r->start, 110 if (!devm_request_mem_region(&pdev->dev, r->start,
111 resource_size(r), pdev->name)) { 111 resource_size(r), pdev->name)) {
112 dev_err(&pdev->dev, "request mem failed"); 112 dev_err(&pdev->dev, "request mem failed");
113 ret = -ENOMEM; 113 return -EBUSY;
114 goto out_free_rng;
115 } 114 }
116 115
117 priv->regs = devm_ioremap_nocache(&pdev->dev, r->start, 116 priv->regs = devm_ioremap_nocache(&pdev->dev, r->start,
118 resource_size(r)); 117 resource_size(r));
119 if (!priv->regs) { 118 if (!priv->regs) {
120 dev_err(&pdev->dev, "ioremap failed"); 119 dev_err(&pdev->dev, "ioremap failed");
121 ret = -ENOMEM; 120 return -ENOMEM;
122 goto out_free_rng;
123 } 121 }
124 122
125 clk_enable(clk); 123 error = devm_hwrng_register(&pdev->dev, &priv->rng);
126 124 if (error) {
127 ret = hwrng_register(rng); 125 dev_err(&pdev->dev, "failed to register rng device: %d\n",
128 if (ret) { 126 error);
129 dev_err(&pdev->dev, "failed to register rng device\n"); 127 return error;
130 goto out_clk_disable;
131 } 128 }
132 129
133 dev_info(&pdev->dev, "registered RNG driver\n"); 130 dev_info(&pdev->dev, "registered RNG driver\n");
134 131
135 return 0; 132 return 0;
136
137out_clk_disable:
138 clk_disable(clk);
139out_free_rng:
140 kfree(rng);
141out_free_priv:
142 kfree(priv);
143out:
144 return ret;
145}
146
147static int bcm63xx_rng_remove(struct platform_device *pdev)
148{
149 struct hwrng *rng = platform_get_drvdata(pdev);
150 struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
151
152 hwrng_unregister(rng);
153 clk_disable(priv->clk);
154 kfree(priv);
155 kfree(rng);
156
157 return 0;
158} 133}
159 134
160static struct platform_driver bcm63xx_rng_driver = { 135static struct platform_driver bcm63xx_rng_driver = {
161 .probe = bcm63xx_rng_probe, 136 .probe = bcm63xx_rng_probe,
162 .remove = bcm63xx_rng_remove,
163 .driver = { 137 .driver = {
164 .name = "bcm63xx-rng", 138 .name = "bcm63xx-rng",
165 }, 139 },
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 32a8a867f7f8..571ef61f8ea9 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -179,7 +179,8 @@ skip_init:
179 add_early_randomness(rng); 179 add_early_randomness(rng);
180 180
181 current_quality = rng->quality ? : default_quality; 181 current_quality = rng->quality ? : default_quality;
182 current_quality &= 1023; 182 if (current_quality > 1024)
183 current_quality = 1024;
183 184
184 if (current_quality == 0 && hwrng_fill) 185 if (current_quality == 0 && hwrng_fill)
185 kthread_stop(hwrng_fill); 186 kthread_stop(hwrng_fill);
@@ -536,6 +537,48 @@ void hwrng_unregister(struct hwrng *rng)
536} 537}
537EXPORT_SYMBOL_GPL(hwrng_unregister); 538EXPORT_SYMBOL_GPL(hwrng_unregister);
538 539
540static void devm_hwrng_release(struct device *dev, void *res)
541{
542 hwrng_unregister(*(struct hwrng **)res);
543}
544
545static int devm_hwrng_match(struct device *dev, void *res, void *data)
546{
547 struct hwrng **r = res;
548
549 if (WARN_ON(!r || !*r))
550 return 0;
551
552 return *r == data;
553}
554
555int devm_hwrng_register(struct device *dev, struct hwrng *rng)
556{
557 struct hwrng **ptr;
558 int error;
559
560 ptr = devres_alloc(devm_hwrng_release, sizeof(*ptr), GFP_KERNEL);
561 if (!ptr)
562 return -ENOMEM;
563
564 error = hwrng_register(rng);
565 if (error) {
566 devres_free(ptr);
567 return error;
568 }
569
570 *ptr = rng;
571 devres_add(dev, ptr);
572 return 0;
573}
574EXPORT_SYMBOL_GPL(devm_hwrng_register);
575
576void devm_hwrng_unregister(struct device *dev, struct hwrng *rng)
577{
578 devres_release(dev, devm_hwrng_release, devm_hwrng_match, rng);
579}
580EXPORT_SYMBOL_GPL(devm_hwrng_unregister);
581
539static int __init hwrng_modinit(void) 582static int __init hwrng_modinit(void)
540{ 583{
541 return register_miscdev(); 584 return register_miscdev();
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index fed0830bf724..dc4701fd814f 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -131,16 +131,7 @@ static int exynos_rng_probe(struct platform_device *pdev)
131 pm_runtime_use_autosuspend(&pdev->dev); 131 pm_runtime_use_autosuspend(&pdev->dev);
132 pm_runtime_enable(&pdev->dev); 132 pm_runtime_enable(&pdev->dev);
133 133
134 return hwrng_register(&exynos_rng->rng); 134 return devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
135}
136
137static int exynos_rng_remove(struct platform_device *pdev)
138{
139 struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
140
141 hwrng_unregister(&exynos_rng->rng);
142
143 return 0;
144} 135}
145 136
146#ifdef CONFIG_PM 137#ifdef CONFIG_PM
@@ -172,7 +163,6 @@ static struct platform_driver exynos_rng_driver = {
172 .pm = &exynos_rng_pm_ops, 163 .pm = &exynos_rng_pm_ops,
173 }, 164 },
174 .probe = exynos_rng_probe, 165 .probe = exynos_rng_probe,
175 .remove = exynos_rng_remove,
176}; 166};
177 167
178module_platform_driver(exynos_rng_driver); 168module_platform_driver(exynos_rng_driver);
diff --git a/drivers/char/hw_random/iproc-rng200.c b/drivers/char/hw_random/iproc-rng200.c
new file mode 100644
index 000000000000..3eaf7cb96d36
--- /dev/null
+++ b/drivers/char/hw_random/iproc-rng200.c
@@ -0,0 +1,239 @@
1/*
2* Copyright (C) 2015 Broadcom Corporation
3*
4* This program is free software; you can redistribute it and/or
5* modify it under the terms of the GNU General Public License as
6* published by the Free Software Foundation version 2.
7*
8* This program is distributed "as is" WITHOUT ANY WARRANTY of any
9* kind, whether express or implied; without even the implied warranty
10* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*/
13/*
14 * DESCRIPTION: The Broadcom iProc RNG200 Driver
15 */
16
17#include <linux/hw_random.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/of_address.h>
23#include <linux/of_platform.h>
24#include <linux/platform_device.h>
25#include <linux/delay.h>
26
27/* Registers */
28#define RNG_CTRL_OFFSET 0x00
29#define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF
30#define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001
31#define RNG_CTRL_RNG_RBGEN_DISABLE 0x00000000
32
33#define RNG_SOFT_RESET_OFFSET 0x04
34#define RNG_SOFT_RESET 0x00000001
35
36#define RBG_SOFT_RESET_OFFSET 0x08
37#define RBG_SOFT_RESET 0x00000001
38
39#define RNG_INT_STATUS_OFFSET 0x18
40#define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK 0x80000000
41#define RNG_INT_STATUS_STARTUP_TRANSITIONS_MET_IRQ_MASK 0x00020000
42#define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK 0x00000020
43#define RNG_INT_STATUS_TOTAL_BITS_COUNT_IRQ_MASK 0x00000001
44
45#define RNG_FIFO_DATA_OFFSET 0x20
46
47#define RNG_FIFO_COUNT_OFFSET 0x24
48#define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK 0x000000FF
49
50struct iproc_rng200_dev {
51 struct hwrng rng;
52 void __iomem *base;
53};
54
55#define to_rng_priv(rng) container_of(rng, struct iproc_rng200_dev, rng)
56
57static void iproc_rng200_restart(void __iomem *rng_base)
58{
59 uint32_t val;
60
61 /* Disable RBG */
62 val = ioread32(rng_base + RNG_CTRL_OFFSET);
63 val &= ~RNG_CTRL_RNG_RBGEN_MASK;
64 val |= RNG_CTRL_RNG_RBGEN_DISABLE;
65 iowrite32(val, rng_base + RNG_CTRL_OFFSET);
66
67 /* Clear all interrupt status */
68 iowrite32(0xFFFFFFFFUL, rng_base + RNG_INT_STATUS_OFFSET);
69
70 /* Reset RNG and RBG */
71 val = ioread32(rng_base + RBG_SOFT_RESET_OFFSET);
72 val |= RBG_SOFT_RESET;
73 iowrite32(val, rng_base + RBG_SOFT_RESET_OFFSET);
74
75 val = ioread32(rng_base + RNG_SOFT_RESET_OFFSET);
76 val |= RNG_SOFT_RESET;
77 iowrite32(val, rng_base + RNG_SOFT_RESET_OFFSET);
78
79 val = ioread32(rng_base + RNG_SOFT_RESET_OFFSET);
80 val &= ~RNG_SOFT_RESET;
81 iowrite32(val, rng_base + RNG_SOFT_RESET_OFFSET);
82
83 val = ioread32(rng_base + RBG_SOFT_RESET_OFFSET);
84 val &= ~RBG_SOFT_RESET;
85 iowrite32(val, rng_base + RBG_SOFT_RESET_OFFSET);
86
87 /* Enable RBG */
88 val = ioread32(rng_base + RNG_CTRL_OFFSET);
89 val &= ~RNG_CTRL_RNG_RBGEN_MASK;
90 val |= RNG_CTRL_RNG_RBGEN_ENABLE;
91 iowrite32(val, rng_base + RNG_CTRL_OFFSET);
92}
93
94static int iproc_rng200_read(struct hwrng *rng, void *buf, size_t max,
95 bool wait)
96{
97 struct iproc_rng200_dev *priv = to_rng_priv(rng);
98 uint32_t num_remaining = max;
99 uint32_t status;
100
101 #define MAX_RESETS_PER_READ 1
102 uint32_t num_resets = 0;
103
104 #define MAX_IDLE_TIME (1 * HZ)
105 unsigned long idle_endtime = jiffies + MAX_IDLE_TIME;
106
107 while ((num_remaining > 0) && time_before(jiffies, idle_endtime)) {
108
109 /* Is RNG sane? If not, reset it. */
110 status = ioread32(priv->base + RNG_INT_STATUS_OFFSET);
111 if ((status & (RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK |
112 RNG_INT_STATUS_NIST_FAIL_IRQ_MASK)) != 0) {
113
114 if (num_resets >= MAX_RESETS_PER_READ)
115 return max - num_remaining;
116
117 iproc_rng200_restart(priv->base);
118 num_resets++;
119 }
120
121 /* Are there any random numbers available? */
122 if ((ioread32(priv->base + RNG_FIFO_COUNT_OFFSET) &
123 RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK) > 0) {
124
125 if (num_remaining >= sizeof(uint32_t)) {
126 /* Buffer has room to store entire word */
127 *(uint32_t *)buf = ioread32(priv->base +
128 RNG_FIFO_DATA_OFFSET);
129 buf += sizeof(uint32_t);
130 num_remaining -= sizeof(uint32_t);
131 } else {
132 /* Buffer can only store partial word */
133 uint32_t rnd_number = ioread32(priv->base +
134 RNG_FIFO_DATA_OFFSET);
135 memcpy(buf, &rnd_number, num_remaining);
136 buf += num_remaining;
137 num_remaining = 0;
138 }
139
140 /* Reset the IDLE timeout */
141 idle_endtime = jiffies + MAX_IDLE_TIME;
142 } else {
143 if (!wait)
144 /* Cannot wait, return immediately */
145 return max - num_remaining;
146
147 /* Can wait, give others chance to run */
148 usleep_range(min(num_remaining * 10, 500U), 500);
149 }
150 }
151
152 return max - num_remaining;
153}
154
155static int iproc_rng200_init(struct hwrng *rng)
156{
157 struct iproc_rng200_dev *priv = to_rng_priv(rng);
158 uint32_t val;
159
160 /* Setup RNG. */
161 val = ioread32(priv->base + RNG_CTRL_OFFSET);
162 val &= ~RNG_CTRL_RNG_RBGEN_MASK;
163 val |= RNG_CTRL_RNG_RBGEN_ENABLE;
164 iowrite32(val, priv->base + RNG_CTRL_OFFSET);
165
166 return 0;
167}
168
169static void iproc_rng200_cleanup(struct hwrng *rng)
170{
171 struct iproc_rng200_dev *priv = to_rng_priv(rng);
172 uint32_t val;
173
174 /* Disable RNG hardware */
175 val = ioread32(priv->base + RNG_CTRL_OFFSET);
176 val &= ~RNG_CTRL_RNG_RBGEN_MASK;
177 val |= RNG_CTRL_RNG_RBGEN_DISABLE;
178 iowrite32(val, priv->base + RNG_CTRL_OFFSET);
179}
180
181static int iproc_rng200_probe(struct platform_device *pdev)
182{
183 struct iproc_rng200_dev *priv;
184 struct resource *res;
185 struct device *dev = &pdev->dev;
186 int ret;
187
188 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
189 if (!priv)
190 return -ENOMEM;
191
192 /* Map peripheral */
193 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
194 if (!res) {
195 dev_err(dev, "failed to get rng resources\n");
196 return -EINVAL;
197 }
198
199 priv->base = devm_ioremap_resource(dev, res);
200 if (IS_ERR(priv->base)) {
201 dev_err(dev, "failed to remap rng regs\n");
202 return PTR_ERR(priv->base);
203 }
204
205 priv->rng.name = "iproc-rng200",
206 priv->rng.read = iproc_rng200_read,
207 priv->rng.init = iproc_rng200_init,
208 priv->rng.cleanup = iproc_rng200_cleanup,
209
210 /* Register driver */
211 ret = devm_hwrng_register(dev, &priv->rng);
212 if (ret) {
213 dev_err(dev, "hwrng registration failed\n");
214 return ret;
215 }
216
217 dev_info(dev, "hwrng registered\n");
218
219 return 0;
220}
221
222static const struct of_device_id iproc_rng200_of_match[] = {
223 { .compatible = "brcm,iproc-rng200", },
224 {},
225};
226MODULE_DEVICE_TABLE(of, iproc_rng200_of_match);
227
228static struct platform_driver iproc_rng200_driver = {
229 .driver = {
230 .name = "iproc-rng200",
231 .of_match_table = iproc_rng200_of_match,
232 },
233 .probe = iproc_rng200_probe,
234};
235module_platform_driver(iproc_rng200_driver);
236
237MODULE_AUTHOR("Broadcom");
238MODULE_DESCRIPTION("iProc RNG200 Random Number Generator driver");
239MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/msm-rng.c b/drivers/char/hw_random/msm-rng.c
index cea1c703d62f..96fb986402eb 100644
--- a/drivers/char/hw_random/msm-rng.c
+++ b/drivers/char/hw_random/msm-rng.c
@@ -157,7 +157,7 @@ static int msm_rng_probe(struct platform_device *pdev)
157 rng->hwrng.cleanup = msm_rng_cleanup, 157 rng->hwrng.cleanup = msm_rng_cleanup,
158 rng->hwrng.read = msm_rng_read, 158 rng->hwrng.read = msm_rng_read,
159 159
160 ret = hwrng_register(&rng->hwrng); 160 ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
161 if (ret) { 161 if (ret) {
162 dev_err(&pdev->dev, "failed to register hwrng\n"); 162 dev_err(&pdev->dev, "failed to register hwrng\n");
163 return ret; 163 return ret;
@@ -166,14 +166,6 @@ static int msm_rng_probe(struct platform_device *pdev)
166 return 0; 166 return 0;
167} 167}
168 168
169static int msm_rng_remove(struct platform_device *pdev)
170{
171 struct msm_rng *rng = platform_get_drvdata(pdev);
172
173 hwrng_unregister(&rng->hwrng);
174 return 0;
175}
176
177static const struct of_device_id msm_rng_of_match[] = { 169static const struct of_device_id msm_rng_of_match[] = {
178 { .compatible = "qcom,prng", }, 170 { .compatible = "qcom,prng", },
179 {} 171 {}
@@ -182,7 +174,6 @@ MODULE_DEVICE_TABLE(of, msm_rng_of_match);
182 174
183static struct platform_driver msm_rng_driver = { 175static struct platform_driver msm_rng_driver = {
184 .probe = msm_rng_probe, 176 .probe = msm_rng_probe,
185 .remove = msm_rng_remove,
186 .driver = { 177 .driver = {
187 .name = KBUILD_MODNAME, 178 .name = KBUILD_MODNAME,
188 .of_match_table = of_match_ptr(msm_rng_of_match), 179 .of_match_table = of_match_ptr(msm_rng_of_match),
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index be1c3f607398..6234a4a19b56 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -105,7 +105,7 @@ static int octeon_rng_probe(struct platform_device *pdev)
105 return 0; 105 return 0;
106} 106}
107 107
108static int __exit octeon_rng_remove(struct platform_device *pdev) 108static int octeon_rng_remove(struct platform_device *pdev)
109{ 109{
110 struct hwrng *rng = platform_get_drvdata(pdev); 110 struct hwrng *rng = platform_get_drvdata(pdev);
111 111
@@ -119,7 +119,7 @@ static struct platform_driver octeon_rng_driver = {
119 .name = "octeon_rng", 119 .name = "octeon_rng",
120 }, 120 },
121 .probe = octeon_rng_probe, 121 .probe = octeon_rng_probe,
122 .remove = __exit_p(octeon_rng_remove), 122 .remove = octeon_rng_remove,
123}; 123};
124 124
125module_platform_driver(octeon_rng_driver); 125module_platform_driver(octeon_rng_driver);
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index d14dcf788f17..8a1432e8bb80 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -236,7 +236,7 @@ static int omap4_rng_init(struct omap_rng_dev *priv)
236 u32 val; 236 u32 val;
237 237
238 /* Return if RNG is already running. */ 238 /* Return if RNG is already running. */
239 if (omap_rng_read(priv, RNG_CONFIG_REG) & RNG_CONTROL_ENABLE_TRNG_MASK) 239 if (omap_rng_read(priv, RNG_CONTROL_REG) & RNG_CONTROL_ENABLE_TRNG_MASK)
240 return 0; 240 return 0;
241 241
242 val = RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; 242 val = RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
@@ -262,7 +262,7 @@ static void omap4_rng_cleanup(struct omap_rng_dev *priv)
262 262
263 val = omap_rng_read(priv, RNG_CONTROL_REG); 263 val = omap_rng_read(priv, RNG_CONTROL_REG);
264 val &= ~RNG_CONTROL_ENABLE_TRNG_MASK; 264 val &= ~RNG_CONTROL_ENABLE_TRNG_MASK;
265 omap_rng_write(priv, RNG_CONFIG_REG, val); 265 omap_rng_write(priv, RNG_CONTROL_REG, val);
266} 266}
267 267
268static irqreturn_t omap4_rng_irq(int irq, void *dev_id) 268static irqreturn_t omap4_rng_irq(int irq, void *dev_id)
@@ -408,7 +408,7 @@ err_ioremap:
408 return ret; 408 return ret;
409} 409}
410 410
411static int __exit omap_rng_remove(struct platform_device *pdev) 411static int omap_rng_remove(struct platform_device *pdev)
412{ 412{
413 struct omap_rng_dev *priv = platform_get_drvdata(pdev); 413 struct omap_rng_dev *priv = platform_get_drvdata(pdev);
414 414
@@ -422,9 +422,7 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
422 return 0; 422 return 0;
423} 423}
424 424
425#ifdef CONFIG_PM_SLEEP 425static int __maybe_unused omap_rng_suspend(struct device *dev)
426
427static int omap_rng_suspend(struct device *dev)
428{ 426{
429 struct omap_rng_dev *priv = dev_get_drvdata(dev); 427 struct omap_rng_dev *priv = dev_get_drvdata(dev);
430 428
@@ -434,7 +432,7 @@ static int omap_rng_suspend(struct device *dev)
434 return 0; 432 return 0;
435} 433}
436 434
437static int omap_rng_resume(struct device *dev) 435static int __maybe_unused omap_rng_resume(struct device *dev)
438{ 436{
439 struct omap_rng_dev *priv = dev_get_drvdata(dev); 437 struct omap_rng_dev *priv = dev_get_drvdata(dev);
440 438
@@ -445,22 +443,15 @@ static int omap_rng_resume(struct device *dev)
445} 443}
446 444
447static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume); 445static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
448#define OMAP_RNG_PM (&omap_rng_pm)
449
450#else
451
452#define OMAP_RNG_PM NULL
453
454#endif
455 446
456static struct platform_driver omap_rng_driver = { 447static struct platform_driver omap_rng_driver = {
457 .driver = { 448 .driver = {
458 .name = "omap_rng", 449 .name = "omap_rng",
459 .pm = OMAP_RNG_PM, 450 .pm = &omap_rng_pm,
460 .of_match_table = of_match_ptr(omap_rng_of_match), 451 .of_match_table = of_match_ptr(omap_rng_of_match),
461 }, 452 },
462 .probe = omap_rng_probe, 453 .probe = omap_rng_probe,
463 .remove = __exit_p(omap_rng_remove), 454 .remove = omap_rng_remove,
464}; 455};
465 456
466module_platform_driver(omap_rng_driver); 457module_platform_driver(omap_rng_driver);
diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c
index bcf86f91800a..63ce51d09af1 100644
--- a/drivers/char/hw_random/pseries-rng.c
+++ b/drivers/char/hw_random/pseries-rng.c
@@ -61,13 +61,13 @@ static struct hwrng pseries_rng = {
61 .read = pseries_rng_read, 61 .read = pseries_rng_read,
62}; 62};
63 63
64static int __init pseries_rng_probe(struct vio_dev *dev, 64static int pseries_rng_probe(struct vio_dev *dev,
65 const struct vio_device_id *id) 65 const struct vio_device_id *id)
66{ 66{
67 return hwrng_register(&pseries_rng); 67 return hwrng_register(&pseries_rng);
68} 68}
69 69
70static int __exit pseries_rng_remove(struct vio_dev *dev) 70static int pseries_rng_remove(struct vio_dev *dev)
71{ 71{
72 hwrng_unregister(&pseries_rng); 72 hwrng_unregister(&pseries_rng);
73 return 0; 73 return 0;
diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c
index 23caa05380a8..c37cf754a985 100644
--- a/drivers/char/hw_random/xgene-rng.c
+++ b/drivers/char/hw_random/xgene-rng.c
@@ -21,6 +21,7 @@
21 * 21 *
22 */ 22 */
23 23
24#include <linux/acpi.h>
24#include <linux/clk.h> 25#include <linux/clk.h>
25#include <linux/delay.h> 26#include <linux/delay.h>
26#include <linux/hw_random.h> 27#include <linux/hw_random.h>
@@ -310,6 +311,14 @@ static int xgene_rng_init(struct hwrng *rng)
310 return 0; 311 return 0;
311} 312}
312 313
314#ifdef CONFIG_ACPI
315static const struct acpi_device_id xgene_rng_acpi_match[] = {
316 { "APMC0D18", },
317 { }
318};
319MODULE_DEVICE_TABLE(acpi, xgene_rng_acpi_match);
320#endif
321
313static struct hwrng xgene_rng_func = { 322static struct hwrng xgene_rng_func = {
314 .name = "xgene-rng", 323 .name = "xgene-rng",
315 .init = xgene_rng_init, 324 .init = xgene_rng_init,
@@ -415,6 +424,7 @@ static struct platform_driver xgene_rng_driver = {
415 .driver = { 424 .driver = {
416 .name = "xgene-rng", 425 .name = "xgene-rng",
417 .of_match_table = xgene_rng_of_match, 426 .of_match_table = xgene_rng_of_match,
427 .acpi_match_table = ACPI_PTR(xgene_rng_acpi_match),
418 }, 428 },
419}; 429};
420 430