28.06.2019 5:12, Sowjanya Komatineni пишет: > During system suspend state, core power goes off and looses all the > CAR controller register settings. > > This patch creates APIs for saving and restoring the context of Tegra > CPUG, CPULP and SCLK. > > CPU and System clock context includes > - CPUG, CPULP, and SCLK burst policy settings for clock sourcea of all > their normal states. > - SCLK divisor and System clock rate for restoring SCLK, AHB and APB > rates on resume. > - OSC_DIV settings which are used as reference clock input to some PLLs. > - SPARE_REG and CLK_MASK settings. > > These APIs are used in Tegra210 clock driver during suspend and resume > operation. > > Acked-by: Thierry Reding <treding@xxxxxxxxxx> > Signed-off-by: Sowjanya Komatineni <skomatineni@xxxxxxxxxx> > --- > drivers/clk/tegra/clk-tegra-super-gen4.c | 4 -- > drivers/clk/tegra/clk.c | 80 ++++++++++++++++++++++++++++++++ > drivers/clk/tegra/clk.h | 14 ++++++ > 3 files changed, 94 insertions(+), 4 deletions(-) > > diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c > index cdfe7c9697e1..ed69ec4d883e 100644 > --- a/drivers/clk/tegra/clk-tegra-super-gen4.c > +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c > @@ -19,10 +19,6 @@ > #define PLLX_MISC2 0x514 > #define PLLX_MISC3 0x518 > > -#define CCLKG_BURST_POLICY 0x368 > -#define CCLKLP_BURST_POLICY 0x370 > -#define SCLK_BURST_POLICY 0x028 > -#define SYSTEM_CLK_RATE 0x030 > #define SCLK_DIVIDER 0x2c > > static DEFINE_SPINLOCK(sysrate_lock); > diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c > index 573e3c967ae1..9e863362d2bf 100644 > --- a/drivers/clk/tegra/clk.c > +++ b/drivers/clk/tegra/clk.c > @@ -70,6 +70,12 @@ static struct clk **clks; > static int clk_num; > static struct clk_onecell_data clk_data; > > +static u32 cclkg_burst_policy_ctx[2]; > +static u32 cclklp_burst_policy_ctx[2]; > +static u32 sclk_burst_policy_ctx[2]; > +static u32 sys_clk_divisor_ctx, system_rate_ctx; > +static u32 spare_ctx, misc_clk_enb_ctx, clk_arm_ctx; > + > /* Handlers for SoC-specific reset lines */ > static int (*special_reset_assert)(unsigned long); > static int (*special_reset_deassert)(unsigned long); > @@ -199,6 +205,80 @@ const struct tegra_clk_periph_regs *get_reg_bank(int clkid) > } > } > > +void tegra_cclkg_burst_policy_save_context(void) > +{ > + unsigned int i; > + > + for (i = 0; i < BURST_POLICY_REG_SIZE; i++) > + cclkg_burst_policy_ctx[i] = readl_relaxed(clk_base + > + CCLKG_BURST_POLICY + > + (i * 4)); > +} > + > +void tegra_cclkg_burst_policy_restore_context(void) > +{ > + unsigned int i; > + > + for (i = 0; i < BURST_POLICY_REG_SIZE; i++) > + writel_relaxed(cclkg_burst_policy_ctx[i], > + clk_base + CCLKG_BURST_POLICY + (i * 4)); > + > + fence_udelay(2, clk_base); > +} > + > +void tegra_sclk_cclklp_burst_policy_save_context(void) > +{ > + unsigned int i; > + > + for (i = 0; i < BURST_POLICY_REG_SIZE; i++) { > + cclklp_burst_policy_ctx[i] = readl_relaxed(clk_base + > + CCLKLP_BURST_POLICY + > + (i * 4)); > + > + sclk_burst_policy_ctx[i] = readl_relaxed(clk_base + > + SCLK_BURST_POLICY + > + (i * 4)); > + } > + > + sys_clk_divisor_ctx = readl_relaxed(clk_base + SYS_CLK_DIV); > + system_rate_ctx = readl_relaxed(clk_base + SYSTEM_CLK_RATE); > + spare_ctx = readl_relaxed(clk_base + SPARE_REG0); > + misc_clk_enb_ctx = readl_relaxed(clk_base + MISC_CLK_ENB); > + clk_arm_ctx = readl_relaxed(clk_base + CLK_MASK_ARM); > +} > + > +void tegra_sclk_cpulp_burst_policy_restore_context(void) > +{ > + unsigned int i; > + u32 val; > + > + /* > + * resume SCLK and CPULP clocks > + * for SCLk, set safe dividers values first and then restore source > + * and dividers > + */ > + > + writel_relaxed(0x1, clk_base + SYSTEM_CLK_RATE); > + val = readl_relaxed(clk_base + SYS_CLK_DIV); > + if (val < sys_clk_divisor_ctx) > + writel_relaxed(sys_clk_divisor_ctx, clk_base + SYS_CLK_DIV); > + > + fence_udelay(2, clk_base); > + > + for (i = 0; i < BURST_POLICY_REG_SIZE; i++) { > + writel_relaxed(cclklp_burst_policy_ctx[i], > + clk_base + CCLKLP_BURST_POLICY + (i * 4)); > + writel_relaxed(sclk_burst_policy_ctx[i], > + clk_base + SCLK_BURST_POLICY + (i * 4)); > + } > + > + writel_relaxed(sys_clk_divisor_ctx, clk_base + SYS_CLK_DIV); > + writel_relaxed(system_rate_ctx, clk_base + SYSTEM_CLK_RATE); > + writel_relaxed(spare_ctx, clk_base + SPARE_REG0); > + writel_relaxed(misc_clk_enb_ctx, clk_base + MISC_CLK_ENB); > + writel_relaxed(clk_arm_ctx, clk_base + CLK_MASK_ARM); Why fence_udelay was needed above and not needed here? > +}