[3/5] arm/dt: mx51: dynamically add clocks per dt nodes

Message ID 1300108722-3254-4-git-send-email-shawn.guo@linaro.org
State New
Headers show

Commit Message

Shawn Guo March 14, 2011, 1:18 p.m.
This patch is to change the static clock creating and registering to
the dynamic way, which scans dt clock nodes, associate clk with
device_node, and then add them to clkdev accordingly.

It's a pretty straight translation from non-dt clock code to dt one,
and it does not really change any actual clock code.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/mach-mx5/clock-mx51-mx53.c | 1401 ++++++++++++++++++++++++++++++++++-
 1 files changed, 1387 insertions(+), 14 deletions(-)

Comments

Grant Likely March 15, 2011, 7:48 a.m. | #1
On Mon, Mar 14, 2011 at 09:18:40PM +0800, Shawn Guo wrote:
> This patch is to change the static clock creating and registering to
> the dynamic way, which scans dt clock nodes, associate clk with
> device_node, and then add them to clkdev accordingly.
> 
> It's a pretty straight translation from non-dt clock code to dt one,
> and it does not really change any actual clock code.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  arch/arm/mach-mx5/clock-mx51-mx53.c | 1401 ++++++++++++++++++++++++++++++++++-
>  1 files changed, 1387 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
> index dedb7f9..c3ec7f6 100644
> --- a/arch/arm/mach-mx5/clock-mx51-mx53.c
> +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
> @@ -49,6 +49,30 @@ static struct clk emi_fast_clk;
>  static struct clk ipu_clk;
>  static struct clk mipi_hsc1_clk;
>  
> +#ifdef CONFIG_OF
> +/*
> + * The pointers are defined to save the references to the clocks
> + * dynamically created, and then could be used to replace those
> + * static references in non-dt clock code.
> + */
> +static struct clk *osc_clk_dt;
> +static struct clk *pll1_main_clk_dt;
> +static struct clk *pll1_sw_clk_dt;
> +static struct clk *pll2_sw_clk_dt;
> +static struct clk *pll3_sw_clk_dt;
> +static struct clk *lp_apm_clk_dt;
> +static struct clk *periph_apm_clk_dt;
> +static struct clk *main_bus_clk_dt;
> +static struct clk *ipg_clk_dt;
> +static struct clk *ipg_per_clk_dt;
> +static struct clk *cpu_clk_dt;
> +static struct clk *iim_clk_dt;
> +static struct clk *usboh3_clk_dt;
> +static struct clk *usb_phy1_clk_dt;
> +static struct clk *esdhc1_clk_dt;
> +static struct clk *esdhc2_clk_dt;
> +#endif

