clk: keystone: sci-clk: Add restore_context() operation

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>
This commit is contained in:
Thomas Richard (TI) 2026-05-19 17:06:58 +02:00 committed by Nishanth Menon
parent 703b341fdd
commit 3c59123733

View 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,
};
/**