(source == mux->pllx_index))
source = mux->div2_index;
+ mux->pllx_parent = (source == mux->pllx_index);
+
return source;
}
writel_relaxed(val, mux->reg);
udelay(2);
+ mux->pllx_parent = (index == mux->pllx_index);
+
out:
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
struct clk_hw *div_hw = &super->frac_div.hw;
+ if ((super->flags & TEGRA_CCLKG_DIVIDER) && super->pllx_parent)
+ return *parent_rate;
+
__clk_hw_set_clk(div_hw, hw);
return super->div_ops->round_rate(div_hw, rate, parent_rate);
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
struct clk_hw *div_hw = &super->frac_div.hw;
+ if ((super->flags & TEGRA_CCLKG_DIVIDER) && super->pllx_parent)
+ return parent_rate;
+
__clk_hw_set_clk(div_hw, hw);
return super->div_ops->recalc_rate(div_hw, parent_rate);
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
struct clk_hw *div_hw = &super->frac_div.hw;
+ if ((super->flags & TEGRA_CCLKG_DIVIDER) && super->pllx_parent)
+ return 0;
+
__clk_hw_set_clk(div_hw, hw);
return super->div_ops->set_rate(div_hw, rate, parent_rate);
}
struct clk *tegra_clk_register_super_clk(const char *name,
- const char * const *parent_names, u8 num_parents,
+ const char * const *parent_names, u8 num_parents, u8 pllx_index,
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
spinlock_t *lock)
{
super->frac_div.frac_width = 1;
super->frac_div.lock = lock;
super->div_ops = &tegra_clk_frac_div_ops;
+ super->pllx_index = pllx_index;
/* Data in .init is copied by clk_register(), so stack variable OK */
super->hw.init = &init;
clks[TEGRA210_CLK_CML1] = clk;
clk = tegra_clk_register_super_clk("aclk", aclk_parents,
- ARRAY_SIZE(aclk_parents), 0, clk_base + 0x6e0,
+ ARRAY_SIZE(aclk_parents), 0, 0, clk_base + 0x6e0,
0, NULL);
clks[TEGRA210_CLK_ACLK] = clk;
}
static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
- "pll_p_cclkg", "pll_p_out4_cclkg",
- "pll_p_out3_cclkg", "unused", "pll_x" };
+ "pll_p", "pll_p_out4", "pll_p_out3",
+ "unused", "pll_x" };
static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
"pll_p_cclklp", "pll_p_out4_cclklp",
"pll_p_out3_cclklp", "unused", "pll_x",
{
struct clk *clk;
- /*
- * Clock input to cclk_g divided from pll_p using
- * U71 divider of cclk_g.
- */
- clk = tegra_clk_register_divider("pll_p_cclkg", "pll_p",
- clk_base + SUPER_CCLKG_DIVIDER, 0,
- TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
- clk_register_clkdev(clk, "pll_p_cclkg", NULL);
-
- /*
- * Clock input to cclk_g divided from pll_p_out3 using
- * U71 divider of cclk_g.
- */
- clk = tegra_clk_register_divider("pll_p_out3_cclkg", "pll_p_out3",
- clk_base + SUPER_CCLKG_DIVIDER, 0,
- TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
- clk_register_clkdev(clk, "pll_p_out3_cclkg", NULL);
-
- /*
- * Clock input to cclk_g divided from pll_p_out4 using
- * U71 divider of cclk_g.
- */
- clk = tegra_clk_register_divider("pll_p_out4_cclkg", "pll_p_out4",
- clk_base + SUPER_CCLKG_DIVIDER, 0,
- TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
- clk_register_clkdev(clk, "pll_p_out4_cclkg", NULL);
-
/* CCLKG */
- clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
- ARRAY_SIZE(cclk_g_parents),
- CLK_SET_RATE_PARENT,
+ clk = tegra_clk_register_super_clk("cclk_g", cclk_g_parents,
+ ARRAY_SIZE(cclk_g_parents), 8, 0,
clk_base + CCLKG_BURST_POLICY,
- 0, 4, 0, 0, NULL);
+ TEGRA_CCLKG_DIVIDER, NULL);
clks[TEGRA30_CLK_CCLK_G] = clk;
/*
* Flags:
* TEGRA_DIVIDER_2 - LP cluster has additional divider. This flag indicates
* that this is LP cluster clock.
+ *
+ * TEGRA_CCLKG_DIVIDER - G cluster clock may bypass clocks divider. This flag
+ * indicates that this is G cluster clock.
*/
struct tegra_clk_super_mux {
struct clk_hw hw;
u8 div2_index;
u8 pllx_index;
spinlock_t *lock;
+ bool pllx_parent;
};
#define to_clk_super_mux(_hw) container_of(_hw, struct tegra_clk_super_mux, hw)
-#define TEGRA_DIVIDER_2 BIT(0)
+#define TEGRA_DIVIDER_2 BIT(0)
+#define TEGRA_CCLKG_DIVIDER BIT(1)
extern const struct clk_ops tegra_clk_super_ops;
struct clk *tegra_clk_register_super_mux(const char *name,
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock);
struct clk *tegra_clk_register_super_clk(const char *name,
- const char * const *parent_names, u8 num_parents,
+ const char * const *parent_names, u8 num_parents, u8 pllx_index,
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
spinlock_t *lock);