Heh, yeah this seems sub-optimal.  It would be better to share common
clock initialization between dt and non-dt boards, even if it means
that a lot of the clocks are node described in the device tree (at
least for the on-chip SoC clocks; board-accessible clocks still need
to appear in the device tree though.

> +
>  #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
>  
>  /* calculate best pre and post dividers to get the required divider */
> @@ -163,10 +187,18 @@ static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
>  	return NULL;
>  }
>  
> +#ifdef CONFIG_OF
> +static void __iomem *dt_mx51_get_pll_base(struct clk *pll);
> +#endif
> +
>  static inline void __iomem *_get_pll_base(struct clk *pll)
>  {
>  	if (cpu_is_mx51())
> +#ifdef CONFIG_OF
> +		return dt_mx51_get_pll_base(pll);
> +#else
>  		return _mx51_get_pll_base(pll);
> +#endif

If you do it this way, you need to make sure dt_mx51_get_pll_base()
falls back to _mx51_get_pll_base() when a dt is not provided.

g.
Shawn Guo March 16, 2011, 2:08 p.m. | #2
On Tue, Mar 15, 2011 at 01:48:08AM -0600, Grant Likely wrote:
> On Mon, Mar 14, 2011 at 09:18:40PM +0800, Shawn Guo wrote:
> > This patch is to change the static clock creating and registering to
> > the dynamic way, which scans dt clock nodes, associate clk with
> > device_node, and then add them to clkdev accordingly.
> > 
> > It's a pretty straight translation from non-dt clock code to dt one,
> > and it does not really change any actual clock code.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > ---
> >  arch/arm/mach-mx5/clock-mx51-mx53.c | 1401 ++++++++++++++++++++++++++++++++++-
> >  1 files changed, 1387 insertions(+), 14 deletions(-)
> > 
> > diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
> > index dedb7f9..c3ec7f6 100644
> > --- a/arch/arm/mach-mx5/clock-mx51-mx53.c
> > +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
> > @@ -49,6 +49,30 @@ static struct clk emi_fast_clk;
> >  static struct clk ipu_clk;
> >  static struct clk mipi_hsc1_clk;
> >  
> > +#ifdef CONFIG_OF
> > +/*
> > + * The pointers are defined to save the references to the clocks
> > + * dynamically created, and then could be used to replace those
> > + * static references in non-dt clock code.
> > + */
> > +static struct clk *osc_clk_dt;
> > +static struct clk *pll1_main_clk_dt;
> > +static struct clk *pll1_sw_clk_dt;
> > +static struct clk *pll2_sw_clk_dt;
> > +static struct clk *pll3_sw_clk_dt;
> > +static struct clk *lp_apm_clk_dt;
> > +static struct clk *periph_apm_clk_dt;
> > +static struct clk *main_bus_clk_dt;
> > +static struct clk *ipg_clk_dt;
> > +static struct clk *ipg_per_clk_dt;
> > +static struct clk *cpu_clk_dt;
> > +static struct clk *iim_clk_dt;
> > +static struct clk *usboh3_clk_dt;
> > +static struct clk *usb_phy1_clk_dt;
> > +static struct clk *esdhc1_clk_dt;
> > +static struct clk *esdhc2_clk_dt;
> > +#endif
> 
> Heh, yeah this seems sub-optimal.  It would be better to share common
> clock initialization between dt and non-dt boards, even if it means
> that a lot of the clocks are node described in the device tree (at
> least for the on-chip SoC clocks; board-accessible clocks still need
> to appear in the device tree though.
> 
I do not understand the above comment.  These are not statically
defining 'struct clk' but the pointers to them.  They are used to
solve the references to static 'clk' in existing code, since all clk
are created dynamically in dt code.

Patch

diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index dedb7f9..c3ec7f6 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -49,6 +49,30 @@  static struct clk emi_fast_clk;
 static struct clk ipu_clk;
 static struct clk mipi_hsc1_clk;
 
+#ifdef CONFIG_OF
+/*
+ * The pointers are defined to save the references to the clocks
+ * dynamically created, and then could be used to replace those
+ * static references in non-dt clock code.
+ */
+static struct clk *osc_clk_dt;
+static struct clk *pll1_main_clk_dt;
+static struct clk *pll1_sw_clk_dt;
+static struct clk *pll2_sw_clk_dt;
+static struct clk *pll3_sw_clk_dt;
+static struct clk *lp_apm_clk_dt;
+static struct clk *periph_apm_clk_dt;
+static struct clk *main_bus_clk_dt;
+static struct clk *ipg_clk_dt;
+static struct clk *ipg_per_clk_dt;
+static struct clk *cpu_clk_dt;
+static struct clk *iim_clk_dt;
+static struct clk *usboh3_clk_dt;
+static struct clk *usb_phy1_clk_dt;
+static struct clk *esdhc1_clk_dt;
+static struct clk *esdhc2_clk_dt;
+#endif
+
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
 /* calculate best pre and post dividers to get the required divider */
@@ -163,10 +187,18 @@  static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
 	return NULL;
 }
 
+#ifdef CONFIG_OF
+static void __iomem *dt_mx51_get_pll_base(struct clk *pll);
+#endif
+
 static inline void __iomem *_get_pll_base(struct clk *pll)
 {
 	if (cpu_is_mx51())
+#ifdef CONFIG_OF
+		return dt_mx51_get_pll_base(pll);
+#else
 		return _mx51_get_pll_base(pll);
+#endif
 	else
 		return _mx53_get_pll_base(pll);
 }
@@ -1037,6 +1069,22 @@  static unsigned long clk_##name##_get_rate(struct clk *clk)		\
 			(pred + 1) * (podf + 1));			\
 }
 
