blob: 53e7be764d3653798dd2d66b566cc759efdc94d9 [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>
Sean Andersond7ac3732021-04-08 22:13:03 -040017#include <dm/device_compat.h>
Claudiu Bezneac8c16002020-09-07 17:46:34 +030018#include <dm/device-internal.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070019#include <dm/devres.h>
20#include <dm/read.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060021#include <linux/bug.h>
Lukasz Majewski9e38dc32019-06-24 15:50:42 +020022#include <linux/clk-provider.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070023#include <linux/err.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060024#include <asm/global_data.h>
Simon Glass36ad2342015-06-23 15:39:15 -060025
Mario Six799fe562018-01-15 11:06:51 +010026static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
Simon Glass36ad2342015-06-23 15:39:15 -060027{
Mario Six799fe562018-01-15 11:06:51 +010028 return (const struct clk_ops *)dev->driver->ops;
Simon Glass36ad2342015-06-23 15:39:15 -060029}
30
Simon Glass43033962020-07-19 10:15:56 -060031struct clk *dev_get_clk_ptr(struct udevice *dev)
32{
33 return (struct clk *)dev_get_uclass_priv(dev);
34}
35
Stephen Warrena9622432016-06-17 09:44:00 -060036#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glass589d9152016-07-04 11:58:03 -060037# if CONFIG_IS_ENABLED(OF_PLATDATA)
Walter Lozanodc5b4372020-06-25 01:10:13 -030038int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells,
39 struct clk *clk)
Simon Glass589d9152016-07-04 11:58:03 -060040{
41 int ret;
42
Simon Glass0000e0d2021-03-15 17:25:28 +130043 ret = device_get_by_ofplat_idx(cells->idx, &clk->dev);
Simon Glass589d9152016-07-04 11:58:03 -060044 if (ret)
45 return ret;
Walter Lozanodc5b4372020-06-25 01:10:13 -030046 clk->id = cells->arg[0];
Simon Glass589d9152016-07-04 11:58:03 -060047
48 return 0;
49}
50# else
Stephen Warrena9622432016-06-17 09:44:00 -060051static int clk_of_xlate_default(struct clk *clk,
Simon Glassb7ae2772017-05-18 20:09:40 -060052 struct ofnode_phandle_args *args)
Simon Glass36ad2342015-06-23 15:39:15 -060053{
Stephen Warrena9622432016-06-17 09:44:00 -060054 debug("%s(clk=%p)\n", __func__, clk);
Simon Glass36ad2342015-06-23 15:39:15 -060055
Stephen Warrena9622432016-06-17 09:44:00 -060056 if (args->args_count > 1) {
57 debug("Invaild args_count: %d\n", args->args_count);
58 return -EINVAL;
59 }
Simon Glass36ad2342015-06-23 15:39:15 -060060
Stephen Warrena9622432016-06-17 09:44:00 -060061 if (args->args_count)
62 clk->id = args->args[0];
63 else
64 clk->id = 0;
Simon Glass36ad2342015-06-23 15:39:15 -060065
Sekhar Nori3d23abd2019-07-11 14:30:24 +053066 clk->data = 0;
67
Stephen Warrena9622432016-06-17 09:44:00 -060068 return 0;
Simon Glass36ad2342015-06-23 15:39:15 -060069}
Simon Glass0342bd22016-01-20 19:43:02 -070070
Jagan Tekifc7c7ce2019-02-28 00:26:52 +053071static int clk_get_by_index_tail(int ret, ofnode node,
72 struct ofnode_phandle_args *args,
73 const char *list_name, int index,
74 struct clk *clk)
75{
76 struct udevice *dev_clk;
77 const struct clk_ops *ops;
78
79 assert(clk);
80 clk->dev = NULL;
81 if (ret)
82 goto err;
83
84 ret = uclass_get_device_by_ofnode(UCLASS_CLK, args->node, &dev_clk);
85 if (ret) {
86 debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
87 __func__, ret);
Simon Glassf73f5812021-01-21 13:57:11 -070088 return log_msg_ret("get", ret);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +053089 }
90
91 clk->dev = dev_clk;
92
93 ops = clk_dev_ops(dev_clk);
94
95 if (ops->of_xlate)
96 ret = ops->of_xlate(clk, args);
97 else
98 ret = clk_of_xlate_default(clk, args);
99 if (ret) {
100 debug("of_xlate() failed: %d\n", ret);
Simon Glassf73f5812021-01-21 13:57:11 -0700101 return log_msg_ret("xlate", ret);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530102 }
103
104 return clk_request(dev_clk, clk);
105err:
106 debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n",
107 __func__, ofnode_get_name(node), list_name, index, ret);
Simon Glassf73f5812021-01-21 13:57:11 -0700108
109 return log_msg_ret("prop", ret);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530110}
111
Philipp Tomsichf7604342018-01-08 11:18:18 +0100112static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
113 int index, struct clk *clk)
Simon Glass0342bd22016-01-20 19:43:02 -0700114{
Simon Glass0342bd22016-01-20 19:43:02 -0700115 int ret;
Simon Glass2558bff2017-05-30 21:47:29 -0600116 struct ofnode_phandle_args args;
Simon Glass0342bd22016-01-20 19:43:02 -0700117
Stephen Warrena9622432016-06-17 09:44:00 -0600118 debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
119
120 assert(clk);
Patrice Chotard96fc03d2017-07-18 11:57:07 +0200121 clk->dev = NULL;
122
Philipp Tomsichf7604342018-01-08 11:18:18 +0100123 ret = dev_read_phandle_with_args(dev, prop_name, "#clock-cells", 0,
Mario Six799fe562018-01-15 11:06:51 +0100124 index, &args);
Simon Glass0342bd22016-01-20 19:43:02 -0700125 if (ret) {
126 debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
127 __func__, ret);
Simon Glassf73f5812021-01-21 13:57:11 -0700128 return log_ret(ret);
Simon Glass0342bd22016-01-20 19:43:02 -0700129 }
130
Stephen Warrena9622432016-06-17 09:44:00 -0600131
Jagan Tekia77add32019-02-28 00:26:53 +0530132 return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400133 index, clk);
Stephen Warrena9622432016-06-17 09:44:00 -0600134}
Philipp Tomsichf7604342018-01-08 11:18:18 +0100135
136int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
137{
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530138 struct ofnode_phandle_args args;
139 int ret;
140
141 ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
142 index, &args);
143
144 return clk_get_by_index_tail(ret, dev_ofnode(dev), &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400145 index, clk);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530146}
147
148int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)
149{
150 struct ofnode_phandle_args args;
151 int ret;
152
153 ret = ofnode_parse_phandle_with_args(node, "clocks", "#clock-cells", 0,
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400154 index, &args);
Jagan Tekifc7c7ce2019-02-28 00:26:52 +0530155
156 return clk_get_by_index_tail(ret, node, &args, "clocks",
Sean Andersonf0d5a6b2020-06-24 06:41:08 -0400157 index, clk);
Philipp Tomsichf7604342018-01-08 11:18:18 +0100158}
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100159
Neil Armstrong8a275a02018-04-03 11:44:18 +0200160int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
161{
162 int i, ret, err, count;
163
164 bulk->count = 0;
165
Patrick Delaunayd776a842020-09-25 09:41:14 +0200166 count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", 0);
Neil Armstrong52b26d92018-04-17 11:30:31 +0200167 if (count < 1)
168 return count;
Neil Armstrong8a275a02018-04-03 11:44:18 +0200169
170 bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL);
171 if (!bulk->clks)
172 return -ENOMEM;
173
174 for (i = 0; i < count; i++) {
175 ret = clk_get_by_index(dev, i, &bulk->clks[i]);
176 if (ret < 0)
177 goto bulk_get_err;
178
179 ++bulk->count;
180 }
181
182 return 0;
183
184bulk_get_err:
185 err = clk_release_all(bulk->clks, bulk->count);
186 if (err)
187 debug("%s: could release all clocks for %p\n",
188 __func__, dev);
189
190 return ret;
191}
192
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300193static struct clk *clk_set_default_get_by_id(struct clk *clk)
194{
195 struct clk *c = clk;
196
197 if (CONFIG_IS_ENABLED(CLK_CCF)) {
198 int ret = clk_get_by_id(clk->id, &c);
199
200 if (ret) {
201 debug("%s(): could not get parent clock pointer, id %lu\n",
202 __func__, clk->id);
203 ERR_PTR(ret);
204 }
205 }
206
207 return c;
208}
209
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200210static int clk_set_default_parents(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100211{
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300212 struct clk clk, parent_clk, *c, *p;
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100213 int index;
214 int num_parents;
215 int ret;
216
217 num_parents = dev_count_phandle_with_args(dev, "assigned-clock-parents",
Patrick Delaunayd776a842020-09-25 09:41:14 +0200218 "#clock-cells", 0);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100219 if (num_parents < 0) {
220 debug("%s: could not read assigned-clock-parents for %p\n",
221 __func__, dev);
222 return 0;
223 }
224
225 for (index = 0; index < num_parents; index++) {
226 ret = clk_get_by_indexed_prop(dev, "assigned-clock-parents",
227 index, &parent_clk);
Neil Armstrongf3cc6312018-07-26 15:19:32 +0200228 /* If -ENOENT, this is a no-op entry */
229 if (ret == -ENOENT)
230 continue;
231
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100232 if (ret) {
233 debug("%s: could not get parent clock %d for %s\n",
234 __func__, index, dev_read_name(dev));
235 return ret;
236 }
237
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300238 p = clk_set_default_get_by_id(&parent_clk);
239 if (IS_ERR(p))
240 return PTR_ERR(p);
241
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100242 ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
243 index, &clk);
244 if (ret) {
245 debug("%s: could not get assigned clock %d for %s\n",
246 __func__, index, dev_read_name(dev));
247 return ret;
248 }
249
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200250 /* This is clk provider device trying to reparent itself
251 * It cannot be done right now but need to wait after the
252 * device is probed
253 */
254 if (stage == 0 && clk.dev == dev)
255 continue;
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100256
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200257 if (stage > 0 && clk.dev != dev)
258 /* do not setup twice the parent clocks */
259 continue;
260
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300261 c = clk_set_default_get_by_id(&clk);
262 if (IS_ERR(c))
263 return PTR_ERR(c);
264
265 ret = clk_set_parent(c, p);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100266 /*
267 * Not all drivers may support clock-reparenting (as of now).
268 * Ignore errors due to this.
269 */
270 if (ret == -ENOSYS)
271 continue;
272
Jean-Jacques Hiblotb2320812019-09-26 15:42:42 +0200273 if (ret < 0) {
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100274 debug("%s: failed to reparent clock %d for %s\n",
275 __func__, index, dev_read_name(dev));
276 return ret;
277 }
278 }
279
280 return 0;
281}
282
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200283static int clk_set_default_rates(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100284{
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300285 struct clk clk, *c;
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100286 int index;
287 int num_rates;
288 int size;
289 int ret = 0;
290 u32 *rates = NULL;
291
292 size = dev_read_size(dev, "assigned-clock-rates");
293 if (size < 0)
294 return 0;
295
296 num_rates = size / sizeof(u32);
297 rates = calloc(num_rates, sizeof(u32));
298 if (!rates)
299 return -ENOMEM;
300
301 ret = dev_read_u32_array(dev, "assigned-clock-rates", rates, num_rates);
302 if (ret)
303 goto fail;
304
305 for (index = 0; index < num_rates; index++) {
Neil Armstrongf3cc6312018-07-26 15:19:32 +0200306 /* If 0 is passed, this is a no-op */
307 if (!rates[index])
308 continue;
309
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100310 ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
311 index, &clk);
312 if (ret) {
Sean Andersond7ac3732021-04-08 22:13:03 -0400313 dev_dbg(dev,
314 "could not get assigned clock %d (err = %d)\n",
315 index, ret);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100316 continue;
317 }
318
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200319 /* This is clk provider device trying to program itself
320 * It cannot be done right now but need to wait after the
321 * device is probed
322 */
323 if (stage == 0 && clk.dev == dev)
324 continue;
325
326 if (stage > 0 && clk.dev != dev)
327 /* do not setup twice the parent clocks */
328 continue;
329
Claudiu Bezneab91eee62020-09-07 17:46:36 +0300330 c = clk_set_default_get_by_id(&clk);
331 if (IS_ERR(c))
332 return PTR_ERR(c);
333
334 ret = clk_set_rate(c, rates[index]);
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200335
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100336 if (ret < 0) {
Sean Andersond7ac3732021-04-08 22:13:03 -0400337 dev_warn(dev,
338 "failed to set rate on clock index %d (%ld) (error = %d)\n",
339 index, clk.id, ret);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100340 break;
341 }
342 }
343
344fail:
345 free(rates);
346 return ret;
347}
348
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200349int clk_set_defaults(struct udevice *dev, int stage)
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100350{
351 int ret;
352
Simon Glassf1d50f72020-12-19 10:40:13 -0700353 if (!dev_has_ofnode(dev))
Peng Fan40ec4e42019-07-31 07:01:49 +0000354 return 0;
355
Philipp Tomsiche546ec82018-11-26 20:20:19 +0100356 /* If this not in SPL and pre-reloc state, don't take any action. */
357 if (!(IS_ENABLED(CONFIG_SPL_BUILD) || (gd->flags & GD_FLG_RELOC)))
358 return 0;
359
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100360 debug("%s(%s)\n", __func__, dev_read_name(dev));
361
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200362 ret = clk_set_default_parents(dev, stage);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100363 if (ret)
364 return ret;
365
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200366 ret = clk_set_default_rates(dev, stage);
Philipp Tomsich9cf03b02018-01-08 13:59:18 +0100367 if (ret < 0)
368 return ret;
369
370 return 0;
371}
Stephen Warrena9622432016-06-17 09:44:00 -0600372
373int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
374{
375 int index;
376
377 debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
Patrice Chotard96fc03d2017-07-18 11:57:07 +0200378 clk->dev = NULL;
Stephen Warrena9622432016-06-17 09:44:00 -0600379
Simon Glass2558bff2017-05-30 21:47:29 -0600380 index = dev_read_stringlist_search(dev, "clock-names", name);
Stephen Warrena9622432016-06-17 09:44:00 -0600381 if (index < 0) {
Simon Glassb0ea7402016-10-02 17:59:28 -0600382 debug("fdt_stringlist_search() failed: %d\n", index);
Stephen Warrena9622432016-06-17 09:44:00 -0600383 return index;
384 }
385
386 return clk_get_by_index(dev, index, clk);
Simon Glass0342bd22016-01-20 19:43:02 -0700387}
Giulio Benetti6c910872019-12-12 23:53:19 +0100388# endif /* OF_PLATDATA */
Patrice Chotardcafc3412017-07-25 13:24:45 +0200389
developerbdc786d2020-01-09 11:35:07 +0800390int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk)
391{
392 int index;
393
394 debug("%s(node=%p, name=%s, clk=%p)\n", __func__,
395 ofnode_get_name(node), name, clk);
396 clk->dev = NULL;
397
398 index = ofnode_stringlist_search(node, "clock-names", name);
399 if (index < 0) {
400 debug("fdt_stringlist_search() failed: %d\n", index);
401 return index;
402 }
403
404 return clk_get_by_index_nodev(node, index, clk);
405}
406
407int clk_get_optional_nodev(ofnode node, const char *name, struct clk *clk)
408{
409 int ret;
410
411 ret = clk_get_by_name_nodev(node, name, clk);
412 if (ret == -ENODATA)
413 return 0;
414
415 return ret;
416}
417
Patrice Chotardcafc3412017-07-25 13:24:45 +0200418int clk_release_all(struct clk *clk, int count)
419{
420 int i, ret;
421
422 for (i = 0; i < count; i++) {
423 debug("%s(clk[%d]=%p)\n", __func__, i, &clk[i]);
424
425 /* check if clock has been previously requested */
426 if (!clk[i].dev)
427 continue;
428
429 ret = clk_disable(&clk[i]);
430 if (ret && ret != -ENOSYS)
431 return ret;
432
433 ret = clk_free(&clk[i]);
434 if (ret && ret != -ENOSYS)
435 return ret;
436 }
437
438 return 0;
439}
440
Simon Glass589d9152016-07-04 11:58:03 -0600441#endif /* OF_CONTROL */
Stephen Warrena9622432016-06-17 09:44:00 -0600442
443int clk_request(struct udevice *dev, struct clk *clk)
444{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200445 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600446
447 debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200448 if (!clk)
449 return 0;
450 ops = clk_dev_ops(dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600451
452 clk->dev = dev;
453
454 if (!ops->request)
455 return 0;
456
457 return ops->request(clk);
458}
459
460int clk_free(struct clk *clk)
461{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200462 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600463
464 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800465 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200466 return 0;
467 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600468
Simon Glass2cdd3f42020-02-03 07:35:54 -0700469 if (!ops->rfree)
Stephen Warrena9622432016-06-17 09:44:00 -0600470 return 0;
471
Simon Glass2cdd3f42020-02-03 07:35:54 -0700472 return ops->rfree(clk);
Stephen Warrena9622432016-06-17 09:44:00 -0600473}
474
475ulong clk_get_rate(struct clk *clk)
476{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200477 const struct clk_ops *ops;
Simon Glassf73f5812021-01-21 13:57:11 -0700478 int ret;
Stephen Warrena9622432016-06-17 09:44:00 -0600479
480 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800481 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200482 return 0;
483 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600484
485 if (!ops->get_rate)
486 return -ENOSYS;
487
Simon Glassf73f5812021-01-21 13:57:11 -0700488 ret = ops->get_rate(clk);
489 if (ret)
490 return log_ret(ret);
491
492 return 0;
Stephen Warrena9622432016-06-17 09:44:00 -0600493}
494
Lukasz Majewski9e38dc32019-06-24 15:50:42 +0200495struct clk *clk_get_parent(struct clk *clk)
496{
497 struct udevice *pdev;
498 struct clk *pclk;
499
500 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800501 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200502 return NULL;
Lukasz Majewski9e38dc32019-06-24 15:50:42 +0200503
504 pdev = dev_get_parent(clk->dev);
505 pclk = dev_get_clk_ptr(pdev);
506 if (!pclk)
507 return ERR_PTR(-ENODEV);
508
509 return pclk;
510}
511
Lukasz Majewski53155da2019-06-24 15:50:43 +0200512long long clk_get_parent_rate(struct clk *clk)
513{
514 const struct clk_ops *ops;
515 struct clk *pclk;
516
517 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800518 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200519 return 0;
Lukasz Majewski53155da2019-06-24 15:50:43 +0200520
521 pclk = clk_get_parent(clk);
522 if (IS_ERR(pclk))
523 return -ENODEV;
524
525 ops = clk_dev_ops(pclk->dev);
526 if (!ops->get_rate)
527 return -ENOSYS;
528
Lukasz Majewski4ef32172019-06-24 15:50:46 +0200529 /* Read the 'rate' if not already set or if proper flag set*/
530 if (!pclk->rate || pclk->flags & CLK_GET_RATE_NOCACHE)
Lukasz Majewski53155da2019-06-24 15:50:43 +0200531 pclk->rate = clk_get_rate(pclk);
532
533 return pclk->rate;
534}
535
Dario Binacchib7f85892020-12-30 00:06:31 +0100536ulong clk_round_rate(struct clk *clk, ulong rate)
537{
538 const struct clk_ops *ops;
539
540 debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
541 if (!clk_valid(clk))
542 return 0;
543
544 ops = clk_dev_ops(clk->dev);
545 if (!ops->round_rate)
546 return -ENOSYS;
547
548 return ops->round_rate(clk, rate);
549}
550
Stephen Warrena9622432016-06-17 09:44:00 -0600551ulong clk_set_rate(struct clk *clk, ulong rate)
552{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200553 const struct clk_ops *ops;
Stephen Warrena9622432016-06-17 09:44:00 -0600554
555 debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
developerdc338d32020-01-09 11:35:06 +0800556 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200557 return 0;
558 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600559
560 if (!ops->set_rate)
561 return -ENOSYS;
562
563 return ops->set_rate(clk, rate);
564}
565
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100566int clk_set_parent(struct clk *clk, struct clk *parent)
567{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200568 const struct clk_ops *ops;
Claudiu Bezneac8c16002020-09-07 17:46:34 +0300569 int ret;
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100570
571 debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent);
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);
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100575
576 if (!ops->set_parent)
577 return -ENOSYS;
578
Claudiu Bezneac8c16002020-09-07 17:46:34 +0300579 ret = ops->set_parent(clk, parent);
580 if (ret)
581 return ret;
582
583 if (CONFIG_IS_ENABLED(CLK_CCF))
584 ret = device_reparent(clk->dev, parent->dev);
585
586 return ret;
Philipp Tomsichf8e02b22018-01-08 11:15:08 +0100587}
588
Stephen Warrena9622432016-06-17 09:44:00 -0600589int clk_enable(struct clk *clk)
590{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200591 const struct clk_ops *ops;
Peng Fan82628e22019-08-21 13:35:09 +0000592 struct clk *clkp = NULL;
593 int ret;
Stephen Warrena9622432016-06-17 09:44:00 -0600594
595 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800596 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200597 return 0;
598 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600599
Peng Fan82628e22019-08-21 13:35:09 +0000600 if (CONFIG_IS_ENABLED(CLK_CCF)) {
601 /* Take id 0 as a non-valid clk, such as dummy */
602 if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
603 if (clkp->enable_count) {
604 clkp->enable_count++;
605 return 0;
606 }
607 if (clkp->dev->parent &&
608 device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
609 ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent));
610 if (ret) {
611 printf("Enable %s failed\n",
612 clkp->dev->parent->name);
613 return ret;
614 }
615 }
616 }
Stephen Warrena9622432016-06-17 09:44:00 -0600617
Peng Fan82628e22019-08-21 13:35:09 +0000618 if (ops->enable) {
619 ret = ops->enable(clk);
620 if (ret) {
621 printf("Enable %s failed\n", clk->dev->name);
622 return ret;
623 }
624 }
625 if (clkp)
626 clkp->enable_count++;
627 } else {
628 if (!ops->enable)
629 return -ENOSYS;
630 return ops->enable(clk);
631 }
632
633 return 0;
Stephen Warrena9622432016-06-17 09:44:00 -0600634}
635
Neil Armstrong8a275a02018-04-03 11:44:18 +0200636int clk_enable_bulk(struct clk_bulk *bulk)
637{
638 int i, ret;
639
640 for (i = 0; i < bulk->count; i++) {
641 ret = clk_enable(&bulk->clks[i]);
642 if (ret < 0 && ret != -ENOSYS)
643 return ret;
644 }
645
646 return 0;
647}
648
Stephen Warrena9622432016-06-17 09:44:00 -0600649int clk_disable(struct clk *clk)
650{
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200651 const struct clk_ops *ops;
Peng Fan82628e22019-08-21 13:35:09 +0000652 struct clk *clkp = NULL;
653 int ret;
Stephen Warrena9622432016-06-17 09:44:00 -0600654
655 debug("%s(clk=%p)\n", __func__, clk);
developerdc338d32020-01-09 11:35:06 +0800656 if (!clk_valid(clk))
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200657 return 0;
658 ops = clk_dev_ops(clk->dev);
Stephen Warrena9622432016-06-17 09:44:00 -0600659
Peng Fan82628e22019-08-21 13:35:09 +0000660 if (CONFIG_IS_ENABLED(CLK_CCF)) {
661 if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
Claudiu Bezneab02e8dd2020-09-07 17:46:35 +0300662 if (clkp->flags & CLK_IS_CRITICAL)
663 return 0;
664
Peng Fan82628e22019-08-21 13:35:09 +0000665 if (clkp->enable_count == 0) {
666 printf("clk %s already disabled\n",
667 clkp->dev->name);
668 return 0;
669 }
Stephen Warrena9622432016-06-17 09:44:00 -0600670
Peng Fan82628e22019-08-21 13:35:09 +0000671 if (--clkp->enable_count > 0)
672 return 0;
673 }
674
675 if (ops->disable) {
676 ret = ops->disable(clk);
677 if (ret)
678 return ret;
679 }
680
681 if (clkp && clkp->dev->parent &&
682 device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
683 ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent));
684 if (ret) {
685 printf("Disable %s failed\n",
686 clkp->dev->parent->name);
687 return ret;
688 }
689 }
690 } else {
691 if (!ops->disable)
692 return -ENOSYS;
693
694 return ops->disable(clk);
695 }
696
697 return 0;
Stephen Warrena9622432016-06-17 09:44:00 -0600698}
Simon Glass36ad2342015-06-23 15:39:15 -0600699
Neil Armstrong8a275a02018-04-03 11:44:18 +0200700int clk_disable_bulk(struct clk_bulk *bulk)
701{
702 int i, ret;
703
704 for (i = 0; i < bulk->count; i++) {
705 ret = clk_disable(&bulk->clks[i]);
706 if (ret < 0 && ret != -ENOSYS)
707 return ret;
708 }
709
710 return 0;
711}
712
Lukasz Majewski12014be2019-06-24 15:50:44 +0200713int clk_get_by_id(ulong id, struct clk **clkp)
714{
715 struct udevice *dev;
716 struct uclass *uc;
717 int ret;
718
719 ret = uclass_get(UCLASS_CLK, &uc);
720 if (ret)
721 return ret;
722
723 uclass_foreach_dev(dev, uc) {
724 struct clk *clk = dev_get_clk_ptr(dev);
725
726 if (clk && clk->id == id) {
727 *clkp = clk;
728 return 0;
729 }
730 }
731
732 return -ENOENT;
733}
734
Sekhar Noricf3119d2019-08-01 19:12:55 +0530735bool clk_is_match(const struct clk *p, const struct clk *q)
736{
737 /* trivial case: identical struct clk's or both NULL */
738 if (p == q)
739 return true;
740
Jean-Jacques Hiblot718039b2019-10-22 14:00:03 +0200741 /* trivial case #2: on the clk pointer is NULL */
742 if (!p || !q)
743 return false;
744
Sekhar Noricf3119d2019-08-01 19:12:55 +0530745 /* same device, id and data */
746 if (p->dev == q->dev && p->id == q->id && p->data == q->data)
747 return true;
748
749 return false;
750}
751
Jean-Jacques Hiblot6e66b2d2019-10-22 14:00:04 +0200752static void devm_clk_release(struct udevice *dev, void *res)
753{
754 clk_free(res);
755}
756
757static int devm_clk_match(struct udevice *dev, void *res, void *data)
758{
759 return res == data;
760}
761
762struct clk *devm_clk_get(struct udevice *dev, const char *id)
763{
764 int rc;
765 struct clk *clk;
766
767 clk = devres_alloc(devm_clk_release, sizeof(struct clk), __GFP_ZERO);
768 if (unlikely(!clk))
769 return ERR_PTR(-ENOMEM);
770
771 rc = clk_get_by_name(dev, id, clk);
772 if (rc)
773 return ERR_PTR(rc);
774
775 devres_add(dev, clk);
776 return clk;
777}
778
779struct clk *devm_clk_get_optional(struct udevice *dev, const char *id)
780{
781 struct clk *clk = devm_clk_get(dev, id);
782
developer5e108fb2020-01-09 11:35:05 +0800783 if (PTR_ERR(clk) == -ENODATA)
Jean-Jacques Hiblot6e66b2d2019-10-22 14:00:04 +0200784 return NULL;
785
786 return clk;
787}
788
789void devm_clk_put(struct udevice *dev, struct clk *clk)
790{
791 int rc;
792
793 if (!clk)
794 return;
795
796 rc = devres_release(dev, devm_clk_release, devm_clk_match, clk);
797 WARN_ON(rc);
798}
799
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200800int clk_uclass_post_probe(struct udevice *dev)
801{
802 /*
803 * when a clock provider is probed. Call clk_set_defaults()
804 * also after the device is probed. This takes care of cases
805 * where the DT is used to setup default parents and rates
806 * using assigned-clocks
807 */
808 clk_set_defaults(dev, 1);
809
810 return 0;
811}
812
Simon Glass36ad2342015-06-23 15:39:15 -0600813UCLASS_DRIVER(clk) = {
814 .id = UCLASS_CLK,
815 .name = "clk",
Jean-Jacques Hiblot9601f322019-10-22 14:00:06 +0200816 .post_probe = clk_uclass_post_probe,
Simon Glass36ad2342015-06-23 15:39:15 -0600817};