1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright 2017 NXP
4 *
5 * Dong Aisheng <aisheng.dong@nxp.com>
6 */
7
8 #include <linux/clk.h>
9 #include <linux/clk-provider.h>
10 #include <linux/device.h>
11 #include <linux/export.h>
12 #include <linux/of.h>
13 #include <linux/slab.h>
14
of_clk_bulk_get(struct device * dev,struct device_node * np,int num_clks,struct clk_bulk_data * clks)15 static int __must_check of_clk_bulk_get(struct device *dev,
16 struct device_node *np, int num_clks,
17 struct clk_bulk_data *clks)
18 {
19 int ret;
20 int i;
21
22 for (i = 0; i < num_clks; i++) {
23 clks[i].id = NULL;
24 clks[i].clk = NULL;
25 }
26
27 for (i = 0; i < num_clks; i++) {
28 of_property_read_string_index(np, "clock-names", i, &clks[i].id);
29 clks[i].clk = of_clk_get(np, i);
30 if (IS_ERR(clks[i].clk)) {
31 ret = PTR_ERR(clks[i].clk);
32 dev_err_probe(dev, ret, "%pOF: Failed to get clk index: %d (%s)\n",
33 np, i, clks[i].id);
34 clks[i].clk = NULL;
35 goto err;
36 }
37 }
38
39 return 0;
40
41 err:
42 clk_bulk_put(i, clks);
43
44 return ret;
45 }
46
of_clk_bulk_get_all(struct device * dev,struct device_node * np,struct clk_bulk_data ** clks)47 static int __must_check of_clk_bulk_get_all(struct device *dev,
48 struct device_node *np,
49 struct clk_bulk_data **clks)
50 {
51 struct clk_bulk_data *clk_bulk;
52 int num_clks;
53 int ret;
54
55 num_clks = of_clk_get_parent_count(np);
56 if (!num_clks)
57 return 0;
58
59 clk_bulk = kmalloc_objs(*clk_bulk, num_clks);
60 if (!clk_bulk)
61 return -ENOMEM;
62
63 ret = of_clk_bulk_get(dev, np, num_clks, clk_bulk);
64 if (ret) {
65 kfree(clk_bulk);
66 return ret;
67 }
68
69 *clks = clk_bulk;
70
71 return num_clks;
72 }
73
clk_bulk_put(int num_clks,struct clk_bulk_data * clks)74 void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
75 {
76 while (--num_clks >= 0) {
77 clk_put(clks[num_clks].clk);
78 clks[num_clks].clk = NULL;
79 }
80 }
81 EXPORT_SYMBOL_GPL(clk_bulk_put);
82
__clk_bulk_get(struct device * dev,int num_clks,struct clk_bulk_data * clks,bool optional)83 static int __clk_bulk_get(struct device *dev, int num_clks,
84 struct clk_bulk_data *clks, bool optional)
85 {
86 int ret;
87 int i;
88
89 for (i = 0; i < num_clks; i++)
90 clks[i].clk = NULL;
91
92 for (i = 0; i < num_clks; i++) {
93 clks[i].clk = clk_get(dev, clks[i].id);
94 if (IS_ERR(clks[i].clk)) {
95 ret = PTR_ERR(clks[i].clk);
96 clks[i].clk = NULL;
97
98 if (ret == -ENOENT && optional)
99 continue;
100
101 dev_err_probe(dev, ret,
102 "Failed to get clk '%s'\n",
103 clks[i].id);
104 goto err;
105 }
106 }
107
108 return 0;
109
110 err:
111 clk_bulk_put(i, clks);
112
113 return ret;
114 }
115
clk_bulk_get(struct device * dev,int num_clks,struct clk_bulk_data * clks)116 int __must_check clk_bulk_get(struct device *dev, int num_clks,
117 struct clk_bulk_data *clks)
118 {
119 return __clk_bulk_get(dev, num_clks, clks, false);
120 }
121 EXPORT_SYMBOL(clk_bulk_get);
122
clk_bulk_get_optional(struct device * dev,int num_clks,struct clk_bulk_data * clks)123 int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
124 struct clk_bulk_data *clks)
125 {
126 return __clk_bulk_get(dev, num_clks, clks, true);
127 }
128 EXPORT_SYMBOL_GPL(clk_bulk_get_optional);
129
clk_bulk_put_all(int num_clks,struct clk_bulk_data * clks)130 void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
131 {
132 if (IS_ERR_OR_NULL(clks))
133 return;
134
135 clk_bulk_put(num_clks, clks);
136
137 kfree(clks);
138 }
139 EXPORT_SYMBOL(clk_bulk_put_all);
140
clk_bulk_get_all(struct device * dev,struct clk_bulk_data ** clks)141 int __must_check clk_bulk_get_all(struct device *dev,
142 struct clk_bulk_data **clks)
143 {
144 struct device_node *np = dev_of_node(dev);
145
146 if (!np)
147 return 0;
148
149 return of_clk_bulk_get_all(dev, np, clks);
150 }
151 EXPORT_SYMBOL(clk_bulk_get_all);
152
153 #ifdef CONFIG_HAVE_CLK_PREPARE
154
155 /**
156 * clk_bulk_unprepare - undo preparation of a set of clock sources
157 * @num_clks: the number of clk_bulk_data
158 * @clks: the clk_bulk_data table being unprepared
159 *
160 * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable.
161 * Returns 0 on success, -EERROR otherwise.
162 */
clk_bulk_unprepare(int num_clks,const struct clk_bulk_data * clks)163 void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks)
164 {
165 while (--num_clks >= 0)
166 clk_unprepare(clks[num_clks].clk);
167 }
168 EXPORT_SYMBOL_GPL(clk_bulk_unprepare);
169
170 /**
171 * clk_bulk_prepare - prepare a set of clocks
172 * @num_clks: the number of clk_bulk_data
173 * @clks: the clk_bulk_data table being prepared
174 *
175 * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable.
176 * Returns 0 on success, -EERROR otherwise.
177 */
clk_bulk_prepare(int num_clks,const struct clk_bulk_data * clks)178 int __must_check clk_bulk_prepare(int num_clks,
179 const struct clk_bulk_data *clks)
180 {
181 int ret;
182 int i;
183
184 for (i = 0; i < num_clks; i++) {
185 ret = clk_prepare(clks[i].clk);
186 if (ret) {
187 pr_err("Failed to prepare clk '%s': %d\n",
188 clks[i].id, ret);
189 goto err;
190 }
191 }
192
193 return 0;
194
195 err:
196 clk_bulk_unprepare(i, clks);
197
198 return ret;
199 }
200 EXPORT_SYMBOL_GPL(clk_bulk_prepare);
201
202 #endif /* CONFIG_HAVE_CLK_PREPARE */
203
204 /**
205 * clk_bulk_disable - gate a set of clocks
206 * @num_clks: the number of clk_bulk_data
207 * @clks: the clk_bulk_data table being gated
208 *
209 * clk_bulk_disable must not sleep, which differentiates it from
210 * clk_bulk_unprepare. clk_bulk_disable must be called before
211 * clk_bulk_unprepare.
212 */
clk_bulk_disable(int num_clks,const struct clk_bulk_data * clks)213 void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks)
214 {
215
216 while (--num_clks >= 0)
217 clk_disable(clks[num_clks].clk);
218 }
219 EXPORT_SYMBOL_GPL(clk_bulk_disable);
220
221 /**
222 * clk_bulk_enable - ungate a set of clocks
223 * @num_clks: the number of clk_bulk_data
224 * @clks: the clk_bulk_data table being ungated
225 *
226 * clk_bulk_enable must not sleep
227 * Returns 0 on success, -EERROR otherwise.
228 */
clk_bulk_enable(int num_clks,const struct clk_bulk_data * clks)229 int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks)
230 {
231 int ret;
232 int i;
233
234 for (i = 0; i < num_clks; i++) {
235 ret = clk_enable(clks[i].clk);
236 if (ret) {
237 pr_err("Failed to enable clk '%s': %d\n",
238 clks[i].id, ret);
239 goto err;
240 }
241 }
242
243 return 0;
244
245 err:
246 clk_bulk_disable(i, clks);
247
248 return ret;
249 }
250 EXPORT_SYMBOL_GPL(clk_bulk_enable);
251