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 implementation.

Signed-off-by: Shawn Guo <shawn....@linaro.org>
---
 arch/arm/mach-mx5/Makefile          |    2 +-
 arch/arm/mach-mx5/clock-dt.c        |   52 --
 arch/arm/mach-mx5/clock-mx51-mx53.c | 1433 ++++++++++++++++++++++++++++++++++-
 3 files changed, 1410 insertions(+), 77 deletions(-)
 delete mode 100644 arch/arm/mach-mx5/clock-dt.c

diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index bd4542d..540697e 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -18,4 +18,4 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
 obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
-obj-$(CONFIG_MACH_MX51_DT) += board-dt.o clock-dt.o
+obj-$(CONFIG_MACH_MX51_DT) += board-dt.o
diff --git a/arch/arm/mach-mx5/clock-dt.c b/arch/arm/mach-mx5/clock-dt.c
deleted file mode 100644
index 9c04475..0000000
--- a/arch/arm/mach-mx5/clock-dt.c
+++ /dev/null
@@ -1,52 +0,0 @@
-
-/*
- * Copyright 2011 Linaro Ltd.
- * Jason Liu <jason....@linaro.org>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_clk.h>
-
-static struct clk *mx5_dt_clk_get(struct device_node *np,
-                                       const char *output_id, void *data)
-{
-       return data;
-}
-
-static __init void mx5_dt_scan_clks(void)
-{
-       struct device_node *node;
-       struct clk *clk;
-       const char *id;
-       int rc;
-
-       for_each_compatible_node(node, NULL, "clock") {
-               id = of_get_property(node, "clock-outputs", NULL);
-               if (!id)
-                       continue;
-
-               clk = clk_get_sys(id, NULL);
-               if (IS_ERR(clk))
-                       continue;
-
-               rc = of_clk_add_provider(node, mx5_dt_clk_get, clk);
-               if (rc)
-                       pr_err("error adding fixed clk %s\n", node->name);
-       }
-}
-
-void __init mx5_clk_dt_init(void)
-{
-       mx5_dt_scan_clks();
-}
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c 
b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 0a19e75..f5fdded 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -15,6 +15,10 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_clk.h>
 
 #include <asm/div64.h>
 
@@ -43,6 +47,28 @@ static struct clk emi_fast_clk;
 static struct clk ipu_clk;
 static struct clk mipi_hsc1_clk;
 
+/*
+ * The pointers are defined to unify the references to clocks, as clocks
+ * could also be created by dt code in a dynamic way besides the static
+ * way used in existing non-dt clock code.
+ */
+static struct clk *osc_clk_ptr;
+static struct clk *pll1_main_clk_ptr;
+static struct clk *pll1_sw_clk_ptr;
+static struct clk *pll2_sw_clk_ptr;
+static struct clk *pll3_sw_clk_ptr;
+static struct clk *lp_apm_clk_ptr;
+static struct clk *periph_apm_clk_ptr;
+static struct clk *main_bus_clk_ptr;
+static struct clk *ipg_clk_ptr;
+static struct clk *ipg_per_clk_ptr;
+static struct clk *cpu_clk_ptr;
+static struct clk *iim_clk_ptr;
+static struct clk *usboh3_clk_ptr;
+static struct clk *usb_phy1_clk_ptr;
+static struct clk *esdhc1_clk_ptr;
+static struct clk *esdhc2_clk_ptr;
+
 #define MAX_DPLL_WAIT_TRIES    1000 /* 1000 * udelay(1) = 1ms */
 
 /* calculate best pre and post dividers to get the required divider */
