diff options
author | Adrian Chadd <adrian@FreeBSD.org> | 2021-12-14 18:01:08 +0000 |
---|---|---|
committer | Adrian Chadd <adrian@FreeBSD.org> | 2021-12-26 12:18:53 +0000 |
commit | 9df53d07e6bce5d38fca860367da546f6a420a90 (patch) | |
tree | fc4eae32c81dca2c54731b0fde2907d0084739a6 | |
parent | 49fd2d51f07fb29af3fd239f83f249c00cd84123 (diff) | |
download | src-9df53d07e6bce5d38fca860367da546f6a420a90.tar.gz src-9df53d07e6bce5d38fca860367da546f6a420a90.zip |
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
-rw-r--r-- | sys/dev/extres/clk/clk.c | 35 | ||||
-rw-r--r-- | 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", @@ -1040,6 +1041,28 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags, } 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) { int rv; 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); |