aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/dpll3xxx.c
diff options
context:
space:
mode:
authorJon Hunter <jon-hunter@ti.com>2010-12-21 23:31:43 -0500
committerPaul Walmsley <paul@pwsan.com>2010-12-21 23:31:43 -0500
commita36795c1278112af2a78f93c99b7586cb7e2a0a2 (patch)
treeb400d44af9b83d45b9344ed9d39aa319e290bd57 /arch/arm/mach-omap2/dpll3xxx.c
parentb183aaf7274245bb0241d81176cb6b06a3b01ca6 (diff)
OMAP: clock: fix configuration of J-Type DPLLs to work for OMAP3 and OMAP4
J-Type DPLLs have additional configuration parameters that need to be programmed when setting the multipler and divider for the DPLL. These parameters being the sigma delta divider (SD_DIV) for the DPLL and the digital controlled oscillator (DCO) to be used by the DPLL. The current code is implemented specifically to configure the OMAP3630 PER J-Type DPLL. The OMAP4430 USB DPLL is also a J-Type DPLL and so this code needs to be updated to work for both OMAP3 and OMAP4 devices and any other future devices that have J-TYPE DPLLs. For the OMAP3630 PER DPLL both the SD_DIV and DCO paramenters are used but for the OMAP4430 USB DPLL only the SD_DIV field is used. The current implementation will only program the SD_DIV and DCO fields if the DPLL has both and hence this does not work for OMAP4430. In order to make the code more generic add two new fields to the dpll_data structure for the SD_DIV field and DCO field bit-masks and only program these fields if the masks are defined for a specific DPLL. This simplifies the code and allows us to remove the flag DPLL_NO_DCO_SEL. Tested on OMAP36xx Zoom3 and OMAP4 Blaze. Signed-off-by: Jon Hunter <jon-hunter@ti.com> [paul@pwsan.com: removed explicit inlining and added '_' prefix on lookup_*() functions; added testing info to commit message; added 35xx comments back in] Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/dpll3xxx.c')
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index cb535ee4e8fe..5df9f53e6d01 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -223,10 +223,9 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
223} 223}
224 224
225/** 225/**
226 * lookup_dco_sddiv - Set j-type DPLL4 compensation variables 226 * _lookup_dco - Lookup DCO used by j-type DPLL
227 * @clk: pointer to a DPLL struct clk 227 * @clk: pointer to a DPLL struct clk
228 * @dco: digital control oscillator selector 228 * @dco: digital control oscillator selector
229 * @sd_div: target sigma-delta divider
230 * @m: DPLL multiplier to set 229 * @m: DPLL multiplier to set
231 * @n: DPLL divider to set 230 * @n: DPLL divider to set
232 * 231 *
@@ -235,11 +234,9 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
235 * XXX This code is not needed for 3430/AM35xx; can it be optimized 234 * XXX This code is not needed for 3430/AM35xx; can it be optimized
236 * out in non-multi-OMAP builds for those chips? 235 * out in non-multi-OMAP builds for those chips?
237 */ 236 */
238static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m, 237static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
239 u8 n)
240{ 238{
241 unsigned long fint, clkinp, sd; /* watch out for overflow */ 239 unsigned long fint, clkinp; /* watch out for overflow */
242 int mod1, mod2;
243 240
244 clkinp = clk->parent->rate; 241 clkinp = clk->parent->rate;
245 fint = (clkinp / n) * m; 242 fint = (clkinp / n) * m;
@@ -248,6 +245,27 @@ static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
248 *dco = 2; 245 *dco = 2;
249 else 246 else
250 *dco = 4; 247 *dco = 4;
248}
249
250/**
251 * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL
252 * @clk: pointer to a DPLL struct clk
253 * @sd_div: target sigma-delta divider
254 * @m: DPLL multiplier to set
255 * @n: DPLL divider to set
256 *
257 * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
258 *
259 * XXX This code is not needed for 3430/AM35xx; can it be optimized
260 * out in non-multi-OMAP builds for those chips?
261 */
262static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
263{
264 unsigned long clkinp, sd; /* watch out for overflow */
265 int mod1, mod2;
266
267 clkinp = clk->parent->rate;
268
251 /* 269 /*
252 * target sigma-delta to near 250MHz 270 * target sigma-delta to near 250MHz
253 * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)] 271 * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
@@ -276,6 +294,7 @@ static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
276static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel) 294static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
277{ 295{
278 struct dpll_data *dd = clk->dpll_data; 296 struct dpll_data *dd = clk->dpll_data;
297 u8 dco, sd_div;
279 u32 v; 298 u32 v;
280 299
281 /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ 300 /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
@@ -298,18 +317,16 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
298 v |= m << __ffs(dd->mult_mask); 317 v |= m << __ffs(dd->mult_mask);
299 v |= (n - 1) << __ffs(dd->div1_mask); 318 v |= (n - 1) << __ffs(dd->div1_mask);
300 319
301 /* 320 /* Configure dco and sd_div for dplls that have these fields */
302 * XXX This code is not needed for 3430/AM35XX; can it be optimized 321 if (dd->dco_mask) {
303 * out in non-multi-OMAP builds for those chips? 322 _lookup_dco(clk, &dco, m, n);
304 */ 323 v &= ~(dd->dco_mask);
305 if ((dd->flags & DPLL_J_TYPE) && !(dd->flags & DPLL_NO_DCO_SEL)) { 324 v |= dco << __ffs(dd->dco_mask);
306 u8 dco, sd_div; 325 }
307 lookup_dco_sddiv(clk, &dco, &sd_div, m, n); 326 if (dd->sddiv_mask) {
308 /* XXX This probably will need revision for OMAP4 */ 327 _lookup_sddiv(clk, &sd_div, m, n);
309 v &= ~(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK 328 v &= ~(dd->sddiv_mask);
310 | OMAP3630_PERIPH_DPLL_SD_DIV_MASK); 329 v |= sd_div << __ffs(dd->sddiv_mask);
311 v |= dco << __ffs(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK);
312 v |= sd_div << __ffs(OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
313 } 330 }
314 331
315 __raw_writel(v, dd->mult_div1_reg); 332 __raw_writel(v, dd->mult_div1_reg);