diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h
index a9481a5fea..fa921a9f08 100644
--- a/arch/arm/include/asm/arch-mx6/clock.h
+++ b/arch/arm/include/asm/arch-mx6/clock.h
@@ -21,6 +21,50 @@
 #define MXC_CLK32	32768
 #endif
 
+/**
+ * struct imx6_clk_gate - imx6 ccm clock gate
+ *
+ * @off:	ccm gate offset
+ * @bit:	ccm gate bit
+ */
+struct imx6_clk_gate {
+	u16 off;
+	u32 bit;
+};
+
+#define GATE(_off, _bit) {			\
+	.off = _off,				\
+	.bit = _bit,				\
+}
+
+/**
+ * struct imx6_clk_desc - imx6 clock control module descriptor
+ *
+ * @gates:	ccm clock gates
+ */
+struct imx6_clk_desc {
+	const struct imx6_clk_gate *gates;
+};
+
+/**
+ * struct imx6_clk_priv - imx6 clock control module
+ *
+ * @base:	ccm base address
+ * @desc:	ccm descriptor
+ */
+struct imx6_clk_priv {
+	void *base;
+	const struct imx6_clk_desc *desc;
+};
+
+/**
+ * imx6_clk_probe - common imx6 clock probe
+ * @dev:	clock device
+ */
+int imx6_clk_probe(struct udevice *dev);
+
+extern struct clk_ops imx6_clk_ops;
+
 enum mxc_clock {
 	MXC_ARM_CLK = 0,
 	MXC_PER_CLK,
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index a125c23a19..f81903dcf4 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -1,6 +1,6 @@
 config CLK_IMX
 	bool "Clock support for i.MX SoCs"
-	depends on CLK && ARCH_IMX8
+	depends on CLK && (ARCH_MX6 || ARCH_IMX8)
 	default y
 	help
 	  This enables support for common clock driver API on i.MX
@@ -8,6 +8,13 @@ config CLK_IMX
 
 if CLK_IMX
 
+config CLK_IMX6Q
+	bool "Clock driver for i.MX6QDL"
+	default MX6QDL
+	help
+	  This enables common clock driver support for platforms based
+	  on i.MX6 QDL SoC.
+
 config CLK_IMX8
 	bool "Clock support for i.MX8"
 	default ARCH_IMX8
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 5505ae52e2..a4cb2bbf3b 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -2,4 +2,9 @@
 #
 # SPDX-License-Identifier: GPL-2.0
 
+ifdef CONFIG_ARCH_MX6
+obj-$(CONFIG_CLK_IMX) += clk-imx6-common.o
+endif
+
+obj-$(CONFIG_CLK_IMX6Q) += clk-imx6q.o
 obj-$(CONFIG_CLK_IMX8) += clk-imx8.o
diff --git a/drivers/clk/imx/clk-imx6-common.c b/drivers/clk/imx/clk-imx6-common.c
new file mode 100644
index 0000000000..1d38f51f7e
--- /dev/null
+++ b/drivers/clk/imx/clk-imx6-common.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <linux/log2.h>
+
+static const struct imx6_clk_gate *priv_to_gate(struct imx6_clk_priv *priv,
+						unsigned long id)
+{
+	return &priv->desc->gates[id];
+}
+
+static int imx6_set_gate(struct clk *clk, bool on)
+{
+	struct imx6_clk_priv *priv = dev_get_priv(clk->dev);
+	const struct imx6_clk_gate *gate = priv_to_gate(priv, clk->id);
+	u32 reg;
+
+	debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
+	      clk->id, gate->off, ilog2(gate->bit));
+
+	reg = readl(priv->base + gate->off);
+	if (on)
+		reg |= gate->bit;
+	else
+		reg &= ~gate->bit;
+
+	writel(reg, priv->base + gate->off);
+
+	return 0;
+}
+
+static int imx6_clk_enable(struct clk *clk)
+{
+	return imx6_set_gate(clk, true);
+}
+
+static int imx6_clk_disable(struct clk *clk)
+{
+	return imx6_set_gate(clk, false);
+}
+
+struct clk_ops imx6_clk_ops = {
+	.enable = imx6_clk_enable,
+	.disable = imx6_clk_disable,
+};
+
+int imx6_clk_probe(struct udevice *dev)
+{
+	struct imx6_clk_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->desc = (const struct imx6_clk_desc *)dev_get_driver_data(dev);
+	if (!priv->desc)
+		return -EINVAL;
+
+	return 0;
+}
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
new file mode 100644
index 0000000000..8ec713298d
--- /dev/null
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <asm/arch/clock.h>
+#include <dt-bindings/clock/imx6qdl-clock.h>
+
+static const struct imx6_clk_gate imx6q_gates[] = {
+	[IMX6QDL_CLK_USDHC1]		= GATE(0x080, GENMASK(3, 2)),
+	[IMX6QDL_CLK_USDHC2]		= GATE(0x080, GENMASK(5, 4)),
+	[IMX6QDL_CLK_USDHC3]		= GATE(0x080, GENMASK(7, 6)),
+	[IMX6QDL_CLK_USDHC4]		= GATE(0x080, GENMASK(9, 8)),
+};
+
+static const struct imx6_clk_desc imx6q_clk_desc = {
+	.gates = imx6q_gates,
+};
+
+static const struct udevice_id clk_imx6q_ids[] = {
+	{
+	  .compatible = "fsl,imx6q-ccm",
+	  .data = (ulong)&imx6q_clk_desc
+	},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(clk_imx6q) = {
+	.name		= "clk_imx6q",
+	.id		= UCLASS_CLK,
+	.of_match	= clk_imx6q_ids,
+	.priv_auto_alloc_size	= sizeof(struct imx6_clk_priv),
+	.ops		= &imx6_clk_ops,
+	.probe		= imx6_clk_probe,
+};
