aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter De Schrijver <pdeschrijver@nvidia.com>2013-06-05 09:51:25 -0400
committerMike Turquette <mturquette@linaro.org>2013-06-11 20:38:39 -0400
commitaa6fefde62401a84154161a8026872874a70e4c1 (patch)
treeb1787ce0bfe3258b9584f04a9ed49f30bfa6e66b
parentc388eee21ad20929f440d6fae94c995791c5818b (diff)
clk: tegra: allow PLL m,n,p init from SoC files
The m,n,p fields don't have the same bit offset and width across all PLLs. This patch allows SoC specific files to indicate the offset and width. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com> Tested-by: Stephen Warren <swarren@nvidia.com> Acked-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r--drivers/clk/tegra/clk-pll.c60
-rw-r--r--drivers/clk/tegra/clk.h32
2 files changed, 53 insertions, 39 deletions
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 85bec1dd87d8..3b778d3c828e 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -134,15 +134,24 @@
134#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p) 134#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p)
135 135
136#define mask(w) ((1 << (w)) - 1) 136#define mask(w) ((1 << (w)) - 1)
137#define divm_mask(p) mask(p->divm_width) 137#define divm_mask(p) mask(p->params->div_nmp->divm_width)
138#define divn_mask(p) mask(p->divn_width) 138#define divn_mask(p) mask(p->params->div_nmp->divn_width)
139#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \ 139#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
140 mask(p->divp_width)) 140 mask(p->params->div_nmp->divp_width))
141 141
142#define divm_max(p) (divm_mask(p)) 142#define divm_max(p) (divm_mask(p))
143#define divn_max(p) (divn_mask(p)) 143#define divn_max(p) (divn_mask(p))
144#define divp_max(p) (1 << (divp_mask(p))) 144#define divp_max(p) (1 << (divp_mask(p)))
145 145
146static struct div_nmp default_nmp = {
147 .divn_shift = PLL_BASE_DIVN_SHIFT,
148 .divn_width = PLL_BASE_DIVN_WIDTH,
149 .divm_shift = PLL_BASE_DIVM_SHIFT,
150 .divm_width = PLL_BASE_DIVM_WIDTH,
151 .divp_shift = PLL_BASE_DIVP_SHIFT,
152 .divp_width = PLL_BASE_DIVP_WIDTH,
153};
154
146static void clk_pll_enable_lock(struct tegra_clk_pll *pll) 155static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
147{ 156{
148 u32 val; 157 u32 val;
@@ -407,12 +416,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
407 416
408 val = pll_readl_base(pll); 417 val = pll_readl_base(pll);
409 418
410 val &= ~((divm_mask(pll) << pll->divm_shift) | 419 val &= ~((divm_mask(pll) << pll->params->div_nmp->divm_shift) |
411 (divn_mask(pll) << pll->divn_shift) | 420 (divn_mask(pll) << pll->params->div_nmp->divn_shift) |
412 (divp_mask(pll) << pll->divp_shift)); 421 (divp_mask(pll) << pll->params->div_nmp->divp_shift));
413 val |= ((cfg->m << pll->divm_shift) | 422 val |= ((cfg->m << pll->params->div_nmp->divm_shift) |
414 (cfg->n << pll->divn_shift) | 423 (cfg->n << pll->params->div_nmp->divn_shift) |
415 (cfg->p << pll->divp_shift)); 424 (cfg->p << pll->params->div_nmp->divp_shift));
416 425
417 pll_writel_base(val, pll); 426 pll_writel_base(val, pll);
418} 427}
@@ -424,9 +433,9 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll,
424 433
425 val = pll_readl_base(pll); 434 val = pll_readl_base(pll);
426 435
427 cfg->m = (val >> pll->divm_shift) & (divm_mask(pll)); 436 cfg->m = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll));
428 cfg->n = (val >> pll->divn_shift) & (divn_mask(pll)); 437 cfg->n = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll));
429 cfg->p = (val >> pll->divp_shift) & (divp_mask(pll)); 438 cfg->p = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll));
430} 439}
431 440
432static void _update_pll_cpcon(struct tegra_clk_pll *pll, 441static void _update_pll_cpcon(struct tegra_clk_pll *pll,
@@ -646,9 +655,9 @@ static int clk_plle_enable(struct clk_hw *hw)
646 val = pll_readl_base(pll); 655 val = pll_readl_base(pll);
647 val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); 656 val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
648 val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); 657 val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
649 val |= sel.m << pll->divm_shift; 658 val |= sel.m << pll->params->div_nmp->divm_shift;
650 val |= sel.n << pll->divn_shift; 659 val |= sel.n << pll->params->div_nmp->divn_shift;
651 val |= sel.p << pll->divp_shift; 660 val |= sel.p << pll->params->div_nmp->divp_shift;
652 val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; 661 val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
653 pll_writel_base(val, pll); 662 pll_writel_base(val, pll);
654 } 663 }
@@ -679,9 +688,9 @@ static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
679 u32 divn = 0, divm = 0, divp = 0; 688 u32 divn = 0, divm = 0, divp = 0;
680 u64 rate = parent_rate; 689 u64 rate = parent_rate;
681 690
682 divp = (val >> pll->divp_shift) & (divp_mask(pll)); 691 divp = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll));
683 divn = (val >> pll->divn_shift) & (divn_mask(pll)); 692 divn = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll));
684 divm = (val >> pll->divm_shift) & (divm_mask(pll)); 693 divm = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll));
685 divm *= divp; 694 divm *= divp;
686 695
687 rate *= divn; 696 rate *= divn;
@@ -902,7 +911,8 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
902 911
903 val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE); 912 val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
904 val &= ~(divn_mask(pll) | divm_mask(pll)); 913 val &= ~(divn_mask(pll) | divm_mask(pll));
905 val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift); 914 val |= (cfg.m << pll->params->div_nmp->divm_shift) |
915 (cfg.n << pll->params->div_nmp->divn_shift);
906 writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE); 916 writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE);
907 } else 917 } else
908 _update_pll_mnp(pll, &cfg); 918 _update_pll_mnp(pll, &cfg);
@@ -1180,8 +1190,8 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
1180 val = pll_readl_base(pll); 1190 val = pll_readl_base(pll);
1181 val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); 1191 val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
1182 val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); 1192 val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
1183 val |= sel.m << pll->divm_shift; 1193 val |= sel.m << pll->params->div_nmp->divm_shift;
1184 val |= sel.n << pll->divn_shift; 1194 val |= sel.n << pll->params->div_nmp->divn_shift;
1185 val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; 1195 val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
1186 pll_writel_base(val, pll); 1196 pll_writel_base(val, pll);
1187 udelay(1); 1197 udelay(1);
@@ -1242,12 +1252,8 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
1242 pll->flags = pll_flags; 1252 pll->flags = pll_flags;
1243 pll->lock = lock; 1253 pll->lock = lock;
1244 1254
1245 pll->divp_shift = PLL_BASE_DIVP_SHIFT; 1255 if (!pll_params->div_nmp)
1246 pll->divp_width = PLL_BASE_DIVP_WIDTH; 1256 pll_params->div_nmp = &default_nmp;
1247 pll->divn_shift = PLL_BASE_DIVN_SHIFT;
1248 pll->divn_width = PLL_BASE_DIVN_WIDTH;
1249 pll->divm_shift = PLL_BASE_DIVM_SHIFT;
1250 pll->divm_width = PLL_BASE_DIVM_WIDTH;
1251 1257
1252 return pll; 1258 return pll;
1253} 1259}
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 11278a80e63e..d70eb2d2957f 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -128,6 +128,25 @@ struct pdiv_map {
128}; 128};
129 129
130/** 130/**
131 * struct div_nmp - offset and width of m,n and p fields
132 *
133 * @divn_shift: shift to the feedback divider bit field
134 * @divn_width: width of the feedback divider bit field
135 * @divm_shift: shift to the input divider bit field
136 * @divm_width: width of the input divider bit field
137 * @divp_shift: shift to the post divider bit field
138 * @divp_width: width of the post divider bit field
139 */
140struct div_nmp {
141 u8 divn_shift;
142 u8 divn_width;
143 u8 divm_shift;
144 u8 divm_width;
145 u8 divp_shift;
146 u8 divp_width;
147};
148
149/**
131 * struct clk_pll_params - PLL parameters 150 * struct clk_pll_params - PLL parameters
132 * 151 *
133 * @input_min: Minimum input frequency 152 * @input_min: Minimum input frequency
@@ -166,6 +185,7 @@ struct tegra_clk_pll_params {
166 int lock_delay; 185 int lock_delay;
167 int max_p; 186 int max_p;
168 struct pdiv_map *pdiv_tohw; 187 struct pdiv_map *pdiv_tohw;
188 struct div_nmp *div_nmp;
169}; 189};
170 190
171/** 191/**
@@ -179,12 +199,6 @@ struct tegra_clk_pll_params {
179 * @flags: PLL flags 199 * @flags: PLL flags
180 * @fixed_rate: PLL rate if it is fixed 200 * @fixed_rate: PLL rate if it is fixed
181 * @lock: register lock 201 * @lock: register lock
182 * @divn_shift: shift to the feedback divider bit field
183 * @divn_width: width of the feedback divider bit field
184 * @divm_shift: shift to the input divider bit field
185 * @divm_width: width of the input divider bit field
186 * @divp_shift: shift to the post divider bit field
187 * @divp_width: width of the post divider bit field
188 * 202 *
189 * Flags: 203 * Flags:
190 * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for 204 * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
@@ -214,12 +228,6 @@ struct tegra_clk_pll {
214 u32 flags; 228 u32 flags;
215 unsigned long fixed_rate; 229 unsigned long fixed_rate;
216 spinlock_t *lock; 230 spinlock_t *lock;
217 u8 divn_shift;
218 u8 divn_width;
219 u8 divm_shift;
220 u8 divm_width;
221 u8 divp_shift;
222 u8 divp_width;
223 struct tegra_clk_pll_freq_table *freq_table; 231 struct tegra_clk_pll_freq_table *freq_table;
224 struct tegra_clk_pll_params *params; 232 struct tegra_clk_pll_params *params;
225}; 233};