Skip to content

Commit 1c6b7c2

Browse files
paliherbertx
authored andcommitted
hwrng: OMAP3 ROM Random Number Generator support
This driver provides kernel-side support for the Random Number Generator hardware found on OMAP34xx processors. This driver comes from Maemo 2.6.28 kernel and was tested on Nokia RX-51. It is platform device because it needs board specific function for smc calls. Signed-off-by: Pali Rohár <[email protected]> Signed-off-by: Juha Yrjola <[email protected]> Acked-by: Tony Lindgren <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 16c0c4e commit 1c6b7c2

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed

drivers/char/hw_random/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,19 @@ config HW_RANDOM_OMAP
165165

166166
If unsure, say Y.
167167

168+
config HW_RANDOM_OMAP3_ROM
169+
tristate "OMAP3 ROM Random Number Generator support"
170+
depends on HW_RANDOM && ARCH_OMAP3
171+
default HW_RANDOM
172+
---help---
173+
This driver provides kernel-side support for the Random Number
174+
Generator hardware found on OMAP34xx processors.
175+
176+
To compile this driver as a module, choose M here: the
177+
module will be called omap3-rom-rng.
178+
179+
If unsure, say Y.
180+
168181
config HW_RANDOM_OCTEON
169182
tristate "Octeon Random Number Generator support"
170183
depends on HW_RANDOM && CAVIUM_OCTEON_SOC

drivers/char/hw_random/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ n2-rng-y := n2-drv.o n2-asm.o
1515
obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
1616
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
1717
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
18+
obj-$(CONFIG_HW_RANDOM_OMAP3_ROM) += omap3-rom-rng.o
1819
obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
1920
obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
2021
obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* omap3-rom-rng.c - RNG driver for TI OMAP3 CPU family
3+
*
4+
* Copyright (C) 2009 Nokia Corporation
5+
* Author: Juha Yrjola <[email protected]>
6+
*
7+
* Copyright (C) 2013 Pali Rohár <[email protected]>
8+
*
9+
* This file is licensed under the terms of the GNU General Public
10+
* License version 2. This program is licensed "as is" without any
11+
* warranty of any kind, whether express or implied.
12+
*/
13+
14+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15+
16+
#include <linux/module.h>
17+
#include <linux/init.h>
18+
#include <linux/random.h>
19+
#include <linux/hw_random.h>
20+
#include <linux/timer.h>
21+
#include <linux/clk.h>
22+
#include <linux/err.h>
23+
#include <linux/platform_device.h>
24+
25+
#define RNG_RESET 0x01
26+
#define RNG_GEN_PRNG_HW_INIT 0x02
27+
#define RNG_GEN_HW 0x08
28+
29+
/* param1: ptr, param2: count, param3: flag */
30+
static u32 (*omap3_rom_rng_call)(u32, u32, u32);
31+
32+
static struct timer_list idle_timer;
33+
static int rng_idle;
34+
static struct clk *rng_clk;
35+
36+
static void omap3_rom_rng_idle(unsigned long data)
37+
{
38+
int r;
39+
40+
r = omap3_rom_rng_call(0, 0, RNG_RESET);
41+
if (r != 0) {
42+
pr_err("reset failed: %d\n", r);
43+
return;
44+
}
45+
clk_disable_unprepare(rng_clk);
46+
rng_idle = 1;
47+
}
48+
49+
static int omap3_rom_rng_get_random(void *buf, unsigned int count)
50+
{
51+
u32 r;
52+
u32 ptr;
53+
54+
del_timer_sync(&idle_timer);
55+
if (rng_idle) {
56+
clk_prepare_enable(rng_clk);
57+
r = omap3_rom_rng_call(0, 0, RNG_GEN_PRNG_HW_INIT);
58+
if (r != 0) {
59+
clk_disable_unprepare(rng_clk);
60+
pr_err("HW init failed: %d\n", r);
61+
return -EIO;
62+
}
63+
rng_idle = 0;
64+
}
65+
66+
ptr = virt_to_phys(buf);
67+
r = omap3_rom_rng_call(ptr, count, RNG_GEN_HW);
68+
mod_timer(&idle_timer, jiffies + msecs_to_jiffies(500));
69+
if (r != 0)
70+
return -EINVAL;
71+
return 0;
72+
}
73+
74+
static int omap3_rom_rng_data_present(struct hwrng *rng, int wait)
75+
{
76+
return 1;
77+
}
78+
79+
static int omap3_rom_rng_data_read(struct hwrng *rng, u32 *data)
80+
{
81+
int r;
82+
83+
r = omap3_rom_rng_get_random(data, 4);
84+
if (r < 0)
85+
return r;
86+
return 4;
87+
}
88+
89+
static struct hwrng omap3_rom_rng_ops = {
90+
.name = "omap3-rom",
91+
.data_present = omap3_rom_rng_data_present,
92+
.data_read = omap3_rom_rng_data_read,
93+
};
94+
95+
static int omap3_rom_rng_probe(struct platform_device *pdev)
96+
{
97+
pr_info("initializing\n");
98+
99+
omap3_rom_rng_call = pdev->dev.platform_data;
100+
if (!omap3_rom_rng_call) {
101+
pr_err("omap3_rom_rng_call is NULL\n");
102+
return -EINVAL;
103+
}
104+
105+
setup_timer(&idle_timer, omap3_rom_rng_idle, 0);
106+
rng_clk = clk_get(&pdev->dev, "ick");
107+
if (IS_ERR(rng_clk)) {
108+
pr_err("unable to get RNG clock\n");
109+
return PTR_ERR(rng_clk);
110+
}
111+
112+
/* Leave the RNG in reset state. */
113+
clk_prepare_enable(rng_clk);
114+
omap3_rom_rng_idle(0);
115+
116+
return hwrng_register(&omap3_rom_rng_ops);
117+
}
118+
119+
static int omap3_rom_rng_remove(struct platform_device *pdev)
120+
{
121+
hwrng_unregister(&omap3_rom_rng_ops);
122+
clk_disable_unprepare(rng_clk);
123+
clk_put(rng_clk);
124+
return 0;
125+
}
126+
127+
static struct platform_driver omap3_rom_rng_driver = {
128+
.driver = {
129+
.name = "omap3-rom-rng",
130+
.owner = THIS_MODULE,
131+
},
132+
.probe = omap3_rom_rng_probe,
133+
.remove = omap3_rom_rng_remove,
134+
};
135+
136+
module_platform_driver(omap3_rom_rng_driver);
137+
138+
MODULE_ALIAS("platform:omap3-rom-rng");
139+
MODULE_AUTHOR("Juha Yrjola");
140+
MODULE_AUTHOR("Pali Rohár <[email protected]>");
141+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)