hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/clk/clk-devres.c
....@@ -4,41 +4,100 @@
44 #include <linux/export.h>
55 #include <linux/gfp.h>
66
7
+struct devm_clk_state {
8
+ struct clk *clk;
9
+ void (*exit)(struct clk *clk);
10
+};
11
+
712 static void devm_clk_release(struct device *dev, void *res)
813 {
9
- clk_put(*(struct clk **)res);
14
+ struct devm_clk_state *state = res;
15
+
16
+ if (state->exit)
17
+ state->exit(state->clk);
18
+
19
+ clk_put(state->clk);
20
+}
21
+
22
+static struct clk *__devm_clk_get(struct device *dev, const char *id,
23
+ struct clk *(*get)(struct device *dev, const char *id),
24
+ int (*init)(struct clk *clk),
25
+ void (*exit)(struct clk *clk))
26
+{
27
+ struct devm_clk_state *state;
28
+ struct clk *clk;
29
+ int ret;
30
+
31
+ state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
32
+ if (!state)
33
+ return ERR_PTR(-ENOMEM);
34
+
35
+ clk = get(dev, id);
36
+ if (IS_ERR(clk)) {
37
+ ret = PTR_ERR(clk);
38
+ goto err_clk_get;
39
+ }
40
+
41
+ if (init) {
42
+ ret = init(clk);
43
+ if (ret)
44
+ goto err_clk_init;
45
+ }
46
+
47
+ state->clk = clk;
48
+ state->exit = exit;
49
+
50
+ devres_add(dev, state);
51
+
52
+ return clk;
53
+
54
+err_clk_init:
55
+
56
+ clk_put(clk);
57
+err_clk_get:
58
+
59
+ devres_free(state);
60
+ return ERR_PTR(ret);
1061 }
1162
1263 struct clk *devm_clk_get(struct device *dev, const char *id)
1364 {
14
- struct clk **ptr, *clk;
15
-
16
- ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
17
- if (!ptr)
18
- return ERR_PTR(-ENOMEM);
19
-
20
- clk = clk_get(dev, id);
21
- if (!IS_ERR(clk)) {
22
- *ptr = clk;
23
- devres_add(dev, ptr);
24
- } else {
25
- devres_free(ptr);
26
- }
27
-
28
- return clk;
65
+ return __devm_clk_get(dev, id, clk_get, NULL, NULL);
2966 }
3067 EXPORT_SYMBOL(devm_clk_get);
3168
69
+struct clk *devm_clk_get_prepared(struct device *dev, const char *id)
70
+{
71
+ return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare);
72
+}
73
+EXPORT_SYMBOL_GPL(devm_clk_get_prepared);
74
+
75
+struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
76
+{
77
+ return __devm_clk_get(dev, id, clk_get,
78
+ clk_prepare_enable, clk_disable_unprepare);
79
+}
80
+EXPORT_SYMBOL_GPL(devm_clk_get_enabled);
81
+
3282 struct clk *devm_clk_get_optional(struct device *dev, const char *id)
3383 {
34
- struct clk *clk = devm_clk_get(dev, id);
35
-
36
- if (clk == ERR_PTR(-ENOENT))
37
- return NULL;
38
-
39
- return clk;
84
+ return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
4085 }
4186 EXPORT_SYMBOL(devm_clk_get_optional);
87
+
88
+struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id)
89
+{
90
+ return __devm_clk_get(dev, id, clk_get_optional,
91
+ clk_prepare, clk_unprepare);
92
+}
93
+EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared);
94
+
95
+struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
96
+{
97
+ return __devm_clk_get(dev, id, clk_get_optional,
98
+ clk_prepare_enable, clk_disable_unprepare);
99
+}
100
+EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
42101
43102 struct clk_bulk_devres {
44103 struct clk_bulk_data *clks;
....@@ -146,18 +205,19 @@
146205 struct clk *devm_get_clk_from_child(struct device *dev,
147206 struct device_node *np, const char *con_id)
148207 {
149
- struct clk **ptr, *clk;
208
+ struct devm_clk_state *state;
209
+ struct clk *clk;
150210
151
- ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
152
- if (!ptr)
211
+ state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
212
+ if (!state)
153213 return ERR_PTR(-ENOMEM);
154214
155215 clk = of_clk_get_by_name(np, con_id);
156216 if (!IS_ERR(clk)) {
157
- *ptr = clk;
158
- devres_add(dev, ptr);
217
+ state->clk = clk;
218
+ devres_add(dev, state);
159219 } else {
160
- devres_free(ptr);
220
+ devres_free(state);
161221 }
162222
163223 return clk;