git: a2ae5a27ce08 - main - clk: Add a clknode method to get and set the phase
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 30 Oct 2026 07:35:24 UTC
The branch main has been updated by manu:
URL: https://cgit.FreeBSD.org/src/commit/?id=a2ae5a27ce0898221e2fdbf7fdf2aee6a9925096
commit a2ae5a27ce0898221e2fdbf7fdf2aee6a9925096
Author: Emmanuel Vadot <manu@FreeBSD.org>
AuthorDate: 2026-10-20 08:09:18 +0000
Commit: Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2026-10-30 07:35:11 +0000
clk: Add a clknode method to get and set the phase
Add clknode_get_phase/clknode_set_phase (and the clk_get_phase and
clk_set_phase consumer API) so that clocks which can shift their phase,
such as the MMC sample and drive clocks of some SoCs, can expose it.
Reviewed by: mmel
Differential Revision: https://reviews.freebsd.org/D60883
---
sys/dev/clk/clk.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/clk/clk.h | 4 ++++
sys/dev/clk/clknode_if.m | 20 +++++++++++++++++
3 files changed, 82 insertions(+)
diff --git a/sys/dev/clk/clk.c b/sys/dev/clk/clk.c
index 5c74d84cacc8..e2073dfe7f99 100644
--- a/sys/dev/clk/clk.c
+++ b/sys/dev/clk/clk.c
@@ -1228,6 +1228,64 @@ clk_test_freq(clk_t clk, uint64_t freq, int flags)
return (rv);
}
+int
+clknode_set_phase(struct clknode *clknode, int degrees)
+{
+ int rv;
+
+ CLK_TOPO_ASSERT();
+
+ CLKNODE_XLOCK(clknode);
+ rv = CLKNODE_SET_PHASE(clknode, degrees);
+ CLKNODE_UNLOCK(clknode);
+ return (rv);
+}
+
+int
+clknode_get_phase(struct clknode *clknode, int *degrees)
+{
+ int rv;
+
+ CLK_TOPO_ASSERT();
+
+ CLKNODE_XLOCK(clknode);
+ rv = CLKNODE_GET_PHASE(clknode, degrees);
+ CLKNODE_UNLOCK(clknode);
+ return (rv);
+}
+
+int
+clk_set_phase(clk_t clk, int degrees)
+{
+ int rv;
+ struct clknode *clknode;
+
+ clknode = clk->clknode;
+ KASSERT(clknode->ref_cnt > 0,
+ ("Attempt to access unreferenced clock: %s\n", clknode->name));
+
+ CLK_TOPO_XLOCK();
+ rv = clknode_set_phase(clknode, degrees);
+ CLK_TOPO_UNLOCK();
+ return (rv);
+}
+
+int
+clk_get_phase(clk_t clk, int *degrees)
+{
+ int rv;
+ struct clknode *clknode;
+
+ clknode = clk->clknode;
+ KASSERT(clknode->ref_cnt > 0,
+ ("Attempt to access unreferenced clock: %s\n", clknode->name));
+
+ CLK_TOPO_SLOCK();
+ rv = clknode_get_phase(clknode, degrees);
+ CLK_TOPO_UNLOCK();
+ return (rv);
+}
+
int
clk_get_parent(clk_t clk, clk_t *parent)
{
diff --git a/sys/dev/clk/clk.h b/sys/dev/clk/clk.h
index 4702e8741a67..6f9aa75b46dd 100644
--- a/sys/dev/clk/clk.h
+++ b/sys/dev/clk/clk.h
@@ -116,6 +116,8 @@ int clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
int enablecnt);
int clknode_test_freq(struct clknode *clknode, uint64_t freq, int flags,
int enablecnt, uint64_t *out_freq);
+int clknode_set_phase(struct clknode *clknode, int degrees);
+int clknode_get_phase(struct clknode *clknode, int *degrees);
int clknode_enable(struct clknode *clknode);
int clknode_disable(struct clknode *clknode);
int clknode_stop(struct clknode *clknode, int depth);
@@ -129,6 +131,8 @@ int clk_release(clk_t clk);
int clk_get_freq(clk_t clk, uint64_t *freq);
int clk_set_freq(clk_t clk, uint64_t freq, int flags);
int clk_test_freq(clk_t clk, uint64_t freq, int flags);
+int clk_set_phase(clk_t clk, int degrees);
+int clk_get_phase(clk_t clk, int *degrees);
int clk_enable(clk_t clk);
int clk_disable(clk_t clk);
int clk_stop(clk_t clk);
diff --git a/sys/dev/clk/clknode_if.m b/sys/dev/clk/clknode_if.m
index 7269ee03bd74..95b0f64bee41 100644
--- a/sys/dev/clk/clknode_if.m
+++ b/sys/dev/clk/clknode_if.m
@@ -87,3 +87,23 @@ METHOD int set_mux {
struct clknode *clk;
int idx;
};
+
+#
+# Set clock phase (in degrees)
+# Return: ENXIO - method is not implemented
+# 0 - success
+#
+METHOD int set_phase {
+ struct clknode *clk;
+ int degrees;
+};
+
+#
+# Get clock phase (in degrees)
+# Return: ENXIO - method is not implemented
+# 0 - success
+#
+METHOD int get_phase {
+ struct clknode *clk;
+ int *degrees;
+};