clk: iproc: Add PWRCTRL support
authorJon Mason <jonmason@broadcom.com>
Thu, 15 Oct 2015 19:48:26 +0000 (15:48 -0400)
committerStephen Boyd <sboyd@codeaurora.org>
Wed, 21 Oct 2015 23:53:15 +0000 (16:53 -0700)
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>
drivers/clk/bcm/clk-iproc-pll.c
drivers/clk/bcm/clk-iproc.h

index 2dda4e8295a912a4ca28f091fc8a4af86f1c4662..e27acb9c655c43b54d1afe090a8e455f28a54d18 100644 (file)
@@ -148,14 +148,25 @@ static void __pll_disable(struct iproc_pll *pll)
                writel(val, pll->asiu_base + ctrl->asiu.offset);
        }
 
-       /* latch input value so core power can be shut down */
-       val = readl(pll->pwr_base + ctrl->aon.offset);
-       val |= (1 << ctrl->aon.iso_shift);
-       writel(val, pll->pwr_base + ctrl->aon.offset);
-
-       /* power down the core */
-       val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
-       writel(val, pll->pwr_base + ctrl->aon.offset);
+       if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
+               val = readl(pll->pll_base + ctrl->aon.offset);
+               val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
+               writel(val, pll->pll_base + ctrl->aon.offset);
+
+               if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+                       readl(pll->pll_base + ctrl->aon.offset);
+       }
+
+       if (pll->pwr_base) {
+               /* latch input value so core power can be shut down */
+               val = readl(pll->pwr_base + ctrl->aon.offset);
+               val |= 1 << ctrl->aon.iso_shift;
+               writel(val, pll->pwr_base + ctrl->aon.offset);
+
+               /* power down the core */
+               val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
+               writel(val, pll->pwr_base + ctrl->aon.offset);
+       }
 }
 
 static int __pll_enable(struct iproc_pll *pll)
@@ -163,11 +174,22 @@ static int __pll_enable(struct iproc_pll *pll)
        const struct iproc_pll_ctrl *ctrl = pll->ctrl;
        u32 val;
 
-       /* power up the PLL and make sure it's not latched */
-       val = readl(pll->pwr_base + ctrl->aon.offset);
-       val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
-       val &= ~(1 << ctrl->aon.iso_shift);
-       writel(val, pll->pwr_base + ctrl->aon.offset);
+       if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
+               val = readl(pll->pll_base + ctrl->aon.offset);
+               val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
+               writel(val, pll->pll_base + ctrl->aon.offset);
+
+               if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+                       readl(pll->pll_base + ctrl->aon.offset);
+       }
+
+       if (pll->pwr_base) {
+               /* power up the PLL and make sure it's not latched */
+               val = readl(pll->pwr_base + ctrl->aon.offset);
+               val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
+               val &= ~(1 << ctrl->aon.iso_shift);
+               writel(val, pll->pwr_base + ctrl->aon.offset);
+       }
 
        /* certain PLLs also need to be ungated from the ASIU top level */
        if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
@@ -610,9 +632,8 @@ void __init iproc_pll_clk_setup(struct device_node *node,
        if (WARN_ON(!pll->pll_base))
                goto err_pll_iomap;
 
+       /* Some SoCs do not require the pwr_base, thus failing is not fatal */
        pll->pwr_base = of_iomap(node, 1);
-       if (WARN_ON(!pll->pwr_base))
-               goto err_pwr_iomap;
 
        /* some PLLs require gating control at the top ASIU level */
        if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
@@ -695,9 +716,9 @@ err_pll_register:
                iounmap(pll->asiu_base);
 
 err_asiu_iomap:
-       iounmap(pll->pwr_base);
+       if (pll->pwr_base)
+               iounmap(pll->pwr_base);
 
-err_pwr_iomap:
        iounmap(pll->pll_base);
 
 err_pll_iomap:
index d834b7abd5c6a703b8ebf361d70a96c3361ecb3d..ff7bfad48c136dbac1dfa040fac05187868f5248 100644 (file)
  */
 #define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
 
+/*
+ * Some PLLs use a different way to control clock power, via the PWRDWN bit in
+ * the PLL control register
+ */
+#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
+
 /*
  * Parameters for VCO frequency configuration
  *