clk: starfive: jh7110: Add sleep pm ops

Save and restore the clock registers in sleep pm ops.

Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
This commit is contained in:
Hal Feng 2024-04-16 14:41:24 +08:00
parent c1e4f3f3a0
commit ed23ed1b5f
3 changed files with 115 additions and 0 deletions

View file

@ -385,6 +385,21 @@ int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv,
}
EXPORT_SYMBOL_GPL(jh7110_reset_controller_register);
static int jh7110_syscrg_suspend(struct device *dev)
{
return clk_save_context();
}
static int jh7110_syscrg_resume(struct device *dev)
{
clk_restore_context();
return 0;
}
static const struct dev_pm_ops jh7110_syscrg_pm_ops = {
LATE_SYSTEM_SLEEP_PM_OPS(jh7110_syscrg_suspend, jh7110_syscrg_resume)
};
static int __init jh7110_syscrg_probe(struct platform_device *pdev)
{
struct jh71x0_clk_priv *priv;
@ -558,6 +573,7 @@ static struct platform_driver jh7110_syscrg_driver = {
.driver = {
.name = "clk-starfive-jh7110-sys",
.of_match_table = jh7110_syscrg_match,
.pm = pm_sleep_ptr(&jh7110_syscrg_pm_ops),
.suppress_bind_attrs = true,
},
};

View file

@ -223,11 +223,95 @@ static void jh71x0_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
#define jh71x0_clk_debug_init NULL
#endif
#ifdef CONFIG_PM_SLEEP
static int jh7110_clk_save_context(struct clk_hw *hw)
{
struct jh71x0_clk *clk = jh71x0_clk_from(hw);
struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk);
if (!clk || !priv)
return 0;
spin_lock(&priv->rmw_lock);
clk->saved_reg = jh71x0_clk_reg_get(clk);
spin_unlock(&priv->rmw_lock);
return 0;
}
static void jh7110_clk_gate_restore_context(struct clk_hw *hw)
{
struct jh71x0_clk *clk = jh71x0_clk_from(hw);
if (!clk)
return;
jh71x0_clk_reg_rmw(clk, JH71X0_CLK_ENABLE, clk->saved_reg);
}
static void jh7110_clk_div_restore_context(struct clk_hw *hw)
{
struct jh71x0_clk *clk = jh71x0_clk_from(hw);
if (!clk)
return;
jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, clk->saved_reg);
}
static void jh7110_clk_mux_restore_context(struct clk_hw *hw)
{
struct jh71x0_clk *clk = jh71x0_clk_from(hw);
if (!clk)
return;
jh71x0_clk_reg_rmw(clk, JH71X0_CLK_MUX_MASK, clk->saved_reg);
}
static void jh7110_clk_inv_restore_context(struct clk_hw *hw)
{
struct jh71x0_clk *clk = jh71x0_clk_from(hw);
if (!clk)
return;
jh71x0_clk_reg_rmw(clk, JH71X0_CLK_INVERT, clk->saved_reg);
}
static void jh7110_clk_gdiv_restore_context(struct clk_hw *hw)
{
jh7110_clk_div_restore_context(hw);
jh7110_clk_gate_restore_context(hw);
}
static void jh7110_clk_gmux_restore_context(struct clk_hw *hw)
{
jh7110_clk_mux_restore_context(hw);
jh7110_clk_gate_restore_context(hw);
}
static void jh7110_clk_mdiv_restore_context(struct clk_hw *hw)
{
jh7110_clk_mux_restore_context(hw);
jh7110_clk_div_restore_context(hw);
}
static void jh7110_clk_gmd_restore_context(struct clk_hw *hw)
{
jh7110_clk_mux_restore_context(hw);
jh7110_clk_div_restore_context(hw);
jh7110_clk_gate_restore_context(hw);
}
#endif
static const struct clk_ops jh71x0_clk_gate_ops = {
.enable = jh71x0_clk_enable,
.disable = jh71x0_clk_disable,
.is_enabled = jh71x0_clk_is_enabled,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_gate_restore_context),
};
static const struct clk_ops jh71x0_clk_div_ops = {
@ -235,6 +319,8 @@ static const struct clk_ops jh71x0_clk_div_ops = {
.determine_rate = jh71x0_clk_determine_rate,
.set_rate = jh71x0_clk_set_rate,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_div_restore_context),
};
static const struct clk_ops jh71x0_clk_fdiv_ops = {
@ -252,6 +338,8 @@ static const struct clk_ops jh71x0_clk_gdiv_ops = {
.determine_rate = jh71x0_clk_determine_rate,
.set_rate = jh71x0_clk_set_rate,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_gdiv_restore_context),
};
static const struct clk_ops jh71x0_clk_mux_ops = {
@ -259,6 +347,8 @@ static const struct clk_ops jh71x0_clk_mux_ops = {
.set_parent = jh71x0_clk_set_parent,
.get_parent = jh71x0_clk_get_parent,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_mux_restore_context),
};
static const struct clk_ops jh71x0_clk_gmux_ops = {
@ -269,6 +359,8 @@ static const struct clk_ops jh71x0_clk_gmux_ops = {
.set_parent = jh71x0_clk_set_parent,
.get_parent = jh71x0_clk_get_parent,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_gmux_restore_context),
};
static const struct clk_ops jh71x0_clk_mdiv_ops = {
@ -278,6 +370,8 @@ static const struct clk_ops jh71x0_clk_mdiv_ops = {
.set_parent = jh71x0_clk_set_parent,
.set_rate = jh71x0_clk_set_rate,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_mdiv_restore_context),
};
static const struct clk_ops jh71x0_clk_gmd_ops = {
@ -290,12 +384,16 @@ static const struct clk_ops jh71x0_clk_gmd_ops = {
.set_parent = jh71x0_clk_set_parent,
.set_rate = jh71x0_clk_set_rate,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_gmd_restore_context),
};
static const struct clk_ops jh71x0_clk_inv_ops = {
.get_phase = jh71x0_clk_get_phase,
.set_phase = jh71x0_clk_set_phase,
.debug_init = jh71x0_clk_debug_init,
.save_context = pm_sleep_ptr(jh7110_clk_save_context),
.restore_context = pm_sleep_ptr(jh7110_clk_inv_restore_context),
};
const struct clk_ops *starfive_jh71x0_clk_ops(u32 max)

View file

@ -107,6 +107,7 @@ struct jh71x0_clk {
struct clk_hw hw;
unsigned int idx;
unsigned int max_div;
u32 saved_reg;
};
struct jh71x0_clk_priv {