From 926655f929063619b13db8b4f2ef8c9a08605492 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 21 Mar 2016 15:58:52 -0400 Subject: [PATCH] clk: tegra: Fix pllre Tegra210 and add pll_re_out1 Use a new Tegra210 version of the pll_register_pllre function to allow setting the proper settings for the m and n div fields. Additionally define PLL_RE_OUT1 on Tegra210. Signed-off-by: Rhyland Klein [treding@nvidia.com: define PLLRE_OUT1 register offset] Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 46 ++++++++++++++++++++++++ drivers/clk/tegra/clk-tegra210.c | 16 +++++++-- drivers/clk/tegra/clk.h | 6 ++++ include/dt-bindings/clock/tegra210-car.h | 2 +- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 6ac3f843e7ca..4e194ecc8d5e 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -2013,6 +2013,52 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, #endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) +struct clk *tegra_clk_register_pllre_tegra210(const char *name, + const char *parent_name, void __iomem *clk_base, + void __iomem *pmc, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock, unsigned long parent_rate) +{ + u32 val; + struct tegra_clk_pll *pll; + struct clk *clk; + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); + + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + /* program minimum rate by default */ + + val = pll_readl_base(pll); + if (val & PLL_BASE_ENABLE) + WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) & + BIT(pll_params->iddq_bit_idx)); + else { + val = 0x4 << divm_shift(pll); + val |= 0x41 << divn_shift(pll); + pll_writel_base(val, pll); + } + + /* disable lock override */ + + val = pll_readl_misc(pll); + val &= ~BIT(29); + pll_writel_misc(val, pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pllre_ops); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + static int clk_plle_tegra210_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 6f661717e593..b8551813ec43 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -92,6 +92,7 @@ #define PLLE_AUX 0x48c #define PLLRE_BASE 0x4c4 #define PLLRE_MISC0 0x4c8 +#define PLLRE_OUT1 0x4cc #define PLLDP_BASE 0x590 #define PLLDP_MISC 0x594 @@ -2653,8 +2654,10 @@ static void __init tegra210_pll_init(void __iomem *clk_base, clks[TEGRA210_CLK_PLL_D_OUT0] = clk; /* PLLRE */ - clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, - 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); + clk = tegra_clk_register_pllre_tegra210("pll_re_vco", "pll_ref", + clk_base, pmc, 0, + &pll_re_vco_params, + &pll_re_lock, pll_ref_freq); clk_register_clkdev(clk, "pll_re_vco", NULL); clks[TEGRA210_CLK_PLL_RE_VCO] = clk; @@ -2664,6 +2667,15 @@ static void __init tegra210_pll_init(void __iomem *clk_base, clk_register_clkdev(clk, "pll_re_out", NULL); clks[TEGRA210_CLK_PLL_RE_OUT] = clk; + clk = tegra_clk_register_divider("pll_re_out1_div", "pll_re_vco", + clk_base + PLLRE_OUT1, 0, + TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_re_out1", "pll_re_out1_div", + clk_base + PLLRE_OUT1, 1, 0, + CLK_SET_RATE_PARENT, 0, NULL); + clks[TEGRA210_CLK_PLL_RE_OUT1] = clk; + /* PLLE */ clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref", clk_base, 0, &pll_e_params, NULL); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 7264f17e269e..9421f0310999 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -386,6 +386,12 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, struct tegra_clk_pll_params *pll_params, spinlock_t *lock, unsigned long parent_rate); +struct clk *tegra_clk_register_pllre_tegra210(const char *name, + const char *parent_name, void __iomem *clk_base, + void __iomem *pmc, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock, unsigned long parent_rate); + struct clk *tegra_clk_register_plle_tegra114(const char *name, const char *parent_name, void __iomem *clk_base, unsigned long flags, diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h index 0a05b0d36ae7..bd3530e56d46 100644 --- a/include/dt-bindings/clock/tegra210-car.h +++ b/include/dt-bindings/clock/tegra210-car.h @@ -346,7 +346,7 @@ #define TEGRA210_CLK_PLL_P_OUT_HSIO 316 #define TEGRA210_CLK_PLL_P_OUT_XUSB 317 #define TEGRA210_CLK_XUSB_SSP_SRC 318 -/* 319 */ +#define TEGRA210_CLK_PLL_RE_OUT1 319 /* 320 */ /* 321 */ /* 322 */ -- 2.20.1