Message ID | 1584279836-29825-12-git-send-email-aisheng.dong@nxp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | clk: imx8: add new clock binding for better pm support | expand |
Quoting Dong Aisheng (2020-03-15 06:43:55) > LPCG clock state may be lost when it's power domain is completely > off during system suspend/resume and we need save and restore the > state properly. > > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> > --- Reviewed-by: Stephen Boyd <sboyd@kernel.org> > diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c > index 2242e5047a0e..5bd8af371059 100644 > --- a/drivers/clk/imx/clk-lpcg-scu.c > +++ b/drivers/clk/imx/clk-lpcg-scu.c > @@ -122,3 +128,34 @@ void imx_clk_lpcg_scu_unregister(struct clk_hw *hw) > clk_hw_unregister(&clk->hw); > kfree(clk); > } > + > +static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev) > +{ > + struct clk_lpcg_scu *clk = dev_get_drvdata(dev); > + > + clk->state = readl_relaxed(clk->reg); > + dev_dbg(dev, "save lpcg state 0x%x\n", clk->state); > + > + return 0; > +} > + > +static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev) > +{ > + struct clk_lpcg_scu *clk = dev_get_drvdata(dev); > + > + /* > + * FIXME: Sometimes writes don't work unless the CPU issues Is this ever going to be resolved? Maybe the FIXME can be dropped and we can accept that writes don't work? > + * them twice > + */ > + > + writel(clk->state, clk->reg); > + writel(clk->state, clk->reg); > + dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index 3385de76f6c7..4d4a3a65bcec 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -364,6 +364,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = { .driver = { .name = "imx8qxp-lpcg-clk", .of_match_table = imx8qxp_lpcg_match, + .pm = &imx_clk_lpcg_scu_pm_ops, .suppress_bind_attrs = true, }, .probe = imx8qxp_lpcg_clk_probe, diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c index 2242e5047a0e..5bd8af371059 100644 --- a/drivers/clk/imx/clk-lpcg-scu.c +++ b/drivers/clk/imx/clk-lpcg-scu.c @@ -33,6 +33,9 @@ struct clk_lpcg_scu { void __iomem *reg; u8 bit_idx; bool hw_gate; + + /* for state save&restore */ + u32 state; }; #define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw) @@ -112,6 +115,9 @@ struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, hw = ERR_PTR(ret); } + if (dev) + dev_set_drvdata(dev, clk); + return hw; } @@ -122,3 +128,34 @@ void imx_clk_lpcg_scu_unregister(struct clk_hw *hw) clk_hw_unregister(&clk->hw); kfree(clk); } + +static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev) +{ + struct clk_lpcg_scu *clk = dev_get_drvdata(dev); + + clk->state = readl_relaxed(clk->reg); + dev_dbg(dev, "save lpcg state 0x%x\n", clk->state); + + return 0; +} + +static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev) +{ + struct clk_lpcg_scu *clk = dev_get_drvdata(dev); + + /* + * FIXME: Sometimes writes don't work unless the CPU issues + * them twice + */ + + writel(clk->state, clk->reg); + writel(clk->state, clk->reg); + dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state); + + return 0; +} + +const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend, + imx_clk_lpcg_scu_resume) +}; diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 6b29713a71d2..b1dfdaf0734e 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -11,6 +11,7 @@ #include <linux/of.h> extern struct list_head imx_scu_clks[]; +extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; int imx_clk_scu_init(struct device_node *np); struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
LPCG clock state may be lost when it's power domain is completely off during system suspend/resume and we need save and restore the state properly. Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> --- ChangeLog: v5: * make suspend/resume function static * improve code comments v4: no changes v3: new patch --- drivers/clk/imx/clk-imx8qxp-lpcg.c | 1 + drivers/clk/imx/clk-lpcg-scu.c | 37 ++++++++++++++++++++++++++++++ drivers/clk/imx/clk-scu.h | 1 + 3 files changed, 39 insertions(+)