Branch data Line data Source code
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>
6 : :
7 : 0 : static void devm_clk_release(struct device *dev, void *res)
8 : : {
9 : 0 : clk_put(*(struct clk **)res);
10 : 0 : }
11 : :
12 : 0 : struct clk *devm_clk_get(struct device *dev, const char *id)
13 : : {
14 : 0 : struct clk **ptr, *clk;
15 : :
16 : 0 : ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
17 [ # # ]: 0 : if (!ptr)
18 : : return ERR_PTR(-ENOMEM);
19 : :
20 : 0 : clk = clk_get(dev, id);
21 [ # # ]: 0 : if (!IS_ERR(clk)) {
22 : 0 : *ptr = clk;
23 : 0 : devres_add(dev, ptr);
24 : : } else {
25 : 0 : devres_free(ptr);
26 : : }
27 : :
28 : : return clk;
29 : : }
30 : : EXPORT_SYMBOL(devm_clk_get);
31 : :
32 : 0 : struct clk *devm_clk_get_optional(struct device *dev, const char *id)
33 : : {
34 : 0 : struct clk *clk = devm_clk_get(dev, id);
35 : :
36 [ # # ]: 0 : if (clk == ERR_PTR(-ENOENT))
37 : 0 : return NULL;
38 : :
39 : : return clk;
40 : : }
41 : : EXPORT_SYMBOL(devm_clk_get_optional);
42 : :
43 : : struct clk_bulk_devres {
44 : : struct clk_bulk_data *clks;
45 : : int num_clks;
46 : : };
47 : :
48 : 0 : static void devm_clk_bulk_release(struct device *dev, void *res)
49 : : {
50 : 0 : struct clk_bulk_devres *devres = res;
51 : :
52 : 0 : clk_bulk_put(devres->num_clks, devres->clks);
53 : 0 : }
54 : :
55 : 0 : static int __devm_clk_bulk_get(struct device *dev, int num_clks,
56 : : struct clk_bulk_data *clks, bool optional)
57 : : {
58 : 0 : struct clk_bulk_devres *devres;
59 : 0 : int ret;
60 : :
61 : 0 : devres = devres_alloc(devm_clk_bulk_release,
62 : : sizeof(*devres), GFP_KERNEL);
63 [ # # ]: 0 : if (!devres)
64 : : return -ENOMEM;
65 : :
66 [ # # ]: 0 : if (optional)
67 : 0 : ret = clk_bulk_get_optional(dev, num_clks, clks);
68 : : else
69 : 0 : ret = clk_bulk_get(dev, num_clks, clks);
70 [ # # ]: 0 : if (!ret) {
71 : 0 : devres->clks = clks;
72 : 0 : devres->num_clks = num_clks;
73 : 0 : devres_add(dev, devres);
74 : : } else {
75 : 0 : devres_free(devres);
76 : : }
77 : :
78 : : return ret;
79 : : }
80 : :
81 : 0 : int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
82 : : struct clk_bulk_data *clks)
83 : : {
84 : 0 : return __devm_clk_bulk_get(dev, num_clks, clks, false);
85 : : }
86 : : EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
87 : :
88 : 0 : int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
89 : : struct clk_bulk_data *clks)
90 : : {
91 : 0 : return __devm_clk_bulk_get(dev, num_clks, clks, true);
92 : : }
93 : : EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
94 : :
95 : 0 : int __must_check devm_clk_bulk_get_all(struct device *dev,
96 : : struct clk_bulk_data **clks)
97 : : {
98 : 0 : struct clk_bulk_devres *devres;
99 : 0 : int ret;
100 : :
101 : 0 : devres = devres_alloc(devm_clk_bulk_release,
102 : : sizeof(*devres), GFP_KERNEL);
103 [ # # ]: 0 : if (!devres)
104 : : return -ENOMEM;
105 : :
106 : 0 : ret = clk_bulk_get_all(dev, &devres->clks);
107 [ # # ]: 0 : if (ret > 0) {
108 : 0 : *clks = devres->clks;
109 : 0 : devres->num_clks = ret;
110 : 0 : devres_add(dev, devres);
111 : : } else {
112 : 0 : devres_free(devres);
113 : : }
114 : :
115 : : return ret;
116 : : }
117 : : EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
118 : :
119 : 0 : static int devm_clk_match(struct device *dev, void *res, void *data)
120 : : {
121 : 0 : struct clk **c = res;
122 [ # # # # ]: 0 : if (!c || !*c) {
123 [ # # # # : 0 : WARN_ON(!c || !*c);
# # ]
124 : : return 0;
125 : : }
126 : 0 : return *c == data;
127 : : }
128 : :
129 : 0 : void devm_clk_put(struct device *dev, struct clk *clk)
130 : : {
131 : 0 : int ret;
132 : :
133 : 0 : ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
134 : :
135 [ # # ]: 0 : WARN_ON(ret);
136 : 0 : }
137 : : EXPORT_SYMBOL(devm_clk_put);
138 : :
139 : 0 : struct clk *devm_get_clk_from_child(struct device *dev,
140 : : struct device_node *np, const char *con_id)
141 : : {
142 : 0 : struct clk **ptr, *clk;
143 : :
144 : 0 : ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
145 [ # # ]: 0 : if (!ptr)
146 : : return ERR_PTR(-ENOMEM);
147 : :
148 : 0 : clk = of_clk_get_by_name(np, con_id);
149 : 0 : if (!IS_ERR(clk)) {
150 : : *ptr = clk;
151 : : devres_add(dev, ptr);
152 : : } else {
153 : 0 : devres_free(ptr);
154 : : }
155 : :
156 : 0 : return clk;
157 : : }
158 : : EXPORT_SYMBOL(devm_get_clk_from_child);
|