clk: Allow phase adjustment from debugfs
authorJohn Keeping <john@metanate.com>
Thu, 20 Apr 2023 10:38:04 +0000 (11:38 +0100)
committerStephen Boyd <sboyd@kernel.org>
Tue, 24 Oct 2023 03:20:57 +0000 (20:20 -0700)
For testing it may be useful to manually adjust a clock's phase.  Add
support for writing to the existing clk_phase debugfs file, with the
written value clamped to [0, 360) to match the behaviour of the
clk_set_phase() function.

This is a dangerous feature, so use the existing define
CLOCK_ALLOW_WRITE_DEBUGFS to allow it only if the source is modified.

Signed-off-by: John Keeping <john@metanate.com>
Link: https://lore.kernel.org/r/20230420103805.125246-1-john@metanate.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/clk.c

index 0544615d2a1de237bcfb1880cadddaad1b7eb77d..2f0885e4f6bf366d0f0b76d239c5d42807c831f4 100644 (file)
@@ -3343,6 +3343,21 @@ static int clk_rate_set(void *data, u64 val)
 
 #define clk_rate_mode  0644
 
+static int clk_phase_set(void *data, u64 val)
+{
+       struct clk_core *core = data;
+       int degrees = do_div(val, 360);
+       int ret;
+
+       clk_prepare_lock();
+       ret = clk_core_set_phase_nolock(core, degrees);
+       clk_prepare_unlock();
+
+       return ret;
+}
+
+#define clk_phase_mode 0644
+
 static int clk_prepare_enable_set(void *data, u64 val)
 {
        struct clk_core *core = data;
@@ -3370,6 +3385,9 @@ DEFINE_DEBUGFS_ATTRIBUTE(clk_prepare_enable_fops, clk_prepare_enable_get,
 #else
 #define clk_rate_set   NULL
 #define clk_rate_mode  0444
+
+#define clk_phase_set  NULL
+#define clk_phase_mode 0644
 #endif
 
 static int clk_rate_get(void *data, u64 *val)
@@ -3385,6 +3403,16 @@ static int clk_rate_get(void *data, u64 *val)
 
 DEFINE_DEBUGFS_ATTRIBUTE(clk_rate_fops, clk_rate_get, clk_rate_set, "%llu\n");
 
+static int clk_phase_get(void *data, u64 *val)
+{
+       struct clk_core *core = data;
+
+       *val = core->phase;
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(clk_phase_fops, clk_phase_get, clk_phase_set, "%llu\n");
+
 static const struct {
        unsigned long flag;
        const char *name;
@@ -3575,7 +3603,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
        debugfs_create_file("clk_min_rate", 0444, root, core, &clk_min_rate_fops);
        debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops);
        debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy);
-       debugfs_create_u32("clk_phase", 0444, root, &core->phase);
+       debugfs_create_file("clk_phase", clk_phase_mode, root, core,
+                           &clk_phase_fops);
        debugfs_create_file("clk_flags", 0444, root, core, &clk_flags_fops);
        debugfs_create_u32("clk_prepare_count", 0444, root, &core->prepare_count);
        debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count);