aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/tegra
diff options
context:
space:
mode:
authorPeter De Schrijver <pdeschrijver@nvidia.com>2013-09-09 06:22:55 -0400
committerPeter De Schrijver <pdeschrijver@nvidia.com>2013-11-26 11:46:51 -0500
commit798e910bee3f9ad69a8b16d7e705086852d9f2de (patch)
treededd66ad923319d1125350fcc7b6fb54711b41fb /drivers/clk/tegra
parent540fc26a02a950a523a62a16d75b87f0e2103584 (diff)
clk: tegra: Add support for PLLSS
Tegra124 introduces a new PLL type, PLLSS. Add support for it. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Diffstat (limited to 'drivers/clk/tegra')
-rw-r--r--drivers/clk/tegra/clk-pll.c123
-rw-r--r--drivers/clk/tegra/clk.h5
2 files changed, 126 insertions, 2 deletions
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 3aa85bf2f425..689c468aca2f 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -137,6 +137,36 @@
137#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5) 137#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
138#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4) 138#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
139 139
140#define PLLSS_MISC_KCP 0
141#define PLLSS_MISC_KVCO 0
142#define PLLSS_MISC_SETUP 0
143#define PLLSS_EN_SDM 0
144#define PLLSS_EN_SSC 0
145#define PLLSS_EN_DITHER2 0
146#define PLLSS_EN_DITHER 1
147#define PLLSS_SDM_RESET 0
148#define PLLSS_CLAMP 0
149#define PLLSS_SDM_SSC_MAX 0
150#define PLLSS_SDM_SSC_MIN 0
151#define PLLSS_SDM_SSC_STEP 0
152#define PLLSS_SDM_DIN 0
153#define PLLSS_MISC_DEFAULT ((PLLSS_MISC_KCP << 25) | \
154 (PLLSS_MISC_KVCO << 24) | \
155 PLLSS_MISC_SETUP)
156#define PLLSS_CFG_DEFAULT ((PLLSS_EN_SDM << 31) | \
157 (PLLSS_EN_SSC << 30) | \
158 (PLLSS_EN_DITHER2 << 29) | \
159 (PLLSS_EN_DITHER << 28) | \
160 (PLLSS_SDM_RESET) << 27 | \
161 (PLLSS_CLAMP << 22))
162#define PLLSS_CTRL1_DEFAULT \
163 ((PLLSS_SDM_SSC_MAX << 16) | PLLSS_SDM_SSC_MIN)
164#define PLLSS_CTRL2_DEFAULT \
165 ((PLLSS_SDM_SSC_STEP << 16) | PLLSS_SDM_DIN)
166#define PLLSS_LOCK_OVERRIDE BIT(24)
167#define PLLSS_REF_SRC_SEL_SHIFT 25
168#define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT)
169
140#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset) 170#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
141#define pll_readl_base(p) pll_readl(p->params->base_reg, p) 171#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
142#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p) 172#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
@@ -764,7 +794,7 @@ const struct clk_ops tegra_clk_plle_ops = {
764 .enable = clk_plle_enable, 794 .enable = clk_plle_enable,
765}; 795};
766 796
767#ifdef CONFIG_ARCH_TEGRA_114_SOC 797#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
768 798
769static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params, 799static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
770 unsigned long parent_rate) 800 unsigned long parent_rate)
@@ -1405,7 +1435,7 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
1405 return clk; 1435 return clk;
1406} 1436}
1407 1437
1408#ifdef CONFIG_ARCH_TEGRA_114_SOC 1438#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
1409const struct clk_ops tegra_clk_pllxc_ops = { 1439const struct clk_ops tegra_clk_pllxc_ops = {
1410 .is_enabled = clk_pll_is_enabled, 1440 .is_enabled = clk_pll_is_enabled,
1411 .enable = clk_pll_iddq_enable, 1441 .enable = clk_pll_iddq_enable,
@@ -1702,3 +1732,92 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
1702 return clk; 1732 return clk;
1703} 1733}
1704#endif 1734#endif
1735
1736#ifdef CONFIG_ARCH_TEGRA_124_SOC
1737const struct clk_ops tegra_clk_pllss_ops = {
1738 .is_enabled = clk_pll_is_enabled,
1739 .enable = clk_pll_iddq_enable,
1740 .disable = clk_pll_iddq_disable,
1741 .recalc_rate = clk_pll_recalc_rate,
1742 .round_rate = clk_pll_ramp_round_rate,
1743 .set_rate = clk_pllxc_set_rate,
1744};
1745
1746struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
1747 void __iomem *clk_base, unsigned long flags,
1748 struct tegra_clk_pll_params *pll_params,
1749 spinlock_t *lock)
1750{
1751 struct tegra_clk_pll *pll;
1752 struct clk *clk, *parent;
1753 struct tegra_clk_pll_freq_table cfg;
1754 unsigned long parent_rate;
1755 u32 val;
1756 int i;
1757
1758 if (!pll_params->div_nmp)
1759 return ERR_PTR(-EINVAL);
1760
1761 parent = __clk_lookup(parent_name);
1762 if (IS_ERR(parent)) {
1763 WARN(1, "parent clk %s of %s must be registered first\n",
1764 name, parent_name);
1765 return ERR_PTR(-EINVAL);
1766 }
1767
1768 pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK;
1769 pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
1770 if (IS_ERR(pll))
1771 return ERR_CAST(pll);
1772
1773 val = pll_readl_base(pll);
1774 val &= ~PLLSS_REF_SRC_SEL_MASK;
1775 pll_writel_base(val, pll);
1776
1777 parent_rate = __clk_get_rate(parent);
1778
1779 pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
1780
1781 /* initialize PLL to minimum rate */
1782
1783 cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
1784 cfg.n = cfg.m * pll_params->vco_min / parent_rate;
1785
1786 for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++)
1787 ;
1788 if (!i) {
1789 kfree(pll);
1790 return ERR_PTR(-EINVAL);
1791 }
1792
1793 cfg.p = pll_params->pdiv_tohw[i-1].hw_val;
1794
1795 _update_pll_mnp(pll, &cfg);
1796
1797 pll_writel_misc(PLLSS_MISC_DEFAULT, pll);
1798 pll_writel(PLLSS_CFG_DEFAULT, pll_params->ext_misc_reg[0], pll);
1799 pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[1], pll);
1800 pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll);
1801
1802 val = pll_readl_base(pll);
1803 if (val & PLL_BASE_ENABLE) {
1804 if (val & BIT(pll_params->iddq_bit_idx)) {
1805 WARN(1, "%s is on but IDDQ set\n", name);
1806 kfree(pll);
1807 return ERR_PTR(-EINVAL);
1808 }
1809 } else
1810 val |= BIT(pll_params->iddq_bit_idx);
1811
1812 val &= ~PLLSS_LOCK_OVERRIDE;
1813 pll_writel_base(val, pll);
1814
1815 clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
1816 &tegra_clk_pllss_ops);
1817
1818 if (IS_ERR(clk))
1819 kfree(pll);
1820
1821 return clk;
1822}
1823#endif
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 05abfc5fdff8..7f110acfe2a1 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -298,6 +298,11 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
298 struct tegra_clk_pll_params *pll_params, 298 struct tegra_clk_pll_params *pll_params,
299 spinlock_t *lock); 299 spinlock_t *lock);
300 300
301struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
302 void __iomem *clk_base, unsigned long flags,
303 struct tegra_clk_pll_params *pll_params,
304 spinlock_t *lock);
305
301/** 306/**
302 * struct tegra_clk_pll_out - PLL divider down clock 307 * struct tegra_clk_pll_out - PLL divider down clock
303 * 308 *