Commit 345c4296 authored by Stephen Boyd's avatar Stephen Boyd

Merge tag 'tegra-for-4.8-clk' of...

Merge tag 'tegra-for-4.8-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into clk-next

Pull tegra clk driver updates from Thierry Reding:

Fixes and enhancements mostly for Tegra210 clocks that allow DSI and
HDMI to work on Tegra X1. There's also a refactoring, including fixes,
the USB PLL.

* tag 'tegra-for-4.8-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  clk: tegra: Initialize UTMI PLL when enabling PLLU
  clk: tegra: Micro-optimize Tegra210 clock setup
  clk: tegra: Make sor_safe the parent of dpaux and dpaux1
  clk: tegra: Mark timer clock as critical
  clk: tegra: Enable sor1 and sor1_src on Tegra210
  clk: tegra: Squash sor1 safe/brick/src into a single mux
  clk: tegra: Disable spread spectrum on pll_d2
  clk: tegra: Fixup post dividers on Tegra210
parents e6cbf998 15d68e8c
......@@ -238,7 +238,6 @@ enum clk_id {
tegra_clk_sor0,
tegra_clk_sor0_lvds,
tegra_clk_sor1,
tegra_clk_sor1_brick,
tegra_clk_sor1_src,
tegra_clk_spdif,
tegra_clk_spdif_2x,
......
......@@ -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
......@@ -594,15 +594,17 @@ static u32 mux_pllp_plld_plld2_clkm_idx[] = {
[0] = 0, [1] = 2, [2] = 5, [3] = 6
};
static const char *mux_plldp_sor1_src[] = {
"pll_dp", "clk_sor1_src"
};
#define mux_plldp_sor1_src_idx NULL
static const char *mux_clkm_sor1_brick_sor1_src[] = {
"clk_m", "sor1_brick", "sor1_src", "sor1_brick"
};
#define mux_clkm_sor1_brick_sor1_src_idx NULL
static const char *mux_sor_safe_sor1_brick_sor1_src[] = {
/*
* Bit 0 of the mux selects sor1_brick, irrespective of bit 1, so the
* sor1_brick parent appears twice in the list below. This is merely
* to support clk_get_parent() if firmware happened to set these bits
* to 0b11. While not an invalid setting, code should always set the
* bits to 0b01 to select sor1_brick.
*/
"sor_safe", "sor1_brick", "sor1_src", "sor1_brick"
};
#define mux_sor_safe_sor1_brick_sor1_src_idx NULL
static const char *mux_pllp_pllre_clkm[] = {
"pll_p", "pll_re_out1", "clk_m"
......@@ -778,8 +780,7 @@ static struct tegra_periph_init_data periph_clks[] = {
MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg),
MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape),
MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock),
NODIV("sor1_brick", mux_plldp_sor1_src, CLK_SOURCE_SOR1, 14, MASK(1), 183, 0, tegra_clk_sor1_brick, &sor1_lock),
NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock),
NODIV("sor1", mux_sor_safe_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 14, MASK(2), 183, 0, tegra_clk_sor1, &sor1_lock),
MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy),
MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi),
I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c),
......@@ -791,7 +792,7 @@ static struct tegra_periph_init_data periph_clks[] = {
static struct tegra_periph_init_data gate_clks[] = {
GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0),
GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0),
GATE("timer", "clk_m", 5, 0, tegra_clk_timer, CLK_IS_CRITICAL),
GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0),
GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0),
GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0),
......
......@@ -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)