Commit 15d68e8c authored by Andrew Bresticker's avatar Andrew Bresticker Committed by Thierry Reding

clk: tegra: Initialize UTMI PLL when enabling PLLU

Move the UTMI PLL initialization code form clk-tegra<chip>.c files into
clk-pll.c. UTMI PLL was being configured and set in HW control right
after registration. However, when the clock init_table is processed and
child clks of PLLU are enabled, it will call in and enable PLLU as
well, and initiate SW enabling sequence even though PLLU is already in
HW control. This leads to getting UTMIPLL stuck with a SEQ_BUSY status.

Doing the initialization once during pllu_enable means we configure it
properly into HW control.

A side effect of the commonization/localization of the UTMI PLL init
code, is that it corrects some errors that were present for earlier
generations. For instance, in clk-tegra124.c, it used to have:

    #define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)

when the correct shift to use is present in the new version:

    #define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)

which matches the Tegra124 TRM register definition.
Signed-off-by: default avatarAndrew Bresticker <abrestic@chromium.org>
[rklein: Merged in some later fixes for potential deadlocks]
Signed-off-by: default avatarRhyland Klein <rklein@nvidia.com>
[treding: coding style bike-shedding, remove unused variable]
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 74d3ba0b
......@@ -191,6 +191,53 @@
#define PLLSS_REF_SRC_SEL_SHIFT 25
#define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT)
#define UTMIP_PLL_CFG1 0x484
#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
#define UTMIP_PLL_CFG2 0x488
#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6)
#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25)
#define UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN BIT(30)
#define UTMIPLL_HW_PWRDN_CFG0 0x52c
#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0)
#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1)
#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5)
#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
#define PLLU_HW_PWRDN_CFG0 0x530
#define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL BIT(0)
#define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
#define PLLU_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT BIT(7)
#define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE BIT(28)
#define XUSB_PLL_CFG0 0x534
#define XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY 0x3ff
#define XUSB_PLL_CFG0_PLLU_LOCK_DLY (0x3ff << 14)
#define PLLU_BASE_CLKENABLE_USB BIT(21)
#define PLLU_BASE_OVERRIDE BIT(24)
#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
......@@ -973,6 +1020,133 @@ const struct clk_ops tegra_clk_plle_ops = {
.enable = clk_plle_enable,
};
/*
* Structure defining the fields for USB UTMI clocks Parameters.
*/
struct utmi_clk_param {
/* Oscillator Frequency in Hz */
u32 osc_frequency;
/* UTMIP PLL Enable Delay Count */
u8 enable_delay_count;
/* UTMIP PLL Stable count */
u8 stable_count;
/* UTMIP PLL Active delay count */
u8 active_delay_count;
/* UTMIP PLL Xtal frequency count */
u8 xtal_freq_count;
};
static const struct utmi_clk_param utmi_parameters[] = {
{
.osc_frequency = 13000000, .enable_delay_count = 0x02,
.stable_count = 0x33, .active_delay_count = 0x05,
.xtal_freq_count = 0x7f
}, {
.osc_frequency = 19200000, .enable_delay_count = 0x03,
.stable_count = 0x4b, .active_delay_count = 0x06,
.xtal_freq_count = 0xbb
}, {
.osc_frequency = 12000000, .enable_delay_count = 0x02,
.stable_count = 0x2f, .active_delay_count = 0x04,
.xtal_freq_count = 0x76
}, {
.osc_frequency = 26000000, .enable_delay_count = 0x04,
.stable_count = 0x66, .active_delay_count = 0x09,
.xtal_freq_count = 0xfe
}, {
.osc_frequency = 16800000, .enable_delay_count = 0x03,
.stable_count = 0x41, .active_delay_count = 0x0a,
.xtal_freq_count = 0xa4
}, {
.osc_frequency = 38400000, .enable_delay_count = 0x0,
.stable_count = 0x0, .active_delay_count = 0x6,
.xtal_freq_count = 0x80
},
};
static int clk_pllu_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
struct clk_hw *pll_ref = clk_hw_get_parent(hw);
struct clk_hw *osc = clk_hw_get_parent(pll_ref);
const struct utmi_clk_param *params = NULL;
unsigned long flags = 0, input_rate;
unsigned int i;
int ret = 0;
u32 value;
if (!osc) {
pr_err("%s: failed to get OSC clock\n", __func__);
return -EINVAL;
}
input_rate = clk_hw_get_rate(osc);
if (pll->lock)
spin_lock_irqsave(pll->lock, flags);
_clk_pll_enable(hw);
ret = clk_pll_wait_for_lock(pll);
if (ret < 0)
goto out;
for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
if (input_rate == utmi_parameters[i].osc_frequency) {
params = &utmi_parameters[i];
break;
}
}
if (!params) {
pr_err("%s: unexpected input rate %lu Hz\n", __func__,
input_rate);
ret = -EINVAL;
goto out;
}
value = pll_readl_base(pll);
value &= ~PLLU_BASE_OVERRIDE;
pll_writel_base(value, pll);
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
/* Program UTMIP PLL stable and active counts */
value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
/* Remove power downs from UTMIP PLL control bits */
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
/* Program UTMIP PLL delay and oscillator frequency counts */
value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
/* Remove power downs from UTMIP PLL control bits */
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
out:
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
return ret;
}
static const struct clk_ops tegra_clk_pllu_ops = {
.is_enabled = clk_pll_is_enabled,
.enable = clk_pllu_enable,
.disable = clk_pll_disable,
.recalc_rate = clk_pll_recalc_rate,
};
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
unsigned long parent_rate)
{
......@@ -1505,6 +1679,112 @@ static void clk_plle_tegra114_disable(struct clk_hw *hw)
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
}
static int clk_pllu_tegra114_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
const struct utmi_clk_param *params = NULL;
struct clk *osc = __clk_lookup("osc");
unsigned long flags = 0, input_rate;
unsigned int i;
int ret = 0;
u32 value;
if (!osc) {
pr_err("%s: failed to get OSC clock\n", __func__);
return -EINVAL;
}
input_rate = clk_hw_get_rate(__clk_get_hw(osc));
if (pll->lock)
spin_lock_irqsave(pll->lock, flags);
_clk_pll_enable(hw);
ret = clk_pll_wait_for_lock(pll);
if (ret < 0)
goto out;
for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
if (input_rate == utmi_parameters[i].osc_frequency) {
params = &utmi_parameters[i];
break;
}
}
if (!params) {
pr_err("%s: unexpected input rate %lu Hz\n", __func__,
input_rate);
ret = -EINVAL;
goto out;
}
value = pll_readl_base(pll);
value &= ~PLLU_BASE_OVERRIDE;
pll_writel_base(value, pll);
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
/* Program UTMIP PLL stable and active counts */
value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
/* Remove power downs from UTMIP PLL control bits */
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
/* Program UTMIP PLL delay and oscillator frequency counts */
value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
/* Remove power downs from UTMIP PLL control bits */
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
/* Setup HW control of UTMIPLL */
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
udelay(1);
/*
* Setup SW override of UTMIPLL assuming USB2.0 ports are assigned
* to USB2
*/
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
value |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
udelay(1);
/* Enable HW control of UTMIPLL */
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
out:
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
return ret;
}
#endif
static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
......@@ -1614,6 +1894,27 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
return clk;
}
struct clk *tegra_clk_register_pllu(const char *name, const char *parent_name,
void __iomem *clk_base, unsigned long flags,
struct tegra_clk_pll_params *pll_params, spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
pll_params->flags |= TEGRA_PLLU;
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
&tegra_clk_pllu_ops);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
defined(CONFIG_ARCH_TEGRA_124_SOC) || \
defined(CONFIG_ARCH_TEGRA_132_SOC) || \
......@@ -1652,6 +1953,12 @@ static const struct clk_ops tegra_clk_plle_tegra114_ops = {
.recalc_rate = clk_pll_recalc_rate,
};
static const struct clk_ops tegra_clk_pllu_tegra114_ops = {
.is_enabled = clk_pll_is_enabled,
.enable = clk_pllu_tegra114_enable,
.disable = clk_pll_disable,
.recalc_rate = clk_pll_recalc_rate,
};
struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
......@@ -1919,6 +2226,29 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
return clk;
}
struct clk *
tegra_clk_register_pllu_tegra114(const char *name, const char *parent_name,
void __iomem *clk_base, unsigned long flags,
struct tegra_clk_pll_params *pll_params,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
pll_params->flags |= TEGRA_PLLU;
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
&tegra_clk_pllu_tegra114_ops);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
#endif
#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
......@@ -2187,6 +2517,152 @@ static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
return val & PLLE_BASE_ENABLE ? 1 : 0;
}
static int clk_pllu_tegra210_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
struct clk_hw *pll_ref = clk_hw_get_parent(hw);
struct clk_hw *osc = clk_hw_get_parent(pll_ref);
const struct utmi_clk_param *params = NULL;
unsigned long flags = 0, input_rate;
unsigned int i;
int ret = 0;
u32 value;
if (!osc) {
pr_err("%s: failed to get OSC clock\n", __func__);
return -EINVAL;
}
input_rate = clk_hw_get_rate(osc);
if (pll->lock)
spin_lock_irqsave(pll->lock, flags);
_clk_pll_enable(hw);
ret = clk_pll_wait_for_lock(pll);
if (ret < 0)
goto out;
for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
if (input_rate == utmi_parameters[i].osc_frequency) {
params = &utmi_parameters[i];
break;
}
}
if (!params) {
pr_err("%s: unexpected input rate %lu Hz\n", __func__,
input_rate);
ret = -EINVAL;
goto out;
}
value = pll_readl_base(pll);
value &= ~PLLU_BASE_OVERRIDE;
pll_writel_base(value, pll);
/* Put PLLU under HW control */
value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
value |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
value &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
value &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY;
writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
udelay(1);
value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
value |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
udelay(1);
/* Disable PLLU clock branch to UTMIPLL since it uses OSC */
value = pll_readl_base(pll);
value &= ~PLLU_BASE_CLKENABLE_USB;
pll_writel_base(value, pll);
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
if (value & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE) {
pr_debug("UTMIPLL already enabled\n");
goto out;
}
value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
/* Program UTMIP PLL stable and active counts */
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
value |= UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
/* Program UTMIP PLL delay and oscillator frequency counts */
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
/* Remove power downs from UTMIP PLL control bits */
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
value |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
writel(value, pll->clk_base + UTMIP_PLL_CFG1);
udelay(1);
/* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
/* Setup HW control of UTMIPLL */
value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
udelay(1);
value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
value &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY;
writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
udelay(1);
/* Enable HW control of UTMIPLL */
value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
out:
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
return ret;
}
static const struct clk_ops tegra_clk_plle_tegra210_ops = {
.is_enabled = clk_plle_tegra210_is_enabled,
.enable = clk_plle_tegra210_enable,
......@@ -2194,6 +2670,13 @@ static const struct clk_ops tegra_clk_plle_tegra210_ops = {
.recalc_rate = clk_pll_recalc_rate,
};
static const struct clk_ops tegra_clk_pllu_tegra210_ops = {
.is_enabled = clk_pll_is_enabled,
.enable = clk_pllu_tegra210_enable,
.disable = clk_pll_disable,
.recalc_rate = clk_pllre_recalc_rate,
};
struct clk *tegra_clk_register_plle_tegra210(const char *name,
const char *parent_name,
void __iomem *clk_base, unsigned long flags,
......@@ -2434,4 +2917,26 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name,
return clk;
}
struct clk *tegra_clk_register_pllu_tegra210(const char *name,
const char *parent_name, void __iomem *clk_base,
unsigned long flags, struct tegra_clk_pll_params *pll_params,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
pll_params->flags |= TEGRA_PLLU;
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
&tegra_clk_pllu_tegra210_ops);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
#endif
......@@ -113,32 +113,6 @@
#define CCLKG_BURST_POLICY 0x368
#define UTMIP_PLL_CFG2 0x488
#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
#define UTMIP_PLL_CFG1 0x484
#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
#define UTMIPLL_HW_PWRDN_CFG0 0x52c
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4)
#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1)
#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0)
#define CLK_SOURCE_CSITE 0x1d4
#define CLK_SOURCE_EMC 0x19c
......@@ -649,43 +623,6 @@ static unsigned long tegra114_input_freq[] = {
#define MASK(x) (BIT(x) - 1)
struct utmi_clk_param {
/* Oscillator Frequency in KHz */
u32 osc_frequency;
/* UTMIP PLL Enable Delay Count */
u8 enable_delay_count;
/* UTMIP PLL Stable count */
u8 stable_count;
/* UTMIP PLL Active delay count */
u8 active_delay_count;
/* UTMIP PLL Xtal frequency count */
u8 xtal_freq_count;
};
static const struct utmi_clk_param utmi_parameters[] = {
{
.osc_frequency = 13000000, .enable_delay_count = 0x02,
.stable_count = 0x33, .active_delay_count = 0x05,
.xtal_freq_count = 0x7f
}, {
.osc_frequency = 19200000, .enable_delay_count = 0x03,
.stable_count = 0x4b, .active_delay_count = 0x06,
.xtal_freq_count = 0xbb
}, {
.osc_frequency = 12000000, .enable_delay_count = 0x02,
.stable_count = 0x2f, .active_delay_count = 0x04,
.xtal_freq_count = 0x76
}, {
.osc_frequency = 26000000, .enable_delay_count = 0x04,
.stable_count = 0x66, .active_delay_count = 0x09,
.xtal_freq_count = 0xfe
}, {
.osc_frequency = 16800000, .enable_delay_count = 0x03,
.stable_count = 0x41, .active_delay_count = 0x0a,
.xtal_freq_count = 0xa4
},
};
/* peripheral mux definitions */