soc: xilinx: vcu: implement PLL disable
authorMichael Tretter <m.tretter@pengutronix.de>
Thu, 21 Jan 2021 07:16:50 +0000 (08:16 +0100)
committerStephen Boyd <sboyd@kernel.org>
Tue, 9 Feb 2021 02:31:25 +0000 (18:31 -0800)
The disabling of the PLL is not fully implemented, because according to
the ZynqMP register reference the RESET, POR_IN and PWR_POR bits have to
be set to bring the PLL into reset.

Set the bits to disable the PLL.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Acked-by: Michal Simek <michal.simek@xilinx.com>
Link: https://lore.kernel.org/r/20210121071659.1226489-7-m.tretter@pengutronix.de
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/soc/xilinx/xlnx_vcu.c

index ff66551a596670211c534782f3f856e8a0608bdf..34f3299afc0d756c62e3a90fe7dc7b5f6e41ff23 100644 (file)
@@ -329,6 +329,10 @@ static int xvcu_pll_enable(struct xvcu_device *xvcu)
                return ret;
        }
 
+       xvcu_write_field_reg(base, VCU_PLL_CTRL,
+                            1, VCU_PLL_CTRL_BYPASS_MASK,
+                            VCU_PLL_CTRL_BYPASS_SHIFT);
+
        vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
        vcu_pll_ctrl &= ~(VCU_PLL_CTRL_POR_IN_MASK <<
                          VCU_PLL_CTRL_POR_IN_SHIFT);
@@ -340,15 +344,9 @@ static int xvcu_pll_enable(struct xvcu_device *xvcu)
                         VCU_PLL_CTRL_PWR_POR_SHIFT;
        xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
 
-       xvcu_write_field_reg(base, VCU_PLL_CTRL,
-                            1, VCU_PLL_CTRL_BYPASS_MASK,
-                            VCU_PLL_CTRL_BYPASS_SHIFT);
-       xvcu_write_field_reg(base, VCU_PLL_CTRL,
-                            1, VCU_PLL_CTRL_RESET_MASK,
-                            VCU_PLL_CTRL_RESET_SHIFT);
-       xvcu_write_field_reg(base, VCU_PLL_CTRL,
-                            0, VCU_PLL_CTRL_RESET_MASK,
-                            VCU_PLL_CTRL_RESET_SHIFT);
+       vcu_pll_ctrl &= ~(VCU_PLL_CTRL_RESET_MASK << VCU_PLL_CTRL_RESET_SHIFT);
+       vcu_pll_ctrl |= (0 & VCU_PLL_CTRL_RESET_MASK) << VCU_PLL_CTRL_RESET_SHIFT;
+       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
 
        ret = xvcu_pll_wait_for_lock(xvcu);
        if (ret) {
@@ -368,6 +366,18 @@ err:
 
 static void xvcu_pll_disable(struct xvcu_device *xvcu)
 {
+       void __iomem *base = xvcu->vcu_slcr_ba;
+       u32 vcu_pll_ctrl;
+
+       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
+       vcu_pll_ctrl &= ~(VCU_PLL_CTRL_POR_IN_MASK << VCU_PLL_CTRL_POR_IN_SHIFT);
+       vcu_pll_ctrl |= (1 & VCU_PLL_CTRL_POR_IN_MASK) << VCU_PLL_CTRL_POR_IN_SHIFT;
+       vcu_pll_ctrl &= ~(VCU_PLL_CTRL_PWR_POR_MASK << VCU_PLL_CTRL_PWR_POR_SHIFT);
+       vcu_pll_ctrl |= (1 & VCU_PLL_CTRL_PWR_POR_MASK) << VCU_PLL_CTRL_PWR_POR_SHIFT;
+       vcu_pll_ctrl &= ~(VCU_PLL_CTRL_RESET_MASK << VCU_PLL_CTRL_RESET_SHIFT);
+       vcu_pll_ctrl |= (1 & VCU_PLL_CTRL_RESET_MASK) << VCU_PLL_CTRL_RESET_SHIFT;
+       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
+
        clk_disable_unprepare(xvcu->pll_ref);
 }