Skip to content

Commit 68a14a5

Browse files
Sowjanya Komatinenithierryreding
authored andcommitted
clk: tegra: clk-super: Fix to enable PLLP branches to CPU
This patch has a fix to enable PLLP branches to CPU before changing the CPU cluster clock source to PLLP for Gen5 Super clock and disables PLLP branches to CPU when not in use. During system suspend entry and exit, CPU source will be switched to PLLP and this needs PLLP branches to be enabled to CPU prior to the switch. On system resume, warmboot code enables PLLP branches to CPU and powers up the CPU with PLLP clock source. Acked-by: Thierry Reding <[email protected]> Reviewed-by: Dmitry Osipenko <[email protected]> Signed-off-by: Sowjanya Komatineni <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent 2b8cfd6 commit 68a14a5

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

drivers/clk/tegra/clk-super.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#define super_state_to_src_shift(m, s) ((m->width * s))
2929
#define super_state_to_src_mask(m) (((1 << m->width) - 1))
3030

31+
#define CCLK_SRC_PLLP_OUT0 4
32+
#define CCLK_SRC_PLLP_OUT4 5
33+
3134
static u8 clk_super_get_parent(struct clk_hw *hw)
3235
{
3336
struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
@@ -97,12 +100,23 @@ static int clk_super_set_parent(struct clk_hw *hw, u8 index)
97100
if (index == mux->div2_index)
98101
index = mux->pllx_index;
99102
}
103+
104+
/* enable PLLP branches to CPU before selecting PLLP source */
105+
if ((mux->flags & TEGRA210_CPU_CLK) &&
106+
(index == CCLK_SRC_PLLP_OUT0 || index == CCLK_SRC_PLLP_OUT4))
107+
tegra_clk_set_pllp_out_cpu(true);
108+
100109
val &= ~((super_state_to_src_mask(mux)) << shift);
101110
val |= (index & (super_state_to_src_mask(mux))) << shift;
102111

103112
writel_relaxed(val, mux->reg);
104113
udelay(2);
105114

115+
/* disable PLLP branches to CPU if not used */
116+
if ((mux->flags & TEGRA210_CPU_CLK) &&
117+
index != CCLK_SRC_PLLP_OUT0 && index != CCLK_SRC_PLLP_OUT4)
118+
tegra_clk_set_pllp_out_cpu(false);
119+
106120
out:
107121
if (mux->lock)
108122
spin_unlock_irqrestore(mux->lock, flags);

drivers/clk/tegra/clk-tegra-super-gen4.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ static void __init tegra_super_clk_init(void __iomem *clk_base,
180180
gen_info->num_cclk_g_parents,
181181
CLK_SET_RATE_PARENT,
182182
clk_base + CCLKG_BURST_POLICY,
183-
0, 4, 8, 0, NULL);
183+
TEGRA210_CPU_CLK, 4, 8, 0, NULL);
184184
} else {
185185
clk = tegra_clk_register_super_mux("cclk_g",
186186
gen_info->cclk_g_parents,
@@ -196,6 +196,11 @@ static void __init tegra_super_clk_init(void __iomem *clk_base,
196196
dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
197197
if (dt_clk) {
198198
if (gen_info->gen == gen5) {
199+
/*
200+
* TEGRA210_CPU_CLK flag is not needed for cclk_lp as
201+
* cluster switching is not currently supported on
202+
* Tegra210 and also cpu_lp is not used.
203+
*/
199204
clk = tegra_clk_register_super_mux("cclk_lp",
200205
gen_info->cclk_lp_parents,
201206
gen_info->num_cclk_lp_parents,

drivers/clk/tegra/clk.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define CLK_OUT_ENB_W 0x364
2424
#define CLK_OUT_ENB_X 0x280
2525
#define CLK_OUT_ENB_Y 0x298
26+
#define CLK_ENB_PLLP_OUT_CPU BIT(31)
2627
#define CLK_OUT_ENB_SET_L 0x320
2728
#define CLK_OUT_ENB_CLR_L 0x324
2829
#define CLK_OUT_ENB_SET_H 0x328
@@ -199,6 +200,19 @@ const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
199200
}
200201
}
201202

203+
void tegra_clk_set_pllp_out_cpu(bool enable)
204+
{
205+
u32 val;
206+
207+
val = readl_relaxed(clk_base + CLK_OUT_ENB_Y);
208+
if (enable)
209+
val |= CLK_ENB_PLLP_OUT_CPU;
210+
else
211+
val &= ~CLK_ENB_PLLP_OUT_CPU;
212+
213+
writel_relaxed(val, clk_base + CLK_OUT_ENB_Y);
214+
}
215+
202216
struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
203217
{
204218
clk_base = regs;

drivers/clk/tegra/clk.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,9 @@ struct clk *tegra_clk_register_periph_data(void __iomem *clk_base,
669669
* Flags:
670670
* TEGRA_DIVIDER_2 - LP cluster has additional divider. This flag indicates
671671
* that this is LP cluster clock.
672+
* TEGRA210_CPU_CLK - This flag is used to identify CPU cluster for gen5
673+
* super mux parent using PLLP branches. To use PLLP branches to CPU, need
674+
* to configure additional bit PLLP_OUT_CPU in the clock registers.
672675
*/
673676
struct tegra_clk_super_mux {
674677
struct clk_hw hw;
@@ -685,6 +688,7 @@ struct tegra_clk_super_mux {
685688
#define to_clk_super_mux(_hw) container_of(_hw, struct tegra_clk_super_mux, hw)
686689

687690
#define TEGRA_DIVIDER_2 BIT(0)
691+
#define TEGRA210_CPU_CLK BIT(1)
688692

689693
extern const struct clk_ops tegra_clk_super_ops;
690694
struct clk *tegra_clk_register_super_mux(const char *name,
@@ -830,6 +834,7 @@ int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div);
830834
int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
831835
u8 frac_width, u8 flags);
832836
void tegra_clk_osc_resume(void __iomem *clk_base);
837+
void tegra_clk_set_pllp_out_cpu(bool enable);
833838

834839

835840
/* Combined read fence with delay */

0 commit comments

Comments
 (0)