clk: xilinx: move xlnx_vcu clock driver from soc
authorMichael Tretter <m.tretter@pengutronix.de>
Thu, 21 Jan 2021 07:16:59 +0000 (08:16 +0100)
committerStephen Boyd <sboyd@kernel.org>
Tue, 9 Feb 2021 02:31:25 +0000 (18:31 -0800)
The xlnx_vcu driver is actually a clock controller driver which provides
clocks that can be used by a driver for the encoder/decoder units. There
is no reason to keep this driver in soc. Move the driver to clk.

NOTE: The register mapping actually contains registers for AXI
performance monitoring, but these are not used by the driver.

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-16-m.tretter@pengutronix.de
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/xilinx/Kconfig [new file with mode: 0644]
drivers/clk/xilinx/Makefile [new file with mode: 0644]
drivers/clk/xilinx/xlnx_vcu.c [new file with mode: 0644]
drivers/soc/xilinx/Kconfig
drivers/soc/xilinx/Makefile
drivers/soc/xilinx/xlnx_vcu.c [deleted file]

index cee1d4e657bccdd7769fdffbbce666ef239add79..7c5dc348c16feb088fa287a3eb1d73dededbc24c 100644 (file)
@@ -393,6 +393,7 @@ source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/ti/Kconfig"
 source "drivers/clk/uniphier/Kconfig"
 source "drivers/clk/x86/Kconfig"
+source "drivers/clk/xilinx/Kconfig"
 source "drivers/clk/zynqmp/Kconfig"
 
 endif
index dbdc590e7de3aca81ef39256b690b11e26dfc760..074e2233f4450324c1702b115e4b737ef4171b37 100644 (file)
@@ -122,6 +122,7 @@ obj-y                                       += versatile/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_X86)                      += x86/
 endif
+obj-y                                  += xilinx/
 obj-$(CONFIG_ARCH_ZX)                  += zte/
 obj-$(CONFIG_ARCH_ZYNQ)                        += zynq/
 obj-$(CONFIG_COMMON_CLK_ZYNQMP)         += zynqmp/
