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("%s: Invalid parent index %d for clock %s",
646 __func__, idx, clknode->name);
648 if (clknode->parents[idx] == NULL)
649 panic("%s: Invalid parent index %d for clock %s",
650 __func__, idx, clknode->name);
652 /* Remove me from old children list. */
653 if (clknode->parent != NULL) {
654 TAILQ_REMOVE(&clknode->parent->children, clknode, sibling_link);
657 /* Insert into children list of new parent. */
658 clknode->parent_idx = idx;
659 clknode->parent = clknode->parents[idx];
660 TAILQ_INSERT_TAIL(&clknode->parent->children, clknode, sibling_link);
664 * Set parent index - init function.
667 clknode_init_parent_idx(struct clknode *clknode, int idx)
670 if (clknode->parent_cnt == 0) {
671 clknode->parent_idx = CLKNODE_IDX_NONE;
672 clknode->parent = NULL;
675 if ((idx == CLKNODE_IDX_NONE) ||
676 (idx >= clknode->parent_cnt) ||
677 (clknode->parent_names[idx] == NULL))
678 panic("%s: Invalid parent index %d for clock %s",
679 __func__, idx, clknode->name);
680 clknode->parent_idx = idx;
684 clknode_set_parent_by_idx(struct clknode *clknode, int idx)
690 /* We have exclusive topology lock, node lock is not needed. */
693 if (clknode->parent_cnt == 0)
696 if (clknode->parent_idx == idx)
699 oldidx = clknode->parent_idx;
700 clknode_adjust_parent(clknode, idx);
701 rv = CLKNODE_SET_MUX(clknode, idx);
703 clknode_adjust_parent(clknode, oldidx);
706 rv = clknode_get_freq(clknode->parent, &freq);
709 rv = clknode_refresh_cache(clknode, freq);
714 clknode_set_parent_by_name(struct clknode *clknode, const char *name)
720 /* We have exclusive topology lock, node lock is not needed. */
723 if (clknode->parent_cnt == 0)
727 * If this node doesnt have mux, then passthrough request to parent.
728 * This feature is used in clock domain initialization and allows us to
729 * set clock source and target frequency on the tail node of the clock
732 if (clknode->parent_cnt == 1) {
733 rv = clknode_set_parent_by_name(clknode->parent, name);
737 for (idx = 0; idx < clknode->parent_cnt; idx++) {
738 if (clknode->parent_names[idx] == NULL)
740 if (strcmp(clknode->parent_names[idx], name) == 0)
743 if (idx >= clknode->parent_cnt) {
746 if (clknode->parent_idx == idx)
749 oldidx = clknode->parent_idx;
750 clknode_adjust_parent(clknode, idx);
751 rv = CLKNODE_SET_MUX(clknode, idx);
753 clknode_adjust_parent(clknode, oldidx);
754 CLKNODE_UNLOCK(clknode);
757 rv = clknode_get_freq(clknode->parent, &freq);
760 rv = clknode_refresh_cache(clknode, freq);
765 clknode_get_parent(struct clknode *clknode)
768 return (clknode->parent);
772 clknode_get_name(struct clknode *clknode)
775 return (clknode->name);
779 clknode_get_parent_names(struct clknode *clknode)
782 return (clknode->parent_names);
786 clknode_get_parents_num(struct clknode *clknode)
789 return (clknode->parent_cnt);
793 clknode_get_parent_idx(struct clknode *clknode)
796 return (clknode->parent_idx);
800 clknode_get_flags(struct clknode *clknode)
803 return (clknode->flags);
808 clknode_get_softc(struct clknode *clknode)
811 return (clknode->softc);
815 clknode_get_device(struct clknode *clknode)
818 return (clknode->clkdom->dev);
823 clkdom_set_ofw_mapper(struct clkdom * clkdom, clknode_ofw_mapper_func *map)
826 clkdom->ofw_mapper = map;
831 * Real consumers executive
834 clknode_get_freq(struct clknode *clknode, uint64_t *freq)
840 /* Use cached value, if it exists. */
841 *freq = clknode->freq;
845 /* Get frequency from parent, if the clock has a parent. */
846 if (clknode->parent_cnt > 0) {
847 rv = clknode_get_freq(clknode->parent, freq);
853 /* And recalculate my output frequency. */
854 CLKNODE_XLOCK(clknode);
855 rv = CLKNODE_RECALC_FREQ(clknode, freq);
857 CLKNODE_UNLOCK(clknode);
858 printf("Cannot get frequency for clk: %s, error: %d\n",
863 /* Save new frequency to cache. */
864 clknode->freq = *freq;
865 CLKNODE_UNLOCK(clknode);
870 clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
874 uint64_t parent_freq;
876 /* We have exclusive topology lock, node lock is not needed. */
879 /* Check for no change */
880 if (clknode->freq == freq)
886 * We can set frequency only if
889 * clock is glitch free and is enabled by calling consumer only
891 if ((flags & CLK_SET_DRYRUN) == 0 &&
892 clknode->enable_cnt > 1 &&
893 clknode->enable_cnt > enablecnt &&
894 (clknode->flags & CLK_NODE_GLITCH_FREE) == 0) {
898 /* Get frequency from parent, if the clock has a parent. */
899 if (clknode->parent_cnt > 0) {
900 rv = clknode_get_freq(clknode->parent, &parent_freq);
906 /* Set frequency for this clock. */
907 rv = CLKNODE_SET_FREQ(clknode, parent_freq, &freq, flags, &done);
909 printf("Cannot set frequency for clk: %s, error: %d\n",
911 if ((flags & CLK_SET_DRYRUN) == 0)
912 clknode_refresh_cache(clknode, parent_freq);
917 /* Success - invalidate frequency cache for all children. */
918 if ((flags & CLK_SET_DRYRUN) == 0) {
919 clknode->freq = freq;
920 /* Clock might have reparent during set_freq */
921 if (clknode->parent_cnt > 0) {
922 rv = clknode_get_freq(clknode->parent,
928 clknode_refresh_cache(clknode, parent_freq);
930 } else if (clknode->parent != NULL) {
931 /* Nothing changed, pass request to parent. */
932 rv = clknode_set_freq(clknode->parent, freq, flags, enablecnt);
934 /* End of chain without action. */
935 printf("Cannot set frequency for clk: %s, end of chain\n",
944 clknode_enable(struct clknode *clknode)
950 /* Enable clock for each node in chain, starting from source. */
951 if (clknode->parent_cnt > 0) {
952 rv = clknode_enable(clknode->parent);
958 /* Handle this node */
959 CLKNODE_XLOCK(clknode);
960 if (clknode->enable_cnt == 0) {
961 rv = CLKNODE_SET_GATE(clknode, 1);
963 CLKNODE_UNLOCK(clknode);
967 clknode->enable_cnt++;
968 CLKNODE_UNLOCK(clknode);
973 clknode_disable(struct clknode *clknode)
980 CLKNODE_XLOCK(clknode);
981 /* Disable clock for each node in chain, starting from consumer. */
982 if ((clknode->enable_cnt == 1) &&
983 ((clknode->flags & CLK_NODE_CANNOT_STOP) == 0)) {
984 rv = CLKNODE_SET_GATE(clknode, 0);
986 CLKNODE_UNLOCK(clknode);
990 clknode->enable_cnt--;
991 CLKNODE_UNLOCK(clknode);
993 if (clknode->parent_cnt > 0) {
994 rv = clknode_disable(clknode->parent);
1000 clknode_stop(struct clknode *clknode, int depth)
1007 CLKNODE_XLOCK(clknode);
1008 /* The first node cannot be enabled. */
1009 if ((clknode->enable_cnt != 0) && (depth == 0)) {
1010 CLKNODE_UNLOCK(clknode);
1013 /* Stop clock for each node in chain, starting from consumer. */
1014 if ((clknode->enable_cnt == 0) &&
1015 ((clknode->flags & CLK_NODE_CANNOT_STOP) == 0)) {
1016 rv = CLKNODE_SET_GATE(clknode, 0);
1018 CLKNODE_UNLOCK(clknode);
1022 CLKNODE_UNLOCK(clknode);
1024 if (clknode->parent_cnt > 0)
1025 rv = clknode_stop(clknode->parent, depth + 1);
1029 /* --------------------------------------------------------------------------
1031 * Clock consumers interface.
1034 /* Helper function for clk_get*() */
1036 clk_create(struct clknode *clknode, device_t dev)
1042 clk = malloc(sizeof(struct clk), M_CLOCK, M_WAITOK);
1044 clk->clknode = clknode;
1045 clk->enable_cnt = 0;
1052 clk_get_freq(clk_t clk, uint64_t *freq)
1055 struct clknode *clknode;
1057 clknode = clk->clknode;
1058 KASSERT(clknode->ref_cnt > 0,
1059 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1062 rv = clknode_get_freq(clknode, freq);
1068 clk_set_freq(clk_t clk, uint64_t freq, int flags)
1071 struct clknode *clknode;
1073 flags &= CLK_SET_USER_MASK;
1074 clknode = clk->clknode;
1075 KASSERT(clknode->ref_cnt > 0,
1076 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1079 rv = clknode_set_freq(clknode, freq, flags, clk->enable_cnt);
1085 clk_test_freq(clk_t clk, uint64_t freq, int flags)
1088 struct clknode *clknode;
1090 flags &= CLK_SET_USER_MASK;
1091 clknode = clk->clknode;
1092 KASSERT(clknode->ref_cnt > 0,
1093 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1096 rv = clknode_set_freq(clknode, freq, flags | CLK_SET_DRYRUN, 0);
1102 clk_get_parent(clk_t clk, clk_t *parent)
1104 struct clknode *clknode;
1105 struct clknode *parentnode;
1107 clknode = clk->clknode;
1108 KASSERT(clknode->ref_cnt > 0,
1109 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1112 parentnode = clknode_get_parent(clknode);
1113 if (parentnode == NULL) {
1117 *parent = clk_create(parentnode, clk->dev);
1123 clk_set_parent_by_clk(clk_t clk, clk_t parent)
1126 struct clknode *clknode;
1127 struct clknode *parentnode;
1129 clknode = clk->clknode;
1130 parentnode = parent->clknode;
1131 KASSERT(clknode->ref_cnt > 0,
1132 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1133 KASSERT(parentnode->ref_cnt > 0,
1134 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1136 rv = clknode_set_parent_by_name(clknode, parentnode->name);
1142 clk_enable(clk_t clk)
1145 struct clknode *clknode;
1147 clknode = clk->clknode;
1148 KASSERT(clknode->ref_cnt > 0,
1149 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1151 rv = clknode_enable(clknode);
1159 clk_disable(clk_t clk)
1162 struct clknode *clknode;
1164 clknode = clk->clknode;
1165 KASSERT(clknode->ref_cnt > 0,
1166 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1167 KASSERT(clk->enable_cnt > 0,
1168 ("Attempt to disable already disabled clock: %s\n", clknode->name));
1170 rv = clknode_disable(clknode);
1181 struct clknode *clknode;
1183 clknode = clk->clknode;
1184 KASSERT(clknode->ref_cnt > 0,
1185 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1186 KASSERT(clk->enable_cnt == 0,
1187 ("Attempt to stop already enabled clock: %s\n", clknode->name));
1190 rv = clknode_stop(clknode, 0);
1196 clk_release(clk_t clk)
1198 struct clknode *clknode;
1200 clknode = clk->clknode;
1201 KASSERT(clknode->ref_cnt > 0,
1202 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1204 while (clk->enable_cnt > 0) {
1205 clknode_disable(clknode);
1208 CLKNODE_XLOCK(clknode);
1210 CLKNODE_UNLOCK(clknode);
1218 clk_get_name(clk_t clk)
1221 struct clknode *clknode;
1223 clknode = clk->clknode;
1224 KASSERT(clknode->ref_cnt > 0,
1225 ("Attempt to access unreferenced clock: %s\n", clknode->name));
1226 name = clknode_get_name(clknode);
1231 clk_get_by_name(device_t dev, const char *name, clk_t *clk)
1233 struct clknode *clknode;
1236 clknode = clknode_find_by_name(name);
1237 if (clknode == NULL) {
1241 *clk = clk_create(clknode, dev);
1247 clk_get_by_id(device_t dev, struct clkdom *clkdom, intptr_t id, clk_t *clk)
1249 struct clknode *clknode;
1253 clknode = clknode_find_by_id(clkdom, id);
1254 if (clknode == NULL) {
1258 *clk = clk_create(clknode, dev);
1267 clk_set_assigned(device_t dev, phandle_t node)
1269 clk_t clk, clk_parent;
1270 int error, nclocks, i;
1272 error = ofw_bus_parse_xref_list_get_length(node,
1273 "assigned-clock-parents", "#clock-cells", &nclocks);
1276 if (error != ENOENT)
1278 "cannot parse assigned-clock-parents property\n");
1282 for (i = 0; i < nclocks; i++) {
1283 error = clk_get_by_ofw_index_prop(dev, 0,
1284 "assigned-clock-parents", i, &clk_parent);
1286 device_printf(dev, "cannot get parent %d\n", i);
1290 error = clk_get_by_ofw_index_prop(dev, 0, "assigned-clocks",
1293 device_printf(dev, "cannot get assigned clock %d\n", i);
1294 clk_release(clk_parent);
1298 error = clk_set_parent_by_clk(clk, clk_parent);
1299 clk_release(clk_parent);
1309 clk_get_by_ofw_index_prop(device_t dev, phandle_t cnode, const char *prop, int idx, clk_t *clk)
1311 phandle_t parent, *cells;
1314 struct clkdom *clkdom;
1315 struct clknode *clknode;
1319 cnode = ofw_bus_get_node(dev);
1321 device_printf(dev, "%s called on not ofw based device\n",
1327 rv = ofw_bus_parse_xref_list_alloc(cnode, prop, "#clock-cells", idx,
1328 &parent, &ncells, &cells);
1333 clockdev = OF_device_from_xref(parent);
1334 if (clockdev == NULL) {
1340 clkdom = clkdom_get_by_dev(clockdev);
1341 if (clkdom == NULL){
1347 rv = clkdom->ofw_mapper(clkdom, ncells, cells, &clknode);
1349 *clk = clk_create(clknode, dev);
1355 OF_prop_free(cells);
1360 clk_get_by_ofw_index(device_t dev, phandle_t cnode, int idx, clk_t *clk)
1362 return (clk_get_by_ofw_index_prop(dev, cnode, "clocks", idx, clk));
1366 clk_get_by_ofw_name(device_t dev, phandle_t cnode, const char *name, clk_t *clk)
1371 cnode = ofw_bus_get_node(dev);
1373 device_printf(dev, "%s called on not ofw based device\n",
1377 rv = ofw_bus_find_string_index(cnode, "clock-names", name, &idx);
1380 return (clk_get_by_ofw_index(dev, cnode, idx, clk));
1383 /* --------------------------------------------------------------------------
1385 * Support functions for parsing various clock related OFW things.
1389 * Get "clock-output-names" and (optional) "clock-indices" lists.
1390 * Both lists are alocated using M_OFWPROP specifier.
1392 * Returns number of items or 0.
1395 clk_parse_ofw_out_names(device_t dev, phandle_t node, const char ***out_names,
1402 if (!OF_hasprop(node, "clock-output-names"))
1404 rv = ofw_bus_string_list_to_array(node, "clock-output-names",
1410 if (!OF_hasprop(node, "clock-indices"))
1411 return (name_items);
1412 rv = OF_getencprop_alloc(node, "clock-indices", sizeof (uint32_t),
1414 if (rv != name_items) {
1415 device_printf(dev, " Size of 'clock-output-names' and "
1416 "'clock-indices' differs\n");
1417 OF_prop_free(*out_names);
1418 OF_prop_free(*indices);
1421 return (name_items);
1425 * Get output clock name for single output clock node.
1428 clk_parse_ofw_clk_name(device_t dev, phandle_t node, const char **name)
1430 const char **out_names;
1431 const char *tmp_name;
1435 if (!OF_hasprop(node, "clock-output-names")) {
1436 tmp_name = ofw_bus_get_name(dev);
1437 if (tmp_name == NULL)
1439 *name = strdup(tmp_name, M_OFWPROP);
1442 rv = ofw_bus_string_list_to_array(node, "clock-output-names",
1445 OF_prop_free(out_names);
1446 device_printf(dev, "Malformed 'clock-output-names' property\n");
1449 *name = strdup(out_names[0], M_OFWPROP);
1450 OF_prop_free(out_names);
1456 clkdom_sysctl(SYSCTL_HANDLER_ARGS)
1458 struct clkdom *clkdom = arg1;
1459 struct clknode *clknode;
1463 sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
1468 TAILQ_FOREACH(clknode, &clkdom->clknode_list, clkdom_link) {
1469 sbuf_printf(sb, "%s ", clknode->name);
1473 ret = sbuf_finish(sb);
1479 clknode_sysctl(SYSCTL_HANDLER_ARGS)
1481 struct clknode *clknode, *children;
1482 enum clknode_sysctl_type type = arg2;
1484 const char **parent_names;
1488 sb = sbuf_new_for_sysctl(NULL, NULL, 512, req);
1494 case CLKNODE_SYSCTL_PARENT:
1495 if (clknode->parent)
1496 sbuf_printf(sb, "%s", clknode->parent->name);
1498 case CLKNODE_SYSCTL_PARENTS_LIST:
1499 parent_names = clknode_get_parent_names(clknode);
1500 for (i = 0; i < clknode->parent_cnt; i++)
1501 sbuf_printf(sb, "%s ", parent_names[i]);
1503 case CLKNODE_SYSCTL_CHILDREN_LIST:
1504 TAILQ_FOREACH(children, &(clknode->children), sibling_link) {
1505 sbuf_printf(sb, "%s ", children->name);
1511 ret = sbuf_finish(sb);