aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Mason <jonmason@broadcom.com>2015-10-15 15:48:26 -0400
committerStephen Boyd <sboyd@codeaurora.org>2015-10-21 19:53:15 -0400
commit01b6722fdf65a91d588338e5a1964d57fa2dd590 (patch)
tree604e56f8653928722fae07605c2552d72e3fea57
parent2dfc8a27ecfb3a54cc60376e0e7c4872934008f1 (diff)
clk: iproc: Add PWRCTRL support
Some iProc SoC clocks use a different way to control clock power, via the PWRDWN bit in the PLL control register. Since the PLL control register is used to access the PWRDWN bit, there is no need for the pwr_base when this is being used. A new flag, IPROC_CLK_EMBED_PWRCTRL, has been added to identify this usage. We can use the AON interface to write the values to enable/disable PWRDOWN. Signed-off-by: Jon Mason <jonmason@broadcom.com> [sboyd@codeaurora.org: Remove useless parentheses] Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r--drivers/clk/bcm/clk-iproc-pll.c55
-rw-r--r--drivers/clk/bcm/clk-iproc.h6
2 files changed, 44 insertions, 17 deletions
diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c
index 2dda4e8295a9..e27acb9c655c 100644
--- a/drivers/clk/bcm/clk-iproc-pll.c
+++ b/drivers/clk/bcm/clk-iproc-pll.c
@@ -148,14 +148,25 @@ static void __pll_disable(struct iproc_pll *pll)
148 writel(val, pll->asiu_base + ctrl->asiu.offset); 148 writel(val, pll->asiu_base + ctrl->asiu.offset);
149 } 149 }
150 150
151 /* latch input value so core power can be shut down */ 151 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
152 val = readl(pll->pwr_base + ctrl->aon.offset); 152 val = readl(pll->pll_base + ctrl->aon.offset);
153 val |= (1 << ctrl->aon.iso_shift); 153 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
154 writel(val, pll->pwr_base + ctrl->aon.offset); 154 writel(val, pll->pll_base + ctrl->aon.offset);
155 155
156 /* power down the core */ 156 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
157 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift); 157 readl(pll->pll_base + ctrl->aon.offset);
158 writel(val, pll->pwr_base + ctrl->aon.offset); 158 }
159
160 if (pll->pwr_base) {
161 /* latch input value so core power can be shut down */
162 val = readl(pll->pwr_base + ctrl->aon.offset);
163 val |= 1 << ctrl->aon.iso_shift;
164 writel(val, pll->pwr_base + ctrl->aon.offset);
165
166 /* power down the core */
167 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
168 writel(val, pll->pwr_base + ctrl->aon.offset);
169 }
159} 170}
160 171
161static int __pll_enable(struct iproc_pll *pll) 172static int __pll_enable(struct iproc_pll *pll)
@@ -163,11 +174,22 @@ static int __pll_enable(struct iproc_pll *pll)
163 const struct iproc_pll_ctrl *ctrl = pll->ctrl; 174 const struct iproc_pll_ctrl *ctrl = pll->ctrl;
164 u32 val; 175 u32 val;
165 176
166 /* power up the PLL and make sure it's not latched */ 177 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
167 val = readl(pll->pwr_base + ctrl->aon.offset); 178 val = readl(pll->pll_base + ctrl->aon.offset);
168 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift; 179 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
169 val &= ~(1 << ctrl->aon.iso_shift); 180 writel(val, pll->pll_base + ctrl->aon.offset);
170 writel(val, pll->pwr_base + ctrl->aon.offset); 181
182 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
183 readl(pll->pll_base + ctrl->aon.offset);
184 }
185
186 if (pll->pwr_base) {
187 /* power up the PLL and make sure it's not latched */
188 val = readl(pll->pwr_base + ctrl->aon.offset);
189 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
190 val &= ~(1 << ctrl->aon.iso_shift);
191 writel(val, pll->pwr_base + ctrl->aon.offset);
192 }
171 193
172 /* certain PLLs also need to be ungated from the ASIU top level */ 194 /* certain PLLs also need to be ungated from the ASIU top level */
173 if (ctrl->flags & IPROC_CLK_PLL_ASIU) { 195 if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
@@ -610,9 +632,8 @@ void __init iproc_pll_clk_setup(struct device_node *node,
610 if (WARN_ON(!pll->pll_base)) 632 if (WARN_ON(!pll->pll_base))
611 goto err_pll_iomap; 633 goto err_pll_iomap;
612 634
635 /* Some SoCs do not require the pwr_base, thus failing is not fatal */
613 pll->pwr_base = of_iomap(node, 1); 636 pll->pwr_base = of_iomap(node, 1);
614 if (WARN_ON(!pll->pwr_base))
615 goto err_pwr_iomap;
616 637
617 /* some PLLs require gating control at the top ASIU level */ 638 /* some PLLs require gating control at the top ASIU level */
618 if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) { 639 if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
@@ -695,9 +716,9 @@ err_pll_register:
695 iounmap(pll->asiu_base); 716 iounmap(pll->asiu_base);
696 717
697err_asiu_iomap: 718err_asiu_iomap:
698 iounmap(pll->pwr_base); 719 if (pll->pwr_base)
720 iounmap(pll->pwr_base);
699 721
700err_pwr_iomap:
701 iounmap(pll->pll_base); 722 iounmap(pll->pll_base);
702 723
703err_pll_iomap: 724err_pll_iomap:
diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h
index d834b7abd5c6..ff7bfad48c13 100644
--- a/drivers/clk/bcm/clk-iproc.h
+++ b/drivers/clk/bcm/clk-iproc.h
@@ -49,6 +49,12 @@
49#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4) 49#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
50 50
51/* 51/*
52 * Some PLLs use a different way to control clock power, via the PWRDWN bit in
53 * the PLL control register
54 */
55#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
56
57/*
52 * Parameters for VCO frequency configuration 58 * Parameters for VCO frequency configuration
53 * 59 *
54 * VCO frequency = 60 * VCO frequency =