diff options
| author | Jon Mason <jonmason@broadcom.com> | 2015-10-15 15:48:30 -0400 |
|---|---|---|
| committer | Stephen Boyd <sboyd@codeaurora.org> | 2015-10-21 20:03:41 -0400 |
| commit | 40c8bec3f2591856e21124270be51a0a2b77c82d (patch) | |
| tree | 87c3369b839ce450d2ae47e55de5ba000bf5442a /drivers/clk/bcm | |
| parent | f713c6bf32092a259d6baf2be24f9c3dbf2462c3 (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>
Diffstat (limited to 'drivers/clk/bcm')
| -rw-r--r-- | drivers/clk/bcm/clk-iproc-pll.c | 96 | ||||
| -rw-r--r-- | drivers/clk/bcm/clk-iproc.h | 6 |
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 | ||
| 76 | struct iproc_pll { | 76 | struct 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 | ||
| 221 | static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp, | 222 | static 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 | ||
| 242 | static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, | 243 | static 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 | ||
| 493 | static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw, | 494 | static 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 | ||
| 704 | err_pll_register: | 716 | err_pll_register: |
| 717 | if (pll->status_base != pll->control_base) | ||
| 718 | iounmap(pll->status_base); | ||
| 719 | |||
| 720 | err_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 | ||
| 714 | err_pll_iomap: | 730 | err_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 = |
