blob: 15656f5973defe156faaeae2a7252e5fa562ef23 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass36ad2342015-06-23 15:39:15 -06002/*
3 * Copyright (C) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Stephen Warrena9622432016-06-17 09:44:00 -06005 * Copyright (c) 2016, NVIDIA CORPORATION.
Philipp Tomsich9cf03b02018-01-08 13:59:18 +01006 * Copyright (c) 2018, Theobroma Systems Design und Consulting GmbH
Simon Glass36ad2342015-06-23 15:39:15 -06007 */
8
9#include <common.h>
10#include <clk.h>
Stephen Warrena9622432016-06-17 09:44:00 -060011#include <clk-uclass.h>
Simon Glass36ad2342015-06-23 15:39:15 -060012#include <dm.h>
Simon Glass589d9152016-07-04 11:58:03 -060013#include <dt-structs.h>
Simon Glass36ad2342015-06-23 15:39:15 -060014#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070016#include <malloc.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070017#include <dm/devres.h>
18#include <dm/read.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060019#include <linux/bug.h>
Lukasz Majewski9e38dc32019-06-24 15:50:42 +020020#include <linux/clk-provider.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070021#include <linux/err.h>
Simon Glass36ad2342015-06-23 15:39:15 -060022
Mario Six799fe562018-01-15 11:06:51 +010023static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
Simon Glass36ad2342015-06-23 15:39:15 -060024{
Mario Six799fe562018-01-15 11:06:51 +010025 return (const struct clk_ops *)dev->driver->ops;
Simon Glass36ad2342015-06-23 15:39:15 -060026}
27
Stephen Warrena9622432016-06-17 09:44:00 -060028#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glass589d9152016-07-04 11:58:03 -060029# if CONFIG_IS_ENABLED(OF_PLATDATA)
Walter Lozanodc5b4372020-06-25 01:10:13 -030030int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells,
31 struct clk *clk)
Simon Glass589d9152016-07-04 11:58:03 -060032{
33 int ret;
34
Walter Lozanodc5b4372020-06-25 01:10:13 -030035 ret = device_get_by_driver_info((struct driver_info *)cells->node,
36 &clk->dev);
Simon Glass589d9152016-07-04 11:58:03 -060037 if (ret)
38 return ret;
Walter Lozanodc5b4372020-06-25 01:10:13 -030039 clk->id = cells->arg[0];
Simon Glass589d9152016-07-04 11:58:03 -060040
41 return 0;
42}
43# else
Stephen Warrena9622432016-06-17 09:44:00 -060044static int clk_of_xlate_default(struct clk *clk,
Simon Glassb7ae2772017-05-18 20:09:40 -060045 struct ofnode_phandle_args *args)
Simon Glass36ad2342015-06-23 15:39:15 -060046{
Stephen Warrena9622432016-06-17 09:44:00 -060047 debug("%s(clk=%p)\n", __func__, clk);
Simon Glass36ad2342015-06-23 15:39:15 -060048
Stephen Warrena9622432016-06-17 09:44:00 -060049 if (args->args_count > 1) {
50 debug("Invaild args_count: %d\n", args->args_count);
51 return -EINVAL;
52 }
Simon Glass36ad2342015-06-23 15:39:15 -060053
Stephen Warrena9622432016-06-17 09:44:00 -060054 if (args->args_count)
55 clk->id = args->args[0];
56 else
57 clk->id = 0;
Simon Glass36ad2342015-06-23 15:39:15 -060058
Sekhar Nori3d23abd2019-07-11 14:30:24 +053059 clk->data = 0;
60
Stephen Warrena9622432016-06-17 09:44:00 -060061 return 0;
Simon Glass36ad2342015-06-23 15:39:15 -060062}
Simon Glass0342bd22016-01-20 19:43:02 -070063
Jagan Tekifc7c7ce2019-02-28 00:26:52 +053064static int clk_get_by_index_tail(int ret, ofnode node,
65 struct ofnode_phandle_args *args,
66 const char *list_name, int index,
67 struct clk *clk)
68{
69 struct udevice *dev_clk;
70 const struct clk_ops *ops;
71
72 assert(clk);
73 clk->dev = NULL;
74 if (ret)
75 goto err;
76
77 ret = uclass_get_device_by_ofnode(UCLASS_CLK, args->node, &dev_clk);
78 if (ret) {
79 debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
80 __func__, ret);
81 return ret;
82 }
83
84 clk->dev = dev_clk;
85
86 ops = clk_dev_ops(dev_clk);
87
88 if (ops->of_xlate)
89 ret = ops->of_xlate(clk, args);
90 else
91 ret = clk_of_xlate_default(clk, args);
92 if (ret) {
93 debug("of_xlate() failed: %d\n", ret);
94 return ret;
95 }
96
97 return clk_request(dev_clk, clk);
98err:
99 debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n",
100 __func__, ofnode_get_name(node), list_name, index, ret);
101 return ret;
102}
103
Philipp Tomsichf7604342018-01-08 11:18:18 +0100104static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
105 int index, struct clk *clk)
Simon Glass0342bd22016-01-20 19:43:02 -0700106{
Simon Glass0342bd22016-01-20 19:43:02 -0700107 int ret;
Simon Glass2558bff2017-05-30 21:47:29 -0600108 struct ofnode_phandle_args args;
Simon Glass0342bd22016-01-20 19:43:02 -0700109
Stephen Warrena9622432016-06-17 09:44:00 -0600110 debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
111
112 assert(clk);
Patrice Chotard96fc03d2017-07-18 11:57:07 +0200113 clk->dev = NULL;
114
Philipp Tomsichf7604342018-01-08 11:18:18 +0100115 ret = dev_read_phandle_with_args(dev, prop_name, "#clock-cells", 0,
Mario Six799fe562018-01-15 11:06:51 +0100116 index, &args);
Simon Glass0342bd22016-01-20 19:43:02 -0700117 if (ret) {
118 debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
119 __func__, ret);
120 return ret;
121 }
122
Stephen Warrena9622432016-06-17 09:44:00 -0600123
Jagan Tekia77add32019-02-28 00:26:53 +0530124 return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400125 index, clk);
Stephen Warrena9622432016-06-17 09:44:00 -0600126}
Philipp Tomsichf7604342018-01-08 11:18:18 +0100127
128int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
129{
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530130 struct ofnode_phandle_args args;
131 int ret;
132
133 ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
134 index, &args);
135
136 return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400137 index, clk);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530138}
139
140int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)
141{
142 struct ofnode_phandle_args args;
143 int ret;
144
145 ret = ofnode_parse_phandle_with_args(node, "clocks", "#clock-cells", 0,
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400146 index, &args);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530147
148 return clk_get_by_index_tail(ret, node, &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400149 index, clk);
Philipp Tomsichf7604342018-01-08 11:18:18 +0100150}
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100151
Neil Armstrong8a275a02018-04-03 11:44:18 +0200152int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
153{
154 int i, ret, err, count;
155
156 bulk->count = 0;
157
158 count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
Neil Armstrong52b26d92018-04-17 11:30:31 +0200159 if (count < 1)
160 return count;
Neil Armstrong8a275a02018-04-03 11:44:18 +0200161
162 bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL);
163 if (!bulk->clks)
164 return -ENOMEM;
165
166 for (i = 0; i < count; i++) {
167 ret = clk_get_by_index(dev, i, &bulk->clks[i]);
168 if (ret < 0)
169 goto bulk_get_err;
170
171 ++bulk->count;
172 }
173
174 return 0;
175
176bulk_get_err:
177 err = clk_release_all(bulk->clks, bulk->count);
178 if (err)
179 debug("%s: could release all clocks for %p\n",
180 __func__, dev);
181
182 return ret;
183}
184
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200185static int clk_set_default_parents(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100186{
187 struct clk clk, parent_clk;
188 int index;
189 int num_parents;
190 int ret;
191
192 num_parents = dev_count_phandle_with_args(dev, "assigned-clock-parents",
193 "#clock-cells");
194 if (num_parents < 0) {
195 debug("%s: could not read assigned-clock-parents for %p\n",
196 __func__, dev);
197 return 0;
198 }
199
200 for (index = 0; index < num_parents; index++) {
201 ret = clk_get_by_indexed_prop(dev, "assigned-clock-parents",
202 index, &parent_clk);
Neil Armstrongf3cc6312018-07-26 15:19:32 +0200203 /* If -ENOENT, this is a no-op entry */
204 if (ret == -ENOENT)
205 continue;
206
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100207 if (ret) {
208 debug("%s: could not get parent clock %d for %s\n",
209 __func__, index, dev_read_name(dev));
210 return ret;
211 }
212
213 ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
214 index, &clk);
215 if (ret) {
216 debug("%s: could not get assigned clock %d for %s\n",
217 __func__, index, dev_read_name(dev));
218 return ret;
219 }
220
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200221 /* This is clk provider device trying to reparent itself
222 * It cannot be done right now but need to wait after the
223 * device is probed
224 */
225 if (stage == 0 && clk.dev == dev)
226 continue;
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100227
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200228 if (stage > 0 && clk.dev != dev)
229 /* do not setup twice the parent clocks */
230 continue;
231
232 ret = clk_set_parent(&clk, &parent_clk);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100233 /*
234 * Not all drivers may support clock-reparenting (as of now).
235 * Ignore errors due to this.
236 */
237 if (ret == -ENOSYS)
238 continue;
239
Jean-Jacques Hiblotb2320812019-09-26 15:42:42 +0200240 if (ret < 0) {
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100241 debug("%s: failed to reparent clock %d for %s\n",
242 __func__, index, dev_read_name(dev));
243 return ret;
244 }
245 }
246
247 return 0;
248}
249
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200250static int clk_set_default_rates(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100251{
252 struct clk clk;
253 int index;
254 int num_rates;
255 int size;
256 int ret = 0;
257 u32 *rates = NULL;
258
259 size = dev_read_size(dev, "assigned-clock-rates");
260 if (size < 0)
261 return 0;
262
263 num_rates = size / sizeof(u32);
264 rates = calloc(num_rates, sizeof(u32));
265 if (!rates)
266 return -ENOMEM;
267
268 ret = dev_read_u32_array(dev, "assigned-clock-rates", rates, num_rates);
269 if (ret)
270 goto fail;
271
272 for (index = 0; index < num_rates; index++) {
Neil Armstrongf3cc6312018-07-26 15:19:32 +0200273 /* If 0 is passed, this is a no-op */
274 if (!rates[index])
275 continue;
276
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100277 ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
278 index, &clk);
279 if (ret) {
280 debug("%s: could not get assigned clock %d for %s\n",
281 __func__, index, dev_read_name(dev));
282 continue;
283 }
284
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200285 /* This is clk provider device trying to program itself
286 * It cannot be done right now but need to wait after the
287 * device is probed
288 */
289 if (stage == 0 && clk.dev == dev)
290 continue;
291
292 if (stage > 0 && clk.dev != dev)
293 /* do not setup twice the parent clocks */
294 continue;
295
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100296 ret = clk_set_rate(&clk, rates[index]);
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200297
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100298 if (ret < 0) {
Simon Glass33363732019-01-21 14:53:19 -0700299 debug("%s: failed to set rate on clock index %d (%ld) for %s\n",
300 __func__, index, clk.id, dev_read_name(dev));
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100301 break;
302 }
303 }
304
305fail:
306 free(rates);
307 return ret;
308}
309
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200310int clk_set_defaults(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100311{
312 int ret;
313
Peng Fan40ec4e42019-07-31 07:01:49 +0000314 if (!dev_of_valid(dev))
315 return 0;
316
Philipp Tomsiche546ec82018-11-26 20:20:19 +0100317 /* If this not in SPL and pre-reloc state, don't take any action. */
318 if (!(IS_ENABLED(CONFIG_SPL_BUILD) || (gd->flags & GD_FLG_RELOC)))
319 return 0;
320
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100321 debug("%s(%s)\n", __func__, dev_read_name(dev));
322
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200323 ret = clk_set_default_parents(dev, stage);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100324 if (ret)
325 return ret;
326
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200327 ret = clk_set_default_rates(dev, stage);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100328 if (ret < 0)
329 return ret;
330
331 return 0;
332}
Stephen Warrena9622432016-06-17 09:44:00 -0600333
334int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
335{
336 int index;
337
338 debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
Patrice Chotard96fc03d2017-07-18 11:57:07 +0200339 clk->dev = NULL;
Stephen Warrena9622432016-06-17 09:44:00 -0600340
Simon Glass2558bff2017-05-30 21:47:29 -0600341 index = dev_read_stringlist_search(dev, "clock-names", name);
Stephen Warrena9622432016-06-17 09:44:00 -0600342 if (index < 0) {
Simon Glassb0ea7402016-10-02 17:59:28 -0600343 debug("fdt_stringlist_search() failed: %d\n", index);
Stephen Warrena9622432016-06-17 09:44:00 -0600344 return index;
345 }
346
347 return clk_get_by_index(dev, index, clk);
Simon Glass0342bd22016-01-20 19:43:02 -0700348}
Giulio Benetti6c910872019-12-12 23:53:19 +0100349# endif /* OF_PLATDATA */
Patrice Chotardcafc3412017-07-25 13:24:45 +0200350
developerbdc786d2020-01-09 11:35:07 +0800351int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk)
352{
353 int index;
354
355 debug("%s(node=%p, name=%s, clk=%p)\n", __func__,
356 ofnode_get_name(node), name, clk);
357 clk->dev = NULL;
358
359 index = ofnode_stringlist_search(node, "clock-names", name);
360 if (index < 0) {
361 debug("fdt_stringlist_search() failed: %d\n", index);
362 return index;
363 }
364
365 return clk_get_by_index_nodev(node, index, clk);
366}
367
368int clk_get_optional_nodev(ofnode node, const char *name, struct clk *clk)
369{
370 int ret;
371
372 ret = clk_get_by_name_nodev(node, name, clk);
373 if (ret == -ENODATA)
374 return 0;
375
376 return ret;
377}
378
Patrice Chotardcafc3412017-07-25 13:24:45 +0200379int clk_release_all(struct clk *clk, int count)
380{
381 int i, ret;
382
383 for (i = 0; i < count; i++) {
384 debug("%s(clk[%d]=%p)\n", __func__, i, &clk[i]);
385
386 /* check if clock has been previously requested */
387 if (!clk[i].dev)
388 continue;
389
390 ret = clk_disable(&clk[i]);
391 if (ret && ret != -ENOSYS)
392 return ret;
393
394 ret = clk_free(&clk[i]);
395 if (ret && ret != -ENOSYS)
396 return ret;
397 }
398
399 return 0;
400}
401
Simon Glass589d9152016-07-04 11:58:03 -0600402#endif /* OF_CONTROL */
Stephen Warrena9622432016-06-17 09:44:00 -0600403
404int clk_request(struct udevice *dev, struct clk *clk)
405{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200406 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600407
408 debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200409 if (!clk)
410 return 0;
411 ops = clk_dev_ops(dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600412
413 clk->dev = dev;
414
415 if (!ops->request)
416 return 0;
417
418 return ops->request(clk);
419}
420
421int clk_free(struct clk *clk)
422{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200423 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600424
425 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800426 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200427 return 0;
428 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600429
Simon Glass2cdd3f42020-02-03 07:35:54 -0700430 if (!ops->rfree)
Stephen Warrena9622432016-06-17 09:44:00 -0600431 return 0;
432
Simon Glass2cdd3f42020-02-03 07:35:54 -0700433 return ops->rfree(clk);
Stephen Warrena9622432016-06-17 09:44:00 -0600434}
435
436ulong clk_get_rate(struct clk *clk)
437{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200438 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600439
440 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800441 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200442 return 0;
443 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600444
445 if (!ops->get_rate)
446 return -ENOSYS;
447
448 return ops->get_rate(clk);
449}
450
Lukasz Majewski9e38dc32019-06-24 15:50:42 +0200451struct clk *clk_get_parent(struct clk *clk)
452{
453 struct udevice *pdev;
454 struct clk *pclk;
455
456 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800457 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200458 return NULL;
Lukasz Majewski9e38dc32019-06-24 15:50:42 +0200459
460 pdev = dev_get_parent(clk->dev);
461 pclk = dev_get_clk_ptr(pdev);
462 if (!pclk)
463 return ERR_PTR(-ENODEV);
464
465 return pclk;
466}
467
Lukasz Majewski53155da2019-06-24 15:50:43 +0200468long long clk_get_parent_rate(struct clk *clk)
469{
470 const struct clk_ops *ops;
471 struct clk *pclk;
472
473 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800474 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200475 return 0;
Lukasz Majewski53155da2019-06-24 15:50:43 +0200476
477 pclk = clk_get_parent(clk);
478 if (IS_ERR(pclk))
479 return -ENODEV;
480
481 ops = clk_dev_ops(pclk->dev);
482 if (!ops->get_rate)
483 return -ENOSYS;
484
Lukasz Majewski4ef32172019-06-24 15:50:46 +0200485 /* Read the 'rate' if not already set or if proper flag set*/
486 if (!pclk->rate || pclk->flags & CLK_GET_RATE_NOCACHE)
Lukasz Majewski53155da2019-06-24 15:50:43 +0200487 pclk->rate = clk_get_rate(pclk);
488
489 return pclk->rate;
490}
491
Stephen Warrena9622432016-06-17 09:44:00 -0600492ulong clk_set_rate(struct clk *clk, ulong rate)
493{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200494 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600495
496 debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
developerdc338d32020-01-09 11:35:06 +0800497 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200498 return 0;
499 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600500
501 if (!ops->set_rate)
502 return -ENOSYS;
503
504 return ops->set_rate(clk, rate);
505}
506
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100507int clk_set_parent(struct clk *clk, struct clk *parent)
508{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200509 const struct clk_ops *ops;
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100510
511 debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent);
developerdc338d32020-01-09 11:35:06 +0800512 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200513 return 0;
514 ops = clk_dev_ops(clk->dev);
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100515
516 if (!ops->set_parent)
517 return -ENOSYS;
518
519 return ops->set_parent(clk, parent);
520}
521
Stephen Warrena9622432016-06-17 09:44:00 -0600522int clk_enable(struct clk *clk)
523{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200524 const struct clk_ops *ops;
Peng Fan82628e22019-08-21 13:35:09 +0000525 struct clk *clkp = NULL;
526 int ret;
Stephen Warrena9622432016-06-17 09:44:00 -0600527
528 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800529 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200530 return 0;
531 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600532
Peng Fan82628e22019-08-21 13:35:09 +0000533 if (CONFIG_IS_ENABLED(CLK_CCF)) {
534 /* Take id 0 as a non-valid clk, such as dummy */
535 if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
536 if (clkp->enable_count) {
537 clkp->enable_count++;
538 return 0;
539 }
540 if (clkp->dev->parent &&
541 device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
542 ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent));
543 if (ret) {
544 printf("Enable %s failed\n",
545 clkp->dev->parent->name);
546 return ret;
547 }
548 }
549 }
Stephen Warrena9622432016-06-17 09:44:00 -0600550
Peng Fan82628e22019-08-21 13:35:09 +0000551 if (ops->enable) {
552 ret = ops->enable(clk);
553 if (ret) {
554 printf("Enable %s failed\n", clk->dev->name);
555 return ret;
556 }
557 }
558 if (clkp)
559 clkp->enable_count++;
560 } else {
561 if (!ops->enable)
562 return -ENOSYS;
563 return ops->enable(clk);
564 }
565
566 return 0;
Stephen Warrena9622432016-06-17 09:44:00 -0600567}
568
Neil Armstrong8a275a02018-04-03 11:44:18 +0200569int clk_enable_bulk(struct clk_bulk *bulk)
570{
571 int i, ret;
572
573 for (i = 0; i < bulk->count; i++) {
574 ret = clk_enable(&bulk->clks[i]);
575 if (ret < 0 && ret != -ENOSYS)
576 return ret;
577 }
578
579 return 0;
580}
581
Stephen Warrena9622432016-06-17 09:44:00 -0600582int clk_disable(struct clk *clk)
583{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200584 const struct clk_ops *ops;
Peng Fan82628e22019-08-21 13:35:09 +0000585 struct clk *clkp = NULL;
586 int ret;
Stephen Warrena9622432016-06-17 09:44:00 -0600587
588 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800589 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200590 return 0;
591 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600592
Peng Fan82628e22019-08-21 13:35:09 +0000593 if (CONFIG_IS_ENABLED(CLK_CCF)) {
594 if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
595 if (clkp->enable_count == 0) {
596 printf("clk %s already disabled\n",
597 clkp->dev->name);
598 return 0;
599 }
Stephen Warrena9622432016-06-17 09:44:00 -0600600
Peng Fan82628e22019-08-21 13:35:09 +0000601 if (--clkp->enable_count > 0)
602 return 0;
603 }
604
605 if (ops->disable) {
606 ret = ops->disable(clk);
607 if (ret)
608 return ret;
609 }
610
611 if (clkp && clkp->dev->parent &&
612 device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
613 ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent));
614 if (ret) {
615 printf("Disable %s failed\n",
616 clkp->dev->parent->name);
617 return ret;
618 }
619 }
620 } else {
621 if (!ops->disable)
622 return -ENOSYS;
623
624 return ops->disable(clk);
625 }
626
627 return 0;
Stephen Warrena9622432016-06-17 09:44:00 -0600628}
Simon Glass36ad2342015-06-23 15:39:15 -0600629
Neil Armstrong8a275a02018-04-03 11:44:18 +0200630int clk_disable_bulk(struct clk_bulk *bulk)
631{
632 int i, ret;
633
634 for (i = 0; i < bulk->count; i++) {
635 ret = clk_disable(&bulk->clks[i]);
636 if (ret < 0 && ret != -ENOSYS)
637 return ret;
638 }
639
640 return 0;
641}
642
Lukasz Majewski12014be2019-06-24 15:50:44 +0200643int clk_get_by_id(ulong id, struct clk **clkp)
644{
645 struct udevice *dev;
646 struct uclass *uc;
647 int ret;
648
649 ret = uclass_get(UCLASS_CLK, &uc);
650 if (ret)
651 return ret;
652
653 uclass_foreach_dev(dev, uc) {
654 struct clk *clk = dev_get_clk_ptr(dev);
655
656 if (clk && clk->id == id) {
657 *clkp = clk;
658 return 0;
659 }
660 }
661
662 return -ENOENT;
663}
664
Sekhar Noricf3119d2019-08-01 19:12:55 +0530665bool clk_is_match(const struct clk *p, const struct clk *q)
666{
667 /* trivial case: identical struct clk's or both NULL */
668 if (p == q)
669 return true;
670
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200671 /* trivial case #2: on the clk pointer is NULL */
672 if (!p || !q)
673 return false;
674
Sekhar Noricf3119d2019-08-01 19:12:55 +0530675 /* same device, id and data */
676 if (p->dev == q->dev && p->id == q->id && p->data == q->data)
677 return true;
678
679 return false;
680}
681
Jean-Jacques Hiblot6e66b2d2019-10-22 14:00:04 +0200682static void devm_clk_release(struct udevice *dev, void *res)
683{
684 clk_free(res);
685}
686
687static int devm_clk_match(struct udevice *dev, void *res, void *data)
688{
689 return res == data;
690}
691
692struct clk *devm_clk_get(struct udevice *dev, const char *id)
693{
694 int rc;
695 struct clk *clk;
696
697 clk = devres_alloc(devm_clk_release, sizeof(struct clk), __GFP_ZERO);
698 if (unlikely(!clk))
699 return ERR_PTR(-ENOMEM);
700
701 rc = clk_get_by_name(dev, id, clk);
702 if (rc)
703 return ERR_PTR(rc);
704
705 devres_add(dev, clk);
706 return clk;
707}
708
709struct clk *devm_clk_get_optional(struct udevice *dev, const char *id)
710{
711 struct clk *clk = devm_clk_get(dev, id);
712
developer5e108fb2020-01-09 11:35:05 +0800713 if (PTR_ERR(clk) == -ENODATA)
Jean-Jacques Hiblot6e66b2d2019-10-22 14:00:04 +0200714 return NULL;
715
716 return clk;
717}
718
719void devm_clk_put(struct udevice *dev, struct clk *clk)
720{
721 int rc;
722
723 if (!clk)
724 return;
725
726 rc = devres_release(dev, devm_clk_release, devm_clk_match, clk);
727 WARN_ON(rc);
728}
729
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200730int clk_uclass_post_probe(struct udevice *dev)
731{
732 /*
733 * when a clock provider is probed. Call clk_set_defaults()
734 * also after the device is probed. This takes care of cases
735 * where the DT is used to setup default parents and rates
736 * using assigned-clocks
737 */
738 clk_set_defaults(dev, 1);
739
740 return 0;
741}
742
Simon Glass36ad2342015-06-23 15:39:15 -0600743UCLASS_DRIVER(clk) = {
744 .id = UCLASS_CLK,
745 .name = "clk",
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200746 .post_probe = clk_uclass_post_probe,
Simon Glass36ad2342015-06-23 15:39:15 -0600747};