diff options
author | Ranjani Vaidyanathan <Ranjani.Vaidyanathan@nxp.com> | 2018-01-10 11:51:26 -0600 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2018-01-11 18:50:53 +0800 |
commit | 05caa1390f88cb7d7a226a3742beb1374eba88c5 (patch) | |
tree | ec36b4c5d89a78bb6a7b08c499b33f20581507e4 | |
parent | be5672bb1fc4871ffb8569b524c2969341384fd9 (diff) |
MLK-17363-1 imx8: pm-domain: fix clock parent restore issue after suspend/resume
Currently the clock parent actually is failed to be restored in power
domain driver due to the set_parent will bail out early as the clk core
already cached the same old parent.
Implement a CLK_SET_PARENT_NOCACHE flag in clk core and register all
SC mux clocks with this flag to make sure the clk core won't bypass
the SC clock parent setting.
[ Aisheng: "Add commit message" ]
Reviewed-by: Anson Huang <anson.huang@nxp.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
Signed-off-by: Ranjani Vaidyanathan <Ranjani.Vaidyanathan@nxp.com>
(cherry picked from commit 459b9d4dfb898b0df1614f5021fdeb3b7154fc06)
-rw-r--r-- | drivers/clk/clk.c | 3 | ||||
-rw-r--r-- | drivers/clk/imx/clk-mux-scu.c | 4 | ||||
-rw-r--r-- | drivers/soc/imx/pm-domains.c | 5 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 1 |
4 files changed, 10 insertions, 3 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0fb39fe217d1..69dfb01b0c56 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1797,7 +1797,8 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) /* prevent racing with updates to the clock topology */ clk_prepare_lock(); - if (core->parent == parent) + if ((core->parent == parent) && + !(core->flags & CLK_SET_PARENT_NOCACHE)) goto out; /* verify ops for for multi-parent clks */ diff --git a/drivers/clk/imx/clk-mux-scu.c b/drivers/clk/imx/clk-mux-scu.c index 8bdd4e6b9238..ac1c8bc385bd 100644 --- a/drivers/clk/imx/clk-mux-scu.c +++ b/drivers/clk/imx/clk-mux-scu.c @@ -354,7 +354,7 @@ struct clk *clk_register_mux_gpr_scu(struct device *dev, const char *name, init.ops = &clk_mux_gpr_scu_ops; init.parent_names = parents; init.num_parents = num_parents; - init.flags = 0; + init.flags |= CLK_SET_PARENT_NOCACHE; gpr_scu_mux->hw.init = &init; gpr_scu_mux->rsrc_id = rsrc_id; @@ -431,7 +431,7 @@ struct clk *clk_register_mux2_scu(struct device *dev, const char *name, init.ops = &clk_mux2_scu_ops; init.parent_names = parents; init.num_parents = num_parents; - init.flags = flags; + init.flags = flags |= CLK_SET_PARENT_NOCACHE; mux->hw.init = &init; mux->rsrc_id = rsrc_id; diff --git a/drivers/soc/imx/pm-domains.c b/drivers/soc/imx/pm-domains.c index 4b51c99303e9..37a942f80d95 100644 --- a/drivers/soc/imx/pm-domains.c +++ b/drivers/soc/imx/pm-domains.c @@ -54,6 +54,7 @@ enum imx_pd_state { struct clk_stat { struct clk *clk; + struct clk *parent; unsigned long rate; }; @@ -146,11 +147,15 @@ static int imx8_pd_power_on(struct generic_pm_domain *domain) list_for_each_entry(imx8_rsrc_clk, &pd->clks, node) { clk_stats[i].clk = imx8_rsrc_clk->clk; + clk_stats[i].parent = imx8_rsrc_clk->parent; clk_stats[i].rate = clk_hw_get_rate(__clk_get_hw(imx8_rsrc_clk->clk)); i++; } for (i = 0; i <= count; i++) { + /* restore parent first */ + clk_set_parent(clk_stats[i].clk, clk_stats[i].parent); + /* invalid cached rate first by get rate once */ clk_get_rate(clk_stats[i].clk); /* restore the lost rate */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index a428aec36ace..599cad2fbea5 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -35,6 +35,7 @@ #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE BIT(12) +#define CLK_SET_PARENT_NOCACHE BIT(13) /* do not use the cached clk parent */ struct clk; struct clk_hw; |