diff options
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r-- | drivers/char/hw_random/Kconfig | 12 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/nomadik-rng.c | 103 |
3 files changed, 116 insertions, 0 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index c0df30faa66a..d31483c54883 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -186,3 +186,15 @@ config HW_RANDOM_MXC_RNGA | |||
186 | module will be called mxc-rnga. | 186 | module will be called mxc-rnga. |
187 | 187 | ||
188 | If unsure, say Y. | 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. | ||
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 5eeb1303f0d0..4273308aa1e3 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -18,3 +18,4 @@ obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o | |||
18 | obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o | 18 | obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o |
19 | obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o | 19 | obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o |
20 | obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o | 20 | obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o |
21 | obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o | ||
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c new file mode 100644 index 000000000000..a8b4c4010144 --- /dev/null +++ b/drivers/char/hw_random/nomadik-rng.c | |||
@@ -0,0 +1,103 @@ | |||
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"); | ||