Message ID | 1415368177-6637-2-git-send-email-zyw@rock-chips.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Chris, Am Freitag, 7. November 2014, 21:49:33 schrieb Chris Zhong: > save and restore some clks, which might be changed in suspend. > > Signed-off-by: Tony Xie <xxx@rock-chips.com> > Signed-off-by: Chris Zhong <zyw@rock-chips.com> > Reviewed-by: Doug Anderson <dianders@chromium.org> > Tested-by: Doug Anderson <dianders@chromium.org> I've applied this patch to my v3.19-clk/next branch Heiko
Quoting Chris Zhong (2014-11-07 05:49:33) > save and restore some clks, which might be changed in suspend. > > Signed-off-by: Tony Xie <xxx@rock-chips.com> > Signed-off-by: Chris Zhong <zyw@rock-chips.com> > Reviewed-by: Doug Anderson <dianders@chromium.org> > Tested-by: Doug Anderson <dianders@chromium.org> Looks good to me. Regards, Mike > > --- > > Changes in v7: None > Changes in v6: > - modify comments > > Changes in v5: > - modify comments > > Changes in v4: None > Changes in v3: None > Changes in v2: > - __raw_readl/__raw_writel replaced by readl_relaxed/writel_relaxed > > drivers/clk/rockchip/clk-rk3288.c | 60 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 60 insertions(+) > > diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c > index 2327829..66a9cb0 100644 > --- a/drivers/clk/rockchip/clk-rk3288.c > +++ b/drivers/clk/rockchip/clk-rk3288.c > @@ -16,6 +16,7 @@ > #include <linux/clk-provider.h> > #include <linux/of.h> > #include <linux/of_address.h> > +#include <linux/syscore_ops.h> > #include <dt-bindings/clock/rk3288-cru.h> > #include "clk.h" > > @@ -762,6 +763,64 @@ static const char *rk3288_critical_clocks[] __initconst = { > "hclk_peri", > }; > > +#ifdef CONFIG_PM_SLEEP > +static void __iomem *rk3288_cru_base; > + > +/* Some CRU registers will be reset in maskrom when the system > + * wakes up from fastboot. > + * So save them before suspend, restore them after resume. > + */ > +static const int rk3288_saved_cru_reg_ids[] = { > + RK3288_MODE_CON, > + RK3288_CLKSEL_CON(0), > + RK3288_CLKSEL_CON(1), > + RK3288_CLKSEL_CON(10), > + RK3288_CLKSEL_CON(33), > + RK3288_CLKSEL_CON(37), > +}; > + > +static u32 rk3288_saved_cru_regs[ARRAY_SIZE(rk3288_saved_cru_reg_ids)]; > + > +static int rk3288_clk_suspend(void) > +{ > + int i, reg_id; > + > + for (i = 0; i < ARRAY_SIZE(rk3288_saved_cru_reg_ids); i++) { > + reg_id = rk3288_saved_cru_reg_ids[i]; > + > + rk3288_saved_cru_regs[i] = > + readl_relaxed(rk3288_cru_base + reg_id); > + } > + return 0; > +} > + > +static void rk3288_clk_resume(void) > +{ > + int i, reg_id; > + > + for (i = ARRAY_SIZE(rk3288_saved_cru_reg_ids) - 1; i >= 0; i--) { > + reg_id = rk3288_saved_cru_reg_ids[i]; > + > + writel_relaxed(rk3288_saved_cru_regs[i] | 0xffff0000, > + rk3288_cru_base + reg_id); > + } > +} > + > +static struct syscore_ops rk3288_clk_syscore_ops = { > + .suspend = rk3288_clk_suspend, > + .resume = rk3288_clk_resume, > +}; > + > +static void rk3288_clk_sleep_init(void __iomem *reg_base) > +{ > + rk3288_cru_base = reg_base; > + register_syscore_ops(&rk3288_clk_syscore_ops); > +} > + > +#else /* CONFIG_PM_SLEEP */ > +static void rk3288_clk_sleep_init(void __iomem *reg_base) {} > +#endif > + > static void __init rk3288_clk_init(struct device_node *np) > { > void __iomem *reg_base; > @@ -810,5 +869,6 @@ static void __init rk3288_clk_init(struct device_node *np) > ROCKCHIP_SOFTRST_HIWORD_MASK); > > rockchip_register_restart_notifier(RK3288_GLB_SRST_FST); > + rk3288_clk_sleep_init(reg_base); > } > CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); > -- > 1.9.1 >
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 2327829..66a9cb0 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -16,6 +16,7 @@ #include <linux/clk-provider.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/syscore_ops.h> #include <dt-bindings/clock/rk3288-cru.h> #include "clk.h" @@ -762,6 +763,64 @@ static const char *rk3288_critical_clocks[] __initconst = { "hclk_peri", }; +#ifdef CONFIG_PM_SLEEP +static void __iomem *rk3288_cru_base; + +/* Some CRU registers will be reset in maskrom when the system + * wakes up from fastboot. + * So save them before suspend, restore them after resume. + */ +static const int rk3288_saved_cru_reg_ids[] = { + RK3288_MODE_CON, + RK3288_CLKSEL_CON(0), + RK3288_CLKSEL_CON(1), + RK3288_CLKSEL_CON(10), + RK3288_CLKSEL_CON(33), + RK3288_CLKSEL_CON(37), +}; + +static u32 rk3288_saved_cru_regs[ARRAY_SIZE(rk3288_saved_cru_reg_ids)]; + +static int rk3288_clk_suspend(void) +{ + int i, reg_id; + + for (i = 0; i < ARRAY_SIZE(rk3288_saved_cru_reg_ids); i++) { + reg_id = rk3288_saved_cru_reg_ids[i]; + + rk3288_saved_cru_regs[i] = + readl_relaxed(rk3288_cru_base + reg_id); + } + return 0; +} + +static void rk3288_clk_resume(void) +{ + int i, reg_id; + + for (i = ARRAY_SIZE(rk3288_saved_cru_reg_ids) - 1; i >= 0; i--) { + reg_id = rk3288_saved_cru_reg_ids[i]; + + writel_relaxed(rk3288_saved_cru_regs[i] | 0xffff0000, + rk3288_cru_base + reg_id); + } +} + +static struct syscore_ops rk3288_clk_syscore_ops = { + .suspend = rk3288_clk_suspend, + .resume = rk3288_clk_resume, +}; + +static void rk3288_clk_sleep_init(void __iomem *reg_base) +{ + rk3288_cru_base = reg_base; + register_syscore_ops(&rk3288_clk_syscore_ops); +} + +#else /* CONFIG_PM_SLEEP */ +static void rk3288_clk_sleep_init(void __iomem *reg_base) {} +#endif + static void __init rk3288_clk_init(struct device_node *np) { void __iomem *reg_base; @@ -810,5 +869,6 @@ static void __init rk3288_clk_init(struct device_node *np) ROCKCHIP_SOFTRST_HIWORD_MASK); rockchip_register_restart_notifier(RK3288_GLB_SRST_FST); + rk3288_clk_sleep_init(reg_base); } CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);