diff --git a/drivers/clk/xilinx/Kconfig b/drivers/clk/xilinx/Kconfig
new file mode 100644 (file)
index 0000000..5224114
--- /dev/null
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config XILINX_VCU
+       tristate "Xilinx VCU logicoreIP Init"
+       depends on HAS_IOMEM && COMMON_CLK
+       select REGMAP_MMIO
+       help
+         Provides the driver to enable and disable the isolation between the
+         processing system and programmable logic part by using the logicoreIP
+         register set. This driver also configures the frequency based on the
+         clock information from the logicoreIP register set.
+
+         If you say yes here you get support for the logicoreIP.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called xlnx_vcu.
+
diff --git a/drivers/clk/xilinx/Makefile b/drivers/clk/xilinx/Makefile
new file mode 100644 (file)
index 0000000..dee8fd5
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_XILINX_VCU)       += xlnx_vcu.o
diff --git a/drivers/clk/xilinx/xlnx_vcu.c b/drivers/clk/xilinx/xlnx_vcu.c
new file mode 100644 (file)
index 0000000..d66b131
--- /dev/null
@@ -0,0 +1,743 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx VCU Init
+ *
+ * Copyright (C) 2016 - 2017 Xilinx, Inc.
+ *
+ * Contacts   Dhaval Shah <dshah@xilinx.com>
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/xlnx-vcu.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/xlnx-vcu.h>
+
+#define VCU_PLL_CTRL                   0x24
+#define VCU_PLL_CTRL_RESET             BIT(0)
+#define VCU_PLL_CTRL_POR_IN            BIT(1)
+#define VCU_PLL_CTRL_PWR_POR           BIT(2)
+#define VCU_PLL_CTRL_BYPASS            BIT(3)
+#define VCU_PLL_CTRL_FBDIV             GENMASK(14, 8)
+#define VCU_PLL_CTRL_CLKOUTDIV         GENMASK(18, 16)
+
+#define VCU_PLL_CFG                    0x28
+#define VCU_PLL_CFG_RES                        GENMASK(3, 0)
+#define VCU_PLL_CFG_CP                 GENMASK(8, 5)
+#define VCU_PLL_CFG_LFHF               GENMASK(12, 10)
+#define VCU_PLL_CFG_LOCK_CNT           GENMASK(22, 13)
+#define VCU_PLL_CFG_LOCK_DLY           GENMASK(31, 25)
+#define VCU_ENC_CORE_CTRL              0x30
+#define VCU_ENC_MCU_CTRL               0x34
+#define VCU_DEC_CORE_CTRL              0x38
+#define VCU_DEC_MCU_CTRL               0x3c
+#define VCU_PLL_STATUS                 0x60
+#define VCU_PLL_STATUS_LOCK_STATUS     BIT(0)
+
+#define MHZ                            1000000
+#define FVCO_MIN                       (1500U * MHZ)
+#define FVCO_MAX                       (3000U * MHZ)
+
+/**
+ * struct xvcu_device - Xilinx VCU init device structure
+ * @dev: Platform device
+ * @pll_ref: pll ref clock source
+ * @aclk: axi clock source
+ * @logicore_reg_ba: logicore reg base address
+ * @vcu_slcr_ba: vcu_slcr Register base address
+ * @pll: handle for the VCU PLL
+ * @pll_post: handle for the VCU PLL post divider
+ * @clk_data: clocks provided by the vcu clock provider
+ */
+struct xvcu_device {
+       struct device *dev;
+       struct clk *pll_ref;
+       struct clk *aclk;
+       struct regmap *logicore_reg_ba;
+       void __iomem *vcu_slcr_ba;
+       struct clk_hw *pll;
+       struct clk_hw *pll_post;
+       struct clk_hw_onecell_data *clk_data;
+};
+
+static struct regmap_config vcu_settings_regmap_config = {
+       .name = "regmap",
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = 0xfff,
+       .cache_type = REGCACHE_NONE,
+};
+
+/**
+ * struct xvcu_pll_cfg - Helper data
+ * @fbdiv: The integer portion of the feedback divider to the PLL
+ * @cp: PLL charge pump control
+ * @res: PLL loop filter resistor control
+ * @lfhf: PLL loop filter high frequency capacitor control
+ * @lock_dly: Lock circuit configuration settings for lock windowsize
+ * @lock_cnt: Lock circuit counter setting
+ */
+struct xvcu_pll_cfg {
+       u32 fbdiv;
+       u32 cp;
+       u32 res;
+       u32 lfhf;
+       u32 lock_dly;
+       u32 lock_cnt;
+};
+
+static const struct xvcu_pll_cfg xvcu_pll_cfg[] = {
+       { 25, 3, 10, 3, 63, 1000 },
+       { 26, 3, 10, 3, 63, 1000 },
+       { 27, 4, 6, 3, 63, 1000 },
+       { 28, 4, 6, 3, 63, 1000 },
+       { 29, 4, 6, 3, 63, 1000 },
+       { 30, 4, 6, 3, 63, 1000 },
+       { 31, 6, 1, 3, 63, 1000 },
+       { 32, 6, 1, 3, 63, 1000 },
+       { 33, 4, 10, 3, 63, 1000 },
+       { 34, 5, 6, 3, 63, 1000 },
+       { 35, 5, 6, 3, 63, 1000 },
+       { 36, 5, 6, 3, 63, 1000 },
+       { 37, 5, 6, 3, 63, 1000 },
+       { 38, 5, 6, 3, 63, 975 },
+       { 39, 3, 12, 3, 63, 950 },
+       { 40, 3, 12, 3, 63, 925 },
+       { 41, 3, 12, 3, 63, 900 },
+       { 42, 3, 12, 3, 63, 875 },
+       { 43, 3, 12, 3, 63, 850 },
+       { 44, 3, 12, 3, 63, 850 },
+       { 45, 3, 12, 3, 63, 825 },
+       { 46, 3, 12, 3, 63, 800 },
+       { 47, 3, 12, 3, 63, 775 },
+       { 48, 3, 12, 3, 63, 775 },
+       { 49, 3, 12, 3, 63, 750 },
+       { 50, 3, 12, 3, 63, 750 },
+       { 51, 3, 2, 3, 63, 725 },
+       { 52, 3, 2, 3, 63, 700 },
+       { 53, 3, 2, 3, 63, 700 },
+       { 54, 3, 2, 3, 63, 675 },
+       { 55, 3, 2, 3, 63, 675 },
+       { 56, 3, 2, 3, 63, 650 },
+       { 57, 3, 2, 3, 63, 650 },
+       { 58, 3, 2, 3, 63, 625 },
+       { 59, 3, 2, 3, 63, 625 },
+       { 60, 3, 2, 3, 63, 625 },
+       { 61, 3, 2, 3, 63, 600 },
+       { 62, 3, 2, 3, 63, 600 },
+       { 63, 3, 2, 3, 63, 600 },
+       { 64, 3, 2, 3, 63, 600 },
+       { 65, 3, 2, 3, 63, 600 },
+       { 66, 3, 2, 3, 63, 600 },
+       { 67, 3, 2, 3, 63, 600 },
+       { 68, 3, 2, 3, 63, 600 },
+       { 69, 3, 2, 3, 63, 600 },
+       { 70, 3, 2, 3, 63, 600 },
+       { 71, 3, 2, 3, 63, 600 },
+       { 72, 3, 2, 3, 63, 600 },
+       { 73, 3, 2, 3, 63, 600 },
+       { 74, 3, 2, 3, 63, 600 },
+       { 75, 3, 2, 3, 63, 600 },
+       { 76, 3, 2, 3, 63, 600 },
+       { 77, 3, 2, 3, 63, 600 },
+       { 78, 3, 2, 3, 63, 600 },
+       { 79, 3, 2, 3, 63, 600 },
+       { 80, 3, 2, 3, 63, 600 },
+       { 81, 3, 2, 3, 63, 600 },
+       { 82, 3, 2, 3, 63, 600 },
+       { 83, 4, 2, 3, 63, 600 },
+       { 84, 4, 2, 3, 63, 600 },
+       { 85, 4, 2, 3, 63, 600 },
+       { 86, 4, 2, 3, 63, 600 },
+       { 87, 4, 2, 3, 63, 600 },
+       { 88, 4, 2, 3, 63, 600 },
+       { 89, 4, 2, 3, 63, 600 },
+       { 90, 4, 2, 3, 63, 600 },
+       { 91, 4, 2, 3, 63, 600 },
+       { 92, 4, 2, 3, 63, 600 },
+       { 93, 4, 2, 3, 63, 600 },
+       { 94, 4, 2, 3, 63, 600 },
+       { 95, 4, 2, 3, 63, 600 },
+       { 96, 4, 2, 3, 63, 600 },
+       { 97, 4, 2, 3, 63, 600 },
+       { 98, 4, 2, 3, 63, 600 },
+       { 99, 4, 2, 3, 63, 600 },
+       { 100, 4, 2, 3, 63, 600 },
+       { 101, 4, 2, 3, 63, 600 },
+       { 102, 4, 2, 3, 63, 600 },
+       { 103, 5, 2, 3, 63, 600 },
+       { 104, 5, 2, 3, 63, 600 },
+       { 105, 5, 2, 3, 63, 600 },
+       { 106, 5, 2, 3, 63, 600 },
+       { 107, 3, 4, 3, 63, 600 },
+       { 108, 3, 4, 3, 63, 600 },
+       { 109, 3, 4, 3, 63, 600 },
+       { 110, 3, 4, 3, 63, 600 },
+       { 111, 3, 4, 3, 63, 600 },
+       { 112, 3, 4, 3, 63, 600 },
+       { 113, 3, 4, 3, 63, 600 },
+       { 114, 3, 4, 3, 63, 600 },
+       { 115, 3, 4, 3, 63, 600 },
+       { 116, 3, 4, 3, 63, 600 },
+       { 117, 3, 4, 3, 63, 600 },
+       { 118, 3, 4, 3, 63, 600 },
+       { 119, 3, 4, 3, 63, 600 },
+       { 120, 3, 4, 3, 63, 600 },
+       { 121, 3, 4, 3, 63, 600 },
+       { 122, 3, 4, 3, 63, 600 },
+       { 123, 3, 4, 3, 63, 600 },
+       { 124, 3, 4, 3, 63, 600 },
+       { 125, 3, 4, 3, 63, 600 },
+};
+
+/**
+ * xvcu_read - Read from the VCU register space
+ * @iomem:     vcu reg space base address
+ * @offset:    vcu reg offset from base
+ *
+ * Return:     Returns 32bit value from VCU register specified
+ *
+ */
+static inline u32 xvcu_read(void __iomem *iomem, u32 offset)
+{
+       return ioread32(iomem + offset);
+}
+
+/**
+ * xvcu_write - Write to the VCU register space
+ * @iomem:     vcu reg space base address
+ * @offset:    vcu reg offset from base
+ * @value:     Value to write
+ */
+static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value)
+{
+       iowrite32(value, iomem + offset);
+}
+
+#define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw)
+
+struct vcu_pll {
+       struct clk_hw hw;
+       void __iomem *reg_base;
+       unsigned long fvco_min;
+       unsigned long fvco_max;
+};
+
+static int xvcu_pll_wait_for_lock(struct vcu_pll *pll)
+{
+       void __iomem *base = pll->reg_base;
+       unsigned long timeout;
+       u32 lock_status;
+
+       timeout = jiffies + msecs_to_jiffies(2000);
+       do {
+               lock_status = xvcu_read(base, VCU_PLL_STATUS);
+               if (lock_status & VCU_PLL_STATUS_LOCK_STATUS)
+                       return 0;
+       } while (!time_after(jiffies, timeout));
+
+       return -ETIMEDOUT;
+}
+
+static struct clk_hw *xvcu_register_pll_post(struct device *dev,
+                                            const char *name,
+                                            const struct clk_hw *parent_hw,
+                                            void __iomem *reg_base)
+{
+       u32 div;
+       u32 vcu_pll_ctrl;
+
+       /*
+        * The output divider of the PLL must be set to 1/2 to meet the
+        * timing in the design.
+        */
+       vcu_pll_ctrl = xvcu_read(reg_base, VCU_PLL_CTRL);
+       div = FIELD_GET(VCU_PLL_CTRL_CLKOUTDIV, vcu_pll_ctrl);
+       if (div != 1)
+               return ERR_PTR(-EINVAL);
+
+       return clk_hw_register_fixed_factor(dev, "vcu_pll_post",
+                                           clk_hw_get_name(parent_hw),
+                                           CLK_SET_RATE_PARENT, 1, 2);
+}
+
+static const struct xvcu_pll_cfg *xvcu_find_cfg(int div)
+{
+       const struct xvcu_pll_cfg *cfg = NULL;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++)
+               if (xvcu_pll_cfg[i].fbdiv == div)
+                       cfg = &xvcu_pll_cfg[i];
+
+       return cfg;
+}
+
+static int xvcu_pll_set_div(struct vcu_pll *pll, int div)
+{
+       void __iomem *base = pll->reg_base;
+       const struct xvcu_pll_cfg *cfg = NULL;
+       u32 vcu_pll_ctrl;
+       u32 cfg_val;
+
+       cfg = xvcu_find_cfg(div);
+       if (!cfg)
+               return -EINVAL;
+
+       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
+       vcu_pll_ctrl &= ~VCU_PLL_CTRL_FBDIV;
+       vcu_pll_ctrl |= FIELD_PREP(VCU_PLL_CTRL_FBDIV, cfg->fbdiv);
+       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
+
+       cfg_val = FIELD_PREP(VCU_PLL_CFG_RES, cfg->res) |
+                 FIELD_PREP(VCU_PLL_CFG_CP, cfg->cp) |
+                 FIELD_PREP(VCU_PLL_CFG_LFHF, cfg->lfhf) |
+                 FIELD_PREP(VCU_PLL_CFG_LOCK_CNT, cfg->lock_cnt) |
+                 FIELD_PREP(VCU_PLL_CFG_LOCK_DLY, cfg->lock_dly);
+       xvcu_write(base, VCU_PLL_CFG, cfg_val);
+
+       return 0;
+}
+
+static long xvcu_pll_round_rate(struct clk_hw *hw,
+                               unsigned long rate, unsigned long *parent_rate)
+{
+       struct vcu_pll *pll = to_vcu_pll(hw);
+       unsigned int feedback_div;
+
+       rate = clamp_t(unsigned long, rate, pll->fvco_min, pll->fvco_max);
+
+       feedback_div = DIV_ROUND_CLOSEST_ULL(rate, *parent_rate);
+       feedback_div = clamp_t(unsigned int, feedback_div, 25, 125);
+
+       return *parent_rate * feedback_div;
+}
+
+static unsigned long xvcu_pll_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       struct vcu_pll *pll = to_vcu_pll(hw);
+       void __iomem *base = pll->reg_base;
+       unsigned int div;
+       u32 vcu_pll_ctrl;
+
+       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
+       div = FIELD_GET(VCU_PLL_CTRL_FBDIV, vcu_pll_ctrl);
+
+       return div * parent_rate;
+}
+
+static int xvcu_pll_set_rate(struct clk_hw *hw,
+                            unsigned long rate, unsigned long parent_rate)
+{
+       struct vcu_pll *pll = to_vcu_pll(hw);
+
+       return xvcu_pll_set_div(pll, rate / parent_rate);
+}
+
+static int xvcu_pll_enable(struct clk_hw *hw)
+{
+       struct vcu_pll *pll = to_vcu_pll(hw);
+       void __iomem *base = pll->reg_base;
+       u32 vcu_pll_ctrl;
+       int ret;
+
+       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
+       vcu_pll_ctrl |= VCU_PLL_CTRL_BYPASS;
+       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
+
+       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
+       vcu_pll_ctrl &= ~VCU_PLL_CTRL_POR_IN;
+       vcu_pll_ctrl &= ~VCU_PLL_CTRL_PWR_POR;
+       vcu_pll_ctrl &= ~VCU_PLL_CTRL_RESET;
+       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
+
+       ret = xvcu_pll_wait_for_lock(pll);
+       if (ret) {
+               pr_err("VCU PLL is not locked\n");
+               goto err;
+       }
+
+       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
+       vcu_pll_ctrl &= ~VCU_PLL_CTRL_BYPASS;
+       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
+
+err:
+       return ret;
+}
+
+static void xvcu_pll_disable(struct clk_hw *hw)
+{
+       struct vcu_pll *pll = to_vcu_pll(hw);
+       void __iomem *base = pll->reg_base;
+       u32 vcu_pll_ctrl;
+
+       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
+       vcu_pll_ctrl |= VCU_PLL_CTRL_POR_IN;
+       vcu_pll_ctrl |= VCU_PLL_CTRL_PWR_POR;
+       vcu_pll_ctrl |= VCU_PLL_CTRL_RESET;
+       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
+}
+
+static const struct clk_ops vcu_pll_ops = {
+       .enable = xvcu_pll_enable,
+       .disable = xvcu_pll_disable,
+       .round_rate = xvcu_pll_round_rate,
+       .recalc_rate = xvcu_pll_recalc_rate,
+       .set_rate = xvcu_pll_set_rate,
+};
+
+static struct clk_hw *xvcu_register_pll(struct device *dev,
+                                       void __iomem *reg_base,
+                                       const char *name, const char *parent,
+                                       unsigned long flags)
+{
+       struct vcu_pll *pll;
+       struct clk_hw *hw;
+       struct clk_init_data init;
+       int ret;
+
+       init.name = name;
+       init.parent_names = &parent;
+       init.ops = &vcu_pll_ops;
+       init.num_parents = 1;
+       init.flags = flags;
+
+       pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL);
+       if (!pll)
+               return ERR_PTR(-ENOMEM);
+
+       pll->hw.init = &init;
+       pll->reg_base = reg_base;
+       pll->fvco_min = FVCO_MIN;
+       pll->fvco_max = FVCO_MAX;
+
+       hw = &pll->hw;
+       ret = devm_clk_hw_register(dev, hw);
+       if (ret)
+               return ERR_PTR(ret);
+
+       clk_hw_set_rate_range(hw, pll->fvco_min, pll->fvco_max);
+
+       return hw;
+}
+
+static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev,
+                                               const char *name,
+                                               const struct clk_parent_data *parent_data,
+                                               u8 num_parents,
+                                               void __iomem *reg)
+{
+       u8 mux_flags = CLK_MUX_ROUND_CLOSEST;
+       u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
+                          CLK_DIVIDER_ROUND_CLOSEST;
+       struct clk_hw *mux = NULL;
+       struct clk_hw *divider = NULL;
+       struct clk_hw *gate = NULL;
+       char *name_mux;
+       char *name_div;
+       int err;
+       /* Protect register shared by clocks */
+       spinlock_t *lock;
+
+       lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL);
+       if (!lock)
+               return ERR_PTR(-ENOMEM);
+       spin_lock_init(lock);
+
+       name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux");
+       if (!name_mux)
+               return ERR_PTR(-ENOMEM);
+       mux = clk_hw_register_mux_parent_data(dev, name_mux,
+                                             parent_data, num_parents,
+                                             CLK_SET_RATE_PARENT,
+                                             reg, 0, 1, mux_flags, lock);
+       if (IS_ERR(mux))
+               return mux;
+
+       name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div");
+       if (!name_div) {
+               err = -ENOMEM;
+               goto unregister_mux;
+       }
+       divider = clk_hw_register_divider_parent_hw(dev, name_div, mux,
+                                                   CLK_SET_RATE_PARENT,
+                                                   reg, 4, 6, divider_flags,
+                                                   lock);
+       if (IS_ERR(divider)) {
+               err = PTR_ERR(divider);
+               goto unregister_mux;
+       }
+
+       gate = clk_hw_register_gate_parent_hw(dev, name, divider,
+                                             CLK_SET_RATE_PARENT, reg, 12, 0,
+                                             lock);
+       if (IS_ERR(gate)) {
+               err = PTR_ERR(gate);
+               goto unregister_divider;
+       }
+
+       return gate;
+
+unregister_divider:
+       clk_hw_unregister_divider(divider);
+unregister_mux:
+       clk_hw_unregister_mux(mux);
+
+       return ERR_PTR(err);
+}
+
+static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw)
+{
+       struct clk_hw *gate = hw;
+       struct clk_hw *divider;
+       struct clk_hw *mux;
+
+       if (!gate)
+               return;
+
+       divider = clk_hw_get_parent(gate);
+       clk_hw_unregister_gate(gate);
+       if (!divider)
+               return;
+
+       mux = clk_hw_get_parent(divider);
+       clk_hw_unregister_mux(mux);
+       if (!divider)
+               return;
+
+       clk_hw_unregister_divider(divider);
+}
+
+static int xvcu_register_clock_provider(struct xvcu_device *xvcu)
+{
+       struct device *dev = xvcu->dev;
+       struct clk_parent_data parent_data[2] = { 0 };
+       struct clk_hw_onecell_data *data;
+       struct clk_hw **hws;
+       struct clk_hw *hw;
+       void __iomem *reg_base = xvcu->vcu_slcr_ba;
+
+       data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       data->num = CLK_XVCU_NUM_CLOCKS;
+       hws = data->hws;
+
+       xvcu->clk_data = data;
+
+       hw = xvcu_register_pll(dev, reg_base,
+                              "vcu_pll", __clk_get_name(xvcu->pll_ref),
+                              CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+       xvcu->pll = hw;
+
+       hw = xvcu_register_pll_post(dev, "vcu_pll_post", xvcu->pll, reg_base);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+       xvcu->pll_post = hw;
+
+       parent_data[0].fw_name = "pll_ref";
+       parent_data[1].hw = xvcu->pll_post;
+
+       hws[CLK_XVCU_ENC_CORE] =
+               xvcu_clk_hw_register_leaf(dev, "venc_core_clk",
+                                         parent_data,
+                                         ARRAY_SIZE(parent_data),
+                                         reg_base + VCU_ENC_CORE_CTRL);
+       hws[CLK_XVCU_ENC_MCU] =
+               xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk",
+                                         parent_data,
+                                         ARRAY_SIZE(parent_data),
+                                         reg_base + VCU_ENC_MCU_CTRL);
+       hws[CLK_XVCU_DEC_CORE] =
+               xvcu_clk_hw_register_leaf(dev, "vdec_core_clk",
+                                         parent_data,
+                                         ARRAY_SIZE(parent_data),
+                                         reg_base + VCU_DEC_CORE_CTRL);
+       hws[CLK_XVCU_DEC_MCU] =
+               xvcu_clk_hw_register_leaf(dev, "vdec_mcu_clk",
+                                         parent_data,
+                                         ARRAY_SIZE(parent_data),
+                                         reg_base + VCU_DEC_MCU_CTRL);
+
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
+}
+
+static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu)
+{
+       struct clk_hw_onecell_data *data = xvcu->clk_data;
+       struct clk_hw **hws = data->hws;
+
+       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_MCU]))
+               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_MCU]);
+       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_CORE]))
+               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_CORE]);
+       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU]))
+               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]);
+       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE]))
+               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]);
+
+       clk_hw_unregister_fixed_factor(xvcu->pll_post);
+}
+
+/**
+ * xvcu_probe - Probe existence of the logicoreIP
+ *                     and initialize PLL
+ *
+ * @pdev:      Pointer to the platform_device structure
+ *
+ * Return:     Returns 0 on success
+ *             Negative error code otherwise
+ */
+static int xvcu_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct xvcu_device *xvcu;
+       void __iomem *regs;
+       int ret;
+
+       xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL);
+       if (!xvcu)
+               return -ENOMEM;
+
+       xvcu->dev = &pdev->dev;
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr");
+       if (!res) {
+               dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n");
+               return -ENODEV;
+       }
+
+       xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start,
+                                        resource_size(res));
+       if (!xvcu->vcu_slcr_ba) {
+               dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n");
+               return -ENOMEM;
+       }
+
+       xvcu->logicore_reg_ba =
+               syscon_regmap_lookup_by_compatible("xlnx,vcu-settings");
+       if (IS_ERR(xvcu->logicore_reg_ba)) {
+               dev_info(&pdev->dev,
+                        "could not find xlnx,vcu-settings: trying direct register access\n");
+
+               res = platform_get_resource_byname(pdev,
+                                                  IORESOURCE_MEM, "logicore");
+               if (!res) {
+                       dev_err(&pdev->dev, "get logicore memory resource failed.\n");
+                       return -ENODEV;
+               }
+
+               regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+               if (!regs) {
+                       dev_err(&pdev->dev, "logicore register mapping failed.\n");
+                       return -ENOMEM;
+               }
+
+               xvcu->logicore_reg_ba =
+                       devm_regmap_init_mmio(&pdev->dev, regs,
+                                             &vcu_settings_regmap_config);
+               if (IS_ERR(xvcu->logicore_reg_ba)) {
+                       dev_err(&pdev->dev, "failed to init regmap\n");
+                       return PTR_ERR(xvcu->logicore_reg_ba);
+               }
+       }
+
+       xvcu->aclk = devm_clk_get(&pdev->dev, "aclk");
+       if (IS_ERR(xvcu->aclk)) {
+               dev_err(&pdev->dev, "Could not get aclk clock\n");
+               return PTR_ERR(xvcu->aclk);
+       }
+
+       xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
+       if (IS_ERR(xvcu->pll_ref)) {
+               dev_err(&pdev->dev, "Could not get pll_ref clock\n");
+               return PTR_ERR(xvcu->pll_ref);
+       }
+
+       ret = clk_prepare_enable(xvcu->aclk);
+       if (ret) {
+               dev_err(&pdev->dev, "aclk clock enable failed\n");
+               return ret;
+       }
+
+       /*
+        * Do the Gasket isolation and put the VCU out of reset
+        * Bit 0 : Gasket isolation
+        * Bit 1 : put VCU out of reset
+        */
+       regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE);
+
+       ret = xvcu_register_clock_provider(xvcu);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register clock provider\n");
+               goto error_clk_provider;
+       }
+
+       dev_set_drvdata(&pdev->dev, xvcu);
+
+       return 0;
+
+error_clk_provider:
+       xvcu_unregister_clock_provider(xvcu);
+       clk_disable_unprepare(xvcu->aclk);
+       return ret;
+}
+
+/**
+ * xvcu_remove - Insert gasket isolation
+ *                     and disable the clock
+ * @pdev:      Pointer to the platform_device structure
+ *
+ * Return:     Returns 0 on success
+ *             Negative error code otherwise
+ */
+static int xvcu_remove(struct platform_device *pdev)
+{
+       struct xvcu_device *xvcu;
+
+       xvcu = platform_get_drvdata(pdev);
+       if (!xvcu)
+               return -ENODEV;
+
+       xvcu_unregister_clock_provider(xvcu);
+
+       /* Add the Gasket isolation and put the VCU in reset. */
+       regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
+
+       clk_disable_unprepare(xvcu->aclk);
+
+       return 0;
+}
+
+static const struct of_device_id xvcu_of_id_table[] = {
+       { .compatible = "xlnx,vcu" },
+       { .compatible = "xlnx,vcu-logicoreip-1.0" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, xvcu_of_id_table);
+
+static struct platform_driver xvcu_driver = {
+       .driver = {
+               .name           = "xilinx-vcu",
+               .of_match_table = xvcu_of_id_table,
+       },
+       .probe                  = xvcu_probe,
+       .remove                 = xvcu_remove,
+};
+
+module_platform_driver(xvcu_driver);
+
+MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx VCU init Driver");
+MODULE_LICENSE("GPL v2");
index 9fe703772e5ac8806e565e7bde4e14a90e39c884..53af9115dc3118efa956238ee6af91ac11f9895c 100644 (file)
@@ -1,23 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 menu "Xilinx SoC drivers"
 
-config XILINX_VCU
-       tristate "Xilinx VCU logicoreIP Init"
-       depends on HAS_IOMEM && COMMON_CLK
-       select REGMAP_MMIO
-       help
-         Provides the driver to enable and disable the isolation between the
-         processing system and programmable logic part by using the logicoreIP
-         register set. This driver also configures the frequency based on the
-         clock information from the logicoreIP register set.
-
-         If you say yes here you get support for the logicoreIP.
-
-         If unsure, say N.
-
-         To compile this driver as a module, choose M here: the
-         module will be called xlnx_vcu.
-
 config ZYNQMP_POWER
        bool "Enable Xilinx Zynq MPSoC Power Management driver"
        depends on PM && ZYNQMP_FIRMWARE
index f66bfea5de175ae2b75f6ec43034e9b6fbb6c275..9854e6f6086b5350c1859c0f33b8d9967e819e7e 100644 (file)
@@ -1,4 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_XILINX_VCU)       += xlnx_vcu.o
 obj-$(CONFIG_ZYNQMP_POWER)     += zynqmp_power.o
 obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o
