hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/clk/clk-devres.c
....@@ -1,49 +1,103 @@
1
-/*
2
- * This program is free software; you can redistribute it and/or modify
3
- * it under the terms of the GNU General Public License version 2 as
4
- * published by the Free Software Foundation.
5
- */
6
-
1
+// SPDX-License-Identifier: GPL-2.0
72 #include <linux/clk.h>
83 #include <linux/device.h>
94 #include <linux/export.h>
105 #include <linux/gfp.h>
116
7
+struct devm_clk_state {
8
+ struct clk *clk;
9
+ void (*exit)(struct clk *clk);
10
+};
11
+
1212 static void devm_clk_release(struct device *dev, void *res)
1313 {
14
- 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);
1561 }
1662
1763 struct clk *devm_clk_get(struct device *dev, const char *id)
1864 {
19
- struct clk **ptr, *clk;
20
-
21
- ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
22
- if (!ptr)
23
- return ERR_PTR(-ENOMEM);
24
-
25
- clk = clk_get(dev, id);
26
- if (!IS_ERR(clk)) {
27
- *ptr = clk;
28
- devres_add(dev, ptr);
29
- } else {
30
- devres_free(ptr);
31
- }
32
-
33
- return clk;
65
+ return __devm_clk_get(dev, id, clk_get, NULL, NULL);
3466 }
3567 EXPORT_SYMBOL(devm_clk_get);
3668
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
+
3782 struct clk *devm_clk_get_optional(struct device *dev, const char *id)
3883 {
39
- struct clk *clk = devm_clk_get(dev, id);
40
-
41
- if (clk == ERR_PTR(-ENOENT))
42
- return NULL;
43
-
44
- return clk;
84
+ return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
4585 }
4686 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);
47101
48102 struct clk_bulk_devres {
49103 struct clk_bulk_data *clks;
....@@ -97,13 +151,20 @@
97151 }
98152 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
99153
154
+static void devm_clk_bulk_release_all(struct device *dev, void *res)
155
+{
156
+ struct clk_bulk_devres *devres = res;
157
+
158
+ clk_bulk_put_all(devres->num_clks, devres->clks);
159
+}
160
+
100161 int __must_check devm_clk_bulk_get_all(struct device *dev,
101162 struct clk_bulk_data **clks)
102163 {
103164 struct clk_bulk_devres *devres;
104165 int ret;
105166
106
- devres = devres_alloc(devm_clk_bulk_release,
167
+ devres = devres_alloc(devm_clk_bulk_release_all,
107168 sizeof(*devres), GFP_KERNEL);
108169 if (!devres)
109170 return -ENOMEM;
....@@ -144,18 +205,19 @@
144205 struct clk *devm_get_clk_from_child(struct device *dev,
145206 struct device_node *np, const char *con_id)
146207 {
147
- struct clk **ptr, *clk;
208
+ struct devm_clk_state *state;
209
+ struct clk *clk;
148210
149
- ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
150
- if (!ptr)
211
+ state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
212
+ if (!state)
151213 return ERR_PTR(-ENOMEM);
152214
153215 clk = of_clk_get_by_name(np, con_id);
154216 if (!IS_ERR(clk)) {
155
- *ptr = clk;
156
- devres_add(dev, ptr);
217
+ state->clk = clk;
218
+ devres_add(dev, state);
157219 } else {
158
- devres_free(ptr);
220
+ devres_free(state);
159221 }
160222
161223 return clk;