Skip to content

Commit 8d9d4bd

Browse files
tmlindherbertx
authored andcommitted
hwrng: omap3-rom - Use runtime PM instead of custom functions
Nowadays we have runtime PM, and we can use it with autosuspend_timeout to idle things automatically. This allows us to get rid of the custom PM implementation. We enable clocks and init RNG in runtime_resume, and reset RNG and disable clocks in runtime_suspend. And then omap3_rom_rng_read() becomes very simple and we don't need the old functions for omap3_rom_rng_idle() and omap3_rom_rng_get_random(). We can now also get rid of pr_fmt as we're using dev_err instead. Cc: Aaro Koskinen <[email protected]> Cc: Adam Ford <[email protected]> Cc: Pali Rohár <[email protected]> Cc: Sebastian Reichel <[email protected]> Cc: Tero Kristo <[email protected]> Signed-off-by: Tony Lindgren <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent b8d665a commit 8d9d4bd

File tree

1 file changed

+73
-53
lines changed

1 file changed

+73
-53
lines changed

drivers/char/hw_random/omap3-rom-rng.c

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
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>
@@ -23,73 +21,83 @@
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-
3430
struct 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

95103
static 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

139153
static 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
};
155169
MODULE_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+
157176
static 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

Comments
 (0)