diff --git a/drivers/soc/xilinx/xlnx_vcu.c b/drivers/soc/xilinx/xlnx_vcu.c
deleted file mode 100644 (file)
index d66b131..0000000
+++ /dev/null
@@ -1,743 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Xilinx VCU Init
- *
- * Copyright (C) 2016 - 2017 Xilinx, Inc.
- *
- * Contacts   Dhaval Shah <dshah@xilinx.com>
- */
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/xlnx-vcu.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#include <dt-bindings/clock/xlnx-vcu.h>
-
-#define VCU_PLL_CTRL                   0x24
-#define VCU_PLL_CTRL_RESET             BIT(0)
-#define VCU_PLL_CTRL_POR_IN            BIT(1)
-#define VCU_PLL_CTRL_PWR_POR           BIT(2)
-#define VCU_PLL_CTRL_BYPASS            BIT(3)
-#define VCU_PLL_CTRL_FBDIV             GENMASK(14, 8)
-#define VCU_PLL_CTRL_CLKOUTDIV         GENMASK(18, 16)
-
-#define VCU_PLL_CFG                    0x28
-#define VCU_PLL_CFG_RES                        GENMASK(3, 0)
-#define VCU_PLL_CFG_CP                 GENMASK(8, 5)
-#define VCU_PLL_CFG_LFHF               GENMASK(12, 10)
-#define VCU_PLL_CFG_LOCK_CNT           GENMASK(22, 13)
-#define VCU_PLL_CFG_LOCK_DLY           GENMASK(31, 25)
-#define VCU_ENC_CORE_CTRL              0x30
-#define VCU_ENC_MCU_CTRL               0x34
-#define VCU_DEC_CORE_CTRL              0x38
-#define VCU_DEC_MCU_CTRL               0x3c
-#define VCU_PLL_STATUS                 0x60
-#define VCU_PLL_STATUS_LOCK_STATUS     BIT(0)
-
-#define MHZ                            1000000
-#define FVCO_MIN                       (1500U * MHZ)
-#define FVCO_MAX                       (3000U * MHZ)
-
-/**
- * struct xvcu_device - Xilinx VCU init device structure
- * @dev: Platform device
- * @pll_ref: pll ref clock source
- * @aclk: axi clock source
- * @logicore_reg_ba: logicore reg base address
- * @vcu_slcr_ba: vcu_slcr Register base address
- * @pll: handle for the VCU PLL
- * @pll_post: handle for the VCU PLL post divider
- * @clk_data: clocks provided by the vcu clock provider
- */
-struct xvcu_device {
-       struct device *dev;
-       struct clk *pll_ref;
-       struct clk *aclk;
-       struct regmap *logicore_reg_ba;
-       void __iomem *vcu_slcr_ba;
-       struct clk_hw *pll;
-       struct clk_hw *pll_post;
-       struct clk_hw_onecell_data *clk_data;
-};
-
-static struct regmap_config vcu_settings_regmap_config = {
-       .name = "regmap",
-       .reg_bits = 32,
-       .val_bits = 32,
-       .reg_stride = 4,
-       .max_register = 0xfff,
-       .cache_type = REGCACHE_NONE,
-};
-
-/**
- * struct xvcu_pll_cfg - Helper data
- * @fbdiv: The integer portion of the feedback divider to the PLL
- * @cp: PLL charge pump control
- * @res: PLL loop filter resistor control
- * @lfhf: PLL loop filter high frequency capacitor control
- * @lock_dly: Lock circuit configuration settings for lock windowsize
- * @lock_cnt: Lock circuit counter setting
- */
-struct xvcu_pll_cfg {
-       u32 fbdiv;
-       u32 cp;
-       u32 res;
-       u32 lfhf;
-       u32 lock_dly;
-       u32 lock_cnt;
-};
-
-static const struct xvcu_pll_cfg xvcu_pll_cfg[] = {
-       { 25, 3, 10, 3, 63, 1000 },
-       { 26, 3, 10, 3, 63, 1000 },
-       { 27, 4, 6, 3, 63, 1000 },
-       { 28, 4, 6, 3, 63, 1000 },
-       { 29, 4, 6, 3, 63, 1000 },
-       { 30, 4, 6, 3, 63, 1000 },
-       { 31, 6, 1, 3, 63, 1000 },
-       { 32, 6, 1, 3, 63, 1000 },
-       { 33, 4, 10, 3, 63, 1000 },
-       { 34, 5, 6, 3, 63, 1000 },
-       { 35, 5, 6, 3, 63, 1000 },
-       { 36, 5, 6, 3, 63, 1000 },
-       { 37, 5, 6, 3, 63, 1000 },
-       { 38, 5, 6, 3, 63, 975 },
-       { 39, 3, 12, 3, 63, 950 },
-       { 40, 3, 12, 3, 63, 925 },
-       { 41, 3, 12, 3, 63, 900 },
-       { 42, 3, 12, 3, 63, 875 },
-       { 43, 3, 12, 3, 63, 850 },
-       { 44, 3, 12, 3, 63, 850 },
-       { 45, 3, 12, 3, 63, 825 },
-       { 46, 3, 12, 3, 63, 800 },
-       { 47, 3, 12, 3, 63, 775 },
-       { 48, 3, 12, 3, 63, 775 },
-       { 49, 3, 12, 3, 63, 750 },
-       { 50, 3, 12, 3, 63, 750 },
-       { 51, 3, 2, 3, 63, 725 },
-       { 52, 3, 2, 3, 63, 700 },
-       { 53, 3, 2, 3, 63, 700 },
-       { 54, 3, 2, 3, 63, 675 },
-       { 55, 3, 2, 3, 63, 675 },
-       { 56, 3, 2, 3, 63, 650 },
-       { 57, 3, 2, 3, 63, 650 },
-       { 58, 3, 2, 3, 63, 625 },
-       { 59, 3, 2, 3, 63, 625 },
-       { 60, 3, 2, 3, 63, 625 },
-       { 61, 3, 2, 3, 63, 600 },
-       { 62, 3, 2, 3, 63, 600 },
-       { 63, 3, 2, 3, 63, 600 },
-       { 64, 3, 2, 3, 63, 600 },
-       { 65, 3, 2, 3, 63, 600 },
-       { 66, 3, 2, 3, 63, 600 },
-       { 67, 3, 2, 3, 63, 600 },
-       { 68, 3, 2, 3, 63, 600 },
-       { 69, 3, 2, 3, 63, 600 },
-       { 70, 3, 2, 3, 63, 600 },
-       { 71, 3, 2, 3, 63, 600 },
-       { 72, 3, 2, 3, 63, 600 },
-       { 73, 3, 2, 3, 63, 600 },
-       { 74, 3, 2, 3, 63, 600 },
-       { 75, 3, 2, 3, 63, 600 },
-       { 76, 3, 2, 3, 63, 600 },
-       { 77, 3, 2, 3, 63, 600 },
-       { 78, 3, 2, 3, 63, 600 },
-       { 79, 3, 2, 3, 63, 600 },
-       { 80, 3, 2, 3, 63, 600 },
-       { 81, 3, 2, 3, 63, 600 },
-       { 82, 3, 2, 3, 63, 600 },
-       { 83, 4, 2, 3, 63, 600 },
-       { 84, 4, 2, 3, 63, 600 },
-       { 85, 4, 2, 3, 63, 600 },
-       { 86, 4, 2, 3, 63, 600 },
-       { 87, 4, 2, 3, 63, 600 },
-       { 88, 4, 2, 3, 63, 600 },
-       { 89, 4, 2, 3, 63, 600 },
-       { 90, 4, 2, 3, 63, 600 },
-       { 91, 4, 2, 3, 63, 600 },
-       { 92, 4, 2, 3, 63, 600 },
-       { 93, 4, 2, 3, 63, 600 },
-       { 94, 4, 2, 3, 63, 600 },
-       { 95, 4, 2, 3, 63, 600 },
-       { 96, 4, 2, 3, 63, 600 },
-       { 97, 4, 2, 3, 63, 600 },
-       { 98, 4, 2, 3, 63, 600 },
-       { 99, 4, 2, 3, 63, 600 },
-       { 100, 4, 2, 3, 63, 600 },
-       { 101, 4, 2, 3, 63, 600 },
-       { 102, 4, 2, 3, 63, 600 },
-       { 103, 5, 2, 3, 63, 600 },
-       { 104, 5, 2, 3, 63, 600 },
-       { 105, 5, 2, 3, 63, 600 },
-       { 106, 5, 2, 3, 63, 600 },
-       { 107, 3, 4, 3, 63, 600 },
-       { 108, 3, 4, 3, 63, 600 },
-       { 109, 3, 4, 3, 63, 600 },
-       { 110, 3, 4, 3, 63, 600 },
-       { 111, 3, 4, 3, 63, 600 },
-       { 112, 3, 4, 3, 63, 600 },
-       { 113, 3, 4, 3, 63, 600 },
-       { 114, 3, 4, 3, 63, 600 },
-       { 115, 3, 4, 3, 63, 600 },
-       { 116, 3, 4, 3, 63, 600 },
-       { 117, 3, 4, 3, 63, 600 },
-       { 118, 3, 4, 3, 63, 600 },
-       { 119, 3, 4, 3, 63, 600 },
-       { 120, 3, 4, 3, 63, 600 },
-       { 121, 3, 4, 3, 63, 600 },
-       { 122, 3, 4, 3, 63, 600 },
-       { 123, 3, 4, 3, 63, 600 },
-       { 124, 3, 4, 3, 63, 600 },
-       { 125, 3, 4, 3, 63, 600 },
-};
-
-/**
- * xvcu_read - Read from the VCU register space
- * @iomem:     vcu reg space base address
- * @offset:    vcu reg offset from base
- *
- * Return:     Returns 32bit value from VCU register specified
- *
- */
-static inline u32 xvcu_read(void __iomem *iomem, u32 offset)
-{
-       return ioread32(iomem + offset);
-}
-
-/**
- * xvcu_write - Write to the VCU register space
- * @iomem:     vcu reg space base address
- * @offset:    vcu reg offset from base
- * @value:     Value to write
- */
-static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value)
-{
-       iowrite32(value, iomem + offset);
-}
-
-#define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw)
-
-struct vcu_pll {
-       struct clk_hw hw;
-       void __iomem *reg_base;
-       unsigned long fvco_min;
-       unsigned long fvco_max;
-};
-
-static int xvcu_pll_wait_for_lock(struct vcu_pll *pll)
-{
-       void __iomem *base = pll->reg_base;
-       unsigned long timeout;
-       u32 lock_status;
-
-       timeout = jiffies + msecs_to_jiffies(2000);
-       do {
-               lock_status = xvcu_read(base, VCU_PLL_STATUS);
-               if (lock_status & VCU_PLL_STATUS_LOCK_STATUS)
-                       return 0;
-       } while (!time_after(jiffies, timeout));
-
-       return -ETIMEDOUT;
-}
-
-static struct clk_hw *xvcu_register_pll_post(struct device *dev,
-                                            const char *name,
-                                            const struct clk_hw *parent_hw,
-                                            void __iomem *reg_base)
-{
-       u32 div;
-       u32 vcu_pll_ctrl;
-
-       /*
-        * The output divider of the PLL must be set to 1/2 to meet the
-        * timing in the design.
-        */
-       vcu_pll_ctrl = xvcu_read(reg_base, VCU_PLL_CTRL);
-       div = FIELD_GET(VCU_PLL_CTRL_CLKOUTDIV, vcu_pll_ctrl);
-       if (div != 1)
-               return ERR_PTR(-EINVAL);
-
-       return clk_hw_register_fixed_factor(dev, "vcu_pll_post",
-                                           clk_hw_get_name(parent_hw),
-                                           CLK_SET_RATE_PARENT, 1, 2);
-}
-
-static const struct xvcu_pll_cfg *xvcu_find_cfg(int div)
-{
-       const struct xvcu_pll_cfg *cfg = NULL;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++)
-               if (xvcu_pll_cfg[i].fbdiv == div)
-                       cfg = &xvcu_pll_cfg[i];
-
-       return cfg;
-}
-
-static int xvcu_pll_set_div(struct vcu_pll *pll, int div)
-{
-       void __iomem *base = pll->reg_base;
-       const struct xvcu_pll_cfg *cfg = NULL;
-       u32 vcu_pll_ctrl;
-       u32 cfg_val;
-
-       cfg = xvcu_find_cfg(div);
-       if (!cfg)
-               return -EINVAL;
-
-       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
-       vcu_pll_ctrl &= ~VCU_PLL_CTRL_FBDIV;
-       vcu_pll_ctrl |= FIELD_PREP(VCU_PLL_CTRL_FBDIV, cfg->fbdiv);
-       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
-
-       cfg_val = FIELD_PREP(VCU_PLL_CFG_RES, cfg->res) |
-                 FIELD_PREP(VCU_PLL_CFG_CP, cfg->cp) |
-                 FIELD_PREP(VCU_PLL_CFG_LFHF, cfg->lfhf) |
-                 FIELD_PREP(VCU_PLL_CFG_LOCK_CNT, cfg->lock_cnt) |
-                 FIELD_PREP(VCU_PLL_CFG_LOCK_DLY, cfg->lock_dly);
-       xvcu_write(base, VCU_PLL_CFG, cfg_val);
-
-       return 0;
-}
-
-static long xvcu_pll_round_rate(struct clk_hw *hw,
-                               unsigned long rate, unsigned long *parent_rate)
-{
-       struct vcu_pll *pll = to_vcu_pll(hw);
-       unsigned int feedback_div;
-
-       rate = clamp_t(unsigned long, rate, pll->fvco_min, pll->fvco_max);
-
-       feedback_div = DIV_ROUND_CLOSEST_ULL(rate, *parent_rate);
-       feedback_div = clamp_t(unsigned int, feedback_div, 25, 125);
-
-       return *parent_rate * feedback_div;
-}
-
-static unsigned long xvcu_pll_recalc_rate(struct clk_hw *hw,
-                                         unsigned long parent_rate)
-{
-       struct vcu_pll *pll = to_vcu_pll(hw);
-       void __iomem *base = pll->reg_base;
-       unsigned int div;
-       u32 vcu_pll_ctrl;
-
-       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
-       div = FIELD_GET(VCU_PLL_CTRL_FBDIV, vcu_pll_ctrl);
-
-       return div * parent_rate;
-}
-
-static int xvcu_pll_set_rate(struct clk_hw *hw,
-                            unsigned long rate, unsigned long parent_rate)
-{
-       struct vcu_pll *pll = to_vcu_pll(hw);
-
-       return xvcu_pll_set_div(pll, rate / parent_rate);
-}
-
-static int xvcu_pll_enable(struct clk_hw *hw)
-{
-       struct vcu_pll *pll = to_vcu_pll(hw);
-       void __iomem *base = pll->reg_base;
-       u32 vcu_pll_ctrl;
-       int ret;
-
-       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
-       vcu_pll_ctrl |= VCU_PLL_CTRL_BYPASS;
-       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
-
-       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
-       vcu_pll_ctrl &= ~VCU_PLL_CTRL_POR_IN;
-       vcu_pll_ctrl &= ~VCU_PLL_CTRL_PWR_POR;
-       vcu_pll_ctrl &= ~VCU_PLL_CTRL_RESET;
-       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
-
-       ret = xvcu_pll_wait_for_lock(pll);
-       if (ret) {
-               pr_err("VCU PLL is not locked\n");
-               goto err;
-       }
-
-       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
-       vcu_pll_ctrl &= ~VCU_PLL_CTRL_BYPASS;
-       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
-
-err:
-       return ret;
-}
-
-static void xvcu_pll_disable(struct clk_hw *hw)
-{
-       struct vcu_pll *pll = to_vcu_pll(hw);
-       void __iomem *base = pll->reg_base;
-       u32 vcu_pll_ctrl;
-
-       vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
-       vcu_pll_ctrl |= VCU_PLL_CTRL_POR_IN;
-       vcu_pll_ctrl |= VCU_PLL_CTRL_PWR_POR;
-       vcu_pll_ctrl |= VCU_PLL_CTRL_RESET;
-       xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
-}
-
-static const struct clk_ops vcu_pll_ops = {
-       .enable = xvcu_pll_enable,
-       .disable = xvcu_pll_disable,
-       .round_rate = xvcu_pll_round_rate,
-       .recalc_rate = xvcu_pll_recalc_rate,
-       .set_rate = xvcu_pll_set_rate,
-};
-
-static struct clk_hw *xvcu_register_pll(struct device *dev,
-                                       void __iomem *reg_base,
-                                       const char *name, const char *parent,
-                                       unsigned long flags)
-{
-       struct vcu_pll *pll;
-       struct clk_hw *hw;
-       struct clk_init_data init;
-       int ret;
-
-       init.name = name;
-       init.parent_names = &parent;
-       init.ops = &vcu_pll_ops;
-       init.num_parents = 1;
-       init.flags = flags;
-
-       pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL);
-       if (!pll)
-               return ERR_PTR(-ENOMEM);
-
-       pll->hw.init = &init;
-       pll->reg_base = reg_base;
-       pll->fvco_min = FVCO_MIN;
-       pll->fvco_max = FVCO_MAX;
-
-       hw = &pll->hw;
-       ret = devm_clk_hw_register(dev, hw);
-       if (ret)
-               return ERR_PTR(ret);
-
-       clk_hw_set_rate_range(hw, pll->fvco_min, pll->fvco_max);
-
-       return hw;
-}
-
-static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev,
-                                               const char *name,
-                                               const struct clk_parent_data *parent_data,
-                                               u8 num_parents,
-                                               void __iomem *reg)
-{
-       u8 mux_flags = CLK_MUX_ROUND_CLOSEST;
-       u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
-                          CLK_DIVIDER_ROUND_CLOSEST;
-       struct clk_hw *mux = NULL;
-       struct clk_hw *divider = NULL;
-       struct clk_hw *gate = NULL;
-       char *name_mux;
-       char *name_div;
-       int err;
-       /* Protect register shared by clocks */
-       spinlock_t *lock;
-
-       lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL);
-       if (!lock)
-               return ERR_PTR(-ENOMEM);
-       spin_lock_init(lock);
-
-       name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux");
-       if (!name_mux)
-               return ERR_PTR(-ENOMEM);
-       mux = clk_hw_register_mux_parent_data(dev, name_mux,
-                                             parent_data, num_parents,
-                                             CLK_SET_RATE_PARENT,
-                                             reg, 0, 1, mux_flags, lock);
-       if (IS_ERR(mux))
-               return mux;
-
-       name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div");
-       if (!name_div) {
-               err = -ENOMEM;
-               goto unregister_mux;
-       }
-       divider = clk_hw_register_divider_parent_hw(dev, name_div, mux,
-                                                   CLK_SET_RATE_PARENT,
-                                                   reg, 4, 6, divider_flags,
-                                                   lock);
-       if (IS_ERR(divider)) {
-               err = PTR_ERR(divider);
-               goto unregister_mux;
-       }
-
-       gate = clk_hw_register_gate_parent_hw(dev, name, divider,
-                                             CLK_SET_RATE_PARENT, reg, 12, 0,
-                                             lock);
-       if (IS_ERR(gate)) {
-               err = PTR_ERR(gate);
-               goto unregister_divider;
-       }
-
-       return gate;
-
-unregister_divider:
-       clk_hw_unregister_divider(divider);
-unregister_mux:
-       clk_hw_unregister_mux(mux);
-
-       return ERR_PTR(err);
-}
-
-static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw)
-{
-       struct clk_hw *gate = hw;
-       struct clk_hw *divider;
-       struct clk_hw *mux;
-
-       if (!gate)
-               return;
-
-       divider = clk_hw_get_parent(gate);
-       clk_hw_unregister_gate(gate);
-       if (!divider)
-               return;
-
-       mux = clk_hw_get_parent(divider);
-       clk_hw_unregister_mux(mux);
-       if (!divider)
-               return;
-
-       clk_hw_unregister_divider(divider);
-}
-
-static int xvcu_register_clock_provider(struct xvcu_device *xvcu)
-{
-       struct device *dev = xvcu->dev;
-       struct clk_parent_data parent_data[2] = { 0 };
-       struct clk_hw_onecell_data *data;
-       struct clk_hw **hws;
-       struct clk_hw *hw;
-       void __iomem *reg_base = xvcu->vcu_slcr_ba;
-
-       data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       data->num = CLK_XVCU_NUM_CLOCKS;
-       hws = data->hws;
-
-       xvcu->clk_data = data;
-
-       hw = xvcu_register_pll(dev, reg_base,
-                              "vcu_pll", __clk_get_name(xvcu->pll_ref),
-                              CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE);
-       if (IS_ERR(hw))
-               return PTR_ERR(hw);
-       xvcu->pll = hw;
-
-       hw = xvcu_register_pll_post(dev, "vcu_pll_post", xvcu->pll, reg_base);
-       if (IS_ERR(hw))
-               return PTR_ERR(hw);
-       xvcu->pll_post = hw;
-
-       parent_data[0].fw_name = "pll_ref";
-       parent_data[1].hw = xvcu->pll_post;
-
-       hws[CLK_XVCU_ENC_CORE] =
-               xvcu_clk_hw_register_leaf(dev, "venc_core_clk",
-                                         parent_data,
-                                         ARRAY_SIZE(parent_data),
-                                         reg_base + VCU_ENC_CORE_CTRL);
-       hws[CLK_XVCU_ENC_MCU] =
-               xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk",
-                                         parent_data,
-                                         ARRAY_SIZE(parent_data),
-                                         reg_base + VCU_ENC_MCU_CTRL);
-       hws[CLK_XVCU_DEC_CORE] =
-               xvcu_clk_hw_register_leaf(dev, "vdec_core_clk",
-                                         parent_data,
-                                         ARRAY_SIZE(parent_data),
-                                         reg_base + VCU_DEC_CORE_CTRL);
-       hws[CLK_XVCU_DEC_MCU] =
-               xvcu_clk_hw_register_leaf(dev, "vdec_mcu_clk",
-                                         parent_data,
-                                         ARRAY_SIZE(parent_data),
-                                         reg_base + VCU_DEC_MCU_CTRL);
-
-       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
-}
-
-static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu)
-{
-       struct clk_hw_onecell_data *data = xvcu->clk_data;
-       struct clk_hw **hws = data->hws;
-
-       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_MCU]))
-               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_MCU]);
-       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_CORE]))
-               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_CORE]);
-       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU]))
-               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]);
-       if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE]))
-               xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]);
-
-       clk_hw_unregister_fixed_factor(xvcu->pll_post);
-}
-
-/**
- * xvcu_probe - Probe existence of the logicoreIP
- *                     and initialize PLL
- *
- * @pdev:      Pointer to the platform_device structure
- *
- * Return:     Returns 0 on success
- *             Negative error code otherwise
- */
-static int xvcu_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       struct xvcu_device *xvcu;
-       void __iomem *regs;
-       int ret;
-
-       xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL);
-       if (!xvcu)
-               return -ENOMEM;
-
-       xvcu->dev = &pdev->dev;
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr");
-       if (!res) {
-               dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n");
-               return -ENODEV;
-       }
-
-       xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start,
-                                        resource_size(res));
-       if (!xvcu->vcu_slcr_ba) {
-               dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n");
-               return -ENOMEM;
-       }
-
-       xvcu->logicore_reg_ba =
-               syscon_regmap_lookup_by_compatible("xlnx,vcu-settings");
-       if (IS_ERR(xvcu->logicore_reg_ba)) {
-               dev_info(&pdev->dev,
-                        "could not find xlnx,vcu-settings: trying direct register access\n");
-
-               res = platform_get_resource_byname(pdev,
-                                                  IORESOURCE_MEM, "logicore");
-               if (!res) {
-                       dev_err(&pdev->dev, "get logicore memory resource failed.\n");
-                       return -ENODEV;
-               }
-
-               regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-               if (!regs) {
-                       dev_err(&pdev->dev, "logicore register mapping failed.\n");
-                       return -ENOMEM;
-               }
-
-               xvcu->logicore_reg_ba =
-                       devm_regmap_init_mmio(&pdev->dev, regs,
-                                             &vcu_settings_regmap_config);
-               if (IS_ERR(xvcu->logicore_reg_ba)) {
-                       dev_err(&pdev->dev, "failed to init regmap\n");
-                       return PTR_ERR(xvcu->logicore_reg_ba);
-               }
-       }
-
-       xvcu->aclk = devm_clk_get(&pdev->dev, "aclk");
-       if (IS_ERR(xvcu->aclk)) {
-               dev_err(&pdev->dev, "Could not get aclk clock\n");
-               return PTR_ERR(xvcu->aclk);
-       }
-
-       xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
-       if (IS_ERR(xvcu->pll_ref)) {
-               dev_err(&pdev->dev, "Could not get pll_ref clock\n");
-               return PTR_ERR(xvcu->pll_ref);
-       }
-
-       ret = clk_prepare_enable(xvcu->aclk);
-       if (ret) {
-               dev_err(&pdev->dev, "aclk clock enable failed\n");
-               return ret;
-       }
-
-       /*
-        * Do the Gasket isolation and put the VCU out of reset
-        * Bit 0 : Gasket isolation
-        * Bit 1 : put VCU out of reset
-        */
-       regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE);
-
-       ret = xvcu_register_clock_provider(xvcu);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register clock provider\n");
-               goto error_clk_provider;
-       }
-
-       dev_set_drvdata(&pdev->dev, xvcu);
-
-       return 0;
-
-error_clk_provider:
-       xvcu_unregister_clock_provider(xvcu);
-       clk_disable_unprepare(xvcu->aclk);
-       return ret;
-}
-
-/**
- * xvcu_remove - Insert gasket isolation
- *                     and disable the clock
- * @pdev:      Pointer to the platform_device structure
- *
- * Return:     Returns 0 on success
- *             Negative error code otherwise
- */
-static int xvcu_remove(struct platform_device *pdev)
-{
-       struct xvcu_device *xvcu;
-
-       xvcu = platform_get_drvdata(pdev);
-       if (!xvcu)
-               return -ENODEV;
-
-       xvcu_unregister_clock_provider(xvcu);
-
-       /* Add the Gasket isolation and put the VCU in reset. */
-       regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
-
-       clk_disable_unprepare(xvcu->aclk);
-
-       return 0;
-}
-
-static const struct of_device_id xvcu_of_id_table[] = {
-       { .compatible = "xlnx,vcu" },
-       { .compatible = "xlnx,vcu-logicoreip-1.0" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, xvcu_of_id_table);
-
-static struct platform_driver xvcu_driver = {
-       .driver = {
-               .name           = "xilinx-vcu",
-               .of_match_table = xvcu_of_id_table,
-       },
-       .probe                  = xvcu_probe,
-       .remove                 = xvcu_remove,
-};
-
-module_platform_driver(xvcu_driver);
-
-MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>");
-MODULE_DESCRIPTION("Xilinx VCU init Driver");
-MODULE_LICENSE("GPL v2");