diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2013-10-10 23:07:58 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-10-11 01:50:20 -0400 |
commit | 66548e40583b1470300341c6784fdc5176f7609f (patch) | |
tree | f8025f7e31ea5eab9db246107cba82651bd0eb36 /drivers/char/hw_random | |
parent | a4da0d50b2a00b79390092e6248ca88b7d93c81d (diff) |
hwrng: Add a driver for the hwrng found in power7+ systems
Add a driver for the hwrng found in power7+ systems, based on the
existing code for the arch_get_random_long() hook.
We only register a single instance of the driver, not one per device,
because we use the existing per_cpu array of devices in the arch code.
This means we always read from the "closest" device, avoiding inter-chip
memory traffic.
Signed-off-by: Guo Chao <yan@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r-- | drivers/char/hw_random/Kconfig | 13 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/powernv-rng.c | 81 |
3 files changed, 95 insertions, 0 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 0aa9d91daef5..c206de2951f2 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -290,6 +290,19 @@ config HW_RANDOM_PSERIES | |||
290 | 290 | ||
291 | If unsure, say Y. | 291 | If unsure, say Y. |
292 | 292 | ||
293 | config HW_RANDOM_POWERNV | ||
294 | tristate "PowerNV Random Number Generator support" | ||
295 | depends on HW_RANDOM && PPC_POWERNV | ||
296 | default HW_RANDOM | ||
297 | ---help--- | ||
298 | This is the driver for Random Number Generator hardware found | ||
299 | in POWER7+ and above machines for PowerNV platform. | ||
300 | |||
301 | To compile this driver as a module, choose M here: the | ||
302 | module will be called powernv-rng. | ||
303 | |||
304 | If unsure, say Y. | ||
305 | |||
293 | config HW_RANDOM_EXYNOS | 306 | config HW_RANDOM_EXYNOS |
294 | tristate "EXYNOS HW random number generator support" | 307 | tristate "EXYNOS HW random number generator support" |
295 | depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK | 308 | depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK |
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index bed467c9300e..d7d2435ff7fa 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o | |||
24 | obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o | 24 | obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o |
25 | obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o | 25 | obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o |
26 | obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o | 26 | obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o |
27 | obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o | ||
27 | obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o | 28 | obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o |
28 | obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o | 29 | obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o |
29 | obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o | 30 | obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o |
diff --git a/drivers/char/hw_random/powernv-rng.c b/drivers/char/hw_random/powernv-rng.c new file mode 100644 index 000000000000..3f4f63204560 --- /dev/null +++ b/drivers/char/hw_random/powernv-rng.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Michael Ellerman, Guo Chao, IBM Corp. | ||
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 | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/random.h> | ||
16 | #include <linux/hw_random.h> | ||
17 | |||
18 | static int powernv_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) | ||
19 | { | ||
20 | unsigned long *buf; | ||
21 | int i, len; | ||
22 | |||
23 | /* We rely on rng_buffer_size() being >= sizeof(unsigned long) */ | ||
24 | len = max / sizeof(unsigned long); | ||
25 | |||
26 | buf = (unsigned long *)data; | ||
27 | |||
28 | for (i = 0; i < len; i++) | ||
29 | powernv_get_random_long(buf++); | ||
30 | |||
31 | return len * sizeof(unsigned long); | ||
32 | } | ||
33 | |||
34 | static struct hwrng powernv_hwrng = { | ||
35 | .name = "powernv-rng", | ||
36 | .read = powernv_rng_read, | ||
37 | }; | ||
38 | |||
39 | static int powernv_rng_remove(struct platform_device *pdev) | ||
40 | { | ||
41 | hwrng_unregister(&powernv_hwrng); | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static int powernv_rng_probe(struct platform_device *pdev) | ||
47 | { | ||
48 | int rc; | ||
49 | |||
50 | rc = hwrng_register(&powernv_hwrng); | ||
51 | if (rc) { | ||
52 | /* We only register one device, ignore any others */ | ||
53 | if (rc == -EEXIST) | ||
54 | rc = -ENODEV; | ||
55 | |||
56 | return rc; | ||
57 | } | ||
58 | |||
59 | pr_info("Registered powernv hwrng.\n"); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static struct of_device_id powernv_rng_match[] = { | ||
65 | { .compatible = "ibm,power-rng",}, | ||
66 | {}, | ||
67 | }; | ||
68 | MODULE_DEVICE_TABLE(of, powernv_rng_match); | ||
69 | |||
70 | static struct platform_driver powernv_rng_driver = { | ||
71 | .driver = { | ||
72 | .name = "powernv_rng", | ||
73 | .of_match_table = powernv_rng_match, | ||
74 | }, | ||
75 | .probe = powernv_rng_probe, | ||
76 | .remove = powernv_rng_remove, | ||
77 | }; | ||
78 | module_platform_driver(powernv_rng_driver); | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_DESCRIPTION("Bare metal HWRNG driver for POWER7+ and above"); | ||