+#ifdef CONFIG_OF
+#define CLK_SET_PARENT(name, nr, bitsname)				\
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	u32 reg, mux;							\
+									\
+	mux = _get_mux(parent, pll1_sw_clk_dt, pll2_sw_clk_dt,		\
+			pll3_sw_clk_dt, lp_apm_clk_dt);			\
+	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
+		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
+	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
+									\
+	return 0;							\
+}
+#else
 #define CLK_SET_PARENT(name, nr, bitsname)				\
 static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
 {									\
@@ -1051,6 +1099,7 @@  static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
 									\
 	return 0;							\
 }
+#endif
 
 #define CLK_SET_RATE(name, nr, bitsname)				\
 static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
@@ -1439,37 +1488,1361 @@  int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 	return 0;
 }
 
+/*
+ * Dynamically create and register clks per dt nodes
+ */
 #ifdef CONFIG_OF
-static struct clk *mx5_dt_clk_get(struct device_node *np,
-					const char *output_id, void *data)
+static inline void __iomem *dt_mx51_get_pll_base(struct clk *pll)
+{
+	if (pll == pll1_main_clk_dt)
+		return MX51_DPLL1_BASE;
+	else if (pll == pll2_sw_clk_dt)
+		return MX51_DPLL2_BASE;
+	else if (pll == pll3_sw_clk_dt)
+		return MX51_DPLL3_BASE;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static unsigned long dt_clk_pll1_sw_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	if (clk->parent == pll2_sw_clk_dt) {
+		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
+		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
+	} else if (clk->parent == pll3_sw_clk_dt) {
+		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
+		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
+	} else
+		div = 1;
+	return parent_rate / div;
+}
+
+static int dt_clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, step;
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	/* When switching from pll_main_clk to a bypass clock, first select a
+	 * multiplexed clock in 'step_sel', then shift the glitchless mux
+	 * 'pll1_sw_clk_sel'.
+	 *
+	 * When switching back, do it in reverse order
+	 */
+	if (parent == pll1_main_clk_dt) {
+		/* Switch to pll1_main_clk */
+		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+		__raw_writel(reg, MXC_CCM_CCSR);
+		/* step_clk mux switched to lp_apm, to save power. */
+		reg = __raw_readl(MXC_CCM_CCSR);
+		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
+				MXC_CCM_CCSR_STEP_SEL_OFFSET);
+	} else {
+		if (parent == lp_apm_clk_dt) {
+			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
+		} else  if (parent == pll2_sw_clk_dt) {
+			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
+		} else  if (parent == pll3_sw_clk_dt) {
+			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
+		} else
+			return -EINVAL;
+
+		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+		reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+
+		__raw_writel(reg, MXC_CCM_CCSR);
+		/* Switch to step_clk */
+		reg = __raw_readl(MXC_CCM_CCSR);
+		reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+	}
+	__raw_writel(reg, MXC_CCM_CCSR);
+	return 0;
+}
+
+static int dt_clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
 {
-	return data;
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	if (parent == pll2_sw_clk_dt)
+		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+	else
+		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+
+	__raw_writel(reg, MXC_CCM_CCSR);
+	return 0;
 }
 
