2 * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include "opt_platform.h"
31 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/queue.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 #include <sys/limits.h>
42 #include <sys/sysctl.h>
43 #include <sys/systm.h>
47 #include <dev/fdt/fdt_common.h>
48 #include <dev/ofw/ofw_bus.h>
49 #include <dev/ofw/ofw_bus_subr.h>
51 #include <dev/extres/clk/clk.h>
53 MALLOC_DEFINE(M_CLOCK, "clocks", "Clock framework");
55 /* Forward declarations. */
60 typedef TAILQ_HEAD(clknode_list, clknode) clknode_list_t;
61 typedef TAILQ_HEAD(clkdom_list, clkdom) clkdom_list_t;
63 /* Default clock methods. */
64 static int clknode_method_init(struct clknode *clk, device_t dev);
65 static int clknode_method_recalc_freq(struct clknode *clk, uint64_t *freq);
66 static int clknode_method_set_freq(struct clknode *clk, uint64_t fin,
67 uint64_t *fout, int flags, int *stop);
68 static int clknode_method_set_gate(struct clknode *clk, bool enable);
69 static int clknode_method_set_mux(struct clknode *clk, int idx);
72 * Clock controller methods.
74 static clknode_method_t clknode_methods[] = {
75 CLKNODEMETHOD(clknode_init, clknode_method_init),
76 CLKNODEMETHOD(clknode_recalc_freq, clknode_method_recalc_freq),
77 CLKNODEMETHOD(clknode_set_freq, clknode_method_set_freq),
78 CLKNODEMETHOD(clknode_set_gate, clknode_method_set_gate),
79 CLKNODEMETHOD(clknode_set_mux, clknode_method_set_mux),
83 DEFINE_CLASS_0(clknode, clknode_class, clknode_methods, 0);
86 * Clock node - basic element for modeling SOC clock graph. It holds the clock
87 * provider's data about the clock, and the links for the clock's membership in
93 /* Clock nodes topology. */
94 struct clkdom *clkdom; /* Owning clock domain */
95 TAILQ_ENTRY(clknode) clkdom_link; /* Domain list entry */
96 TAILQ_ENTRY(clknode) clklist_link; /* Global list entry */
98 /* String based parent list. */
99 const char **parent_names; /* Array of parent names */
100 int parent_cnt; /* Number of parents */
101 int parent_idx; /* Parent index or -1 */
103 /* Cache for already resolved names. */
104 struct clknode **parents; /* Array of potential parents */
105 struct clknode *parent; /* Current parent */
107 /* Parent/child relationship links. */
108 clknode_list_t children; /* List of our children */
109 TAILQ_ENTRY(clknode) sibling_link; /* Our entry in parent's list */
111 /* Details of this device. */
112 void *softc; /* Instance softc */
113 const char *name; /* Globally unique name */
114 intptr_t id; /* Per domain unique id */
115 int flags; /* CLK_FLAG_* */
116 struct sx lock; /* Lock for this clock */
117 int ref_cnt; /* Reference counter */
118 int enable_cnt; /* Enabled counter */
121 uint64_t freq; /* Actual frequency */
123 struct sysctl_ctx_list sysctl_ctx;
127 * Per consumer data, information about how a consumer is using a clock node.
128 * A pointer to this structure is used as a handle in the consumer interface.
132 struct clknode *clknode;
137 * Clock domain - a group of clocks provided by one clock device.
140 device_t dev; /* Link to provider device */
141 TAILQ_ENTRY(clkdom) link; /* Global domain list entry */
142 clknode_list_t clknode_list; /* All clocks in the domain */
145 clknode_ofw_mapper_func *ofw_mapper; /* Find clock using FDT xref */
150 * The system-wide list of clock domains.
152 static clkdom_list_t clkdom_list = TAILQ_HEAD_INITIALIZER(clkdom_list);
155 * Each clock node is linked on a system-wide list and can be searched by name.
157 static clknode_list_t clknode_list = TAILQ_HEAD_INITIALIZER(clknode_list);
160 * Locking - we use three levels of locking:
161 * - First, topology lock is taken. This one protect all lists.
162 * - Second level is per clknode lock. It protects clknode data.
163 * - Third level is outside of this file, it protect clock device registers.
164 * First two levels use sleepable locks; clock device can use mutex or sx lock.
166 static struct sx clk_topo_lock;
167 SX_SYSINIT(clock_topology, &clk_topo_lock, "Clock topology lock");
169 #define CLK_TOPO_SLOCK() sx_slock(&clk_topo_lock)
170 #define CLK_TOPO_XLOCK() sx_xlock(&clk_topo_lock)
171 #define CLK_TOPO_UNLOCK() sx_unlock(&clk_topo_lock)
172 #define CLK_TOPO_ASSERT() sx_assert(&clk_topo_lock, SA_LOCKED)
173 #define CLK_TOPO_XASSERT() sx_assert(&clk_topo_lock, SA_XLOCKED)
175 #define CLKNODE_SLOCK(_sc) sx_slock(&((_sc)->lock))
176 #define CLKNODE_XLOCK(_sc) sx_xlock(&((_sc)->lock))
177 #define CLKNODE_UNLOCK(_sc) sx_unlock(&((_sc)->lock))
179 static void clknode_adjust_parent(struct clknode *clknode, int idx);
181 enum clknode_sysctl_type {
182 CLKNODE_SYSCTL_PARENT,
183 CLKNODE_SYSCTL_PARENTS_LIST,
184 CLKNODE_SYSCTL_CHILDREN_LIST,
187 static int clknode_sysctl(SYSCTL_HANDLER_ARGS);
188 static int clkdom_sysctl(SYSCTL_HANDLER_ARGS);
191 * Default clock methods for base class.
194 clknode_method_init(struct clknode *clknode, device_t dev)
201 clknode_method_recalc_freq(struct clknode *clknode, uint64_t *freq)
208 clknode_method_set_freq(struct clknode *clknode, uint64_t fin, uint64_t *fout,
209 int flags, int *stop)
217 clknode_method_set_gate(struct clknode *clk, bool enable)
224 clknode_method_set_mux(struct clknode *clk, int idx)
231 * Internal functions.
235 * Duplicate an array of parent names.
237 * Compute total size and allocate a single block which holds both the array of
238 * pointers to strings and the copied strings themselves. Returns a pointer to
239 * the start of the block where the array of copied string pointers lives.
241 * XXX Revisit this, no need for the DECONST stuff.
244 strdup_list(const char **names, int num)
247 const char **outptr, *ptr;
250 len = sizeof(char *) * num;
251 for (i = 0; i < num; i++) {
252 if (names[i] == NULL)
254 slen = strlen(names[i]);
256 panic("Clock parent names array have empty string");
259 outptr = malloc(len, M_CLOCK, M_WAITOK | M_ZERO);
260 ptr = (char *)(outptr + num);
261 for (i = 0; i < num; i++) {
262 if (names[i] == NULL)
265 slen = strlen(names[i]) + 1;
266 bcopy(names[i], __DECONST(void *, outptr[i]), slen);
273 * Recompute the cached frequency for this node and all its children.
276 clknode_refresh_cache(struct clknode *clknode, uint64_t freq)
279 struct clknode *entry;
283 /* Compute generated frequency. */
284 rv = CLKNODE_RECALC_FREQ(clknode, &freq);
286 /* XXX If an error happens while refreshing children
287 * this leaves the world in a partially-updated state.
290 panic("clknode_refresh_cache failed for '%s'\n",
294 /* Refresh cache for this node. */
295 clknode->freq = freq;
297 /* Refresh cache for all children. */
298 TAILQ_FOREACH(entry, &(clknode->children), sibling_link) {
299 rv = clknode_refresh_cache(entry, freq);
311 clknode_find_by_name(const char *name)
313 struct clknode *entry;
317 TAILQ_FOREACH(entry, &clknode_list, clklist_link) {
318 if (strcmp(entry->name, name) == 0)
325 clknode_find_by_id(struct clkdom *clkdom, intptr_t id)
327 struct clknode *entry;
331 TAILQ_FOREACH(entry, &clkdom->clknode_list, clkdom_link) {
339 /* -------------------------------------------------------------------------- */
341 * Clock domain functions
344 /* Find clock domain associated to device in global list. */
346 clkdom_get_by_dev(const device_t dev)
348 struct clkdom *entry;
352 TAILQ_FOREACH(entry, &clkdom_list, link) {
353 if (entry->dev == dev)
361 /* Default DT mapper. */
363 clknode_default_ofw_map(struct clkdom *clkdom, uint32_t ncells,
364 phandle_t *cells, struct clknode **clk)
370 *clk = clknode_find_by_id(clkdom, 1);
371 else if (ncells == 1)
372 *clk = clknode_find_by_id(clkdom, cells[0]);
383 * Create a clock domain. Returns with the topo lock held.
386 clkdom_create(device_t dev)
388 struct clkdom *clkdom;
390 clkdom = malloc(sizeof(struct clkdom), M_CLOCK, M_WAITOK | M_ZERO);
392 TAILQ_INIT(&clkdom->clknode_list);
394 clkdom->ofw_mapper = clknode_default_ofw_map;
397 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
398 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
400 CTLTYPE_STRING | CTLFLAG_RD,
401 clkdom, 0, clkdom_sysctl,
403 "Clock list for the domain");
409 clkdom_unlock(struct clkdom *clkdom)
416 clkdom_xlock(struct clkdom *clkdom)
423 * Finalize initialization of clock domain. Releases topo lock.
425 * XXX Revisit failure handling.
428 clkdom_finit(struct clkdom *clkdom)
430 struct clknode *clknode;
436 if ((node = ofw_bus_get_node(clkdom->dev)) == -1) {
437 device_printf(clkdom->dev,
438 "%s called on not ofw based device\n", __func__);
444 /* Make clock domain globally visible. */
446 TAILQ_INSERT_TAIL(&clkdom_list, clkdom, link);
448 OF_device_register_xref(OF_xref_from_node(node), clkdom->dev);
451 /* Register all clock names into global list. */
452 TAILQ_FOREACH(clknode, &clkdom->clknode_list, clkdom_link) {
453 TAILQ_INSERT_TAIL(&clknode_list, clknode, clklist_link);
456 * At this point all domain nodes must be registered and all
457 * parents must be valid.
459 TAILQ_FOREACH(clknode, &clkdom->clknode_list, clkdom_link) {
460 if (clknode->parent_cnt == 0)
462 for (i = 0; i < clknode->parent_cnt; i++) {
463 if (clknode->parents[i] != NULL)
465 if (clknode->parent_names[i] == NULL)
467 clknode->parents[i] = clknode_find_by_name(
468 clknode->parent_names[i]);
469 if (clknode->parents[i] == NULL) {
470 device_printf(clkdom->dev,
471 "Clock %s have unknown parent: %s\n",
472 clknode->name, clknode->parent_names[i]);
477 /* If parent index is not set yet... */
478 if (clknode->parent_idx == CLKNODE_IDX_NONE) {
479 device_printf(clkdom->dev,
480 "Clock %s have not set parent idx\n",
485 if (clknode->parents[clknode->parent_idx] == NULL) {
486 device_printf(clkdom->dev,
487 "Clock %s have unknown parent(idx %d): %s\n",
488 clknode->name, clknode->parent_idx,
489 clknode->parent_names[clknode->parent_idx]);
493 clknode_adjust_parent(clknode, clknode->parent_idx);
499 /* Dump clock domain. */
501 clkdom_dump(struct clkdom * clkdom)
503 struct clknode *clknode;
508 TAILQ_FOREACH(clknode, &clkdom->clknode_list, clkdom_link) {
509 rv = clknode_get_freq(clknode, &freq);
510 printf("Clock: %s, parent: %s(%d), freq: %ju\n", clknode->name,
511 clknode->parent == NULL ? "(NULL)" : clknode->parent->name,
513 (uintmax_t)((rv == 0) ? freq: rv));
519 * Create and initialize clock object, but do not register it.
522 clknode_create(struct clkdom * clkdom, clknode_class_t clknode_class,
523 const struct clknode_init_def *def)
525 struct clknode *clknode;
526 struct sysctl_oid *clknode_oid;
528 KASSERT(def->name != NULL, ("clock name is NULL"));
529 KASSERT(def->name[0] != '\0', ("clock name is empty"));
532 if (clknode_find_by_name(def->name) != NULL)
533 panic("Duplicated clock registration: %s\n", def->name);
537 /* Create object and initialize it. */
538 clknode = malloc(sizeof(struct clknode), M_CLOCK, M_WAITOK | M_ZERO);
539 kobj_init((kobj_t)clknode, (kobj_class_t)clknode_class);
540 sx_init(&clknode->lock, "Clocknode lock");
542 /* Allocate softc if required. */
543 if (clknode_class->size > 0) {
544 clknode->softc = malloc(clknode_class->size,
545 M_CLOCK, M_WAITOK | M_ZERO);
548 /* Prepare array for ptrs to parent clocks. */
549 clknode->parents = malloc(sizeof(struct clknode *) * def->parent_cnt,
550 M_CLOCK, M_WAITOK | M_ZERO);
552 /* Copy all strings unless they're flagged as static. */
553 if (def->flags & CLK_NODE_STATIC_STRINGS) {
554 clknode->name = def->name;
555 clknode->parent_names = def->parent_names;
557 clknode->name = strdup(def->name, M_CLOCK);
558 clknode->parent_names =
559 strdup_list(def->parent_names, def->parent_cnt);
563 clknode->id = def->id;
564 clknode->clkdom = clkdom;
565 clknode->flags = def->flags;
566 clknode->parent_cnt = def->parent_cnt;
567 clknode->parent = NULL;
568 clknode->parent_idx = CLKNODE_IDX_NONE;
569 TAILQ_INIT(&clknode->children);
571 sysctl_ctx_init(&clknode->sysctl_ctx);
572 clknode_oid = SYSCTL_ADD_NODE(&clknode->sysctl_ctx,
573 SYSCTL_STATIC_CHILDREN(_clock),
574 OID_AUTO, clknode->name,
575 CTLFLAG_RD, 0, "A clock node");
577 SYSCTL_ADD_U64(&clknode->sysctl_ctx,
578 SYSCTL_CHILDREN(clknode_oid),
579 OID_AUTO, "frequency",
580 CTLFLAG_RD, &clknode->freq, 0, "The clock frequency");
581 SYSCTL_ADD_PROC(&clknode->sysctl_ctx,
582 SYSCTL_CHILDREN(clknode_oid),
584 CTLTYPE_STRING | CTLFLAG_RD,
585 clknode, CLKNODE_SYSCTL_PARENT, clknode_sysctl,
588 SYSCTL_ADD_PROC(&clknode->sysctl_ctx,
589 SYSCTL_CHILDREN(clknode_oid),
591 CTLTYPE_STRING | CTLFLAG_RD,
592 clknode, CLKNODE_SYSCTL_PARENTS_LIST, clknode_sysctl,
594 "The clock parents list");
595 SYSCTL_ADD_PROC(&clknode->sysctl_ctx,
596 SYSCTL_CHILDREN(clknode_oid),
597 OID_AUTO, "childrens",
598 CTLTYPE_STRING | CTLFLAG_RD,
599 clknode, CLKNODE_SYSCTL_CHILDREN_LIST, clknode_sysctl,
601 "The clock childrens list");
602 SYSCTL_ADD_INT(&clknode->sysctl_ctx,
603 SYSCTL_CHILDREN(clknode_oid),
604 OID_AUTO, "enable_cnt",
605 CTLFLAG_RD, &clknode->enable_cnt, 0, "The clock enable counter");
611 * Register clock object into clock domain hierarchy.
614 clknode_register(struct clkdom * clkdom, struct clknode *clknode)
618 rv = CLKNODE_INIT(clknode, clknode_get_device(clknode));
620 printf(" CLKNODE_INIT failed: %d\n", rv);
624 TAILQ_INSERT_TAIL(&clkdom->clknode_list, clknode, clkdom_link);
630 * Clock providers interface.
634 * Reparent clock node.
637 clknode_adjust_parent(struct clknode *clknode, int idx)
642 if (clknode->parent_cnt == 0)
644 if ((idx == CLKNODE_IDX_NONE) || (idx >= clknode->parent_cnt))
645 panic("Invalid clock parent index\n");
647 if (clknode->parents[idx] == NULL)
648 panic("%s: Attempt to set invalid parent %d for clock %s",
649 __func__, idx, clknode->name);
651 /* Remove me from old children list. */
652 if (clknode->parent != NULL) {
653 TAILQ_REMOVE(&clknode->parent->children, clknode, sibling_link);
656 /* Insert into children list of new parent. */
657 clknode->parent_idx = idx;
658 clknode->parent = clknode->parents[idx];
659 TAILQ_INSERT_TAIL(&clknode->parent->children, clknode, sibling_link);
663 * Set parent index - init function.
666 clknode_init_parent_idx(struct clknode *clknode, int idx)
669 if (clknode->parent_cnt == 0) {
670 clknode->parent_idx = CLKNODE_IDX_NONE;
671 clknode->parent = NULL;
674 if ((idx == CLKNODE_IDX_NONE) ||
675 (idx >= clknode->parent_cnt) ||
676 (clknode->parent_names[idx] == NULL))
677 panic("%s: Invalid clock parent index: %d\n", __func__, idx);
679 clknode->parent_idx = idx;
683 clknode_set_parent_by_idx(struct clknode *clknode, int idx)
689 /* We have exclusive topology lock, node lock is not needed. */
692 if (clknode->parent_cnt == 0)
695 if (clknode->parent_idx == idx)
698 oldidx = clknode->parent_idx;
699 clknode_adjust_parent(clknode, idx);
700 rv = CLKNODE_SET_MUX(clknode, idx);
702 clknode_adjust_parent(clknode, oldidx);
705 rv = clknode_get_freq(clknode->parent, &freq);
708 rv = clknode_refresh_cache(clknode, freq);
713 clknode_set_parent_by_name(struct clknode *clknode, const char *name)
719 /* We have exclusive topology lock, node lock is not needed. */
722 if (clknode->parent_cnt == 0)
726 * If this node doesnt have mux, then passthrough request to parent.
727 * This feature is used in clock domain initialization and allows us to
728 * set clock source and target frequency on the tail node of the clock
731 if (clknode->parent_cnt == 1) {
732 rv = clknode_set_parent_by_name(clknode->parent, name);
736 for (idx = 0; idx < clknode->parent_cnt; idx++) {
737 if (clknode->parent_names[idx] == NULL)
739 if (strcmp(clknode->parent_names[idx], name) == 0)
742 if (idx >= clknode->parent_cnt) {
745 if (clknode->parent_idx == idx)
748 oldidx = clknode->parent_idx;
749 clknode_adjust_parent(clknode, idx);
750 rv = CLKNODE_SET_MUX(clknode, idx);
752 clknode_adjust_parent(clknode, oldidx);
753 CLKNODE_UNLOCK(clknode);
756 rv = clknode_get_freq(clknode->parent, &freq);
759 rv = clknode_refresh_cache(clknode, freq);
764 clknode_get_parent(struct clknode *clknode)
767 return (clknode->parent);
771 clknode_get_name(struct clknode *clknode)
774 return (clknode->name);
778 clknode_get_parent_names(struct clknode *clknode)
781 return (clknode->parent_names);
785 clknode_get_parents_num(struct clknode *clknode)
788 return (clknode->parent_cnt);
792 clknode_get_parent_idx(struct clknode *clknode)
795 return (clknode->parent_idx);
799 clknode_get_flags(struct clknode *clknode)
802 return (clknode->flags);
807 clknode_get_softc(struct clknode *clknode)
810 return (clknode->softc);
814 clknode_get_device(struct clknode *clknode)
817 return (clknode->clkdom->dev);
822 clkdom_set_ofw_mapper(struct clkdom * clkdom, clknode_ofw_mapper_func *map)
825 clkdom->ofw_mapper = map;
830 * Real consumers executive
833 clknode_get_freq(struct clknode *clknode, uint64_t *freq)
839 /* Use cached value, if it exists. */
840 *freq = clknode->freq;
844 /* Get frequency from parent, if the clock has a parent. */
845 if (clknode->parent_cnt > 0) {
846 rv = clknode_get_freq(clknode->parent, freq);
852 /* And recalculate my output frequency. */
853 CLKNODE_XLOCK(clknode);
854 rv = CLKNODE_RECALC_FREQ(clknode, freq);
856 CLKNODE_UNLOCK(clknode);
857 printf("Cannot get frequency for clk: %s, error: %d\n",
862 /* Save new frequency to cache. */
863 clknode->freq = *freq;
864 CLKNODE_UNLOCK(clknode);
869 clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
873 uint64_t parent_freq;
875 /* We have exclusive topology lock, node lock is not needed. */
878 /* Check for no change */
879 if (clknode->freq == freq)
885 * We can set frequency only if
888 * clock is glitch free and is enabled by calling consumer only
890 if ((flags & CLK_SET_DRYRUN) == 0 &&
891 clknode->enable_cnt > 1 &&
892 clknode->enable_cnt > enablecnt &&
893 (clknode->flags & CLK_NODE_GLITCH_FREE) == 0) {
897 /* Get frequency from parent, if the clock has a parent. */
898 if (clknode->parent_cnt > 0) {
899 rv = clknode_get_freq(clknode->parent, &parent_freq);
905 /* Set frequency for this clock. */
906 rv = CLKNODE_SET_FREQ(clknode, parent_freq, &freq, flags, &done);
908 printf("Cannot set frequency for clk: %s, error: %d\n",
910 if ((flags & CLK_SET_DRYRUN) == 0)
911 clknode_refresh_cache(clknode, parent_freq);
916 /* Success - invalidate frequency cache for all children. */
917 if ((flags & CLK_SET_DRYRUN) == 0) {
918 clknode->freq = freq;
919 clknode_refresh_cache(clknode, parent_freq);
921 } else if (clknode->parent != NULL) {
922 /* Nothing changed, pass request to parent. */
923 rv = clknode_set_freq(clknode->parent, freq, flags, enablecnt);
925 /* End of chain without action. */
926 printf("Cannot set frequency for clk: %s, end of chain\n",
935 clknode_enable(struct clknode *clknode)
941 /* Enable clock for each node in chain, starting from source. */
942 if (clknode->parent_cnt > 0) {
943 rv = clknode_enable(clknode->parent);
949 /* Handle this node */
950 CLKNODE_XLOCK(clknode);
951 if (clknode->enable_cnt == 0) {
952 rv = CLKNODE_SET_GATE(clknode, 1);
954 CLKNODE_UNLOCK(clknode);
958 clknode->enable_cnt++;
959 CLKNODE_UNLOCK(clknode);
964 clknode_disable(struct clknode *clknode)
971 CLKNODE_XLOCK(clknode);
972 /* Disable clock for each node in chain, starting from consumer. */
973 if ((clknode->enable_cnt == 1) &&
974 ((clknode->flags & CLK_NODE_CANNOT_STOP) == 0)) {
975 rv = CLKNODE_SET_GATE(clknode, 0);
977 CLKNODE_UNLOCK(clknode);
981 clknode->enable_cnt--;
982 CLKNODE_UNLOCK(clknode);
984 if (clknode->parent_cnt > 0) {
985 rv = clknode_disable(clknode->parent);
991 clknode_stop(struct clknode *clknode, int depth)
998 CLKNODE_XLOCK(clknode);
999 /* The first node cannot be enabled. */
1000 if ((clknode->enable_cnt != 0) && (depth == 0)) {
1001 CLKNODE_UNLOCK(clknode);
1004 /* Stop clock for each node in chain, starting from consumer. */
1005 if ((clknode->enable_cnt == 0) &&
1006 ((clknode->flags & CLK_NODE_CANNOT_STOP) == 0)) {
1007 rv = CLKNODE_SET_GATE(clknode, 0);
1009 CLKNODE_UNLOCK(clknode);
1013 CLKNODE_UNLOCK(clknode);
1015 if (clknode->parent_cnt > 0)
1016 rv = clknode_stop(clknode->parent, depth + 1);
1020 /* --------------------------------------------------------------------------
1022 * Clock consumers interface.
1025 /* Helper function for clk_get*() */
1027 clk_create(struct clknode *clknode, device_t dev)
1033 clk = malloc(sizeof(struct clk), M_CLOCK, M_WAITOK);
1035 clk->clknode = clknode;
1036 clk->enable_cnt = 0;
1043 clk_get_freq(clk_t clk, uint64_t *freq)
1046 struct clknode *clknode;
1048 clknode = clk->clknode;
1049 KASSERT(clknode->ref_cnt > 0,
1050 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1053 rv = clknode_get_freq(clknode, freq);
1059 clk_set_freq(clk_t clk, uint64_t freq, int flags)
1062 struct clknode *clknode;
1064 flags &= CLK_SET_USER_MASK;
1065 clknode = clk->clknode;
1066 KASSERT(clknode->ref_cnt > 0,
1067 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1070 rv = clknode_set_freq(clknode, freq, flags, clk->enable_cnt);
1076 clk_test_freq(clk_t clk, uint64_t freq, int flags)
1079 struct clknode *clknode;
1081 flags &= CLK_SET_USER_MASK;
1082 clknode = clk->clknode;
1083 KASSERT(clknode->ref_cnt > 0,
1084 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1087 rv = clknode_set_freq(clknode, freq, flags | CLK_SET_DRYRUN, 0);
1093 clk_get_parent(clk_t clk, clk_t *parent)
1095 struct clknode *clknode;
1096 struct clknode *parentnode;
1098 clknode = clk->clknode;
1099 KASSERT(clknode->ref_cnt > 0,
1100 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1103 parentnode = clknode_get_parent(clknode);
1104 if (parentnode == NULL) {
1108 *parent = clk_create(parentnode, clk->dev);
1114 clk_set_parent_by_clk(clk_t clk, clk_t parent)
1117 struct clknode *clknode;
1118 struct clknode *parentnode;
1120 clknode = clk->clknode;
1121 parentnode = parent->clknode;
1122 KASSERT(clknode->ref_cnt > 0,
1123 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1124 KASSERT(parentnode->ref_cnt > 0,
1125 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1127 rv = clknode_set_parent_by_name(clknode, parentnode->name);
1133 clk_enable(clk_t clk)
1136 struct clknode *clknode;
1138 clknode = clk->clknode;
1139 KASSERT(clknode->ref_cnt > 0,
1140 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1142 rv = clknode_enable(clknode);
1150 clk_disable(clk_t clk)
1153 struct clknode *clknode;
1155 clknode = clk->clknode;
1156 KASSERT(clknode->ref_cnt > 0,
1157 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1158 KASSERT(clk->enable_cnt > 0,
1159 ("Attempt to disable already disabled clock: %s\n", clknode->name));
1161 rv = clknode_disable(clknode);
1172 struct clknode *clknode;
1174 clknode = clk->clknode;
1175 KASSERT(clknode->ref_cnt > 0,
1176 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1177 KASSERT(clk->enable_cnt == 0,
1178 ("Attempt to stop already enabled clock: %s\n", clknode->name));
1181 rv = clknode_stop(clknode, 0);
1187 clk_release(clk_t clk)
1189 struct clknode *clknode;
1191 clknode = clk->clknode;
1192 KASSERT(clknode->ref_cnt > 0,
1193 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1195 while (clk->enable_cnt > 0) {
1196 clknode_disable(clknode);
1199 CLKNODE_XLOCK(clknode);
1201 CLKNODE_UNLOCK(clknode);
1209 clk_get_name(clk_t clk)
1212 struct clknode *clknode;
1214 clknode = clk->clknode;
1215 KASSERT(clknode->ref_cnt > 0,
1216 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1217 name = clknode_get_name(clknode);
1222 clk_get_by_name(device_t dev, const char *name, clk_t *clk)
1224 struct clknode *clknode;
1227 clknode = clknode_find_by_name(name);
1228 if (clknode == NULL) {
1232 *clk = clk_create(clknode, dev);
1238 clk_get_by_id(device_t dev, struct clkdom *clkdom, intptr_t id, clk_t *clk)
1240 struct clknode *clknode;
1244 clknode = clknode_find_by_id(clkdom, id);
1245 if (clknode == NULL) {
1249 *clk = clk_create(clknode, dev);
1258 clk_set_assigned(device_t dev, phandle_t node)
1260 clk_t clk, clk_parent;
1261 int error, nclocks, i;
1263 error = ofw_bus_parse_xref_list_get_length(node,
1264 "assigned-clock-parents", "#clock-cells", &nclocks);
1267 if (error != ENOENT)
1269 "cannot parse assigned-clock-parents property\n");
1273 for (i = 0; i < nclocks; i++) {
1274 error = clk_get_by_ofw_index_prop(dev, 0,
1275 "assigned-clock-parents", i, &clk_parent);
1277 device_printf(dev, "cannot get parent %d\n", i);
1281 error = clk_get_by_ofw_index_prop(dev, 0, "assigned-clocks",
1284 device_printf(dev, "cannot get assigned clock %d\n", i);
1285 clk_release(clk_parent);
1289 error = clk_set_parent_by_clk(clk, clk_parent);
1290 clk_release(clk_parent);
1300 clk_get_by_ofw_index_prop(device_t dev, phandle_t cnode, const char *prop, int idx, clk_t *clk)
1302 phandle_t parent, *cells;
1305 struct clkdom *clkdom;
1306 struct clknode *clknode;
1310 cnode = ofw_bus_get_node(dev);
1312 device_printf(dev, "%s called on not ofw based device\n",
1318 rv = ofw_bus_parse_xref_list_alloc(cnode, prop, "#clock-cells", idx,
1319 &parent, &ncells, &cells);
1324 clockdev = OF_device_from_xref(parent);
1325 if (clockdev == NULL) {
1331 clkdom = clkdom_get_by_dev(clockdev);
1332 if (clkdom == NULL){
1338 rv = clkdom->ofw_mapper(clkdom, ncells, cells, &clknode);
1340 *clk = clk_create(clknode, dev);
1346 OF_prop_free(cells);
1351 clk_get_by_ofw_index(device_t dev, phandle_t cnode, int idx, clk_t *clk)
1353 return (clk_get_by_ofw_index_prop(dev, cnode, "clocks", idx, clk));
1357 clk_get_by_ofw_name(device_t dev, phandle_t cnode, const char *name, clk_t *clk)
1362 cnode = ofw_bus_get_node(dev);
1364 device_printf(dev, "%s called on not ofw based device\n",
1368 rv = ofw_bus_find_string_index(cnode, "clock-names", name, &idx);
1371 return (clk_get_by_ofw_index(dev, cnode, idx, clk));
1374 /* --------------------------------------------------------------------------
1376 * Support functions for parsing various clock related OFW things.
1380 * Get "clock-output-names" and (optional) "clock-indices" lists.
1381 * Both lists are alocated using M_OFWPROP specifier.
1383 * Returns number of items or 0.
1386 clk_parse_ofw_out_names(device_t dev, phandle_t node, const char ***out_names,
1393 if (!OF_hasprop(node, "clock-output-names"))
1395 rv = ofw_bus_string_list_to_array(node, "clock-output-names",
1401 if (!OF_hasprop(node, "clock-indices"))
1402 return (name_items);
1403 rv = OF_getencprop_alloc(node, "clock-indices", sizeof (uint32_t),
1405 if (rv != name_items) {
1406 device_printf(dev, " Size of 'clock-output-names' and "
1407 "'clock-indices' differs\n");
1408 OF_prop_free(*out_names);
1409 OF_prop_free(*indices);
1412 return (name_items);
1416 * Get output clock name for single output clock node.
1419 clk_parse_ofw_clk_name(device_t dev, phandle_t node, const char **name)
1421 const char **out_names;
1422 const char *tmp_name;
1426 if (!OF_hasprop(node, "clock-output-names")) {
1427 tmp_name = ofw_bus_get_name(dev);
1428 if (tmp_name == NULL)
1430 *name = strdup(tmp_name, M_OFWPROP);
1433 rv = ofw_bus_string_list_to_array(node, "clock-output-names",
1436 OF_prop_free(out_names);
1437 device_printf(dev, "Malformed 'clock-output-names' property\n");
1440 *name = strdup(out_names[0], M_OFWPROP);
1441 OF_prop_free(out_names);
1447 clkdom_sysctl(SYSCTL_HANDLER_ARGS)
1449 struct clkdom *clkdom = arg1;
1450 struct clknode *clknode;
1454 sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
1459 TAILQ_FOREACH(clknode, &clkdom->clknode_list, clkdom_link) {
1460 sbuf_printf(sb, "%s ", clknode->name);
1464 ret = sbuf_finish(sb);
1470 clknode_sysctl(SYSCTL_HANDLER_ARGS)
1472 struct clknode *clknode, *children;
1473 enum clknode_sysctl_type type = arg2;
1475 const char **parent_names;
1479 sb = sbuf_new_for_sysctl(NULL, NULL, 512, req);
1485 case CLKNODE_SYSCTL_PARENT:
1486 if (clknode->parent)
1487 sbuf_printf(sb, "%s", clknode->parent->name);
1489 case CLKNODE_SYSCTL_PARENTS_LIST:
1490 parent_names = clknode_get_parent_names(clknode);
1491 for (i = 0; i < clknode->parent_cnt; i++)
1492 sbuf_printf(sb, "%s ", parent_names[i]);
1494 case CLKNODE_SYSCTL_CHILDREN_LIST:
1495 TAILQ_FOREACH(children, &(clknode->children), sibling_link) {
1496 sbuf_printf(sb, "%s ", children->name);
1502 ret = sbuf_finish(sb);