This patch implements save and restore context for clk_super_mux
and clk_super.

During system supend, core power goes off the and context of Tegra
CAR registers is lost.

So during suspend entry, context of super clock registers are saved
through save_context clk_ops and are restored through restore_context
clk_ops to have them in same state as before suspend.

Signed-off-by: Sowjanya Komatineni <skomatin...@nvidia.com>
---
 drivers/clk/tegra/clk-super.c | 40 ++++++++++++++++++++++++++++++++++++++++
 drivers/clk/tegra/clk.h       |  1 +
 2 files changed, 41 insertions(+)

diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
index d73c587e4853..84492afd3f1d 100644
--- a/drivers/clk/tegra/clk-super.c
+++ b/drivers/clk/tegra/clk-super.c
@@ -121,9 +121,27 @@ static int clk_super_set_parent(struct clk_hw *hw, u8 
index)
        return err;
 }
 
+static int clk_super_mux_save_context(struct clk_hw *hw)
+{
+       struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
+
+       mux->parent_index_ctx = clk_super_get_parent(hw);
+
+       return 0;
+}
+
+static void clk_super_mux_restore_context(struct clk_hw *hw)
+{
+       struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
+
+       clk_super_set_parent(hw, mux->parent_index_ctx);
+}
+
 static const struct clk_ops tegra_clk_super_mux_ops = {
        .get_parent = clk_super_get_parent,
        .set_parent = clk_super_set_parent,
+       .save_context = clk_super_mux_save_context,
+       .restore_context = clk_super_mux_restore_context,
 };
 
 static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -159,12 +177,34 @@ static int clk_super_set_rate(struct clk_hw *hw, unsigned 
long rate,
        return super->div_ops->set_rate(div_hw, rate, parent_rate);
 }
 
+static int clk_super_save_context(struct clk_hw *hw)
+{
+       struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
+       struct clk_hw *div_hw = &super->frac_div.hw;
+
+       super->parent_index_ctx = clk_super_get_parent(hw);
+
+       return super->div_ops->save_context(div_hw);
+}
+
+static void clk_super_restore_context(struct clk_hw *hw)
+{
+       struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
+       struct clk_hw *div_hw = &super->frac_div.hw;
+
+       clk_super_set_parent(hw, super->parent_index_ctx);
+
+       super->div_ops->restore_context(div_hw);
+}
+
 const struct clk_ops tegra_clk_super_ops = {
        .get_parent = clk_super_get_parent,
        .set_parent = clk_super_set_parent,
        .set_rate = clk_super_set_rate,
        .round_rate = clk_super_round_rate,
        .recalc_rate = clk_super_recalc_rate,
+       .save_context = clk_super_save_context,
+       .restore_context = clk_super_restore_context,
 };
 
 struct clk *tegra_clk_register_super_mux(const char *name,
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index c357b49e49b0..562a3ee2d537 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -708,6 +708,7 @@ struct tegra_clk_super_mux {
        u8              div2_index;
        u8              pllx_index;
        spinlock_t      *lock;
+       u8              parent_index_ctx;
 };
 
 #define to_clk_super_mux(_hw) container_of(_hw, struct tegra_clk_super_mux, hw)
-- 
2.7.4

Reply via email to