Commit | Line | Data |
---|---|---|
66548e40 ME |
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"); |