aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Mason <jonmason@broadcom.com>2015-10-15 15:48:30 -0400
committerStephen Boyd <sboyd@codeaurora.org>2015-10-21 20:03:41 -0400
commit40c8bec3f2591856e21124270be51a0a2b77c82d (patch)
tree87c3369b839ce450d2ae47e55de5ba000bf5442a
parentf713c6bf32092a259d6baf2be24f9c3dbf2462c3 (diff)
clk: iproc: Separate status and control variables
Some PLLs have separate registers for Status and Control. The means the pll_base needs to be split into 2 new variables, so that those PLLs can specify device tree registers for those independently. Also, add a new driver flag to identify this presence of the split, and let the driver know that additional registers need to be used. Signed-off-by: Jon Mason <jonmason@broadcom.com> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r--drivers/clk/bcm/clk-iproc-pll.c96
-rw-r--r--drivers/clk/bcm/clk-iproc.h6
2 files changed, 62 insertions, 40 deletions
diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c
index 2be93955262e..7f7da79f4adc 100644
--- a/drivers/clk/bcm/clk-iproc-pll.c
+++ b/drivers/clk/bcm/clk-iproc-pll.c
@@ -74,7 +74,8 @@ struct iproc_clk {
74}; 74};
75 75
76struct iproc_pll { 76struct iproc_pll {
77 void __iomem *pll_base; 77 void __iomem *status_base;
78 void __iomem *control_base;
78 void __iomem *pwr_base; 79 void __iomem *pwr_base;
79 void __iomem *asiu_base; 80 void __iomem *asiu_base;
80 81
@@ -127,7 +128,7 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
127 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 128 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
128 129
129 for (i = 0; i < LOCK_DELAY; i++) { 130 for (i = 0; i < LOCK_DELAY; i++) {
130 u32 val = readl(pll->pll_base + ctrl->status.offset); 131 u32 val = readl(pll->status_base + ctrl->status.offset);
131 132
132 if (val & (1 << ctrl->status.shift)) 133 if (val & (1 << ctrl->status.shift))
133 return 0; 134 return 0;
@@ -145,7 +146,7 @@ static void iproc_pll_write(const struct iproc_pll *pll, void __iomem *base,
145 writel(val, base + offset); 146 writel(val, base + offset);
146 147
147 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK && 148 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK &&
148 base == pll->pll_base)) 149 (base == pll->status_base || base == pll->control_base)))
149 val = readl(base + offset); 150 val = readl(base + offset);
150} 151}
151 152
@@ -161,9 +162,9 @@ static void __pll_disable(struct iproc_pll *pll)
161 } 162 }
162 163
163 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) { 164 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
164 val = readl(pll->pll_base + ctrl->aon.offset); 165 val = readl(pll->control_base + ctrl->aon.offset);
165 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift; 166 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
166 iproc_pll_write(pll, pll->pll_base, ctrl->aon.offset, val); 167 iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
167 } 168 }
168 169
169 if (pll->pwr_base) { 170 if (pll->pwr_base) {
@@ -184,9 +185,9 @@ static int __pll_enable(struct iproc_pll *pll)
184 u32 val; 185 u32 val;
185 186
186 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) { 187 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
187 val = readl(pll->pll_base + ctrl->aon.offset); 188 val = readl(pll->control_base + ctrl->aon.offset);
188 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift); 189 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
189 iproc_pll_write(pll, pll->pll_base, ctrl->aon.offset, val); 190 iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
190 } 191 }
191 192
192 if (pll->pwr_base) { 193 if (pll->pwr_base) {
@@ -213,9 +214,9 @@ static void __pll_put_in_reset(struct iproc_pll *pll)
213 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 214 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
214 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; 215 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
215 216
216 val = readl(pll->pll_base + reset->offset); 217 val = readl(pll->control_base + reset->offset);
217 val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift); 218 val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
218 iproc_pll_write(pll, pll->pll_base, reset->offset, val); 219 iproc_pll_write(pll, pll->control_base, reset->offset, val);
219} 220}
220 221
221static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp, 222static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
@@ -226,17 +227,17 @@ static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
226 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; 227 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
227 const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter; 228 const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter;
228 229
229 val = readl(pll->pll_base + dig_filter->offset); 230 val = readl(pll->control_base + dig_filter->offset);
230 val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift | 231 val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift |
231 bit_mask(dig_filter->kp_width) << dig_filter->kp_shift | 232 bit_mask(dig_filter->kp_width) << dig_filter->kp_shift |
232 bit_mask(dig_filter->ka_width) << dig_filter->ka_shift); 233 bit_mask(dig_filter->ka_width) << dig_filter->ka_shift);
233 val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift | 234 val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift |
234 ka << dig_filter->ka_shift; 235 ka << dig_filter->ka_shift;
235 iproc_pll_write(pll, pll->pll_base, dig_filter->offset, val); 236 iproc_pll_write(pll, pll->control_base, dig_filter->offset, val);
236 237
237 val = readl(pll->pll_base + reset->offset); 238 val = readl(pll->control_base + reset->offset);
238 val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift; 239 val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
239 iproc_pll_write(pll, pll->pll_base, reset->offset, val); 240 iproc_pll_write(pll, pll->control_base, reset->offset, val);
240} 241}
241 242
242static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, 243static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
@@ -291,9 +292,9 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
291 /* put PLL in reset */ 292 /* put PLL in reset */
292 __pll_put_in_reset(pll); 293 __pll_put_in_reset(pll);
293 294
294 iproc_pll_write(pll, pll->pll_base, ctrl->vco_ctrl.u_offset, 0); 295 iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0);
295 296
296 val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset); 297 val = readl(pll->control_base + ctrl->vco_ctrl.l_offset);
297 298
298 if (rate >= VCO_LOW && rate < VCO_MID) 299 if (rate >= VCO_LOW && rate < VCO_MID)
299 val |= (1 << PLL_VCO_LOW_SHIFT); 300 val |= (1 << PLL_VCO_LOW_SHIFT);
@@ -303,29 +304,29 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
303 else 304 else
304 val |= (1 << PLL_VCO_HIGH_SHIFT); 305 val |= (1 << PLL_VCO_HIGH_SHIFT);
305 306
306 iproc_pll_write(pll, pll->pll_base, ctrl->vco_ctrl.l_offset, val); 307 iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.l_offset, val);
307 308
308 /* program integer part of NDIV */ 309 /* program integer part of NDIV */
309 val = readl(pll->pll_base + ctrl->ndiv_int.offset); 310 val = readl(pll->control_base + ctrl->ndiv_int.offset);
310 val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift); 311 val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
311 val |= vco->ndiv_int << ctrl->ndiv_int.shift; 312 val |= vco->ndiv_int << ctrl->ndiv_int.shift;
312 iproc_pll_write(pll, pll->pll_base, ctrl->ndiv_int.offset, val); 313 iproc_pll_write(pll, pll->control_base, ctrl->ndiv_int.offset, val);
313 314
314 /* program fractional part of NDIV */ 315 /* program fractional part of NDIV */
315 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { 316 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
316 val = readl(pll->pll_base + ctrl->ndiv_frac.offset); 317 val = readl(pll->control_base + ctrl->ndiv_frac.offset);
317 val &= ~(bit_mask(ctrl->ndiv_frac.width) << 318 val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
318 ctrl->ndiv_frac.shift); 319 ctrl->ndiv_frac.shift);
319 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift; 320 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
320 iproc_pll_write(pll, pll->pll_base, ctrl->ndiv_frac.offset, 321 iproc_pll_write(pll, pll->control_base, ctrl->ndiv_frac.offset,
321 val); 322 val);
322 } 323 }
323 324
324 /* program PDIV */ 325 /* program PDIV */
325 val = readl(pll->pll_base + ctrl->pdiv.offset); 326 val = readl(pll->control_base + ctrl->pdiv.offset);
326 val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift); 327 val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
327 val |= vco->pdiv << ctrl->pdiv.shift; 328 val |= vco->pdiv << ctrl->pdiv.shift;
328 iproc_pll_write(pll, pll->pll_base, ctrl->pdiv.offset, val); 329 iproc_pll_write(pll, pll->control_base, ctrl->pdiv.offset, val);
329 330
330 __pll_bring_out_reset(pll, kp, ka, ki); 331 __pll_bring_out_reset(pll, kp, ka, ki);
331 332
@@ -372,7 +373,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
372 return 0; 373 return 0;
373 374
374 /* PLL needs to be locked */ 375 /* PLL needs to be locked */
375 val = readl(pll->pll_base + ctrl->status.offset); 376 val = readl(pll->status_base + ctrl->status.offset);
376 if ((val & (1 << ctrl->status.shift)) == 0) { 377 if ((val & (1 << ctrl->status.shift)) == 0) {
377 clk->rate = 0; 378 clk->rate = 0;
378 return 0; 379 return 0;
@@ -383,13 +384,13 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
383 * 384 *
384 * ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv) 385 * ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
385 */ 386 */
386 val = readl(pll->pll_base + ctrl->ndiv_int.offset); 387 val = readl(pll->control_base + ctrl->ndiv_int.offset);
387 ndiv_int = (val >> ctrl->ndiv_int.shift) & 388 ndiv_int = (val >> ctrl->ndiv_int.shift) &
388 bit_mask(ctrl->ndiv_int.width); 389 bit_mask(ctrl->ndiv_int.width);
389 ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift; 390 ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift;
390 391
391 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { 392 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
392 val = readl(pll->pll_base + ctrl->ndiv_frac.offset); 393 val = readl(pll->control_base + ctrl->ndiv_frac.offset);
393 ndiv_frac = (val >> ctrl->ndiv_frac.shift) & 394 ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
394 bit_mask(ctrl->ndiv_frac.width); 395 bit_mask(ctrl->ndiv_frac.width);
395 396
@@ -398,7 +399,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
398 ndiv_frac; 399 ndiv_frac;
399 } 400 }
400 401
401 val = readl(pll->pll_base + ctrl->pdiv.offset); 402 val = readl(pll->control_base + ctrl->pdiv.offset);
402 pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width); 403 pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
403 404
404 clk->rate = (ndiv * parent_rate) >> ctrl->ndiv_int.shift; 405 clk->rate = (ndiv * parent_rate) >> ctrl->ndiv_int.shift;
@@ -463,14 +464,14 @@ static int iproc_clk_enable(struct clk_hw *hw)
463 u32 val; 464 u32 val;
464 465
465 /* channel enable is active low */ 466 /* channel enable is active low */
466 val = readl(pll->pll_base + ctrl->enable.offset); 467 val = readl(pll->control_base + ctrl->enable.offset);
467 val &= ~(1 << ctrl->enable.enable_shift); 468 val &= ~(1 << ctrl->enable.enable_shift);
468 iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val); 469 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
469 470
470 /* also make sure channel is not held */ 471 /* also make sure channel is not held */
471 val = readl(pll->pll_base + ctrl->enable.offset); 472 val = readl(pll->control_base + ctrl->enable.offset);
472 val &= ~(1 << ctrl->enable.hold_shift); 473 val &= ~(1 << ctrl->enable.hold_shift);
473 iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val); 474 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
474 475
475 return 0; 476 return 0;
476} 477}
@@ -485,9 +486,9 @@ static void iproc_clk_disable(struct clk_hw *hw)
485 if (ctrl->flags & IPROC_CLK_AON) 486 if (ctrl->flags & IPROC_CLK_AON)
486 return; 487 return;
487 488
488 val = readl(pll->pll_base + ctrl->enable.offset); 489 val = readl(pll->control_base + ctrl->enable.offset);
489 val |= 1 << ctrl->enable.enable_shift; 490 val |= 1 << ctrl->enable.enable_shift;
490 iproc_pll_write(pll, pll->pll_base, ctrl->enable.offset, val); 491 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
491} 492}
492 493
493static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw, 494static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
@@ -502,7 +503,7 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
502 if (parent_rate == 0) 503 if (parent_rate == 0)
503 return 0; 504 return 0;
504 505
505 val = readl(pll->pll_base + ctrl->mdiv.offset); 506 val = readl(pll->control_base + ctrl->mdiv.offset);
506 mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width); 507 mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
507 if (mdiv == 0) 508 if (mdiv == 0)
508 mdiv = 256; 509 mdiv = 256;
@@ -549,14 +550,14 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
549 if (div > 256) 550 if (div > 256)
550 return -EINVAL; 551 return -EINVAL;
551 552
552 val = readl(pll->pll_base + ctrl->mdiv.offset); 553 val = readl(pll->control_base + ctrl->mdiv.offset);
553 if (div == 256) { 554 if (div == 256) {
554 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); 555 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
555 } else { 556 } else {
556 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); 557 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
557 val |= div << ctrl->mdiv.shift; 558 val |= div << ctrl->mdiv.shift;
558 } 559 }
559 iproc_pll_write(pll, pll->pll_base, ctrl->mdiv.offset, val); 560 iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val);
560 clk->rate = parent_rate / div; 561 clk->rate = parent_rate / div;
561 562
562 return 0; 563 return 0;
@@ -581,9 +582,10 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll)
581 if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) { 582 if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
582 u32 val; 583 u32 val;
583 584
584 val = readl(pll->pll_base + ctrl->sw_ctrl.offset); 585 val = readl(pll->control_base + ctrl->sw_ctrl.offset);
585 val |= BIT(ctrl->sw_ctrl.shift); 586 val |= BIT(ctrl->sw_ctrl.shift);
586 iproc_pll_write(pll, pll->pll_base, ctrl->sw_ctrl.offset, val); 587 iproc_pll_write(pll, pll->control_base, ctrl->sw_ctrl.offset,
588 val);
587 } 589 }
588} 590}
589 591
@@ -618,8 +620,8 @@ void __init iproc_pll_clk_setup(struct device_node *node,
618 if (WARN_ON(!pll->clks)) 620 if (WARN_ON(!pll->clks))
619 goto err_clks; 621 goto err_clks;
620 622
621 pll->pll_base = of_iomap(node, 0); 623 pll->control_base = of_iomap(node, 0);
622 if (WARN_ON(!pll->pll_base)) 624 if (WARN_ON(!pll->control_base))
623 goto err_pll_iomap; 625 goto err_pll_iomap;
624 626
625 /* Some SoCs do not require the pwr_base, thus failing is not fatal */ 627 /* Some SoCs do not require the pwr_base, thus failing is not fatal */
@@ -632,6 +634,16 @@ void __init iproc_pll_clk_setup(struct device_node *node,
632 goto err_asiu_iomap; 634 goto err_asiu_iomap;
633 } 635 }
634 636
637 if (pll_ctrl->flags & IPROC_CLK_PLL_SPLIT_STAT_CTRL) {
638 /* Some SoCs have a split status/control. If this does not
639 * exist, assume they are unified.
640 */
641 pll->status_base = of_iomap(node, 2);
642 if (!pll->status_base)
643 goto err_status_iomap;
644 } else
645 pll->status_base = pll->control_base;
646
635 /* initialize and register the PLL itself */ 647 /* initialize and register the PLL itself */
636 pll->ctrl = pll_ctrl; 648 pll->ctrl = pll_ctrl;
637 649
@@ -702,6 +714,10 @@ err_clk_register:
702 clk_unregister(pll->clk_data.clks[i]); 714 clk_unregister(pll->clk_data.clks[i]);
703 715
704err_pll_register: 716err_pll_register:
717 if (pll->status_base != pll->control_base)
718 iounmap(pll->status_base);
719
720err_status_iomap:
705 if (pll->asiu_base) 721 if (pll->asiu_base)
706 iounmap(pll->asiu_base); 722 iounmap(pll->asiu_base);
707 723
@@ -709,7 +725,7 @@ err_asiu_iomap:
709 if (pll->pwr_base) 725 if (pll->pwr_base)
710 iounmap(pll->pwr_base); 726 iounmap(pll->pwr_base);
711 727
712 iounmap(pll->pll_base); 728 iounmap(pll->control_base);
713 729
714err_pll_iomap: 730err_pll_iomap:
715 kfree(pll->clks); 731 kfree(pll->clks);
diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h
index b71c19737efd..8988de70a98c 100644
--- a/drivers/clk/bcm/clk-iproc.h
+++ b/drivers/clk/bcm/clk-iproc.h
@@ -55,6 +55,12 @@
55#define IPROC_CLK_EMBED_PWRCTRL BIT(5) 55#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
56 56
57/* 57/*
58 * Some PLLs have separate registers for Status and Control. Identify this to
59 * let the driver know if additional registers need to be used
60 */
61#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
62
63/*
58 * Parameters for VCO frequency configuration 64 * Parameters for VCO frequency configuration
59 * 65 *
60 * VCO frequency = 66 * VCO frequency =