@@ -129,11 +155,11 @@ static inline u32 _get_mux(struct clk *parent, struct clk 
*m0,
 
 static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
 {
-       if (pll == &pll1_main_clk)
+       if (pll == pll1_main_clk_ptr)
                return MX51_DPLL1_BASE;
-       else if (pll == &pll2_sw_clk)
+       else if (pll == pll2_sw_clk_ptr)
                return MX51_DPLL2_BASE;
-       else if (pll == &pll3_sw_clk)
+       else if (pll == pll3_sw_clk_ptr)
                return MX51_DPLL3_BASE;
        else
                BUG();
@@ -310,7 +336,7 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, struct 
clk *parent)
         *
         * When switching back, do it in reverse order
         */
-       if (parent == &pll1_main_clk) {
+       if (parent == pll1_main_clk_ptr) {
                /* Switch to pll1_main_clk */
                reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
                __raw_writel(reg, MXC_CCM_CCSR);
@@ -320,11 +346,11 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, 
struct clk *parent)
                reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
                                MXC_CCM_CCSR_STEP_SEL_OFFSET);
        } else {
-               if (parent == &lp_apm_clk) {
+               if (parent == lp_apm_clk_ptr) {
                        step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
-               } else  if (parent == &pll2_sw_clk) {
+               } else  if (parent == pll2_sw_clk_ptr) {
                        step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
-               } else  if (parent == &pll3_sw_clk) {
+               } else  if (parent == pll3_sw_clk_ptr) {
                        step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
                } else
                        return -EINVAL;
@@ -350,10 +376,10 @@ static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
 
        reg = __raw_readl(MXC_CCM_CCSR);
 
-       if (clk->parent == &pll2_sw_clk) {
+       if (clk->parent == pll2_sw_clk_ptr) {
                div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
                       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
-       } else if (clk->parent == &pll3_sw_clk) {
+       } else if (clk->parent == pll3_sw_clk_ptr) {
                div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
                       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
        } else
@@ -367,7 +393,7 @@ static int _clk_pll2_sw_set_parent(struct clk *clk, struct 
clk *parent)
 
        reg = __raw_readl(MXC_CCM_CCSR);
 
-       if (parent == &pll2_sw_clk)
+       if (parent == pll2_sw_clk_ptr)
                reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
        else
                reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
@@ -380,7 +406,7 @@ static int _clk_lp_apm_set_parent(struct clk *clk, struct 
clk *parent)
 {
        u32 reg;
 
-       if (parent == &osc_clk)
+       if (parent == osc_clk_ptr)
                reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
        else
                return -EINVAL;
@@ -423,7 +449,8 @@ static int _clk_periph_apm_set_parent(struct clk *clk, 
struct clk *parent)
        u32 reg, mux;
        int i = 0;
 
-       mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+       mux = _get_mux(parent, pll1_sw_clk_ptr, pll3_sw_clk_ptr,
+                       lp_apm_clk_ptr, NULL);
 
        reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
        reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
@@ -452,9 +479,9 @@ static int _clk_main_bus_set_parent(struct clk *clk, struct 
clk *parent)
 
        reg = __raw_readl(MXC_CCM_CBCDR);
 
-       if (parent == &pll2_sw_clk)
+       if (parent == pll2_sw_clk_ptr)
                reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-       else if (parent == &periph_apm_clk)
+       else if (parent == periph_apm_clk_ptr)
                reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
        else
                return -EINVAL;
@@ -587,7 +614,7 @@ static unsigned long clk_ipg_per_get_rate(struct clk *clk)
 
        parent_rate = clk_get_rate(clk->parent);
 
-       if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+       if (clk->parent == main_bus_clk_ptr || clk->parent == lp_apm_clk_ptr) {
                /* the main_bus_clk is the one before the DVFS engine */
                reg = __raw_readl(MXC_CCM_CBCDR);
                prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
@@ -597,7 +624,7 @@ static unsigned long clk_ipg_per_get_rate(struct clk *clk)
                podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
                        MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
                return parent_rate / (prediv1 * prediv2 * podf);
-       } else if (clk->parent == &ipg_clk)
+       } else if (clk->parent == ipg_clk_ptr)
                return parent_rate;
        else
                BUG();
@@ -612,11 +639,11 @@ static int _clk_ipg_per_set_parent(struct clk *clk, 
struct clk *parent)
        reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
        reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
 
-       if (parent == &ipg_clk)
+       if (parent == ipg_clk_ptr)
                reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-       else if (parent == &lp_apm_clk)
+       else if (parent == lp_apm_clk_ptr)
                reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-       else if (parent != &main_bus_clk)
+       else if (parent != main_bus_clk_ptr)
                return -EINVAL;
 
        __raw_writel(reg, MXC_CCM_CBCMR);
@@ -830,7 +857,7 @@ static struct clk ipg_clk = {
        .get_rate = clk_ipg_get_rate,
 };
 
-static struct clk ipg_perclk = {
+static struct clk ipg_per_clk = {
        .parent = &lp_apm_clk,
        .get_rate = clk_ipg_per_get_rate,
        .set_parent = _clk_ipg_per_set_parent,
@@ -1036,8 +1063,9 @@ static int clk_##name##_set_parent(struct clk *clk, 
struct clk *parent)   \
 {                                                                      \
        u32 reg, mux;                                                   \
                                                                        \
-       mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,              \
-                       &pll3_sw_clk, &lp_apm_clk);                     \
+       mux = _get_mux(parent, pll1_sw_clk_ptr, pll2_sw_clk_ptr,        \
+                       pll3_sw_clk_ptr, lp_apm_clk_ptr);               \
+                                                                       \
        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;  \
@@ -1115,7 +1143,7 @@ static int clk_usb_phy1_set_parent(struct clk *clk, 
struct clk *parent)
 
        reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
 
-       if (parent == &pll3_sw_clk)
+       if (parent == pll3_sw_clk_ptr)
                reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
 
        __raw_writel(reg, MXC_CCM_CSCMR1);
@@ -1346,7 +1374,7 @@ static void clk_tree_init(void)
 {
        u32 reg;
 
-       ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+       clk_set_parent(ipg_per_clk_ptr, lp_apm_clk_ptr);
 
        /*
         * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
@@ -1367,6 +1395,27 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned 
long osc,
 {
        int i;
 
+       /*
+        * Save the clock pointers that could be referenced by
+        * both non-dt and dt clock codes later in this file.
+        */
+       osc_clk_ptr             = &osc_clk;
+       pll1_main_clk_ptr       = &pll1_main_clk;
+       pll1_sw_clk_ptr         = &pll1_sw_clk;
+       pll2_sw_clk_ptr         = &pll2_sw_clk;
+       pll3_sw_clk_ptr         = &pll3_sw_clk;
+       lp_apm_clk_ptr          = &lp_apm_clk;
+       periph_apm_clk_ptr      = &periph_apm_clk;
+       main_bus_clk_ptr        = &main_bus_clk;
+       ipg_clk_ptr             = &ipg_clk;
+       ipg_per_clk_ptr         = &ipg_per_clk;
+       cpu_clk_ptr             = &cpu_clk;
+       iim_clk_ptr             = &iim_clk;
+       usboh3_clk_ptr          = &usboh3_clk;
+       usb_phy1_clk_ptr        = &usb_phy1_clk;
+       esdhc1_clk_ptr          = &esdhc1_clk;
+       esdhc2_clk_ptr          = &esdhc2_clk;
+
        external_low_reference = ckil;
        external_high_reference = ckih1;
        ckih2_reference = ckih2;
@@ -1432,3 +1481,1339 @@ int __init mx53_clocks_init(unsigned long ckil, 
unsigned long osc,
                MX53_INT_GPT);
        return 0;
 }
+
+/*
+ * Dynamically create and register clks per dt nodes
+ */
+#ifdef CONFIG_OF
+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 __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);
+
+               dev_id = of_get_property(node, "clock-outputs", NULL);
+               if (!dev_id) {
+                       kfree(cl);
+                       continue;
+               }
+
+               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_ptr = clk;
+
+               node->clk = 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;
+       int sz;
+
+       prop = of_get_property(node, prop_name, &sz);
+       if (!prop || sz < 4)
+               goto out;
+
+       /* Extract the phandle from the start of the property value */
+       provhandle = be32_to_cpup(prop);
+       prop += 4;
+       sz -= 4;
+
+       /*
+        * Make sure the clock name is properly terminated and within the
+        * size of the property.
+        */
+       if (strlen(prop) + 1 > sz)
+               goto out;
+
+       provnode = of_find_node_by_phandle(provhandle);
+       if (!provnode)
+               goto out;
+
+       clk = provnode->clk;
+
+       of_node_put(provnode);
+
+       return clk;
+
+out:
+       pr_err("%s: failed to get %s of %s\n", __func__, prop_name, node->name);
+       return NULL;
+}
+
+static inline struct clk *mx5_get_source_clk(struct device_node *node)
+{
+       return mx5_prop_name_to_clk(node, "src-clock");
+}
+
+static inline struct clk *mx5_get_depend_clk(struct device_node *node)
+{
+       return mx5_prop_name_to_clk(node, "dep-clock");
+}
+
+static __init struct clk_lookup *mx5_pre_clk_lookup(struct device_node * node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+       if (cl) {
+               clk = (struct clk *) (cl + 1);
+               clk->parent = mx5_get_source_clk(node);
+               clk->secondary = mx5_get_source_clk(node);
+       }
+
+       return cl;
+}
+
+static __init int mx5_post_clk_lookup(struct clk_lookup *cl,
+                                     struct device_node *node)
+{
+       struct clk *clk;
+       const char *dev_id;
+
+       dev_id = of_get_property(node, "clock-outputs", NULL);
+       if (!dev_id) {
+               kfree(cl);
+               return -EINVAL;
+       }
+
+       clk = (struct clk *) (cl + 1);
+       node->clk = clk;
+
+       cl->dev_id = dev_id;
+       cl->clk = clk;
+       clkdev_add(cl);
+
+       return 0;
+}
+
+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->clk = clk;
+
+       cl->clk = clk;
+       clkdev_add(cl);
+
+       return 0;
+}
+
+static __init int mx5_add_usb_phy1_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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 = clk_usb_phy1_set_parent;
+
+       usb_phy1_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_usb_ahb_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR2;
+       clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_usboh3_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_hsp_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_hsc_enable;
+       clk->disable = _clk_hsc_disable;
+       clk->enable_reg = MXC_CCM_CCGR4;
+       clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_di_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = clk_ipu_enable;
+       clk->disable = clk_ipu_disable;
+       clk->enable_reg = MXC_CCM_CCGR5;
+       clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_sec_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_hsc_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_esc_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR4;
+       clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_esdhc_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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_ptr = 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_ptr = clk;
+       }
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_esdhc_ipg_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_sdma_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR4;
+       clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_ipg_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_main_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = clk_ecspi_get_rate;
+       clk->set_parent = clk_ecspi_set_parent;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cspi_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR4;
+       clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cspi_ipg_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR4;
+       clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ssi_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 2)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+       }
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ssi_ipg_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 2)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+       }
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_nfc_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_i2c_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 2)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+       }
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pwm_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_fec_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR2;
+       clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 2)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+       }
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_root_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = clk_uart_get_rate;
+       clk->set_parent = clk_uart_set_parent;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_ipg_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 2)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+       }
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_32k_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR2;
+       clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_ipg_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR2;
+       clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahbmux1_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_aips_tz_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 1)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahb_max_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_max_enable;
+       clk->disable = _clk_max_disable;
+       clk->enable_reg = MXC_CCM_CCGR0;
+       clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_iim_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable_reg = MXC_CCM_CCGR0;
+       clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+       iim_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_spba_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->enable = _clk_ccgr_enable;
+       clk->disable = _clk_ccgr_disable;
+       clk->enable_reg = MXC_CCM_CCGR5;
+       clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipg_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = clk_ipg_get_rate;
+
+       ipg_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahb_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = clk_ahb_get_rate;
+       clk->set_rate = _clk_ahb_set_rate;
+       clk->round_rate = _clk_ahb_round_rate;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_emi_slow_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_main_bus_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->set_parent = _clk_main_bus_set_parent;
+
+       main_bus_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_emi_fast_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       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;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ddr_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ddr_hf_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = _clk_ddr_hf_get_rate;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cpu_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = clk_cpu_get_rate;
+       clk->set_rate = clk_cpu_set_rate;
+
+       cpu_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipg_per_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = clk_ipg_per_get_rate;
+       clk->set_parent = _clk_ipg_per_set_parent;
+
+       ipg_per_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_periph_apm_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->set_parent = _clk_periph_apm_set_parent;
+
+       periph_apm_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_lp_apm_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->set_parent = _clk_lp_apm_set_parent;
+
+       lp_apm_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pll_switch_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+       const __be32 *reg;
+       int id;
+
+       reg = of_get_property(node, "reg", NULL);
+       if (!reg)
+               return -ENOENT;
+
+       id = be32_to_cpu(*reg);
+       if (id < 0 || id > 2)
+               return -EINVAL;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->id = id;
+
+       switch (id) {
+       case 0:
+               clk->get_rate = clk_pll1_sw_get_rate;
+               clk->set_parent = _clk_pll1_sw_set_parent;
+               pll1_sw_clk_ptr = 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 = _clk_pll2_sw_set_parent;
+               pll2_sw_clk_ptr = 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_ptr = clk;
+       }
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pll1_main_clk(struct device_node *node)
+{
+       struct clk_lookup *cl;
+       struct clk *clk;
+
+       cl = mx5_pre_clk_lookup(node);
+       if (!cl)
+               return -ENOMEM;
+       clk = (struct clk *) (cl + 1);
+
+       clk->get_rate = clk_pll_get_rate;
+       clk->enable = _clk_pll_enable;
+       clk->disable = _clk_pll_disable;
+
+       pll1_main_clk_ptr = clk;
+
+       return mx5_post_clk_lookup(cl, node);
+}
+
+#define MX5_CLK_COMP   "fsl,mxc-clock"
+
+static const struct of_device_id mx5_dt_mxc_clock_ids[] = {
+       { .name = "pll1_main",  .compatible = MX5_CLK_COMP, .data = 
mx5_add_pll1_main_clk },
+       { .name = "pll_switch", .compatible = MX5_CLK_COMP, .data = 
mx5_add_pll_switch_clk },
+       { .name = "lp_apm",     .compatible = MX5_CLK_COMP, .data = 
mx5_add_lp_apm_clk },
+       { .name = "periph_apm", .compatible = MX5_CLK_COMP, .data = 
mx5_add_periph_apm_clk },
+       { .name = "ipg_per",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_ipg_per_clk },
+       { .name = "cpu",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_cpu_clk },
+       { .name = "ddr_hf",     .compatible = MX5_CLK_COMP, .data = 
mx5_add_ddr_hf_clk },
+       { .name = "ddr",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_ddr_clk },
+       { .name = "emi_fast",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_emi_fast_clk },
+       { .name = "main_bus",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_main_bus_clk },
+       { .name = "emi_slow",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_emi_slow_clk },
+       { .name = "ahb",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_ahb_clk },
+       { .name = "ipg",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_ipg_clk },
+       { .name = "spba",       .compatible = MX5_CLK_COMP, .data = 
mx5_add_spba_clk },
+       { .name = "iim",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_iim_clk },
+       { .name = "ahb_max",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_ahb_max_clk },
+       { .name = "aips_tz",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_aips_tz_clk },
+       { .name = "ahbmux1",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_ahbmux1_clk },
+       { .name = "gpt_ipg",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_gpt_ipg_clk },
+       { .name = "gpt",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_gpt_clk },
+       { .name = "gpt_32k",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_gpt_32k_clk },
+       { .name = "uart_ipg",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_uart_ipg_clk },
+       { .name = "uart_root",  .compatible = MX5_CLK_COMP, .data = 
mx5_add_uart_root_clk },
+       { .name = "uart",       .compatible = MX5_CLK_COMP, .data = 
mx5_add_uart_clk },
+       { .name = "fec",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_fec_clk },
+       { .name = "pwm",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_pwm_clk },
+       { .name = "i2c",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_i2c_clk },
+       { .name = "nfc",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_nfc_clk },
+       { .name = "ssi_ipg",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_ssi_ipg_clk },
+       { .name = "ssi",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_ssi_clk },
+       { .name = "cspi_ipg",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_cspi_ipg_clk },
+       { .name = "cspi",       .compatible = MX5_CLK_COMP, .data = 
mx5_add_cspi_clk },
+       { .name = "ecspi_main", .compatible = MX5_CLK_COMP, .data = 
mx5_add_ecspi_main_clk },
+       { .name = "ecspi_ipg",  .compatible = MX5_CLK_COMP, .data = 
mx5_add_ecspi_ipg_clk },
+       { .name = "ecspi",      .compatible = MX5_CLK_COMP, .data = 
mx5_add_ecspi_clk },
+       { .name = "sdma",       .compatible = MX5_CLK_COMP, .data = 
mx5_add_sdma_clk },
+       { .name = "esdhc_ipg",  .compatible = MX5_CLK_COMP, .data = 
mx5_add_esdhc_ipg_clk },
+       { .name = "esdhc",      .compatible = MX5_CLK_COMP, .data = 
mx5_add_esdhc_clk },
+       { .name = "mipi_esc",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_mipi_esc_clk },
+       { .name = "mipi_hsc",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_mipi_hsc_clk },
+       { .name = "ipu_sec",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_ipu_sec_clk },
+       { .name = "ipu",        .compatible = MX5_CLK_COMP, .data = 
mx5_add_ipu_clk },
+       { .name = "ipu_di",     .compatible = MX5_CLK_COMP, .data = 
mx5_add_ipu_di_clk },
+       { .name = "mipi_hsp",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_mipi_hsp_clk },
+       { .name = "usboh3",     .compatible = MX5_CLK_COMP, .data = 
mx5_add_usboh3_clk },
+       { .name = "usb_ahb",    .compatible = MX5_CLK_COMP, .data = 
mx5_add_usb_ahb_clk },
+       { .name = "usb_phy1",   .compatible = MX5_CLK_COMP, .data = 
mx5_add_usb_phy1_clk },
+       { .name = "dummy",      .compatible = MX5_CLK_COMP, .data = 
mx5_add_dummy_clk },
+       { /* sentinel */ }
+};
+
+static __init int mx5_dt_scan_clks(void)
+{
+       struct device_node *np;
+       const struct of_device_id *dt_clk_id;
+       int (*mx5_add_clk)(struct device_node *);
+       int ret;
+
+       ret = mx5_scan_fixed_clks();
+       if (ret) {
+               pr_err("%s: fixed-clock failed %d\n", __func__, ret);
+               return ret;
+       }
+
+       for_each_matching_node(np, mx5_dt_mxc_clock_ids) {
+               dt_clk_id = of_match_node(mx5_dt_mxc_clock_ids, np);
+               mx5_add_clk = dt_clk_id->data;
+               ret = mx5_add_clk(np);
+               if (ret) {
+                       pr_err("%s: clock %s failed %d\n",
+                               __func__, np->name, ret);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+void __init mx5_clk_dt_init(void)
+{
+       mx5_dt_scan_clks();
+
+       clk_tree_init();
+
+       clk_enable(cpu_clk_ptr);
+       clk_enable(main_bus_clk_ptr);
+
+       clk_enable(iim_clk_ptr);
+       mx51_revision();
+       clk_disable(iim_clk_ptr);
+
+       /* move usb_phy_clk to 24MHz */
+       clk_set_parent(usb_phy1_clk_ptr, osc_clk_ptr);
+
+       /* set the usboh3_clk parent to pll2_sw_clk */
+       clk_set_parent(usboh3_clk_ptr, pll2_sw_clk_ptr);
+
+       /* Set SDHC parents to be PLL2 */
+       clk_set_parent(esdhc1_clk_ptr, pll2_sw_clk_ptr);
+       clk_set_parent(esdhc2_clk_ptr, pll2_sw_clk_ptr);
+
+       /* set SDHC root clock as 166.25MHZ*/
+       clk_set_rate(esdhc1_clk_ptr, 166250000);
+       clk_set_rate(esdhc2_clk_ptr, 166250000);
+}
+#endif
-- 
1.7.1


_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to