]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
clk: keystone: sci-clk: Add restore_context() operation
authorThomas Richard (TI) <thomas.richard@bootlin.com>
Tue, 19 May 2026 15:06:58 +0000 (17:06 +0200)
committerNishanth Menon <nm@ti.com>
Tue, 26 May 2026 11:44:33 +0000 (06:44 -0500)
Implement the restore_context() operation to restore the clock rate
and the clock parent state. The clock rate is saved in sci_clk struct
during set_rate() and recalc_rate() operations. The parent index
is saved in sci_clk struct during set_parent() operation. During
clock registration, the core retrieves each clock’s parent using
get_parent() operation to ensure the internal clock tree reflects
the actual hardware state, including any configurations made by the
bootloader. So we also save the parent index in get_parent().

Reviewed-by: Dhruva Gole <d-gole@ti.com>
Reviewed-by: Kendall Willis <k-willis@ti.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
Link: https://patch.msgid.link/20260519-ti-sci-jacinto-s2r-restore-irq-v9-3-c550a8ae0f31@bootlin.com
Signed-off-by: Nishanth Menon <nm@ti.com>
drivers/clk/keystone/sci-clk.c

index 9d5071223f4cb31bbca41694fde724757785514e..7c0f7b3e89e0b328e59952fde895f1da287360f2 100644 (file)
@@ -47,6 +47,8 @@ struct sci_clk_provider {
  * @node:       Link for handling clocks probed via DT
  * @cached_req:         Cached requested freq for determine rate calls
  * @cached_res:         Cached result freq for determine rate calls
+ * @parent_id:  Parent index for this clock
+ * @rate:       Clock rate
  */
 struct sci_clk {
        struct clk_hw hw;
@@ -58,6 +60,8 @@ struct sci_clk {
        struct list_head node;
        unsigned long cached_req;
        unsigned long cached_res;
+       int parent_id;
+       unsigned long rate;
 };
 
 #define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
@@ -150,6 +154,8 @@ static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
                return 0;
        }
 
+       clk->rate = freq;
+
        return freq;
 }
 
@@ -210,10 +216,15 @@ static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
                            unsigned long parent_rate)
 {
        struct sci_clk *clk = to_sci_clk(hw);
+       int ret;
 
-       return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
-                                           clk->clk_id, rate / 10 * 9, rate,
-                                           rate / 10 * 11);
+       ret = clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
+                                          clk->clk_id, rate / 10 * 9, rate,
+                                          rate / 10 * 11);
+       if (!ret)
+               clk->rate = rate;
+
+       return ret;
 }
 
 /**
@@ -234,12 +245,13 @@ static u8 sci_clk_get_parent(struct clk_hw *hw)
                dev_err(clk->provider->dev,
                        "get-parent failed for dev=%d, clk=%d, ret=%d\n",
                        clk->dev_id, clk->clk_id, ret);
+               clk->parent_id = ret;
                return 0;
        }
 
-       parent_id = parent_id - clk->clk_id - 1;
+       clk->parent_id = parent_id - clk->clk_id - 1;
 
-       return (u8)parent_id;
+       return (u8)clk->parent_id;
 }
 
 /**
@@ -252,12 +264,28 @@ static u8 sci_clk_get_parent(struct clk_hw *hw)
 static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
 {
        struct sci_clk *clk = to_sci_clk(hw);
+       int ret;
 
        clk->cached_req = 0;
 
-       return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
-                                             clk->clk_id,
-                                             index + 1 + clk->clk_id);
+       ret = clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
+                                            clk->clk_id,
+                                            index + 1 + clk->clk_id);
+       if (!ret)
+               clk->parent_id = index;
+
+       return ret;
+}
+
+static void sci_clk_restore_context(struct clk_hw *hw)
+{
+       struct sci_clk *clk = to_sci_clk(hw);
+
+       if (clk->num_parents > 1 && clk->parent_id >= 0)
+               sci_clk_set_parent(hw, (u8)clk->parent_id);
+
+       if (clk->rate)
+               sci_clk_set_rate(hw, clk->rate, 0);
 }
 
 static const struct clk_ops sci_clk_ops = {
@@ -269,6 +297,7 @@ static const struct clk_ops sci_clk_ops = {
        .set_rate = sci_clk_set_rate,
        .get_parent = sci_clk_get_parent,
        .set_parent = sci_clk_set_parent,
+       .restore_context = sci_clk_restore_context,
 };
 
 /**