diff --git a/drivers/clk/starfive/clk-starfive-jh7110-sys.c b/drivers/clk/starfive/clk-starfive-jh7110-sys.c index b6b9e967dfc7..da01a750efcd 100644 --- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c +++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c @@ -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, }, }; diff --git a/drivers/clk/starfive/clk-starfive-jh71x0.c b/drivers/clk/starfive/clk-starfive-jh71x0.c index aebc99264a0b..7741e124443f 100644 --- a/drivers/clk/starfive/clk-starfive-jh71x0.c +++ b/drivers/clk/starfive/clk-starfive-jh71x0.c @@ -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) diff --git a/drivers/clk/starfive/clk-starfive-jh71x0.h b/drivers/clk/starfive/clk-starfive-jh71x0.h index 34bb11c72eb7..320fefeec8ea 100644 --- a/drivers/clk/starfive/clk-starfive-jh71x0.h +++ b/drivers/clk/starfive/clk-starfive-jh71x0.h @@ -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 {