-static __init void mx5_dt_scan_clks(void)
+static int dt_clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	if (parent == osc_clk_dt)
+		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
+	else
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CCSR);
+
+	return 0;
+}
+
+static int dt_clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, mux;
+	int i = 0;
+
+	mux = _get_mux(parent, pll1_sw_clk_dt, pll3_sw_clk_dt, lp_apm_clk_dt, NULL);
+
+	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
+	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCMR);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(MXC_CCM_CDHIPR);
+		if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: Set parent for periph_apm clock failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dt_clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+
+	if (parent == pll2_sw_clk_dt)
+		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+	else if (parent == periph_apm_clk_dt)
+		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+	else
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	return 0;
+}
+
+static int dt_clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CBCMR);
+
+	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+
+	if (parent == ipg_clk_dt)
+		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+	else if (parent == lp_apm_clk_dt)
+		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+	else if (parent != main_bus_clk_dt)
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CBCMR);
+
+	return 0;
+}
+
+static int dt_clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+
+	if (parent == pll3_sw_clk_dt)
+		reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
+
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+#define ALLOC_CLK_LOOKUP()						\
+	struct clk_lookup *cl;						\
+	struct clk *clk;						\
+	const char *dev_id;						\
+	int ret;							\
+									\
+	do {								\
+		cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);	\
+		if (!cl)						\
+			return -ENOMEM;					\
+		clk = (struct clk *) (cl + 1);				\
+									\
+		dev_id = of_get_property(node,				\
+				"clock-outputs", NULL);			\
+		if (!dev_id) {						\
+			ret = -EINVAL;					\
+			goto out_kfree;					\
+		}							\
+									\
+		clk->parent = mx5_get_source_clk(node);			\
+		clk->secondary = mx5_get_source_clk(node);		\
+	} while (0)
+
+#define ADD_CLK_LOOKUP()						\
+	do {								\
+		node->data = clk;					\
+									\
+		cl->dev_id = dev_id;					\
+		cl->clk = clk;						\
+		clkdev_add(cl);						\
+									\
+		return 0;						\
+									\
+	out_kfree:							\
+		kfree(cl);						\
+		return ret;						\
+	} while (0)
+
+static unsigned long get_fixed_clk_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static __init int mx5_scan_fixed_clks(void)
 {
 	struct device_node *node;
+	struct clk_lookup *cl;
 	struct clk *clk;
-	const char *id;
-	int rc;
+	const __be32 *rate;
+	const char *dev_id;
+	int ret = 0;
+
+	for_each_compatible_node(node, NULL, "fixed-clock") {
+		cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+		if (!cl) {
+			ret = -ENOMEM;
+			break;
+		}
+		clk = (struct clk *) (cl + 1);
 
-	for_each_compatible_node(node, NULL, "clock") {
-		id = of_get_property(node, "clock-outputs", NULL);
-		if (!id)
+		dev_id = of_get_property(node, "clock-outputs", NULL);
+		if (!dev_id) {
+			kfree(cl);
 			continue;
+		}
 
-		clk = clk_get_sys(id, NULL);
-		if (IS_ERR(clk))
+		rate = of_get_property(node, "clock-frequency", NULL);
+		if (!rate) {
+			kfree(cl);
 			continue;
+		}
+		clk->rate = be32_to_cpu(*rate);
+		clk->get_rate = get_fixed_clk_rate;
+
+		if (!strcmp(node->name, "osc"))
+			osc_clk_dt = clk;
 
-		rc = of_clk_add_provider(node, mx5_dt_clk_get, clk);
-		if (rc)
-			pr_err("error adding fixed clk %s\n", node->name);
+		node->data = clk;
+
+		cl->dev_id = dev_id;
+		cl->clk = clk;
+		clkdev_add(cl);
 	}
+
+	return ret;
+}
+
+static struct clk *mx5_prop_name_to_clk(struct device_node *node,
+		const char *prop_name)
+{
+	struct device_node *provnode;
+	struct clk *clk;
+	const void *prop;
+	u32 provhandle;
+
+	prop = of_get_property(node, prop_name, NULL);
+	if (!prop)
+		return NULL;
+	provhandle = be32_to_cpup(prop);
+
+	provnode = of_find_node_by_phandle(provhandle);
+	if (!provnode)
+		return NULL;
+
+	clk = provnode->data;
+
+	of_node_put(provnode);
+
+	return clk;
+}
+
+static inline struct clk *mx5_get_source_clk(struct device_node *node)
+{
+	return mx5_prop_name_to_clk(node, "clock-source");
+}
+
+static inline struct clk *mx5_get_depend_clk(struct device_node *node)
+{
+	return mx5_prop_name_to_clk(node, "clock-depend");
+}
+
+static __init int mx5_add_dummy_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	node->data = clk;
+
+	cl->clk = clk;
+	clkdev_add(cl);
+
+	return 0;
+}
+
+static __init int mx5_add_usb_phy1_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+	clk->set_parent = dt_clk_usb_phy1_set_parent;
+
+	usb_phy1_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_usb_ahb_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_usboh3_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_usboh3_get_rate;
+	clk->set_parent = clk_usboh3_set_parent;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+
+	usboh3_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_mipi_hsp_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_hsc_enable;
+	clk->disable = _clk_hsc_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ipu_di_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR6;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG5_OFFSET :
+					MXC_CCM_CCGRx_CG6_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ipu_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = clk_ipu_enable;
+	clk->disable = clk_ipu_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ipu_sec_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_mipi_hsc_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG3_OFFSET :
+					MXC_CCM_CCGRx_CG4_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_mipi_esc_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_esdhc_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	if (id == 0) {
+		clk->enable_shift = MXC_CCM_CCGRx_CG1_OFFSET;
+		clk->get_rate = clk_esdhc1_get_rate;
+		clk->set_rate = clk_esdhc1_set_rate;
+		clk->set_parent = clk_esdhc1_set_parent;
+		esdhc1_clk_dt = clk;
+	} else {
+		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
+		clk->get_rate = clk_esdhc2_get_rate;
+		clk->set_rate = clk_esdhc2_set_rate;
+		clk->set_parent = clk_esdhc2_set_parent;
+		esdhc2_clk_dt = clk;
+	}
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_esdhc_ipg_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG0_OFFSET :
+					MXC_CCM_CCGRx_CG2_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_sdma_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ecspi_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG10_OFFSET :
+					MXC_CCM_CCGRx_CG12_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ecspi_ipg_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable_inrun;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG9_OFFSET :
+					MXC_CCM_CCGRx_CG11_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ecspi_main_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_ecspi_get_rate;
+	clk->set_parent = clk_ecspi_set_parent;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_cspi_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_cspi_ipg_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ssi_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+	}
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ssi_ipg_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
+	}
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_nfc_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+	clk->get_rate = clk_nfc_get_rate;
+	clk->set_rate = clk_nfc_set_rate;
+	clk->round_rate = clk_nfc_round_rate;
+	clk->set_parent = clk_nfc_set_parent;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_i2c_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
+	}
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_pwm_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG6_OFFSET :
+					MXC_CCM_CCGRx_CG8_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_fec_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_uart_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG4_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+	}
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_uart_root_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_uart_get_rate;
+	clk->set_parent = clk_uart_set_parent;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_uart_ipg_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
+	}
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_gpt_32k_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_gpt_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_gpt_ipg_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ahbmux1_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_aips_tz_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG12_OFFSET :
+					MXC_CCM_CCGRx_CG13_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ahb_max_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_iim_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+	iim_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_spba_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ipg_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_ipg_get_rate;
+
+	ipg_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ahb_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_ahb_get_rate;
+	clk->set_rate = _clk_ahb_set_rate;
+	clk->round_rate = _clk_ahb_round_rate;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_emi_slow_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+	clk->get_rate = clk_emi_slow_get_rate;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_main_bus_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->set_parent = dt_clk_main_bus_set_parent;
+
+	main_bus_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_emi_fast_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ddr_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ddr_hf_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = _clk_ddr_hf_get_rate;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_cpu_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_cpu_get_rate;
+	clk->set_rate = clk_cpu_set_rate;
+
+	cpu_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ipg_per_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_ipg_per_get_rate;
+	clk->set_parent = dt_clk_ipg_per_set_parent;
+
+	ipg_per_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_periph_apm_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->set_parent = dt_clk_periph_apm_set_parent;
+
+	periph_apm_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_lp_apm_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->set_parent = dt_clk_lp_apm_set_parent;
+
+	lp_apm_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_pll_switch_clk(struct device_node *node)
+{
+	const __be32 *reg;
+	int id;
+
+	ALLOC_CLK_LOOKUP();
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg) {
+		ret = -ENOENT;
+		goto out_kfree;
+	}
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2) {
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	clk->id = id;
+
+	switch (id) {
+	case 0:
+		clk->get_rate = dt_clk_pll1_sw_get_rate;
+		clk->set_parent = dt_clk_pll1_sw_set_parent;
+		pll1_sw_clk_dt = clk;
+		break;
+	case 1:
+		clk->get_rate = clk_pll_get_rate;
+		clk->set_rate = _clk_pll_set_rate;
+		clk->enable = _clk_pll_enable;
+		clk->disable = _clk_pll_disable;
+		clk->set_parent = dt_clk_pll2_sw_set_parent;
+		pll2_sw_clk_dt = clk;
+		break;
+	case 2:
+		clk->get_rate = clk_pll_get_rate;
+		clk->set_rate = _clk_pll_set_rate;
+		clk->enable = _clk_pll_enable;
+		clk->disable = _clk_pll_disable;
+		pll3_sw_clk_dt = clk;
+	}
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_pll1_main_clk(struct device_node *node)
+{
+	ALLOC_CLK_LOOKUP();
+
+	clk->get_rate = clk_pll_get_rate;
+	clk->enable = _clk_pll_enable;
+	clk->disable = _clk_pll_disable;
+
+	pll1_main_clk_dt = clk;
+
+	ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_dt_scan_clks(void)
+{
+	struct device_node *node;
+	int ret;
+
+	ret = mx5_scan_fixed_clks();
+	if (ret) {
+		pr_err("%s: fixed-clock failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	for_each_compatible_node(node, NULL, "fsl,mxc-clock") {
+		if (!strcmp(node->name, "pll1_main"))
+			ret = mx5_add_pll1_main_clk(node);
+		else if (!strcmp(node->name, "pll_switch"))
+			ret = mx5_add_pll_switch_clk(node);
+		else if (!strcmp(node->name, "lp_apm"))
+			ret = mx5_add_lp_apm_clk(node);
+		else if (!strcmp(node->name, "periph_apm"))
+			ret = mx5_add_periph_apm_clk(node);
+		else if (!strcmp(node->name, "ipg_per"))
+			ret = mx5_add_ipg_per_clk(node);
+		else if (!strcmp(node->name, "cpu"))
+			ret = mx5_add_cpu_clk(node);
+		else if (!strcmp(node->name, "ddr_hf"))
+			ret = mx5_add_ddr_hf_clk(node);
+		else if (!strcmp(node->name, "ddr"))
+			ret = mx5_add_ddr_clk(node);
+		else if (!strcmp(node->name, "emi_fast"))
+			ret = mx5_add_emi_fast_clk(node);
+		else if (!strcmp(node->name, "main_bus"))
+			ret = mx5_add_main_bus_clk(node);
+		else if (!strcmp(node->name, "emi_slow"))
+			ret = mx5_add_emi_slow_clk(node);
+		else if (!strcmp(node->name, "ahb"))
+			ret = mx5_add_ahb_clk(node);
+		else if (!strcmp(node->name, "ipg"))
+			ret = mx5_add_ipg_clk(node);
+		else if (!strcmp(node->name, "spba"))
+			ret = mx5_add_spba_clk(node);
+		else if (!strcmp(node->name, "iim"))
+			ret = mx5_add_iim_clk(node);
+		else if (!strcmp(node->name, "ahb_max"))
+			ret = mx5_add_ahb_max_clk(node);
+		else if (!strcmp(node->name, "aips_tz"))
+			ret = mx5_add_aips_tz_clk(node);
+		else if (!strcmp(node->name, "ahbmux1"))
+			ret = mx5_add_ahbmux1_clk(node);
+		else if (!strcmp(node->name, "gpt_ipg"))
+			ret = mx5_add_gpt_ipg_clk(node);
+		else if (!strcmp(node->name, "gpt"))
+			ret = mx5_add_gpt_clk(node);
+		else if (!strcmp(node->name, "gpt_32k"))
+			ret = mx5_add_gpt_32k_clk(node);
+		else if (!strcmp(node->name, "uart_ipg"))
+			ret = mx5_add_uart_ipg_clk(node);
+		else if (!strcmp(node->name, "uart_root"))
+			ret = mx5_add_uart_root_clk(node);
+		else if (!strcmp(node->name, "uart"))
+			ret = mx5_add_uart_clk(node);
+		else if (!strcmp(node->name, "fec"))
+			ret = mx5_add_fec_clk(node);
+		else if (!strcmp(node->name, "pwm"))
+			ret = mx5_add_pwm_clk(node);
+		else if (!strcmp(node->name, "i2c"))
+			ret = mx5_add_i2c_clk(node);
+		else if (!strcmp(node->name, "nfc"))
+			ret = mx5_add_nfc_clk(node);
+		else if (!strcmp(node->name, "ssi_ipg"))
+			ret = mx5_add_ssi_ipg_clk(node);
+		else if (!strcmp(node->name, "ssi"))
+			ret = mx5_add_ssi_clk(node);
+		else if (!strcmp(node->name, "cspi_ipg"))
+			ret = mx5_add_cspi_ipg_clk(node);
+		else if (!strcmp(node->name, "cspi"))
+			ret = mx5_add_cspi_clk(node);
+		else if (!strcmp(node->name, "ecspi_main"))
+			ret = mx5_add_ecspi_main_clk(node);
+		else if (!strcmp(node->name, "ecspi_ipg"))
+			ret = mx5_add_ecspi_ipg_clk(node);
+		else if (!strcmp(node->name, "ecspi"))
+			ret = mx5_add_ecspi_clk(node);
+		else if (!strcmp(node->name, "sdma"))
+			ret = mx5_add_sdma_clk(node);
+		else if (!strcmp(node->name, "esdhc_ipg"))
+			ret = mx5_add_esdhc_ipg_clk(node);
+		else if (!strcmp(node->name, "esdhc"))
+			ret = mx5_add_esdhc_clk(node);
+		else if (!strcmp(node->name, "mipi_esc"))
+			ret = mx5_add_mipi_esc_clk(node);
+		else if (!strcmp(node->name, "mipi_hsc"))
+			ret = mx5_add_mipi_hsc_clk(node);
+		else if (!strcmp(node->name, "ipu_sec"))
+			ret = mx5_add_ipu_sec_clk(node);
+		else if (!strcmp(node->name, "ipu"))
+			ret = mx5_add_ipu_clk(node);
+		else if (!strcmp(node->name, "ipu_di"))
+			ret = mx5_add_ipu_di_clk(node);
+		else if (!strcmp(node->name, "mipi_hsp"))
+			ret = mx5_add_mipi_hsp_clk(node);
+		else if (!strcmp(node->name, "usboh3"))
+			ret = mx5_add_usboh3_clk(node);
+		else if (!strcmp(node->name, "usb_ahb"))
+			ret = mx5_add_usb_ahb_clk(node);
+		else if (!strcmp(node->name, "usb_phy1"))
+			ret = mx5_add_usb_phy1_clk(node);
+		else if (!strcmp(node->name, "dummy"))
+			ret = mx5_add_dummy_clk(node);
+		else
+			pr_warn("%s: unknown clock node %s\n",
+				__func__, node->name);
+
+		if (ret) {
+			pr_err("%s: clock %s failed %d\n",
+				__func__, node->name, ret);
+			break;
+		}
+	}
+
+	return ret;
 }
 
 void __init mx5_clk_dt_init(void)
 {
+	u32 reg;
+
 	mx5_dt_scan_clks();
+
+	/* clk_tree_init(); */
+	clk_set_parent(ipg_per_clk_dt, lp_apm_clk_dt);
+
+	/*
+	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
+	 * 8MHz, its derived from lp_apm.
+	 *
+	 * FIXME: Verify if true for all boards
+	 */
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
+	reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	clk_enable(cpu_clk_dt);
+	clk_enable(main_bus_clk_dt);
+
+	clk_enable(iim_clk_dt);
+	mx51_revision();
+	clk_disable(iim_clk_dt);
+
+	/* move usb_phy_clk to 24MHz */
+	clk_set_parent(usb_phy1_clk_dt, osc_clk_dt);
+
+	/* set the usboh3_clk parent to pll2_sw_clk */
+	clk_set_parent(usboh3_clk_dt, pll2_sw_clk_dt);
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(esdhc1_clk_dt, pll2_sw_clk_dt);
+	clk_set_parent(esdhc2_clk_dt, pll2_sw_clk_dt);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(esdhc1_clk_dt, 166250000);
+	clk_set_rate(esdhc2_clk_dt, 166250000);
 }
 #endif