1111 * warranty of any kind, whether express or implied.
1212 */
1313
14- #define pr_fmt (fmt ) KBUILD_MODNAME ": " fmt
15-
1614#include <linux/module.h>
1715#include <linux/init.h>
1816#include <linux/random.h>
2321#include <linux/of.h>
2422#include <linux/of_device.h>
2523#include <linux/platform_device.h>
24+ #include <linux/pm_runtime.h>
2625
2726#define RNG_RESET 0x01
2827#define RNG_GEN_PRNG_HW_INIT 0x02
2928#define RNG_GEN_HW 0x08
3029
31- /* param1: ptr, param2: count, param3: flag */
32- static u32 (* omap3_rom_rng_call )(u32 , u32 , u32 );
33-
3430struct omap_rom_rng {
3531 struct clk * clk ;
3632 struct device * dev ;
3733 struct hwrng ops ;
34+ u32 (* rom_rng_call )(u32 ptr , u32 count , u32 flag );
3835};
3936
40- static struct delayed_work idle_work ;
41- static int rng_idle ;
42- static struct clk * rng_clk ;
43-
44- static void omap3_rom_rng_idle (struct work_struct * work )
37+ static int omap3_rom_rng_read (struct hwrng * rng , void * data , size_t max , bool w )
4538{
39+ struct omap_rom_rng * ddata ;
40+ u32 ptr ;
4641 int r ;
4742
48- r = omap3_rom_rng_call (0 , 0 , RNG_RESET );
49- if (r != 0 ) {
50- pr_err ("reset failed: %d\n" , r );
51- return ;
43+ ddata = (struct omap_rom_rng * )rng -> priv ;
44+
45+ r = pm_runtime_get_sync (ddata -> dev );
46+ if (r < 0 ) {
47+ pm_runtime_put_noidle (ddata -> dev );
48+
49+ return r ;
5250 }
53- clk_disable_unprepare (rng_clk );
54- rng_idle = 1 ;
51+
52+ ptr = virt_to_phys (data );
53+ r = ddata -> rom_rng_call (ptr , 4 , RNG_GEN_HW );
54+ if (r != 0 )
55+ r = - EINVAL ;
56+ else
57+ r = 4 ;
58+
59+ pm_runtime_mark_last_busy (ddata -> dev );
60+ pm_runtime_put_autosuspend (ddata -> dev );
61+
62+ return r ;
5563}
5664
57- static int omap3_rom_rng_get_random ( void * buf , unsigned int count )
65+ static int omap_rom_rng_runtime_suspend ( struct device * dev )
5866{
59- u32 r ;
60- u32 ptr ;
67+ struct omap_rom_rng * ddata ;
68+ int r ;
6169
62- cancel_delayed_work_sync (& idle_work );
63- if (rng_idle ) {
64- r = clk_prepare_enable (rng_clk );
65- if (r )
66- return r ;
67-
68- r = omap3_rom_rng_call (0 , 0 , RNG_GEN_PRNG_HW_INIT );
69- if (r != 0 ) {
70- clk_disable_unprepare (rng_clk );
71- pr_err ("HW init failed: %d\n" , r );
72- return - EIO ;
73- }
74- rng_idle = 0 ;
75- }
70+ ddata = dev_get_drvdata (dev );
7671
77- ptr = virt_to_phys (buf );
78- r = omap3_rom_rng_call (ptr , count , RNG_GEN_HW );
79- schedule_delayed_work (& idle_work , msecs_to_jiffies (500 ));
72+ r = ddata -> rom_rng_call (0 , 0 , RNG_RESET );
8073 if (r != 0 )
81- return - EINVAL ;
74+ dev_err (dev , "reset failed: %d\n" , r );
75+
76+ clk_disable_unprepare (ddata -> clk );
77+
8278 return 0 ;
8379}
8480
85- static int omap3_rom_rng_read (struct hwrng * rng , void * data , size_t max , bool w )
81+ static int omap_rom_rng_runtime_resume (struct device * dev )
8682{
83+ struct omap_rom_rng * ddata ;
8784 int r ;
8885
89- r = omap3_rom_rng_get_random (data , 4 );
86+ ddata = dev_get_drvdata (dev );
87+
88+ r = clk_prepare_enable (ddata -> clk );
9089 if (r < 0 )
9190 return r ;
92- return 4 ;
91+
92+ r = ddata -> rom_rng_call (0 , 0 , RNG_GEN_PRNG_HW_INIT );
93+ if (r != 0 ) {
94+ clk_disable (ddata -> clk );
95+ dev_err (dev , "HW init failed: %d\n" , r );
96+
97+ return - EIO ;
98+ }
99+
100+ return 0 ;
93101}
94102
95103static int omap3_rom_rng_probe (struct platform_device * pdev )
@@ -113,38 +121,44 @@ static int omap3_rom_rng_probe(struct platform_device *pdev)
113121 }
114122 dev_set_drvdata (ddata -> dev , ddata );
115123
116- omap3_rom_rng_call = pdev -> dev .platform_data ;
117- if (!omap3_rom_rng_call ) {
124+ ddata -> rom_rng_call = pdev -> dev .platform_data ;
125+ if (!ddata -> rom_rng_call ) {
118126 dev_err (ddata -> dev , "rom_rng_call is NULL\n" );
119127 return - EINVAL ;
120128 }
121129
122- INIT_DELAYED_WORK (& idle_work , omap3_rom_rng_idle );
123130 ddata -> clk = devm_clk_get (ddata -> dev , "ick" );
124131 if (IS_ERR (ddata -> clk )) {
125132 dev_err (ddata -> dev , "unable to get RNG clock\n" );
126133 return PTR_ERR (ddata -> clk );
127134 }
128- rng_clk = ddata -> clk ;
129135
130- /* Leave the RNG in reset state. */
131- ret = clk_prepare_enable (ddata -> clk );
132- if (ret )
133- return ret ;
134- omap3_rom_rng_idle (0 );
136+ pm_runtime_enable (ddata -> dev );
137+
138+ ret = hwrng_register (& ddata -> ops );
139+ if (!ret )
140+ goto err_disable ;
141+
142+ pm_runtime_set_autosuspend_delay (ddata -> dev , 500 );
143+ pm_runtime_use_autosuspend (ddata -> dev );
144+
145+ return 0 ;
135146
136- return hwrng_register (& ddata -> ops );
147+ err_disable :
148+ pm_runtime_disable (ddata -> dev );
149+
150+ return ret ;
137151}
138152
139153static int omap3_rom_rng_remove (struct platform_device * pdev )
140154{
141155 struct omap_rom_rng * ddata ;
142156
143157 ddata = dev_get_drvdata (& pdev -> dev );
144- cancel_delayed_work_sync (& idle_work );
145158 hwrng_unregister (& ddata -> ops );
146- if (!rng_idle )
147- clk_disable_unprepare (rng_clk );
159+ pm_runtime_dont_use_autosuspend (ddata -> dev );
160+ pm_runtime_disable (ddata -> dev );
161+
148162 return 0 ;
149163}
150164
@@ -154,10 +168,16 @@ static const struct of_device_id omap_rom_rng_match[] = {
154168};
155169MODULE_DEVICE_TABLE (of , omap_rom_rng_match );
156170
171+ static const struct dev_pm_ops omap_rom_rng_pm_ops = {
172+ SET_SYSTEM_SLEEP_PM_OPS (omap_rom_rng_runtime_suspend ,
173+ omap_rom_rng_runtime_resume )
174+ };
175+
157176static struct platform_driver omap3_rom_rng_driver = {
158177 .driver = {
159178 .name = "omap3-rom-rng" ,
160179 .of_match_table = omap_rom_rng_match ,
180+ .pm = & omap_rom_rng_pm_ops ,
161181 },
162182 .probe = omap3_rom_rng_probe ,
163183 .remove = omap3_rom_rng_remove ,
0 commit comments