[PATCH 21/24] clk: implement set/get phase
Sascha Hauer
s.hauer at pengutronix.de
Wed Jun 2 02:55:04 PDT 2021
Linux has clk_set_phase() and clk_get_phase() along with the
corresponding callbacks in struct clk_ops. Implement the same for
barebox as well.
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
drivers/clk/clk.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/clk.h | 5 +++++
2 files changed, 60 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fe2424dc8a..8b90f30486 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -320,6 +320,61 @@ struct clk_hw *clk_hw_get_parent(struct clk_hw *hw)
return clk_to_clk_hw(clk);
}
+/**
+ * clk_set_phase - adjust the phase shift of a clock signal
+ * @clk: clock signal source
+ * @degrees: number of degrees the signal is shifted
+ *
+ * Shifts the phase of a clock signal by the specified
+ * degrees. Returns 0 on success, -EERROR otherwise.
+ *
+ * This function makes no distinction about the input or reference
+ * signal that we adjust the clock signal phase against. For example
+ * phase locked-loop clock signal generators we may shift phase with
+ * respect to feedback clock signal input, but for other cases the
+ * clock phase may be shifted with respect to some other, unspecified
+ * signal.
+ *
+ * Additionally the concept of phase shift does not propagate through
+ * the clock tree hierarchy, which sets it apart from clock rates and
+ * clock accuracy. A parent clock phase attribute does not have an
+ * impact on the phase attribute of a child clock.
+ */
+int clk_set_phase(struct clk *clk, int degrees)
+{
+ if (!clk)
+ return 0;
+
+ /* sanity check degrees */
+ degrees %= 360;
+ if (degrees < 0)
+ degrees += 360;
+
+ if (!clk->ops->set_phase)
+ return -EINVAL;
+
+ return clk->ops->set_phase(clk_to_clk_hw(clk), degrees);
+}
+
+/**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk)
+{
+ int ret;
+
+ if (!clk->ops->get_phase)
+ return 0;
+
+ ret = clk->ops->get_phase(clk_to_clk_hw(clk));
+
+ return ret;
+}
+
int bclk_register(struct clk *clk)
{
struct clk_hw *hw = clk_to_clk_hw(clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 72971c8e27..6b4c368231 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -237,6 +237,9 @@ int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *hwp);
struct clk *clk_get_parent(struct clk *clk);
struct clk_hw *clk_hw_get_parent(struct clk_hw *hw);
+int clk_set_phase(struct clk *clk, int degrees);
+int clk_get_phase(struct clk *clk);
+
/**
* clk_get_sys - get a clock based upon the device name
* @dev_id: device name
@@ -356,6 +359,8 @@ struct clk_ops {
int (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw, unsigned long,
unsigned long);
+ int (*set_phase)(struct clk_hw *hw, int degrees);
+ int (*get_phase)(struct clk_hw *hw);
};
/**
--
2.29.2
More information about the barebox
mailing list