blob: 31c5997aead8cedac5f46a52ae5255514ea37047 [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>
Claudiu Bezneac8c16002020-09-07 17:46:34 +030017#include <dm/device-internal.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070018#include <dm/devres.h>
19#include <dm/read.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060020#include <linux/bug.h>
Lukasz Majewski9e38dc32019-06-24 15:50:42 +020021#include <linux/clk-provider.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070022#include <linux/err.h>
Simon Glass36ad2342015-06-23 15:39:15 -060023
Mario Six799fe562018-01-15 11:06:51 +010024static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
Simon Glass36ad2342015-06-23 15:39:15 -060025{
Mario Six799fe562018-01-15 11:06:51 +010026 return (const struct clk_ops *)dev->driver->ops;
Simon Glass36ad2342015-06-23 15:39:15 -060027}
28
Simon Glass43033962020-07-19 10:15:56 -060029struct clk *dev_get_clk_ptr(struct udevice *dev)
30{
31 return (struct clk *)dev_get_uclass_priv(dev);
32}
33
Stephen Warrena9622432016-06-17 09:44:00 -060034#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glass589d9152016-07-04 11:58:03 -060035# if CONFIG_IS_ENABLED(OF_PLATDATA)
Walter Lozanodc5b4372020-06-25 01:10:13 -030036int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells,
37 struct clk *clk)
Simon Glass589d9152016-07-04 11:58:03 -060038{
39 int ret;
40
Walter Lozanodc5b4372020-06-25 01:10:13 -030041 ret = device_get_by_driver_info((struct driver_info *)cells->node,
42 &clk->dev);
Simon Glass589d9152016-07-04 11:58:03 -060043 if (ret)
44 return ret;
Walter Lozanodc5b4372020-06-25 01:10:13 -030045 clk->id = cells->arg[0];
Simon Glass589d9152016-07-04 11:58:03 -060046
47 return 0;
48}
49# else
Stephen Warrena9622432016-06-17 09:44:00 -060050static int clk_of_xlate_default(struct clk *clk,
Simon Glassb7ae2772017-05-18 20:09:40 -060051 struct ofnode_phandle_args *args)
Simon Glass36ad2342015-06-23 15:39:15 -060052{
Stephen Warrena9622432016-06-17 09:44:00 -060053 debug("%s(clk=%p)\n", __func__, clk);
Simon Glass36ad2342015-06-23 15:39:15 -060054
Stephen Warrena9622432016-06-17 09:44:00 -060055 if (args->args_count > 1) {
56 debug("Invaild args_count: %d\n", args->args_count);
57 return -EINVAL;
58 }
Simon Glass36ad2342015-06-23 15:39:15 -060059
Stephen Warrena9622432016-06-17 09:44:00 -060060 if (args->args_count)
61 clk->id = args->args[0];
62 else
63 clk->id = 0;
Simon Glass36ad2342015-06-23 15:39:15 -060064
Sekhar Nori3d23abd2019-07-11 14:30:24 +053065 clk->data = 0;
66
Stephen Warrena9622432016-06-17 09:44:00 -060067 return 0;
Simon Glass36ad2342015-06-23 15:39:15 -060068}
Simon Glass0342bd22016-01-20 19:43:02 -070069
Jagan Tekifc7c7ce2019-02-28 00:26:52 +053070static int clk_get_by_index_tail(int ret, ofnode node,
71 struct ofnode_phandle_args *args,
72 const char *list_name, int index,
73 struct clk *clk)
74{
75 struct udevice *dev_clk;
76 const struct clk_ops *ops;
77
78 assert(clk);
79 clk->dev = NULL;
80 if (ret)
81 goto err;
82
83 ret = uclass_get_device_by_ofnode(UCLASS_CLK, args->node, &dev_clk);
84 if (ret) {
85 debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
86 __func__, ret);
87 return ret;
88 }
89
90 clk->dev = dev_clk;
91
92 ops = clk_dev_ops(dev_clk);
93
94 if (ops->of_xlate)
95 ret = ops->of_xlate(clk, args);
96 else
97 ret = clk_of_xlate_default(clk, args);
98 if (ret) {
99 debug("of_xlate() failed: %d\n", ret);
100 return ret;
101 }
102
103 return clk_request(dev_clk, clk);
104err:
105 debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n",
106 __func__, ofnode_get_name(node), list_name, index, ret);
107 return ret;
108}
109
Philipp Tomsichf7604342018-01-08 11:18:18 +0100110static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
111 int index, struct clk *clk)
Simon Glass0342bd22016-01-20 19:43:02 -0700112{
Simon Glass0342bd22016-01-20 19:43:02 -0700113 int ret;
Simon Glass2558bff2017-05-30 21:47:29 -0600114 struct ofnode_phandle_args args;
Simon Glass0342bd22016-01-20 19:43:02 -0700115
Stephen Warrena9622432016-06-17 09:44:00 -0600116 debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
117
118 assert(clk);
Patrice Chotard96fc03d2017-07-18 11:57:07 +0200119 clk->dev = NULL;
120
Philipp Tomsichf7604342018-01-08 11:18:18 +0100121 ret = dev_read_phandle_with_args(dev, prop_name, "#clock-cells", 0,
Mario Six799fe562018-01-15 11:06:51 +0100122 index, &args);
Simon Glass0342bd22016-01-20 19:43:02 -0700123 if (ret) {
124 debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
125 __func__, ret);
126 return ret;
127 }
128
Stephen Warrena9622432016-06-17 09:44:00 -0600129
Jagan Tekia77add32019-02-28 00:26:53 +0530130 return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400131 index, clk);
Stephen Warrena9622432016-06-17 09:44:00 -0600132}
Philipp Tomsichf7604342018-01-08 11:18:18 +0100133
134int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
135{
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530136 struct ofnode_phandle_args args;
137 int ret;
138
139 ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
140 index, &args);
141
142 return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400143 index, clk);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530144}
145
146int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)
147{
148 struct ofnode_phandle_args args;
149 int ret;
150
151 ret = ofnode_parse_phandle_with_args(node, "clocks", "#clock-cells", 0,
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400152 index, &args);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530153
154 return clk_get_by_index_tail(ret, node, &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400155 index, clk);
Philipp Tomsichf7604342018-01-08 11:18:18 +0100156}
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100157
Neil Armstrong8a275a02018-04-03 11:44:18 +0200158int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
159{
160 int i, ret, err, count;
161
162 bulk->count = 0;
163
Patrick Delaunayd776a842020-09-25 09:41:14 +0200164 count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", 0);
Neil Armstrong52b26d92018-04-17 11:30:31 +0200165 if (count < 1)
166 return count;
Neil Armstrong8a275a02018-04-03 11:44:18 +0200167
168 bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL);
169 if (!bulk->clks)
170 return -ENOMEM;
171
172 for (i = 0; i < count; i++) {
173 ret = clk_get_by_index(dev, i, &bulk->clks[i]);
174 if (ret < 0)
175 goto bulk_get_err;
176
177 ++bulk->count;
178 }
179
180 return 0;
181
182bulk_get_err:
183 err = clk_release_all(bulk->clks, bulk->count);
184 if (err)
185 debug("%s: could release all clocks for %p\n",
186 __func__, dev);
187
188 return ret;
189}
190
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300191static struct clk *clk_set_default_get_by_id(struct clk *clk)
192{
193 struct clk *c = clk;
194
195 if (CONFIG_IS_ENABLED(CLK_CCF)) {
196 int ret = clk_get_by_id(clk->id, &c);
197
198 if (ret) {
199 debug("%s(): could not get parent clock pointer, id %lu\n",
200 __func__, clk->id);
201 ERR_PTR(ret);
202 }
203 }
204
205 return c;
206}
207
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200208static int clk_set_default_parents(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100209{
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300210 struct clk clk, parent_clk, *c, *p;
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100211 int index;
212 int num_parents;
213 int ret;
214
215 num_parents = dev_count_phandle_with_args(dev, "assigned-clock-parents",
Patrick Delaunayd776a842020-09-25 09:41:14 +0200216 "#clock-cells", 0);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100217 if (num_parents < 0) {
218 debug("%s: could not read assigned-clock-parents for %p\n",
219 __func__, dev);
220 return 0;
221 }
222
223 for (index = 0; index < num_parents; index++) {
224 ret = clk_get_by_indexed_prop(dev, "assigned-clock-parents",
225 index, &parent_clk);
Neil Armstrongf3cc6312018-07-26 15:19:32 +0200226 /* If -ENOENT, this is a no-op entry */
227 if (ret == -ENOENT)
228 continue;
229
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100230 if (ret) {
231 debug("%s: could not get parent clock %d for %s\n",
232 __func__, index, dev_read_name(dev));
233 return ret;
234 }
235
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300236 p = clk_set_default_get_by_id(&parent_clk);
237 if (IS_ERR(p))
238 return PTR_ERR(p);
239
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100240 ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
241 index, &clk);
242 if (ret) {
243 debug("%s: could not get assigned clock %d for %s\n",
244 __func__, index, dev_read_name(dev));
245 return ret;
246 }
247
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200248 /* This is clk provider device trying to reparent itself
249 * It cannot be done right now but need to wait after the
250 * device is probed
251 */
252 if (stage == 0 && clk.dev == dev)
253 continue;
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100254
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200255 if (stage > 0 && clk.dev != dev)
256 /* do not setup twice the parent clocks */
257 continue;
258
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300259 c = clk_set_default_get_by_id(&clk);
260 if (IS_ERR(c))
261 return PTR_ERR(c);
262
263 ret = clk_set_parent(c, p);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100264 /*
265 * Not all drivers may support clock-reparenting (as of now).
266 * Ignore errors due to this.
267 */
268 if (ret == -ENOSYS)
269 continue;
270
Jean-Jacques Hiblotb2320812019-09-26 15:42:42 +0200271 if (ret < 0) {
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100272 debug("%s: failed to reparent clock %d for %s\n",
273 __func__, index, dev_read_name(dev));
274 return ret;
275 }
276 }
277
278 return 0;
279}
280
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200281static int clk_set_default_rates(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100282{
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300283 struct clk clk, *c;
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100284 int index;
285 int num_rates;
286 int size;
287 int ret = 0;
288 u32 *rates = NULL;
289
290 size = dev_read_size(dev, "assigned-clock-rates");
291 if (size < 0)
292 return 0;
293
294 num_rates = size / sizeof(u32);
295 rates = calloc(num_rates, sizeof(u32));
296 if (!rates)
297 return -ENOMEM;
298
299 ret = dev_read_u32_array(dev, "assigned-clock-rates", rates, num_rates);
300 if (ret)
301 goto fail;
302
303 for (index = 0; index < num_rates; index++) {
Neil Armstrongf3cc6312018-07-26 15:19:32 +0200304 /* If 0 is passed, this is a no-op */
305 if (!rates[index])
306 continue;
307
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100308 ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
309 index, &clk);
310 if (ret) {
311 debug("%s: could not get assigned clock %d for %s\n",
312 __func__, index, dev_read_name(dev));
313 continue;
314 }
315
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200316 /* This is clk provider device trying to program itself
317 * It cannot be done right now but need to wait after the
318 * device is probed
319 */
320 if (stage == 0 && clk.dev == dev)
321 continue;
322
323 if (stage > 0 && clk.dev != dev)
324 /* do not setup twice the parent clocks */
325 continue;
326
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300327 c = clk_set_default_get_by_id(&clk);
328 if (IS_ERR(c))
329 return PTR_ERR(c);
330
331 ret = clk_set_rate(c, rates[index]);
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200332
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100333 if (ret < 0) {
Simon Glass33363732019-01-21 14:53:19 -0700334 debug("%s: failed to set rate on clock index %d (%ld) for %s\n",
335 __func__, index, clk.id, dev_read_name(dev));
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100336 break;
337 }
338 }
339
340fail:
341 free(rates);
342 return ret;
343}
344
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200345int clk_set_defaults(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100346{
347 int ret;
348
Peng Fan40ec4e42019-07-31 07:01:49 +0000349 if (!dev_of_valid(dev))
350 return 0;
351
Philipp Tomsiche546ec82018-11-26 20:20:19 +0100352 /* If this not in SPL and pre-reloc state, don't take any action. */
353 if (!(IS_ENABLED(CONFIG_SPL_BUILD) || (gd->flags & GD_FLG_RELOC)))
354 return 0;
355
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100356 debug("%s(%s)\n", __func__, dev_read_name(dev));
357
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200358 ret = clk_set_default_parents(dev, stage);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100359 if (ret)
360 return ret;
361
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200362 ret = clk_set_default_rates(dev, stage);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100363 if (ret < 0)
364 return ret;
365
366 return 0;
367}
Stephen Warrena9622432016-06-17 09:44:00 -0600368
369int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
370{
371 int index;
372
373 debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
Patrice Chotard96fc03d2017-07-18 11:57:07 +0200374 clk->dev = NULL;
Stephen Warrena9622432016-06-17 09:44:00 -0600375
Simon Glass2558bff2017-05-30 21:47:29 -0600376 index = dev_read_stringlist_search(dev, "clock-names", name);
Stephen Warrena9622432016-06-17 09:44:00 -0600377 if (index < 0) {
Simon Glassb0ea7402016-10-02 17:59:28 -0600378 debug("fdt_stringlist_search() failed: %d\n", index);
Stephen Warrena9622432016-06-17 09:44:00 -0600379 return index;
380 }
381
382 return clk_get_by_index(dev, index, clk);
Simon Glass0342bd22016-01-20 19:43:02 -0700383}
Giulio Benetti6c910872019-12-12 23:53:19 +0100384# endif /* OF_PLATDATA */
Patrice Chotardcafc3412017-07-25 13:24:45 +0200385
developerbdc786d2020-01-09 11:35:07 +0800386int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk)
387{
388 int index;
389
390 debug("%s(node=%p, name=%s, clk=%p)\n", __func__,
391 ofnode_get_name(node), name, clk);
392 clk->dev = NULL;
393
394 index = ofnode_stringlist_search(node, "clock-names", name);
395 if (index < 0) {
396 debug("fdt_stringlist_search() failed: %d\n", index);
397 return index;
398 }
399
400 return clk_get_by_index_nodev(node, index, clk);
401}
402
403int clk_get_optional_nodev(ofnode node, const char *name, struct clk *clk)
404{
405 int ret;
406
407 ret = clk_get_by_name_nodev(node, name, clk);
408 if (ret == -ENODATA)
409 return 0;
410
411 return ret;
412}
413
Patrice Chotardcafc3412017-07-25 13:24:45 +0200414int clk_release_all(struct clk *clk, int count)
415{
416 int i, ret;
417
418 for (i = 0; i < count; i++) {
419 debug("%s(clk[%d]=%p)\n", __func__, i, &clk[i]);
420
421 /* check if clock has been previously requested */
422 if (!clk[i].dev)
423 continue;
424
425 ret = clk_disable(&clk[i]);
426 if (ret && ret != -ENOSYS)
427 return ret;
428
429 ret = clk_free(&clk[i]);
430 if (ret && ret != -ENOSYS)
431 return ret;
432 }
433
434 return 0;
435}
436
Simon Glass589d9152016-07-04 11:58:03 -0600437#endif /* OF_CONTROL */
Stephen Warrena9622432016-06-17 09:44:00 -0600438
439int clk_request(struct udevice *dev, struct clk *clk)
440{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200441 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600442
443 debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200444 if (!clk)
445 return 0;
446 ops = clk_dev_ops(dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600447
448 clk->dev = dev;
449
450 if (!ops->request)
451 return 0;
452
453 return ops->request(clk);
454}
455
456int clk_free(struct clk *clk)
457{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200458 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600459
460 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800461 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200462 return 0;
463 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600464
Simon Glass2cdd3f42020-02-03 07:35:54 -0700465 if (!ops->rfree)
Stephen Warrena9622432016-06-17 09:44:00 -0600466 return 0;
467
Simon Glass2cdd3f42020-02-03 07:35:54 -0700468 return ops->rfree(clk);
Stephen Warrena9622432016-06-17 09:44:00 -0600469}
470
471ulong clk_get_rate(struct clk *clk)
472{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200473 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600474
475 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800476 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200477 return 0;
478 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600479
480 if (!ops->get_rate)
481 return -ENOSYS;
482
483 return ops->get_rate(clk);
484}
485
Lukasz Majewski9e38dc32019-06-24 15:50:42 +0200486struct clk *clk_get_parent(struct clk *clk)
487{
488 struct udevice *pdev;
489 struct clk *pclk;
490
491 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800492 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200493 return NULL;
Lukasz Majewski9e38dc32019-06-24 15:50:42 +0200494
495 pdev = dev_get_parent(clk->dev);
496 pclk = dev_get_clk_ptr(pdev);
497 if (!pclk)
498 return ERR_PTR(-ENODEV);
499
500 return pclk;
501}
502
Lukasz Majewski53155da2019-06-24 15:50:43 +0200503long long clk_get_parent_rate(struct clk *clk)
504{
505 const struct clk_ops *ops;
506 struct clk *pclk;
507
508 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800509 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200510 return 0;
Lukasz Majewski53155da2019-06-24 15:50:43 +0200511
512 pclk = clk_get_parent(clk);
513 if (IS_ERR(pclk))
514 return -ENODEV;
515
516 ops = clk_dev_ops(pclk->dev);
517 if (!ops->get_rate)
518 return -ENOSYS;
519
Lukasz Majewski4ef32172019-06-24 15:50:46 +0200520 /* Read the 'rate' if not already set or if proper flag set*/
521 if (!pclk->rate || pclk->flags & CLK_GET_RATE_NOCACHE)
Lukasz Majewski53155da2019-06-24 15:50:43 +0200522 pclk->rate = clk_get_rate(pclk);
523
524 return pclk->rate;
525}
526
Stephen Warrena9622432016-06-17 09:44:00 -0600527ulong clk_set_rate(struct clk *clk, ulong rate)
528{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200529 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600530
531 debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
developerdc338d32020-01-09 11:35:06 +0800532 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200533 return 0;
534 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600535
536 if (!ops->set_rate)
537 return -ENOSYS;
538
539 return ops->set_rate(clk, rate);
540}
541
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100542int clk_set_parent(struct clk *clk, struct clk *parent)
543{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200544 const struct clk_ops *ops;
Claudiu Bezneac8c16002020-09-07 17:46:34 +0300545 int ret;
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100546
547 debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent);
developerdc338d32020-01-09 11:35:06 +0800548 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200549 return 0;
550 ops = clk_dev_ops(clk->dev);
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100551
552 if (!ops->set_parent)
553 return -ENOSYS;
554
Claudiu Bezneac8c16002020-09-07 17:46:34 +0300555 ret = ops->set_parent(clk, parent);
556 if (ret)
557 return ret;
558
559 if (CONFIG_IS_ENABLED(CLK_CCF))
560 ret = device_reparent(clk->dev, parent->dev);
561
562 return ret;
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100563}
564
Stephen Warrena9622432016-06-17 09:44:00 -0600565int clk_enable(struct clk *clk)
566{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200567 const struct clk_ops *ops;
Peng Fan82628e22019-08-21 13:35:09 +0000568 struct clk *clkp = NULL;
569 int ret;
Stephen Warrena9622432016-06-17 09:44:00 -0600570
571 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800572 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200573 return 0;
574 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600575
Peng Fan82628e22019-08-21 13:35:09 +0000576 if (CONFIG_IS_ENABLED(CLK_CCF)) {
577 /* Take id 0 as a non-valid clk, such as dummy */
578 if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
579 if (clkp->enable_count) {
580 clkp->enable_count++;
581 return 0;
582 }
583 if (clkp->dev->parent &&
584 device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
585 ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent));
586 if (ret) {
587 printf("Enable %s failed\n",
588 clkp->dev->parent->name);
589 return ret;
590 }
591 }
592 }
Stephen Warrena9622432016-06-17 09:44:00 -0600593
Peng Fan82628e22019-08-21 13:35:09 +0000594 if (ops->enable) {
595 ret = ops->enable(clk);
596 if (ret) {
597 printf("Enable %s failed\n", clk->dev->name);
598 return ret;
599 }
600 }
601 if (clkp)
602 clkp->enable_count++;
603 } else {
604 if (!ops->enable)
605 return -ENOSYS;
606 return ops->enable(clk);
607 }
608
609 return 0;
Stephen Warrena9622432016-06-17 09:44:00 -0600610}
611
Neil Armstrong8a275a02018-04-03 11:44:18 +0200612int clk_enable_bulk(struct clk_bulk *bulk)
613{
614 int i, ret;
615
616 for (i = 0; i < bulk->count; i++) {
617 ret = clk_enable(&bulk->clks[i]);
618 if (ret < 0 && ret != -ENOSYS)
619 return ret;
620 }
621
622 return 0;
623}
624
Stephen Warrena9622432016-06-17 09:44:00 -0600625int clk_disable(struct clk *clk)
626{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200627 const struct clk_ops *ops;
Peng Fan82628e22019-08-21 13:35:09 +0000628 struct clk *clkp = NULL;
629 int ret;
Stephen Warrena9622432016-06-17 09:44:00 -0600630
631 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800632 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200633 return 0;
634 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600635
Peng Fan82628e22019-08-21 13:35:09 +0000636 if (CONFIG_IS_ENABLED(CLK_CCF)) {
637 if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
Claudiu Bezneab02e8dd2020-09-07 17:46:35 +0300638 if (clkp->flags & CLK_IS_CRITICAL)
639 return 0;
640
Peng Fan82628e22019-08-21 13:35:09 +0000641 if (clkp->enable_count == 0) {
642 printf("clk %s already disabled\n",
643 clkp->dev->name);
644 return 0;
645 }
Stephen Warrena9622432016-06-17 09:44:00 -0600646
Peng Fan82628e22019-08-21 13:35:09 +0000647 if (--clkp->enable_count > 0)
648 return 0;
649 }
650
651 if (ops->disable) {
652 ret = ops->disable(clk);
653 if (ret)
654 return ret;
655 }
656
657 if (clkp && clkp->dev->parent &&
658 device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
659 ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent));
660 if (ret) {
661 printf("Disable %s failed\n",
662 clkp->dev->parent->name);
663 return ret;
664 }
665 }
666 } else {
667 if (!ops->disable)
668 return -ENOSYS;
669
670 return ops->disable(clk);
671 }
672
673 return 0;
Stephen Warrena9622432016-06-17 09:44:00 -0600674}
Simon Glass36ad2342015-06-23 15:39:15 -0600675
Neil Armstrong8a275a02018-04-03 11:44:18 +0200676int clk_disable_bulk(struct clk_bulk *bulk)
677{
678 int i, ret;
679
680 for (i = 0; i < bulk->count; i++) {
681 ret = clk_disable(&bulk->clks[i]);
682 if (ret < 0 && ret != -ENOSYS)
683 return ret;
684 }
685
686 return 0;
687}
688
Lukasz Majewski12014be2019-06-24 15:50:44 +0200689int clk_get_by_id(ulong id, struct clk **clkp)
690{
691 struct udevice *dev;
692 struct uclass *uc;
693 int ret;
694
695 ret = uclass_get(UCLASS_CLK, &uc);
696 if (ret)
697 return ret;
698
699 uclass_foreach_dev(dev, uc) {
700 struct clk *clk = dev_get_clk_ptr(dev);
701
702 if (clk && clk->id == id) {
703 *clkp = clk;
704 return 0;
705 }
706 }
707
708 return -ENOENT;
709}
710
Sekhar Noricf3119d2019-08-01 19:12:55 +0530711bool clk_is_match(const struct clk *p, const struct clk *q)
712{
713 /* trivial case: identical struct clk's or both NULL */
714 if (p == q)
715 return true;
716
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200717 /* trivial case #2: on the clk pointer is NULL */
718 if (!p || !q)
719 return false;
720
Sekhar Noricf3119d2019-08-01 19:12:55 +0530721 /* same device, id and data */
722 if (p->dev == q->dev && p->id == q->id && p->data == q->data)
723 return true;
724
725 return false;
726}
727
Jean-Jacques Hiblot6e66b2d2019-10-22 14:00:04 +0200728static void devm_clk_release(struct udevice *dev, void *res)
729{
730 clk_free(res);
731}
732
733static int devm_clk_match(struct udevice *dev, void *res, void *data)
734{
735 return res == data;
736}
737
738struct clk *devm_clk_get(struct udevice *dev, const char *id)
739{
740 int rc;
741 struct clk *clk;
742
743 clk = devres_alloc(devm_clk_release, sizeof(struct clk), __GFP_ZERO);
744 if (unlikely(!clk))
745 return ERR_PTR(-ENOMEM);
746
747 rc = clk_get_by_name(dev, id, clk);
748 if (rc)
749 return ERR_PTR(rc);
750
751 devres_add(dev, clk);
752 return clk;
753}
754
755struct clk *devm_clk_get_optional(struct udevice *dev, const char *id)
756{
757 struct clk *clk = devm_clk_get(dev, id);
758
developer5e108fb2020-01-09 11:35:05 +0800759 if (PTR_ERR(clk) == -ENODATA)
Jean-Jacques Hiblot6e66b2d2019-10-22 14:00:04 +0200760 return NULL;
761
762 return clk;
763}
764
765void devm_clk_put(struct udevice *dev, struct clk *clk)
766{
767 int rc;
768
769 if (!clk)
770 return;
771
772 rc = devres_release(dev, devm_clk_release, devm_clk_match, clk);
773 WARN_ON(rc);
774}
775
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200776int clk_uclass_post_probe(struct udevice *dev)
777{
778 /*
779 * when a clock provider is probed. Call clk_set_defaults()
780 * also after the device is probed. This takes care of cases
781 * where the DT is used to setup default parents and rates
782 * using assigned-clocks
783 */
784 clk_set_defaults(dev, 1);
785
786 return 0;
787}
788
Simon Glass36ad2342015-06-23 15:39:15 -0600789UCLASS_DRIVER(clk) = {
790 .id = UCLASS_CLK,
791 .name = "clk",
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200792 .post_probe = clk_uclass_post_probe,
Simon Glass36ad2342015-06-23 15:39:15 -0600793};