]>
Commit | Line | Data |
---|---|---|
a8aceccb TK |
1 | /* |
2 | * TI clock support | |
3 | * | |
4 | * Copyright (C) 2013 Texas Instruments, Inc. | |
5 | * | |
6 | * Tero Kristo <t-kristo@ti.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
13 | * kind, whether express or implied; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | */ | |
17 | ||
1b29e601 | 18 | #include <linux/clk.h> |
a8aceccb TK |
19 | #include <linux/clk-provider.h> |
20 | #include <linux/clkdev.h> | |
21 | #include <linux/clk/ti.h> | |
62e59c4e | 22 | #include <linux/io.h> |
a8aceccb | 23 | #include <linux/of.h> |
819b4861 TK |
24 | #include <linux/of_address.h> |
25 | #include <linux/list.h> | |
989feafb | 26 | #include <linux/regmap.h> |
57c8a661 | 27 | #include <linux/memblock.h> |
21f0bf2d | 28 | #include <linux/device.h> |
a8aceccb | 29 | |
c82f8957 TK |
30 | #include "clock.h" |
31 | ||
a8aceccb TK |
32 | #undef pr_fmt |
33 | #define pr_fmt(fmt) "%s: " fmt, __func__ | |
34 | ||
77b773ae | 35 | static LIST_HEAD(clk_hw_omap_clocks); |
819b4861 | 36 | struct ti_clk_ll_ops *ti_clk_ll_ops; |
c08ee14c | 37 | static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS]; |
819b4861 | 38 | |
47b00dcf | 39 | struct ti_clk_features ti_clk_features; |
e9e63088 | 40 | |
989feafb TK |
41 | struct clk_iomap { |
42 | struct regmap *regmap; | |
43 | void __iomem *mem; | |
44 | }; | |
45 | ||
46 | static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS]; | |
47 | ||
6c0afb50 | 48 | static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg) |
989feafb | 49 | { |
6c0afb50 | 50 | struct clk_iomap *io = clk_memmaps[reg->index]; |
989feafb | 51 | |
6c0afb50 TK |
52 | if (reg->ptr) |
53 | writel_relaxed(val, reg->ptr); | |
54 | else if (io->regmap) | |
55 | regmap_write(io->regmap, reg->offset, val); | |
989feafb | 56 | else |
6c0afb50 | 57 | writel_relaxed(val, io->mem + reg->offset); |
989feafb TK |
58 | } |
59 | ||
4902c202 TK |
60 | static void _clk_rmw(u32 val, u32 mask, void __iomem *ptr) |
61 | { | |
62 | u32 v; | |
63 | ||
64 | v = readl_relaxed(ptr); | |
65 | v &= ~mask; | |
66 | v |= val; | |
67 | writel_relaxed(v, ptr); | |
68 | } | |
69 | ||
70 | static void clk_memmap_rmw(u32 val, u32 mask, const struct clk_omap_reg *reg) | |
71 | { | |
72 | struct clk_iomap *io = clk_memmaps[reg->index]; | |
73 | ||
74 | if (reg->ptr) { | |
75 | _clk_rmw(val, mask, reg->ptr); | |
76 | } else if (io->regmap) { | |
77 | regmap_update_bits(io->regmap, reg->offset, mask, val); | |
78 | } else { | |
79 | _clk_rmw(val, mask, io->mem + reg->offset); | |
80 | } | |
81 | } | |
82 | ||
6c0afb50 | 83 | static u32 clk_memmap_readl(const struct clk_omap_reg *reg) |
989feafb TK |
84 | { |
85 | u32 val; | |
6c0afb50 | 86 | struct clk_iomap *io = clk_memmaps[reg->index]; |
989feafb | 87 | |
6c0afb50 TK |
88 | if (reg->ptr) |
89 | val = readl_relaxed(reg->ptr); | |
90 | else if (io->regmap) | |
91 | regmap_read(io->regmap, reg->offset, &val); | |
989feafb | 92 | else |
6c0afb50 | 93 | val = readl_relaxed(io->mem + reg->offset); |
989feafb TK |
94 | |
95 | return val; | |
96 | } | |
97 | ||
e9e63088 TK |
98 | /** |
99 | * ti_clk_setup_ll_ops - setup low level clock operations | |
100 | * @ops: low level clock ops descriptor | |
101 | * | |
102 | * Sets up low level clock operations for TI clock driver. This is used | |
103 | * to provide various callbacks for the clock driver towards platform | |
104 | * specific code. Returns 0 on success, -EBUSY if ll_ops have been | |
105 | * registered already. | |
106 | */ | |
107 | int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops) | |
108 | { | |
109 | if (ti_clk_ll_ops) { | |
110 | pr_err("Attempt to register ll_ops multiple times.\n"); | |
111 | return -EBUSY; | |
112 | } | |
113 | ||
114 | ti_clk_ll_ops = ops; | |
989feafb TK |
115 | ops->clk_readl = clk_memmap_readl; |
116 | ops->clk_writel = clk_memmap_writel; | |
4902c202 | 117 | ops->clk_rmw = clk_memmap_rmw; |
e9e63088 TK |
118 | |
119 | return 0; | |
120 | } | |
f3b19aa5 | 121 | |
a8aceccb TK |
122 | /** |
123 | * ti_dt_clocks_register - register DT alias clocks during boot | |
124 | * @oclks: list of clocks to register | |
125 | * | |
126 | * Register alias or non-standard DT clock entries during boot. By | |
127 | * default, DT clocks are found based on their node name. If any | |
128 | * additional con-id / dev-id -> clock mapping is required, use this | |
129 | * function to list these. | |
130 | */ | |
131 | void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) | |
132 | { | |
133 | struct ti_dt_clk *c; | |
00a461cc | 134 | struct device_node *node, *parent; |
a8aceccb TK |
135 | struct clk *clk; |
136 | struct of_phandle_args clkspec; | |
5b385a45 TK |
137 | char buf[64]; |
138 | char *ptr; | |
139 | char *tags[2]; | |
140 | int i; | |
141 | int num_args; | |
142 | int ret; | |
143 | static bool clkctrl_nodes_missing; | |
144 | static bool has_clkctrl_data; | |
47b00dcf TK |
145 | static bool compat_mode; |
146 | ||
147 | compat_mode = ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT; | |
a8aceccb TK |
148 | |
149 | for (c = oclks; c->node_name != NULL; c++) { | |
5b385a45 TK |
150 | strcpy(buf, c->node_name); |
151 | ptr = buf; | |
152 | for (i = 0; i < 2; i++) | |
153 | tags[i] = NULL; | |
154 | num_args = 0; | |
155 | while (*ptr) { | |
156 | if (*ptr == ':') { | |
157 | if (num_args >= 2) { | |
158 | pr_warn("Bad number of tags on %s\n", | |
159 | c->node_name); | |
160 | return; | |
161 | } | |
162 | tags[num_args++] = ptr + 1; | |
163 | *ptr = 0; | |
164 | } | |
165 | ptr++; | |
166 | } | |
167 | ||
168 | if (num_args && clkctrl_nodes_missing) | |
169 | continue; | |
170 | ||
171 | node = of_find_node_by_name(NULL, buf); | |
47b00dcf | 172 | if (num_args && compat_mode) { |
00a461cc | 173 | parent = node; |
6c309052 TL |
174 | node = of_get_child_by_name(parent, "clock"); |
175 | if (!node) | |
176 | node = of_get_child_by_name(parent, "clk"); | |
00a461cc JH |
177 | of_node_put(parent); |
178 | } | |
179 | ||
a8aceccb | 180 | clkspec.np = node; |
5b385a45 TK |
181 | clkspec.args_count = num_args; |
182 | for (i = 0; i < num_args; i++) { | |
183 | ret = kstrtoint(tags[i], i ? 10 : 16, clkspec.args + i); | |
184 | if (ret) { | |
185 | pr_warn("Bad tag in %s at %d: %s\n", | |
186 | c->node_name, i, tags[i]); | |
00a461cc | 187 | of_node_put(node); |
5b385a45 TK |
188 | return; |
189 | } | |
190 | } | |
a8aceccb | 191 | clk = of_clk_get_from_provider(&clkspec); |
00a461cc | 192 | of_node_put(node); |
a8aceccb TK |
193 | if (!IS_ERR(clk)) { |
194 | c->lk.clk = clk; | |
195 | clkdev_add(&c->lk); | |
196 | } else { | |
5b385a45 | 197 | if (num_args && !has_clkctrl_data) { |
2274d800 YL |
198 | struct device_node *np; |
199 | ||
200 | np = of_find_compatible_node(NULL, NULL, | |
201 | "ti,clkctrl"); | |
202 | if (np) { | |
5b385a45 | 203 | has_clkctrl_data = true; |
2274d800 | 204 | of_node_put(np); |
5b385a45 TK |
205 | } else { |
206 | clkctrl_nodes_missing = true; | |
207 | ||
208 | pr_warn("missing clkctrl nodes, please update your dts.\n"); | |
209 | continue; | |
210 | } | |
211 | } | |
212 | ||
213 | pr_warn("failed to lookup clock node %s, ret=%ld\n", | |
214 | c->node_name, PTR_ERR(clk)); | |
a8aceccb TK |
215 | } |
216 | } | |
217 | } | |
819b4861 TK |
218 | |
219 | struct clk_init_item { | |
220 | struct device_node *node; | |
ffb009b2 | 221 | void *user; |
819b4861 TK |
222 | ti_of_clk_init_cb_t func; |
223 | struct list_head link; | |
224 | }; | |
225 | ||
226 | static LIST_HEAD(retry_list); | |
227 | ||
228 | /** | |
229 | * ti_clk_retry_init - retries a failed clock init at later phase | |
230 | * @node: device not for the clock | |
ffb009b2 | 231 | * @user: user data pointer |
819b4861 TK |
232 | * @func: init function to be called for the clock |
233 | * | |
234 | * Adds a failed clock init to the retry list. The retry list is parsed | |
235 | * once all the other clocks have been initialized. | |
236 | */ | |
ffb009b2 TK |
237 | int __init ti_clk_retry_init(struct device_node *node, void *user, |
238 | ti_of_clk_init_cb_t func) | |
819b4861 TK |
239 | { |
240 | struct clk_init_item *retry; | |
241 | ||
e665f029 | 242 | pr_debug("%pOFn: adding to retry list...\n", node); |
819b4861 TK |
243 | retry = kzalloc(sizeof(*retry), GFP_KERNEL); |
244 | if (!retry) | |
245 | return -ENOMEM; | |
246 | ||
247 | retry->node = node; | |
248 | retry->func = func; | |
ffb009b2 | 249 | retry->user = user; |
819b4861 TK |
250 | list_add(&retry->link, &retry_list); |
251 | ||
252 | return 0; | |
253 | } | |
254 | ||
255 | /** | |
256 | * ti_clk_get_reg_addr - get register address for a clock register | |
257 | * @node: device node for the clock | |
258 | * @index: register index from the clock node | |
6c0afb50 | 259 | * @reg: pointer to target register struct |
819b4861 | 260 | * |
6c0afb50 TK |
261 | * Builds clock register address from device tree information, and returns |
262 | * the data via the provided output pointer @reg. Returns 0 on success, | |
263 | * negative error value on failure. | |
819b4861 | 264 | */ |
6c0afb50 TK |
265 | int ti_clk_get_reg_addr(struct device_node *node, int index, |
266 | struct clk_omap_reg *reg) | |
819b4861 | 267 | { |
819b4861 | 268 | u32 val; |
c08ee14c | 269 | int i; |
819b4861 | 270 | |
c08ee14c TK |
271 | for (i = 0; i < CLK_MAX_MEMMAPS; i++) { |
272 | if (clocks_node_ptr[i] == node->parent) | |
273 | break; | |
274 | } | |
275 | ||
276 | if (i == CLK_MAX_MEMMAPS) { | |
e665f029 | 277 | pr_err("clk-provider not found for %pOFn!\n", node); |
6c0afb50 | 278 | return -ENOENT; |
c08ee14c TK |
279 | } |
280 | ||
281 | reg->index = i; | |
819b4861 TK |
282 | |
283 | if (of_property_read_u32_index(node, "reg", index, &val)) { | |
e665f029 | 284 | pr_err("%pOFn must have reg[%d]!\n", node, index); |
6c0afb50 | 285 | return -EINVAL; |
819b4861 TK |
286 | } |
287 | ||
288 | reg->offset = val; | |
6c0afb50 | 289 | reg->ptr = NULL; |
819b4861 | 290 | |
6c0afb50 | 291 | return 0; |
819b4861 TK |
292 | } |
293 | ||
e31922ed TK |
294 | void ti_clk_latch(struct clk_omap_reg *reg, s8 shift) |
295 | { | |
296 | u32 latch; | |
297 | ||
298 | if (shift < 0) | |
299 | return; | |
300 | ||
301 | latch = 1 << shift; | |
302 | ||
303 | ti_clk_ll_ops->clk_rmw(latch, latch, reg); | |
304 | ti_clk_ll_ops->clk_rmw(0, latch, reg); | |
305 | ti_clk_ll_ops->clk_readl(reg); /* OCP barrier */ | |
306 | } | |
307 | ||
819b4861 | 308 | /** |
989feafb | 309 | * omap2_clk_provider_init - init master clock provider |
819b4861 TK |
310 | * @parent: master node |
311 | * @index: internal index for clk_reg_ops | |
989feafb TK |
312 | * @syscon: syscon regmap pointer for accessing clock registers |
313 | * @mem: iomem pointer for the clock provider memory area, only used if | |
314 | * syscon is not provided | |
819b4861 | 315 | * |
c08ee14c TK |
316 | * Initializes a master clock IP block. This basically sets up the |
317 | * mapping from clocks node to the memory map index. All the clocks | |
318 | * are then initialized through the common of_clk_init call, and the | |
319 | * clocks will access their memory maps based on the node layout. | |
989feafb | 320 | * Returns 0 in success. |
819b4861 | 321 | */ |
989feafb TK |
322 | int __init omap2_clk_provider_init(struct device_node *parent, int index, |
323 | struct regmap *syscon, void __iomem *mem) | |
819b4861 | 324 | { |
819b4861 | 325 | struct device_node *clocks; |
989feafb | 326 | struct clk_iomap *io; |
819b4861 TK |
327 | |
328 | /* get clocks for this parent */ | |
329 | clocks = of_get_child_by_name(parent, "clocks"); | |
330 | if (!clocks) { | |
e665f029 | 331 | pr_err("%pOFn missing 'clocks' child node.\n", parent); |
989feafb | 332 | return -EINVAL; |
819b4861 TK |
333 | } |
334 | ||
c08ee14c TK |
335 | /* add clocks node info */ |
336 | clocks_node_ptr[index] = clocks; | |
989feafb TK |
337 | |
338 | io = kzalloc(sizeof(*io), GFP_KERNEL); | |
f645f72d SB |
339 | if (!io) |
340 | return -ENOMEM; | |
989feafb TK |
341 | |
342 | io->regmap = syscon; | |
343 | io->mem = mem; | |
344 | ||
345 | clk_memmaps[index] = io; | |
346 | ||
347 | return 0; | |
348 | } | |
349 | ||
350 | /** | |
351 | * omap2_clk_legacy_provider_init - initialize a legacy clock provider | |
352 | * @index: index for the clock provider | |
353 | * @mem: iomem pointer for the clock provider memory area | |
354 | * | |
355 | * Initializes a legacy clock provider memory mapping. | |
356 | */ | |
357 | void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem) | |
358 | { | |
359 | struct clk_iomap *io; | |
360 | ||
7e1c4e27 | 361 | io = memblock_alloc(sizeof(*io), SMP_CACHE_BYTES); |
8a7f97b9 MR |
362 | if (!io) |
363 | panic("%s: Failed to allocate %zu bytes\n", __func__, | |
364 | sizeof(*io)); | |
989feafb TK |
365 | |
366 | io->mem = mem; | |
367 | ||
368 | clk_memmaps[index] = io; | |
c08ee14c | 369 | } |
819b4861 | 370 | |
c08ee14c TK |
371 | /** |
372 | * ti_dt_clk_init_retry_clks - init clocks from the retry list | |
373 | * | |
374 | * Initializes any clocks that have failed to initialize before, | |
375 | * reasons being missing parent node(s) during earlier init. This | |
376 | * typically happens only for DPLLs which need to have both of their | |
377 | * parent clocks ready during init. | |
378 | */ | |
379 | void ti_dt_clk_init_retry_clks(void) | |
380 | { | |
381 | struct clk_init_item *retry; | |
382 | struct clk_init_item *tmp; | |
383 | int retries = 5; | |
384 | ||
385 | while (!list_empty(&retry_list) && retries) { | |
386 | list_for_each_entry_safe(retry, tmp, &retry_list, link) { | |
e665f029 | 387 | pr_debug("retry-init: %pOFn\n", retry->node); |
ffb009b2 | 388 | retry->func(retry->user, retry->node); |
c08ee14c TK |
389 | list_del(&retry->link); |
390 | kfree(retry); | |
391 | } | |
392 | retries--; | |
819b4861 TK |
393 | } |
394 | } | |
c82f8957 | 395 | |
fc04f27d AB |
396 | static const struct of_device_id simple_clk_match_table[] __initconst = { |
397 | { .compatible = "fixed-clock" }, | |
398 | { .compatible = "fixed-factor-clock" }, | |
399 | { } | |
400 | }; | |
401 | ||
c17435c5 TK |
402 | /** |
403 | * ti_clk_add_aliases - setup clock aliases | |
404 | * | |
405 | * Sets up any missing clock aliases. No return value. | |
406 | */ | |
407 | void __init ti_clk_add_aliases(void) | |
408 | { | |
409 | struct device_node *np; | |
410 | struct clk *clk; | |
411 | ||
412 | for_each_matching_node(np, simple_clk_match_table) { | |
413 | struct of_phandle_args clkspec; | |
414 | ||
415 | clkspec.np = np; | |
416 | clk = of_clk_get_from_provider(&clkspec); | |
417 | ||
418 | ti_clk_add_alias(NULL, clk, np->name); | |
419 | } | |
420 | } | |
421 | ||
f3b19aa5 TK |
422 | /** |
423 | * ti_clk_setup_features - setup clock features flags | |
424 | * @features: features definition to use | |
425 | * | |
426 | * Initializes the clock driver features flags based on platform | |
427 | * provided data. No return value. | |
428 | */ | |
429 | void __init ti_clk_setup_features(struct ti_clk_features *features) | |
430 | { | |
431 | memcpy(&ti_clk_features, features, sizeof(*features)); | |
432 | } | |
433 | ||
434 | /** | |
435 | * ti_clk_get_features - get clock driver features flags | |
436 | * | |
437 | * Get TI clock driver features description. Returns a pointer | |
438 | * to the current feature setup. | |
439 | */ | |
440 | const struct ti_clk_features *ti_clk_get_features(void) | |
441 | { | |
442 | return &ti_clk_features; | |
443 | } | |
a5aa8a60 TK |
444 | |
445 | /** | |
446 | * omap2_clk_enable_init_clocks - prepare & enable a list of clocks | |
447 | * @clk_names: ptr to an array of strings of clock names to enable | |
448 | * @num_clocks: number of clock names in @clk_names | |
449 | * | |
450 | * Prepare and enable a list of clocks, named by @clk_names. No | |
451 | * return value. XXX Deprecated; only needed until these clocks are | |
452 | * properly claimed and enabled by the drivers or core code that uses | |
453 | * them. XXX What code disables & calls clk_put on these clocks? | |
454 | */ | |
455 | void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks) | |
456 | { | |
457 | struct clk *init_clk; | |
458 | int i; | |
459 | ||
460 | for (i = 0; i < num_clocks; i++) { | |
461 | init_clk = clk_get(NULL, clk_names[i]); | |
462 | if (WARN(IS_ERR(init_clk), "could not find init clock %s\n", | |
463 | clk_names[i])) | |
464 | continue; | |
465 | clk_prepare_enable(init_clk); | |
466 | } | |
467 | } | |
21f0bf2d TK |
468 | |
469 | /** | |
470 | * ti_clk_add_alias - add a clock alias for a TI clock | |
471 | * @dev: device alias for this clock | |
472 | * @clk: clock handle to create alias for | |
473 | * @con: connection ID for this clock | |
474 | * | |
475 | * Creates a clock alias for a TI clock. Allocates the clock lookup entry | |
476 | * and assigns the data to it. Returns 0 if successful, negative error | |
477 | * value otherwise. | |
478 | */ | |
479 | int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con) | |
480 | { | |
481 | struct clk_lookup *cl; | |
482 | ||
483 | if (!clk) | |
484 | return 0; | |
485 | ||
486 | if (IS_ERR(clk)) | |
487 | return PTR_ERR(clk); | |
488 | ||
489 | cl = kzalloc(sizeof(*cl), GFP_KERNEL); | |
490 | if (!cl) | |
491 | return -ENOMEM; | |
492 | ||
493 | if (dev) | |
494 | cl->dev_id = dev_name(dev); | |
495 | cl->con_id = con; | |
496 | cl->clk = clk; | |
497 | ||
498 | clkdev_add(cl); | |
499 | ||
500 | return 0; | |
501 | } | |
502 | ||
503 | /** | |
504 | * ti_clk_register - register a TI clock to the common clock framework | |
505 | * @dev: device for this clock | |
506 | * @hw: hardware clock handle | |
507 | * @con: connection ID for this clock | |
508 | * | |
509 | * Registers a TI clock to the common clock framework, and adds a clock | |
510 | * alias for it. Returns a handle to the registered clock if successful, | |
511 | * ERR_PTR value in failure. | |
512 | */ | |
513 | struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw, | |
514 | const char *con) | |
515 | { | |
516 | struct clk *clk; | |
517 | int ret; | |
518 | ||
519 | clk = clk_register(dev, hw); | |
520 | if (IS_ERR(clk)) | |
521 | return clk; | |
522 | ||
523 | ret = ti_clk_add_alias(dev, clk, con); | |
524 | if (ret) { | |
525 | clk_unregister(clk); | |
526 | return ERR_PTR(ret); | |
527 | } | |
528 | ||
529 | return clk; | |
530 | } | |
77b773ae TK |
531 | |
532 | /** | |
ead47825 TK |
533 | * ti_clk_register_omap_hw - register a clk_hw_omap to the clock framework |
534 | * @dev: device for this clock | |
535 | * @hw: hardware clock handle | |
536 | * @con: connection ID for this clock | |
77b773ae | 537 | * |
ead47825 TK |
538 | * Registers a clk_hw_omap clock to the clock framewor, adds a clock alias |
539 | * for it, and adds the list to the available clk_hw_omap type clocks. | |
540 | * Returns a handle to the registered clock if successful, ERR_PTR value | |
541 | * in failure. | |
77b773ae | 542 | */ |
ead47825 TK |
543 | struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw, |
544 | const char *con) | |
77b773ae | 545 | { |
ead47825 TK |
546 | struct clk *clk; |
547 | struct clk_hw_omap *oclk; | |
548 | ||
549 | clk = ti_clk_register(dev, hw, con); | |
550 | if (IS_ERR(clk)) | |
551 | return clk; | |
552 | ||
553 | oclk = to_clk_hw_omap(hw); | |
77b773ae | 554 | |
ead47825 TK |
555 | list_add(&oclk->node, &clk_hw_omap_clocks); |
556 | ||
557 | return clk; | |
77b773ae TK |
558 | } |
559 | ||
560 | /** | |
561 | * omap2_clk_for_each - call function for each registered clk_hw_omap | |
562 | * @fn: pointer to a callback function | |
563 | * | |
564 | * Call @fn for each registered clk_hw_omap, passing @hw to each | |
565 | * function. @fn must return 0 for success or any other value for | |
566 | * failure. If @fn returns non-zero, the iteration across clocks | |
567 | * will stop and the non-zero return value will be passed to the | |
568 | * caller of omap2_clk_for_each(). | |
569 | */ | |
570 | int omap2_clk_for_each(int (*fn)(struct clk_hw_omap *hw)) | |
571 | { | |
572 | int ret; | |
573 | struct clk_hw_omap *hw; | |
574 | ||
575 | list_for_each_entry(hw, &clk_hw_omap_clocks, node) { | |
576 | ret = (*fn)(hw); | |
577 | if (ret) | |
578 | break; | |
579 | } | |
580 | ||
581 | return ret; | |
582 | } | |
7fd79ee7 TK |
583 | |
584 | /** | |
585 | * omap2_clk_is_hw_omap - check if the provided clk_hw is OMAP clock | |
586 | * @hw: clk_hw to check if it is an omap clock or not | |
587 | * | |
588 | * Checks if the provided clk_hw is OMAP clock or not. Returns true if | |
589 | * it is, false otherwise. | |
590 | */ | |
591 | bool omap2_clk_is_hw_omap(struct clk_hw *hw) | |
592 | { | |
593 | struct clk_hw_omap *oclk; | |
594 | ||
595 | list_for_each_entry(oclk, &clk_hw_omap_clocks, node) { | |
596 | if (&oclk->hw == hw) | |
597 | return true; | |
598 | } | |
599 | ||
600 | return false; | |
601 | } |