git: 9df53d07e6bc - main - clk: add call for nodes to get the programmed/decided frequency passed back

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Sun, 26 Dec 2021 18:27:15 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=9df53d07e6bce5d38fca860367da546f6a420a90

commit 9df53d07e6bce5d38fca860367da546f6a420a90
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2021-12-14 18:01:08 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2021-12-26 12:18:53 +0000

    clk: add call for nodes to get the programmed/decided frequency passed back
    
    Summary:
    
    The existing call can only really be used for a node wishing to
    configure its parent, but as we don't pass in a pointer to the freq,
    we can't set it to what it would be for a DRY_RUN pass.
    
    So for clock nodes that wish to try setting parent frequencies to see
    which would be the best for its own target frequency, we really do need
    a way to call in and pass in a flag /and/ a pointer to freq so it can be
    updated for us as the clock tree is recursed through.
    
    Reviewers: manu
    
    Approved by: manu
    
    Subscribers: imp
    
    Differential Revision: https://reviews.freebsd.org/D33445
---
 sys/dev/extres/clk/clk.c | 35 +++++++++++++++++++++++++++++------
 sys/dev/extres/clk/clk.h |  2 ++
 2 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/sys/dev/extres/clk/clk.c b/sys/dev/extres/clk/clk.c
index f4284fcd59ba..2be233c465a9 100644
--- a/sys/dev/extres/clk/clk.c
+++ b/sys/dev/extres/clk/clk.c
@@ -965,8 +965,8 @@ clknode_get_freq(struct clknode *clknode, uint64_t *freq)
 	return (0);
 }
 
-int
-clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
+static int
+_clknode_set_freq(struct clknode *clknode, uint64_t *freq, int flags,
     int enablecnt)
 {
 	int rv, done;
@@ -976,7 +976,7 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
 	CLK_TOPO_XASSERT();
 
 	/* Check for no change */
-	if (clknode->freq == freq)
+	if (clknode->freq == *freq)
 		return (0);
 
 	parent_freq = 0;
@@ -1003,7 +1003,7 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
 	}
 
 	/* Set frequency for this clock. */
-	rv = CLKNODE_SET_FREQ(clknode, parent_freq, &freq, flags, &done);
+	rv = CLKNODE_SET_FREQ(clknode, parent_freq, freq, flags, &done);
 	if (rv != 0) {
 		printf("Cannot set frequency for clk: %s, error: %d\n",
 		    clknode->name, rv);
@@ -1015,7 +1015,7 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
 	if (done) {
 		/* Success - invalidate frequency cache for all children. */
 		if ((flags & CLK_SET_DRYRUN) == 0) {
-			clknode->freq = freq;
+			clknode->freq = *freq;
 			/* Clock might have reparent during set_freq */
 			if (clknode->parent_cnt > 0) {
 				rv = clknode_get_freq(clknode->parent,
@@ -1028,7 +1028,8 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
 		}
 	} else if (clknode->parent != NULL) {
 		/* Nothing changed, pass request to parent. */
-		rv = clknode_set_freq(clknode->parent, freq, flags, enablecnt);
+		rv = _clknode_set_freq(clknode->parent, freq, flags,
+		    enablecnt);
 	} else {
 		/* End of chain without action. */
 		printf("Cannot set frequency for clk: %s, end of chain\n",
@@ -1039,6 +1040,28 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
 	return (rv);
 }
 
+int
+clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
+    int enablecnt)
+{
+
+	return (_clknode_set_freq(clknode, &freq, flags, enablecnt));
+}
+
+int
+clknode_try_freq(struct clknode *clknode, uint64_t freq, int flags,
+    int enablecnt, uint64_t *out_freq)
+{
+	int rv;
+
+	rv = _clknode_set_freq(clknode, &freq, flags | CLK_SET_DRYRUN,
+	    enablecnt);
+	if (out_freq != NULL)
+		*out_freq = freq;
+
+	return (rv);
+}
+
 int
 clknode_enable(struct clknode *clknode)
 {
diff --git a/sys/dev/extres/clk/clk.h b/sys/dev/extres/clk/clk.h
index 3ddf8fc574de..5daf3c0731ee 100644
--- a/sys/dev/extres/clk/clk.h
+++ b/sys/dev/extres/clk/clk.h
@@ -115,6 +115,8 @@ struct clknode *clknode_find_by_id(struct clkdom *clkdom, intptr_t id);
 int clknode_get_freq(struct clknode *clknode, uint64_t *freq);
 int clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
     int enablecnt);
+int clknode_try_freq(struct clknode *clknode, uint64_t freq, int flags,
+    int enablecnt, uint64_t *out_freq);
 int clknode_enable(struct clknode *clknode);
 int clknode_disable(struct clknode *clknode);
 int clknode_stop(struct clknode *clknode, int depth);