drm/tests: hdmi: Fix memory leaks in drm_display_mode_from_cea_vic()
[drm/drm-misc.git] / drivers / clk / clk-devres.c
blob82ae1f26e634572b943d18b8d86267f0a69911a6
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/clk.h>
3 #include <linux/device.h>
4 #include <linux/export.h>
5 #include <linux/gfp.h>
7 struct devm_clk_state {
8 struct clk *clk;
9 void (*exit)(struct clk *clk);
12 static void devm_clk_release(struct device *dev, void *res)
14 struct devm_clk_state *state = res;
16 if (state->exit)
17 state->exit(state->clk);
19 clk_put(state->clk);
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))
27 struct devm_clk_state *state;
28 struct clk *clk;
29 int ret;
31 state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
32 if (!state)
33 return ERR_PTR(-ENOMEM);
35 clk = get(dev, id);
36 if (IS_ERR(clk)) {
37 ret = PTR_ERR(clk);
38 goto err_clk_get;
41 if (init) {
42 ret = init(clk);
43 if (ret)
44 goto err_clk_init;
47 state->clk = clk;
48 state->exit = exit;
50 devres_add(dev, state);
52 return clk;
54 err_clk_init:
56 clk_put(clk);
57 err_clk_get:
59 devres_free(state);
60 return ERR_PTR(ret);
63 struct clk *devm_clk_get(struct device *dev, const char *id)
65 return __devm_clk_get(dev, id, clk_get, NULL, NULL);
67 EXPORT_SYMBOL(devm_clk_get);
69 struct clk *devm_clk_get_prepared(struct device *dev, const char *id)
71 return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare);
73 EXPORT_SYMBOL_GPL(devm_clk_get_prepared);
75 struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
77 return __devm_clk_get(dev, id, clk_get,
78 clk_prepare_enable, clk_disable_unprepare);
80 EXPORT_SYMBOL_GPL(devm_clk_get_enabled);
82 struct clk *devm_clk_get_optional(struct device *dev, const char *id)
84 return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
86 EXPORT_SYMBOL(devm_clk_get_optional);
88 struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id)
90 return __devm_clk_get(dev, id, clk_get_optional,
91 clk_prepare, clk_unprepare);
93 EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared);
95 struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
97 return __devm_clk_get(dev, id, clk_get_optional,
98 clk_prepare_enable, clk_disable_unprepare);
100 EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
102 struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
103 const char *id,
104 unsigned long rate)
106 struct clk *clk;
107 int ret;
109 clk = __devm_clk_get(dev, id, clk_get_optional, NULL,
110 clk_disable_unprepare);
111 if (IS_ERR(clk))
112 return ERR_CAST(clk);
114 ret = clk_set_rate(clk, rate);
115 if (ret)
116 goto out_put_clk;
118 ret = clk_prepare_enable(clk);
119 if (ret)
120 goto out_put_clk;
122 return clk;
124 out_put_clk:
125 devm_clk_put(dev, clk);
126 return ERR_PTR(ret);
128 EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled_with_rate);
130 struct clk_bulk_devres {
131 struct clk_bulk_data *clks;
132 int num_clks;
135 static void devm_clk_bulk_release(struct device *dev, void *res)
137 struct clk_bulk_devres *devres = res;
139 clk_bulk_put(devres->num_clks, devres->clks);
142 static int __devm_clk_bulk_get(struct device *dev, int num_clks,
143 struct clk_bulk_data *clks, bool optional)
145 struct clk_bulk_devres *devres;
146 int ret;
148 devres = devres_alloc(devm_clk_bulk_release,
149 sizeof(*devres), GFP_KERNEL);
150 if (!devres)
151 return -ENOMEM;
153 if (optional)
154 ret = clk_bulk_get_optional(dev, num_clks, clks);
155 else
156 ret = clk_bulk_get(dev, num_clks, clks);
157 if (!ret) {
158 devres->clks = clks;
159 devres->num_clks = num_clks;
160 devres_add(dev, devres);
161 } else {
162 devres_free(devres);
165 return ret;
168 int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
169 struct clk_bulk_data *clks)
171 return __devm_clk_bulk_get(dev, num_clks, clks, false);
173 EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
175 int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
176 struct clk_bulk_data *clks)
178 return __devm_clk_bulk_get(dev, num_clks, clks, true);
180 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
182 static void devm_clk_bulk_release_all(struct device *dev, void *res)
184 struct clk_bulk_devres *devres = res;
186 clk_bulk_put_all(devres->num_clks, devres->clks);
189 int __must_check devm_clk_bulk_get_all(struct device *dev,
190 struct clk_bulk_data **clks)
192 struct clk_bulk_devres *devres;
193 int ret;
195 devres = devres_alloc(devm_clk_bulk_release_all,
196 sizeof(*devres), GFP_KERNEL);
197 if (!devres)
198 return -ENOMEM;
200 ret = clk_bulk_get_all(dev, &devres->clks);
201 if (ret > 0) {
202 *clks = devres->clks;
203 devres->num_clks = ret;
204 devres_add(dev, devres);
205 } else {
206 devres_free(devres);
209 return ret;
211 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
213 static void devm_clk_bulk_release_all_enable(struct device *dev, void *res)
215 struct clk_bulk_devres *devres = res;
217 clk_bulk_disable_unprepare(devres->num_clks, devres->clks);
218 clk_bulk_put_all(devres->num_clks, devres->clks);
221 int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
222 struct clk_bulk_data **clks)
224 struct clk_bulk_devres *devres;
225 int ret;
227 devres = devres_alloc(devm_clk_bulk_release_all_enable,
228 sizeof(*devres), GFP_KERNEL);
229 if (!devres)
230 return -ENOMEM;
232 ret = clk_bulk_get_all(dev, &devres->clks);
233 if (ret > 0) {
234 *clks = devres->clks;
235 devres->num_clks = ret;
236 } else {
237 devres_free(devres);
238 return ret;
241 ret = clk_bulk_prepare_enable(devres->num_clks, *clks);
242 if (!ret) {
243 devres_add(dev, devres);
244 } else {
245 clk_bulk_put_all(devres->num_clks, devres->clks);
246 devres_free(devres);
249 return ret;
251 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enable);
253 static int devm_clk_match(struct device *dev, void *res, void *data)
255 struct clk **c = res;
256 if (!c || !*c) {
257 WARN_ON(!c || !*c);
258 return 0;
260 return *c == data;
263 void devm_clk_put(struct device *dev, struct clk *clk)
265 int ret;
267 ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
269 WARN_ON(ret);
271 EXPORT_SYMBOL(devm_clk_put);
273 struct clk *devm_get_clk_from_child(struct device *dev,
274 struct device_node *np, const char *con_id)
276 struct devm_clk_state *state;
277 struct clk *clk;
279 state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
280 if (!state)
281 return ERR_PTR(-ENOMEM);
283 clk = of_clk_get_by_name(np, con_id);
284 if (!IS_ERR(clk)) {
285 state->clk = clk;
286 devres_add(dev, state);
287 } else {
288 devres_free(state);
291 return clk;
293 EXPORT_SYMBOL(devm_get_clk_from_child);