]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00182324-3 - MX6SL MSL: Add clock support for i.MX 6SoloLite
authorJason Liu <r64343@freescale.com>
Mon, 14 May 2012 13:15:57 +0000 (21:15 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:36 +0000 (08:34 +0200)
Add clock support for i.MX 6SoloLite.  A new clock file has been created
to reflect the substantial set of changes in the clocks used between
6SoloLite and other 6 series SoCs.

Signed-off-by: Jason Liu <r64343@freescale.com>
Signed-off-by: Robby Cai <r63905@freescale.com>
arch/arm/mach-mx6/Makefile
arch/arm/mach-mx6/clock_mx6sl.c [new file with mode: 0755]
arch/arm/mach-mx6/crm_regs.h
arch/arm/plat-mxc/include/mach/common.h
arch/arm/plat-mxc/time.c

index e76f438c919459748447e609d4fc78d6dc0c1611..90e10c043b28c9aea89e2c38876042d15f02bd9d 100644 (file)
@@ -7,7 +7,7 @@ obj-y   := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o
 pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o \
 mx6_mmdc.o mx6_ddr_freq.o
 
-obj-$(CONFIG_ARCH_MX6) += clock.o mx6q_suspend.o
+obj-$(CONFIG_ARCH_MX6) += clock.o mx6q_suspend.o clock_mx6sl.o
 obj-$(CONFIG_MACH_MX6Q_ARM2) += board-mx6q_arm2.o
 obj-$(CONFIG_MACH_MX6Q_SABRELITE) += board-mx6q_sabrelite.o
 obj-$(CONFIG_MACH_MX6Q_SABRESD) += board-mx6q_sabresd.o mx6q_sabresd_pmic_pfuze100.o
diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c
new file mode 100755 (executable)
index 0000000..08d9e61
--- /dev/null
@@ -0,0 +1,3713 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/regulator/consumer.h>
+#include <asm/div64.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+#include <mach/mxc_dvfs.h>
+#include "crm_regs.h"
+#include "cpu_op-mx6.h"
+#include "regs-anadig.h"
+
+#ifdef CONFIG_CLK_DEBUG
+#define __INIT_CLK_DEBUG(n)    .name = #n,
+#else
+#define __INIT_CLK_DEBUG(n)
+#endif
+
+extern u32 arm_max_freq;
+extern int mxc_jtag_enabled;
+extern struct regulator *cpu_regulator;
+extern struct cpu_op *(*get_cpu_op)(int *op);
+extern int lp_high_freq;
+extern int lp_med_freq;
+extern int mx6q_revision(void);
+
+static void __iomem *apll_base;
+static struct clk pll1_sys_main_clk;
+static struct clk pll2_528_bus_main_clk;
+static struct clk pll2_pfd2_400M;
+static struct clk pll3_usb_otg_main_clk;
+static struct clk pll4_audio_main_clk;
+static struct clk pll5_video_main_clk;
+static struct clk pll6_enet_main_clk; /* Essentially same as PLL8 on MX6Q/DL */
+static struct clk pll7_usb_host_main_clk;
+static struct clk usdhc3_clk;
+
+static struct cpu_op *cpu_op_tbl;
+static int cpu_op_nr;
+
+#define SPIN_DELAY     1200000 /* in nanoseconds */
+
+#define AUDIO_VIDEO_MIN_CLK_FREQ       650000000
+#define AUDIO_VIDEO_MAX_CLK_FREQ       1300000000
+
+/* We need to check the exp status again after timer expiration,
+ * as there might be interrupt coming between the first time exp
+ * and the time reading, then the time reading may be several ms
+ * after the exp checking due to the irq handle, so we need to
+ * check it to make sure the exp return the right value after
+ * timer expiration. */
+#define WAIT(exp, timeout) \
+({ \
+       struct timespec nstimeofday; \
+       struct timespec curtime; \
+       int result = 1; \
+       getnstimeofday(&nstimeofday); \
+       while (!(exp)) { \
+               getnstimeofday(&curtime); \
+               if ((curtime.tv_nsec - nstimeofday.tv_nsec) > (timeout)) { \
+                       if (!(exp)) \
+                               result = 0; \
+                       break; \
+               } \
+       } \
+       result; \
+})
+
+/* External clock values passed-in by the board code */
+static unsigned long external_high_reference, external_low_reference;
+static unsigned long oscillator_reference, ckih2_reference;
+static unsigned long anaclk_1_reference, anaclk_2_reference;
+
+static void __calc_pre_post_dividers(u32 max_podf, u32 div, u32 *pre, u32 *post)
+{
+       u32 min_pre, temp_pre, old_err, err;
+
+       /* Some of the podfs are 3 bits while others are 6 bits.
+         * Handle both cases here.
+         */
+       if (div >= 512 && (max_podf == 64)) {
+               /* For pre = 3bits and podf = 6 bits, max divider is 512. */
+               *pre = 8;
+               *post = 64;
+       } else if (div >= 64 && (max_podf == 8)) {
+               /* For pre = 3bits and podf = 3 bits, max divider is 64. */
+               *pre = 8;
+               *post = 8;
+       } else if (div >= 8) {
+               /* Find the minimum pre-divider for a max podf */
+               if (max_podf == 64)
+                       min_pre = (div - 1) / (1 << 6) + 1;
+               else
+                       min_pre = (div - 1) / (1 << 3) + 1;
+               old_err = 8;
+               /* Now loop through to find the max pre-divider. */
+               for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+                       err = div % temp_pre;
+                       if (err == 0) {
+                               *pre = temp_pre;
+                               break;
+                       }
+                       err = temp_pre - err;
+                       if (err < old_err) {
+                               old_err = err;
+                               *pre = temp_pre;
+                       }
+               }
+               *post = (div + *pre - 1) / *pre;
+       } else if (div < 8) {
+               *pre = div;
+               *post = 1;
+       }
+}
+
+static int _clk_enable(struct clk *clk)
+{
+       u32 reg;
+       reg = __raw_readl(clk->enable_reg);
+       reg |= MXC_CCM_CCGRx_CG_MASK << clk->enable_shift;
+       __raw_writel(reg, clk->enable_reg);
+
+       if (clk->flags & AHB_HIGH_SET_POINT)
+               lp_high_freq++;
+       else if (clk->flags & AHB_MED_SET_POINT)
+               lp_med_freq++;
+
+       return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+       u32 reg;
+       reg = __raw_readl(clk->enable_reg);
+       reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+       __raw_writel(reg, clk->enable_reg);
+
+       if (clk->flags & AHB_HIGH_SET_POINT)
+               lp_high_freq--;
+       else if (clk->flags & AHB_MED_SET_POINT)
+               lp_med_freq--;
+}
+
+static void _clk_disable_inwait(struct clk *clk)
+{
+       u32 reg;
+       reg = __raw_readl(clk->enable_reg);
+       reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+       reg |= 1 << clk->enable_shift;
+       __raw_writel(reg, clk->enable_reg);
+}
+
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux(struct clk *parent, struct clk *m0,
+                          struct clk *m1, struct clk *m2, struct clk *m3)
+{
+       if (parent == m0)
+               return 0;
+       else if (parent == m1)
+               return 1;
+       else if (parent == m2)
+               return 2;
+       else if (parent == m3)
+               return 3;
+       else
+               BUG();
+
+       return 0;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+       if (pll == &pll1_sys_main_clk)
+               return PLL1_SYS_BASE_ADDR;
+       else if (pll == &pll2_528_bus_main_clk)
+               return PLL2_528_BASE_ADDR;
+       else if (pll == &pll3_usb_otg_main_clk)
+               return PLL3_480_USB1_BASE_ADDR;
+       else if (pll == &pll4_audio_main_clk)
+               return PLL4_AUDIO_BASE_ADDR;
+       else if (pll == &pll5_video_main_clk)
+               return PLL5_VIDEO_BASE_ADDR;
+       else if (pll == &pll6_enet_main_clk)
+               /* Essentially same as PLL8 on MX6Q/DL */
+               return PLL8_ENET_BASE_ADDR;
+       else if (pll == &pll7_usb_host_main_clk)
+               return PLL7_480_USB2_BASE_ADDR;
+       else
+               BUG();
+       return NULL;
+}
+
+
+/*
+ * For the 6-to-1 muxed input clock
+ */
+static inline u32 _get_mux6(struct clk *parent, struct clk *m0, struct clk *m1,
+                           struct clk *m2, struct clk *m3, struct clk *m4,
+                           struct clk *m5)
+{
+       if (parent == m0)
+               return 0;
+       else if (parent == m1)
+               return 1;
+       else if (parent == m2)
+               return 2;
+       else if (parent == m3)
+               return 3;
+       else if (parent == m4)
+               return 4;
+       else if (parent == m5)
+               return 5;
+       else
+               BUG();
+
+       return 0;
+}
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+       return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+       return external_low_reference;
+}
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+       return oscillator_reference;
+}
+
+static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
+{
+       return ckih2_reference;
+}
+
+static unsigned long _clk_anaclk_1_get_rate(struct clk *clk)
+{
+       return anaclk_1_reference;
+}
+
+static int _clk_anaclk_1_set_rate(struct clk *clk, unsigned long rate)
+{
+       anaclk_1_reference = rate;
+       return 0;
+}
+
+static unsigned long _clk_anaclk_2_get_rate(struct clk *clk)
+{
+       return anaclk_2_reference;
+}
+
+static int _clk_anaclk_2_set_rate(struct clk *clk, unsigned long rate)
+{
+       anaclk_2_reference = rate;
+       return 0;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+       __INIT_CLK_DEBUG(ckih_clk)
+       .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+       __INIT_CLK_DEBUG(ckih2_clk)
+       .get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+       __INIT_CLK_DEBUG(osc_clk)
+       .get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+       __INIT_CLK_DEBUG(ckil_clk)
+       .get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk anaclk_1 = {
+       __INIT_CLK_DEBUG(anaclk_1)
+       .get_rate = _clk_anaclk_1_get_rate,
+       .set_rate = _clk_anaclk_1_set_rate,
+};
+
+static struct clk anaclk_2 = {
+       __INIT_CLK_DEBUG(anaclk_2)
+       .get_rate = _clk_anaclk_2_get_rate,
+       .set_rate = _clk_anaclk_2_set_rate,
+};
+
+static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 frac;
+       u64 tmp;
+
+       tmp = (u64)clk_get_rate(clk->parent) * 18;
+       tmp += rate/2;
+       do_div(tmp, rate);
+       frac = tmp;
+       frac = frac < 12 ? 12 : frac;
+       frac = frac > 35 ? 35 : frac;
+       tmp = (u64)clk_get_rate(clk->parent) * 18;
+       do_div(tmp, frac);
+       return tmp;
+}
+
+static unsigned long pfd_get_rate(struct clk *clk)
+{
+       u32 frac;
+       u64 tmp;
+       tmp = (u64)clk_get_rate(clk->parent) * 18;
+
+       frac = (__raw_readl(clk->enable_reg) >> clk->enable_shift) &
+                       ANADIG_PFD_FRAC_MASK;
+
+       do_div(tmp, frac);
+
+       return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 frac;
+       u64 tmp;
+       tmp = (u64)clk_get_rate(clk->parent) * 18;
+
+       /* Round up the divider so that we don't set a rate
+         * higher than what is requested. */
+       tmp += rate/2;
+       do_div(tmp, rate);
+       frac = tmp;
+       frac = frac < 12 ? 12 : frac;
+       frac = frac > 35 ? 35 : frac;
+       /* clear clk frac bits */
+       __raw_writel(ANADIG_PFD_FRAC_MASK << clk->enable_shift,
+                       (int)clk->enable_reg + 8);
+       /* set clk frac bits */
+       __raw_writel(frac << clk->enable_shift,
+                       (int)clk->enable_reg + 4);
+
+       return 0;
+}
+
+static int _clk_pfd_enable(struct clk *clk)
+{
+       /* clear clk gate bit */
+       __raw_writel((1 << (clk->enable_shift + 7)),
+                       (int)clk->enable_reg + 8);
+
+       return 0;
+}
+
+static void _clk_pfd_disable(struct clk *clk)
+{
+       /* set clk gate bit */
+       __raw_writel((1 << (clk->enable_shift + 7)),
+                       (int)clk->enable_reg + 4);
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+       unsigned int reg;
+       void __iomem *pllbase;
+
+       pllbase = _get_pll_base(clk);
+
+       reg = __raw_readl(pllbase);
+       reg &= ~ANADIG_PLL_BYPASS;
+       reg &= ~ANADIG_PLL_POWER_DOWN;
+
+       /* The 480MHz PLLs have the opposite definition for power bit. */
+       if (clk == &pll3_usb_otg_main_clk || clk == &pll7_usb_host_main_clk)
+               reg |= ANADIG_PLL_POWER_DOWN;
+
+       __raw_writel(reg, pllbase);
+
+       /* It will power on pll3 */
+       if (clk == &pll3_usb_otg_main_clk)
+               __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_CLR);
+
+       /* Wait for PLL to lock */
+       if (!WAIT(__raw_readl(pllbase) & ANADIG_PLL_LOCK,
+                               SPIN_DELAY))
+               panic("pll enable failed\n");
+
+       /* Enable the PLL output now*/
+       reg = __raw_readl(pllbase);
+       reg |= ANADIG_PLL_ENABLE;
+       __raw_writel(reg, pllbase);
+
+       return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+       unsigned int reg;
+       void __iomem *pllbase;
+
+       pllbase = _get_pll_base(clk);
+
+       reg = __raw_readl(pllbase);
+       reg |= ANADIG_PLL_BYPASS;
+       reg &= ~ANADIG_PLL_ENABLE;
+
+       __raw_writel(reg, pllbase);
+
+       /*
+        * It will power off PLL3's power, it is the TO1.1 fix
+        * Please see TKT064178 for detail.
+        */
+       if (clk == &pll3_usb_otg_main_clk)
+               __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_SET);
+}
+
+static unsigned long  _clk_pll1_main_get_rate(struct clk *clk)
+{
+       unsigned int div;
+       unsigned long val;
+
+       div = __raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
+       val = (clk_get_rate(clk->parent) * div) / 2;
+       return val;
+}
+
+static int _clk_pll1_main_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int reg, div;
+
+       if (rate < AUDIO_VIDEO_MIN_CLK_FREQ || rate > AUDIO_VIDEO_MAX_CLK_FREQ)
+               return -EINVAL;
+
+       div = (rate * 2) / clk_get_rate(clk->parent);
+
+       /* Update div */
+       reg = __raw_readl(PLL1_SYS_BASE_ADDR) & ~ANADIG_PLL_SYS_DIV_SELECT_MASK;
+       reg |= div;
+       __raw_writel(reg, PLL1_SYS_BASE_ADDR);
+
+       /* Wait for PLL1 to lock */
+       if (!WAIT(__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK,
+                               SPIN_DELAY))
+               panic("pll1 enable failed\n");
+
+       return 0;
+}
+
+static struct clk pll1_sys_main_clk = {
+       __INIT_CLK_DEBUG(pll1_sys_main_clk)
+       .parent = &osc_clk,
+       .get_rate = _clk_pll1_main_get_rate,
+       .set_rate = _clk_pll1_main_set_rate,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CCSR);
+
+       if (parent == &pll1_sys_main_clk) {
+               reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+               __raw_writel(reg, MXC_CCM_CCSR);
+               /* Set the step_clk parent to be lp_apm, to save power. */
+               reg = __raw_readl(MXC_CCM_CCSR);
+               reg = (reg & ~MXC_CCM_CCSR_STEP_SEL);
+       } else {
+               /* Set STEP_CLK to be the parent*/
+               if (parent == &osc_clk) {
+                       /* Set STEP_CLK to be sourced from LPAPM. */
+                       reg = __raw_readl(MXC_CCM_CCSR);
+                       reg = (reg & ~MXC_CCM_CCSR_STEP_SEL);
+                       __raw_writel(reg, MXC_CCM_CCSR);
+               } else {
+                       /* Set STEP_CLK to be sourced from PLL2-PDF (400MHz). */
+                       reg = __raw_readl(MXC_CCM_CCSR);
+                       reg |= MXC_CCM_CCSR_STEP_SEL;
+                       __raw_writel(reg, MXC_CCM_CCSR);
+
+               }
+               reg = __raw_readl(MXC_CCM_CCSR);
+               reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+       }
+       __raw_writel(reg, MXC_CCM_CCSR);
+       return 0;
+}
+
+static unsigned long _clk_pll1_sw_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent);
+}
+
+static struct clk pll1_sw_clk = {
+       __INIT_CLK_DEBUG(pll1_sw_clk)
+       .parent = &pll1_sys_main_clk,
+       .set_parent = _clk_pll1_sw_set_parent,
+       .get_rate = _clk_pll1_sw_get_rate,
+};
+
+static unsigned long _clk_pll2_main_get_rate(struct clk *clk)
+{
+       unsigned int div;
+       unsigned long val;
+
+       div = __raw_readl(PLL2_528_BASE_ADDR) & ANADIG_PLL_528_DIV_SELECT;
+
+       if (div == 1)
+               val = clk_get_rate(clk->parent) * 22;
+
+       else
+               val = clk_get_rate(clk->parent) * 20;
+
+       return val;
+}
+
+static int _clk_pll2_main_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int reg,  div;
+
+       if (rate == 528000000)
+               div = 1;
+       else if (rate == 480000000)
+               div = 0;
+       else
+               return -EINVAL;
+
+       reg = __raw_readl(PLL2_528_BASE_ADDR);
+       reg &= ~ANADIG_PLL_528_DIV_SELECT;
+       reg |= div;
+       __raw_writel(reg, PLL2_528_BASE_ADDR);
+
+       return 0;
+}
+
+static struct clk pll2_528_bus_main_clk = {
+       __INIT_CLK_DEBUG(pll2_528_bus_main_clk)
+       .parent = &osc_clk,
+       .get_rate = _clk_pll2_main_get_rate,
+       .set_rate = _clk_pll2_main_set_rate,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
+static struct clk pll2_pfd2_400M = {
+       __INIT_CLK_DEBUG(pll2_pfd2_400M)
+       .parent = &pll2_528_bus_main_clk,
+       .enable_reg = (void *)PFD_528_BASE_ADDR,
+       .enable_shift = ANADIG_PFD2_FRAC_OFFSET,
+       .enable = _clk_pfd_enable,
+       .disable = _clk_pfd_disable,
+       .get_rate = pfd_get_rate,
+       .set_rate = pfd_set_rate,
+       .get_rate = pfd_get_rate,
+       .round_rate = pfd_round_rate,
+};
+
+static struct clk pll2_pfd0_352M = {
+       __INIT_CLK_DEBUG(pll2_pfd0_352M)
+       .parent = &pll2_528_bus_main_clk,
+       .enable_reg = (void *)PFD_528_BASE_ADDR,
+       .enable_shift = ANADIG_PFD0_FRAC_OFFSET,
+       .enable = _clk_pfd_enable,
+       .disable = _clk_pfd_disable,
+       .set_rate = pfd_set_rate,
+       .get_rate = pfd_get_rate,
+       .round_rate = pfd_round_rate,
+};
+
+static struct clk pll2_pfd1_594M = {
+       __INIT_CLK_DEBUG(pll2_pfd1_594M)
+       .parent = &pll2_528_bus_main_clk,
+       .enable_reg = (void *)PFD_528_BASE_ADDR,
+       .enable_shift = ANADIG_PFD1_FRAC_OFFSET,
+       .enable = _clk_pfd_enable,
+       .disable = _clk_pfd_disable,
+       .set_rate = pfd_set_rate,
+       .get_rate = pfd_get_rate,
+       .round_rate = pfd_round_rate,
+};
+
+static unsigned long _clk_pll2_200M_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200M = {
+       __INIT_CLK_DEBUG(pll2_200M)
+       .parent = &pll2_pfd2_400M,
+       .get_rate = _clk_pll2_200M_get_rate,
+};
+
+static unsigned long _clk_pll3_usb_otg_get_rate(struct clk *clk)
+{
+       unsigned int div;
+       unsigned long val;
+
+       div = __raw_readl(PLL3_480_USB1_BASE_ADDR)
+               & ANADIG_PLL_480_DIV_SELECT_MASK;
+
+       if (div == 1)
+               val = clk_get_rate(clk->parent) * 22;
+       else
+               val = clk_get_rate(clk->parent) * 20;
+       return val;
+}
+
+static int _clk_pll3_usb_otg_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int reg,  div;
+
+       if (rate == 528000000)
+               div = 1;
+       else if (rate == 480000000)
+               div = 0;
+       else
+               return -EINVAL;
+
+       reg = __raw_readl(PLL3_480_USB1_BASE_ADDR);
+       reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK;
+       reg |= div;
+       __raw_writel(reg, PLL3_480_USB1_BASE_ADDR);
+
+       return 0;
+}
+
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_usb_otg_main_clk = {
+       __INIT_CLK_DEBUG(pll3_usb_otg_main_clk)
+       .parent = &osc_clk,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+       .set_rate = _clk_pll3_usb_otg_set_rate,
+       .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* for USB OTG */
+static struct clk usb_phy1_clk = {
+       __INIT_CLK_DEBUG(usb_phy1_clk)
+       .parent = &pll3_usb_otg_main_clk,
+       .set_rate = _clk_pll3_usb_otg_set_rate,
+       .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* For HSIC port 1 */
+static struct clk usb_phy3_clk = {
+       __INIT_CLK_DEBUG(usb_phy3_clk)
+       .parent = &pll3_usb_otg_main_clk,
+       .set_rate = _clk_pll3_usb_otg_set_rate,
+       .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+/* For HSIC port 2 */
+static struct clk usb_phy4_clk = {
+       __INIT_CLK_DEBUG(usb_phy4_clk)
+       .parent = &pll3_usb_otg_main_clk,
+       .set_rate = _clk_pll3_usb_otg_set_rate,
+       .get_rate = _clk_pll3_usb_otg_get_rate,
+};
+
+static struct clk pll3_pfd2_508M = {
+       __INIT_CLK_DEBUG(pll3_pfd2_508M)
+       .parent = &pll3_usb_otg_main_clk,
+       .enable_reg = (void *)PFD_480_BASE_ADDR,
+       .enable_shift = ANADIG_PFD2_FRAC_OFFSET,
+       .enable = _clk_pfd_enable,
+       .disable = _clk_pfd_disable,
+       .set_rate = pfd_set_rate,
+       .get_rate = pfd_get_rate,
+       .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd3_454M = {
+       __INIT_CLK_DEBUG(pll3_pfd3_454M)
+       .parent = &pll3_usb_otg_main_clk,
+       .enable_reg = (void *)PFD_480_BASE_ADDR,
+       .enable_shift = ANADIG_PFD3_FRAC_OFFSET,
+       .enable = _clk_pfd_enable,
+       .disable = _clk_pfd_disable,
+       .set_rate = pfd_set_rate,
+       .get_rate = pfd_get_rate,
+       .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd0_720M = {
+       __INIT_CLK_DEBUG(pll3_pfd0_720M)
+       .parent = &pll3_usb_otg_main_clk,
+       .enable_reg = (void *)PFD_480_BASE_ADDR,
+       .enable_shift = ANADIG_PFD0_FRAC_OFFSET,
+       .enable = _clk_pfd_enable,
+       .disable = _clk_pfd_disable,
+       .set_rate = pfd_set_rate,
+       .get_rate = pfd_get_rate,
+       .round_rate = pfd_round_rate,
+};
+
+static struct clk pll3_pfd1_540M = {
+       __INIT_CLK_DEBUG(pll3_pfd1_540M)
+       .parent = &pll3_usb_otg_main_clk,
+       .enable_reg = (void *)PFD_480_BASE_ADDR,
+       .enable_shift = ANADIG_PFD1_FRAC_OFFSET,
+       .enable = _clk_pfd_enable,
+       .disable = _clk_pfd_disable,
+       .set_rate = pfd_set_rate,
+       .get_rate = pfd_get_rate,
+       .round_rate = pfd_round_rate,
+       .get_rate = pfd_get_rate,
+};
+
+static unsigned long _clk_pll3_sw_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent);
+}
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_sw_clk = {
+       __INIT_CLK_DEBUG(pll3_sw_clk)
+       .parent = &pll3_usb_otg_main_clk,
+       .get_rate = _clk_pll3_sw_get_rate,
+};
+
+static unsigned long _clk_pll3_120M_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120M = {
+       __INIT_CLK_DEBUG(pll3_120M)
+       .parent = &pll3_sw_clk,
+       .get_rate = _clk_pll3_120M_get_rate,
+};
+
+static unsigned long _clk_pll3_80M_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80M = {
+       __INIT_CLK_DEBUG(pll3_80M)
+       .parent = &pll3_sw_clk,
+       .get_rate = _clk_pll3_80M_get_rate,
+};
+
+static unsigned long _clk_pll3_60M_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60M = {
+       __INIT_CLK_DEBUG(pll3_60M)
+       .parent = &pll3_sw_clk,
+       .get_rate = _clk_pll3_60M_get_rate,
+};
+
+static unsigned long _clk_audio_video_get_rate(struct clk *clk)
+{
+       unsigned int div, mfn, mfd;
+       unsigned long rate;
+       unsigned int parent_rate = clk_get_rate(clk->parent);
+       void __iomem *pllbase;
+       unsigned int test_div_sel, control3, post_div;
+
+       pllbase = _get_pll_base(clk);
+
+       test_div_sel = (__raw_readl(pllbase)
+               & ANADIG_PLL_AV_TEST_DIV_SEL_MASK)
+               >> ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET;
+       /* post_div = 4 - test_div_sel; */
+       if (test_div_sel == 0)
+               post_div = 4;
+       else if (test_div_sel == 1)
+               post_div = 2;
+       else
+               post_div = 1;
+
+       /* PMU_REG_MISC2 in RM */
+       if (clk == &pll5_video_main_clk) {
+               control3 = (__raw_readl(ANA_MISC2_BASE_ADDR)
+                       & ANADIG_ANA_MISC2_CONTROL3_MASK)
+                       >> ANADIG_ANA_MISC2_CONTROL3_OFFSET;
+               if (control3 == 1)
+                       post_div *= 2;
+               else if (control3 == 3)
+                       post_div *= 4;
+       }
+
+       div = __raw_readl(pllbase) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
+       mfn = __raw_readl(pllbase + PLL_NUM_DIV_OFFSET);
+       mfd = __raw_readl(pllbase + PLL_DENOM_DIV_OFFSET);
+
+       rate = (parent_rate * div) + ((parent_rate / mfd) * mfn);
+       rate = rate / post_div;
+
+       return rate;
+}
+
+static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int reg,  div;
+       unsigned int mfn, mfd = 1000000;
+       s64 temp64;
+       unsigned int parent_rate = clk_get_rate(clk->parent);
+       void __iomem *pllbase;
+       unsigned long min_clk_rate, pre_div_rate;
+       u32 test_div_sel = 2;
+       u32 control3 = 0;
+
+       if (clk == &pll4_audio_main_clk)
+               min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4;
+       else
+               min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 16;
+
+       if ((rate < min_clk_rate) || (rate > AUDIO_VIDEO_MAX_CLK_FREQ))
+               return -EINVAL;
+
+       pllbase = _get_pll_base(clk);
+
+       pre_div_rate = rate;
+       while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) {
+               pre_div_rate *= 2;
+               /*
+                * test_div_sel field values:
+                * 2 -> Divide by 1
+                * 1 -> Divide by 2
+                * 0 -> Divide by 4
+                *
+                * control3 field values:
+                * 0 -> Divide by 1
+                * 1 -> Divide by 2
+                * 3 -> Divide by 4
+                */
+               if (test_div_sel != 0)
+                       test_div_sel--;
+               else {
+                       control3++;
+                       if (control3 == 2)
+                               control3++;
+               }
+       }
+
+       div = pre_div_rate / parent_rate;
+       temp64 = (u64) (pre_div_rate - (div * parent_rate));
+       temp64 *= mfd;
+       do_div(temp64, parent_rate);
+       mfn = temp64;
+
+       reg = __raw_readl(pllbase)
+                       & ~ANADIG_PLL_SYS_DIV_SELECT_MASK
+                       & ~ANADIG_PLL_AV_TEST_DIV_SEL_MASK;
+       reg |= div |
+               (test_div_sel << ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET);
+       __raw_writel(reg, pllbase);
+       __raw_writel(mfn, pllbase + PLL_NUM_DIV_OFFSET);
+       __raw_writel(mfd, pllbase + PLL_DENOM_DIV_OFFSET);
+
+       reg = __raw_readl(ANA_MISC2_BASE_ADDR)
+               & ~ANADIG_ANA_MISC2_CONTROL3_MASK;
+       reg |= control3 << ANADIG_ANA_MISC2_CONTROL3_OFFSET;
+       __raw_writel(reg, ANA_MISC2_BASE_ADDR);
+
+       return 0;
+}
+
+static unsigned long _clk_audio_video_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       unsigned long min_clk_rate;
+       unsigned int div, post_div = 1;
+       unsigned int mfn, mfd = 1000000;
+       s64 temp64;
+       unsigned int parent_rate = clk_get_rate(clk->parent);
+       unsigned long pre_div_rate;
+       u32 test_div_sel = 2;
+       u32 control3 = 0;
+       unsigned long final_rate;
+
+       if (clk == &pll4_audio_main_clk)
+               min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4;
+       else
+               min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 16;
+
+       if (rate < min_clk_rate)
+               return min_clk_rate;
+
+       if (rate > AUDIO_VIDEO_MAX_CLK_FREQ)
+               return AUDIO_VIDEO_MAX_CLK_FREQ;
+
+       pre_div_rate = rate;
+       while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) {
+               pre_div_rate *= 2;
+               post_div *= 2;
+               if (test_div_sel != 0)
+                       test_div_sel--;
+               else {
+                       control3++;
+                       if (control3 == 2)
+                               control3++;
+               }
+       }
+
+       div = pre_div_rate / parent_rate;
+       temp64 = (u64) (pre_div_rate - (div * parent_rate));
+       temp64 *= mfd;
+       do_div(temp64, parent_rate);
+       mfn = temp64;
+
+       final_rate = (parent_rate * div) + ((parent_rate / mfd) * mfn);
+       final_rate = final_rate / post_div;
+
+       return final_rate;
+}
+
+static int _clk_audio_video_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+       int mux;
+       void __iomem *pllbase;
+
+       if (clk == &pll4_audio_main_clk)
+               pllbase = PLL4_AUDIO_BASE_ADDR;
+       else
+               pllbase = PLL5_VIDEO_BASE_ADDR;
+
+       reg = __raw_readl(pllbase) & ~ANADIG_PLL_BYPASS_CLK_SRC_MASK;
+       mux = _get_mux6(parent, &osc_clk, &anaclk_1, &anaclk_2,
+                               NULL, NULL, NULL);
+       reg |= mux << ANADIG_PLL_BYPASS_CLK_SRC_OFFSET;
+       __raw_writel(reg, pllbase);
+
+       /* Set anaclk_x as input */
+       if (parent == &anaclk_1) {
+               reg = __raw_readl(ANADIG_MISC1_REG);
+               reg |= (ANATOP_LVDS_CLK1_IBEN_MASK &
+                               ~ANATOP_LVDS_CLK1_OBEN_MASK);
+               __raw_writel(reg, ANADIG_MISC1_REG);
+       } else if (parent == &anaclk_2) {
+               reg = __raw_readl(ANADIG_MISC1_REG);
+               reg |= (ANATOP_LVDS_CLK2_IBEN_MASK &
+                               ~ANATOP_LVDS_CLK2_OBEN_MASK);
+               __raw_writel(reg, ANADIG_MISC1_REG);
+       }
+
+       return 0;
+}
+
+static struct clk pll4_audio_main_clk = {
+       __INIT_CLK_DEBUG(pll4_audio_main_clk)
+       .parent = &osc_clk,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+       .set_rate = _clk_audio_video_set_rate,
+       .get_rate = _clk_audio_video_get_rate,
+       .round_rate = _clk_audio_video_round_rate,
+       .set_parent = _clk_audio_video_set_parent,
+};
+
+static struct clk pll5_video_main_clk = {
+       __INIT_CLK_DEBUG(pll5_video_main_clk)
+       .parent = &osc_clk,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+       .set_rate = _clk_audio_video_set_rate,
+       .get_rate = _clk_audio_video_get_rate,
+       .round_rate = _clk_audio_video_round_rate,
+       .set_parent = _clk_audio_video_set_parent,
+};
+
+static struct clk pll6_enet_main_clk = {
+       __INIT_CLK_DEBUG(pll6_enet_main_clk)
+       .parent = &osc_clk,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+};
+
+static unsigned long _clk_pll7_usb_otg_get_rate(struct clk *clk)
+{
+       unsigned int div;
+       unsigned long val;
+
+       div = __raw_readl(PLL7_480_USB2_BASE_ADDR)
+               & ANADIG_PLL_480_DIV_SELECT_MASK;
+
+       if (div == 1)
+               val = clk_get_rate(clk->parent) * 22;
+       else
+               val = clk_get_rate(clk->parent) * 20;
+       return val;
+}
+
+static int _clk_pll7_usb_otg_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int reg,  div;
+
+       if (rate == 528000000)
+               div = 1;
+       else if (rate == 480000000)
+               div = 0;
+       else
+               return -EINVAL;
+
+       reg = __raw_readl(PLL7_480_USB2_BASE_ADDR);
+       reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK;
+       reg |= div;
+       __raw_writel(reg, PLL7_480_USB2_BASE_ADDR);
+
+       return 0;
+}
+
+static struct clk pll7_usb_host_main_clk = {
+       __INIT_CLK_DEBUG(pll7_usb_host_main_clk)
+       .parent = &osc_clk,
+       .enable = _clk_pll_enable,
+       .disable = _clk_pll_disable,
+       .set_rate = _clk_pll7_usb_otg_set_rate,
+       .get_rate = _clk_pll7_usb_otg_get_rate,
+
+};
+
+static unsigned long _clk_arm_get_rate(struct clk *clk)
+{
+       u32 cacrr, div;
+
+       cacrr = __raw_readl(MXC_CCM_CACRR);
+       div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_arm_set_rate(struct clk *clk, unsigned long rate)
+{
+       int i;
+       u32 div;
+       u32 parent_rate;
+
+
+       for (i = 0; i < cpu_op_nr; i++) {
+               if (rate == cpu_op_tbl[i].cpu_rate)
+                       break;
+       }
+       if (i >= cpu_op_nr)
+               return -EINVAL;
+
+       if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) {
+               /* Change the PLL1 rate. */
+               if (pll2_pfd2_400M.usecount != 0)
+                       pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd2_400M);
+               else
+                       pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk);
+               pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate);
+               pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk);
+       }
+
+       parent_rate = clk_get_rate(clk->parent);
+       div = parent_rate / rate;
+
+       if (div == 0)
+               div = 1;
+
+       if ((parent_rate / div) > rate)
+               div++;
+
+       if (div > 8)
+               return -1;
+
+       __raw_writel(div - 1, MXC_CCM_CACRR);
+
+       return 0;
+}
+
+static struct clk cpu_clk = {
+       __INIT_CLK_DEBUG(cpu_clk)
+       .parent = &pll1_sw_clk,
+       .set_rate = _clk_arm_set_rate,
+       .get_rate = _clk_arm_get_rate,
+};
+
+static unsigned long _clk_twd_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) / 2;
+}
+
+static int _clk_ipg_perclk_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+
+       if (parent == &osc_clk)
+               reg |= 0x1 << MXC_CCM_CSCMR1_PERCLK_CLK_SEL_OFFSET;
+       else
+               reg &= ~(0x1 << MXC_CCM_CSCMR1_PERCLK_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+static struct clk twd_clk = {
+       __INIT_CLK_DEBUG(twd_clk)
+       .parent = &cpu_clk,
+       .get_rate = _clk_twd_get_rate,
+};
+
+static int _clk_periph_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+       int mux;
+
+       mux = _get_mux6(parent, &pll2_528_bus_main_clk, &pll2_pfd2_400M,
+               &pll2_pfd0_352M, &pll2_200M, &pll3_sw_clk, &osc_clk);
+
+       if (mux <= 3) {
+               /* Set the pre_periph_clk multiplexer */
+               reg = __raw_readl(MXC_CCM_CBCMR);
+               reg &= ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK;
+               reg |= mux << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
+               __raw_writel(reg, MXC_CCM_CBCMR);
+
+               /* Set the periph_clk_sel multiplexer. */
+               reg = __raw_readl(MXC_CCM_CBCDR);
+               reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+               __raw_writel(reg, MXC_CCM_CBCDR);
+       } else {
+               reg = __raw_readl(MXC_CCM_CBCDR);
+               /* Set the periph_clk2_podf divider to divide by 1. */
+               reg &= ~MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK;
+               __raw_writel(reg, MXC_CCM_CBCDR);
+
+               /* Set the periph_clk2_sel mux. */
+               reg = __raw_readl(MXC_CCM_CBCMR);
+               reg &= ~MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK;
+               reg |= ((mux - 4) << MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET);
+               __raw_writel(reg, MXC_CCM_CBCMR);
+
+               while (__raw_readl(MXC_CCM_CDHIPR))
+                       ;
+
+               reg = __raw_readl(MXC_CCM_CBCDR);
+               /* Set periph_clk_sel to select periph_clk2. */
+               reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+               __raw_writel(reg, MXC_CCM_CBCDR);
+       }
+
+       if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+            & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY), SPIN_DELAY))
+               panic("_clk_periph_set_parent failed\n");
+
+       return 0;
+}
+
+static unsigned long _clk_periph_get_rate(struct clk *clk)
+{
+       u32 div = 1;
+       u32 reg;
+       unsigned long val;
+
+       if ((clk->parent == &pll3_sw_clk) || (clk->parent == &osc_clk)) {
+               reg = __raw_readl(MXC_CCM_CBCDR)
+                       & MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK;
+               div = (reg >> MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET) + 1;
+       }
+       val = clk_get_rate(clk->parent) / div;
+       return val;
+}
+
+static struct clk periph_clk = {
+       __INIT_CLK_DEBUG(periph_clk)
+       .parent = &pll2_528_bus_main_clk,
+       .set_parent = _clk_periph_set_parent,
+       .get_rate = _clk_periph_get_rate,
+};
+
+static unsigned long _clk_axi_get_rate(struct clk *clk)
+{
+       u32 div, reg;
+       unsigned long val;
+
+       reg = __raw_readl(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_AXI_PODF_MASK;
+       div = (reg >> MXC_CCM_CBCDR_AXI_PODF_OFFSET);
+
+       val = clk_get_rate(clk->parent) / (div + 1);
+       return val;
+}
+
+static int _clk_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       reg &= ~MXC_CCM_CBCDR_AXI_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CBCDR_AXI_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCDR);
+
+       if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+            & MXC_CCM_CDHIPR_AXI_PODF_BUSY), SPIN_DELAY))
+               panic("pll _clk_axi_a_set_rate failed\n");
+
+       return 0;
+}
+
+static unsigned long _clk_axi_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum
+        * value for the clock.
+        * Also prevent a div of 0.
+        */
+
+       if (div > 8)
+               div = 8;
+       else if (div == 0)
+               div++;
+
+       return parent_rate / div;
+}
+
+static int _clk_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg;
+       int mux;
+
+       mux = _get_mux6(parent, &periph_clk, &pll2_pfd2_400M,
+                               &pll3_pfd1_540M, NULL, NULL, NULL);
+
+       if (mux == 0) {
+               /* Set the AXI_SEL mux */
+               reg = __raw_readl(MXC_CCM_CBCDR) & ~MXC_CCM_CBCDR_AXI_SEL;
+               __raw_writel(reg, MXC_CCM_CBCDR);
+       } else {
+               /* Set the AXI_ALT_SEL mux. */
+               reg = __raw_readl(MXC_CCM_CBCDR)
+                       & ~MXC_CCM_CBCDR_AXI_ALT_SEL_MASK;
+               reg |= ((mux - 1) << MXC_CCM_CBCDR_AXI_ALT_SEL_OFFSET);
+               __raw_writel(reg, MXC_CCM_CBCDR);
+
+               /* Set the AXI_SEL mux */
+               reg = __raw_readl(MXC_CCM_CBCDR) & ~MXC_CCM_CBCDR_AXI_SEL;
+               reg |= MXC_CCM_CBCDR_AXI_SEL;
+               __raw_writel(reg, MXC_CCM_CBCDR);
+       }
+       return 0;
+}
+
+static struct clk axi_clk = {
+       __INIT_CLK_DEBUG(axi_clk)
+       .parent = &periph_clk,
+       .set_parent = _clk_axi_set_parent,
+       .set_rate = _clk_axi_set_rate,
+       .get_rate = _clk_axi_get_rate,
+       .round_rate = _clk_axi_round_rate,
+};
+
+static unsigned long _clk_ahb_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+              MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCDR);
+
+       if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AHB_PODF_BUSY),
+                               SPIN_DELAY))
+                       panic("_clk_ahb_set_rate failed\n");
+
+       return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 8)
+               div = 8;
+
+       return parent_rate / div;
+}
+
+static struct clk ahb_clk = {
+       __INIT_CLK_DEBUG(ahb_clk)
+       .parent = &periph_clk,
+       .get_rate = _clk_ahb_get_rate,
+       .set_rate = _clk_ahb_set_rate,
+       .round_rate = _clk_ahb_round_rate,
+};
+
+static unsigned long _clk_ipg_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+               MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+
+static struct clk ipg_clk = {
+       __INIT_CLK_DEBUG(ipg_clk)
+       .parent = &ahb_clk,
+       .get_rate = _clk_ipg_get_rate,
+};
+
+static struct clk tzasc1_clk = {
+       __INIT_CLK_DEBUG(tzasc1_clk)
+       .id = 0,
+       .parent = &ipg_clk,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+static struct clk tzasc2_clk = {
+       __INIT_CLK_DEBUG(tzasc2_clk)
+       .id = 0,
+       .parent = &ipg_clk,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6fast1_clk = {
+       __INIT_CLK_DEBUG(mx6fast1_clk)
+       .id = 0,
+       .parent = &ahb_clk,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6per1_clk = {
+       __INIT_CLK_DEBUG(mx6per1_clk)
+       .id = 0,
+       .parent = &ahb_clk,
+       .secondary = &mx6fast1_clk,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+static struct clk mx6per2_clk = {
+       __INIT_CLK_DEBUG(mx6per2_clk)
+       .id = 0,
+       .parent = &ahb_clk,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+static unsigned long _clk_mmdc_ch1_axi_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       div = ((reg & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) >>
+                       MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_mmdc_ch1_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CBCDR);
+       reg &= ~MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCDR);
+
+       if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+               & MXC_CCM_CDHIPR_MMDC_CH1_PODF_BUSY), SPIN_DELAY))
+                       panic("_clk_mmdc_ch1_axi_set_rate failed\n");
+
+       return 0;
+}
+
+static unsigned long _clk_mmdc_ch1_axi_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 8)
+               div = 8;
+
+       return parent_rate / div;
+}
+
+static struct clk mmdc_ch1_axi_clk[] = {
+       {
+       __INIT_CLK_DEBUG(mmdc_ch1_axi_clk)
+       .id = 0,
+       .parent = &pll2_pfd2_400M,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+       .secondary = &mmdc_ch1_axi_clk[1],
+       .get_rate = _clk_mmdc_ch1_axi_get_rate,
+       .set_rate = _clk_mmdc_ch1_axi_set_rate,
+       .round_rate = _clk_mmdc_ch1_axi_round_rate,
+       },
+       {
+       .id = 1,
+       __INIT_CLK_DEBUG(mmdc_ch1_ipg_clk)
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+       .secondary = &tzasc2_clk,
+       },
+};
+
+static struct clk ocram_clk = {
+       __INIT_CLK_DEBUG(ocram_clk)
+       .id = 0,
+       .parent = &axi_clk,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+static unsigned long _clk_ipg_perclk_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       div = ((reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK) >>
+                       MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET) + 1;
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipg_perclk_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 64))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       reg &= ~MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+
+static unsigned long _clk_ipg_perclk_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 64)
+               div = 64;
+
+       return parent_rate / div;
+}
+
+static struct clk ipg_perclk = {
+       __INIT_CLK_DEBUG(ipg_perclk)
+       .parent = &osc_clk,
+       .set_parent = _clk_ipg_perclk_set_parent,
+       .get_rate = _clk_ipg_perclk_get_rate,
+       .set_rate = _clk_ipg_perclk_set_rate,
+       .round_rate = _clk_ipg_perclk_round_rate,
+};
+
+static struct clk spba_clk = {
+       __INIT_CLK_DEBUG(spba_clk)
+       .parent = &ipg_clk,
+       .enable_reg = MXC_CCM_CCGR5,
+       .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+};
+
+static struct clk sdma_clk[] = {
+       {
+        __INIT_CLK_DEBUG(sdma_clk)
+        .parent = &ahb_clk,
+        .enable_reg = MXC_CCM_CCGR5,
+        .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        .secondary = &sdma_clk[1],
+       },
+       {
+        .parent = &mx6per1_clk,
+#ifdef CONFIG_SDMA_IRAM
+        .secondary = &ocram_clk,
+#else
+       .secondary = &mmdc_ch1_axi_clk[0],
+#endif
+       },
+};
+
+static unsigned long _clk_gpt_get_rate(struct clk *clk)
+{
+       unsigned long rate;
+
+       if (mx6q_revision() == IMX_CHIP_REVISION_1_0)
+               return clk_get_rate(clk->parent);
+
+       rate = mx6_timer_rate();
+       if (!rate)
+               return clk_get_rate(clk->parent);
+
+       return rate;
+}
+
+static struct clk gpt_clk[] = {
+       {
+       __INIT_CLK_DEBUG(gpt_clk)
+        .parent = &osc_clk,
+        .id = 0,
+        .enable_reg = MXC_CCM_CCGR1,
+        .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        .get_rate = _clk_gpt_get_rate,
+        },
+};
+
+static unsigned long _clk_iim_get_rate(struct clk *clk)
+{
+       return clk_get_rate(clk->parent);
+}
+
+static struct clk iim_clk = {
+       __INIT_CLK_DEBUG(iim_clk)
+       .parent = &ipg_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CCGR2,
+       .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+       .disable = _clk_disable,
+       .get_rate = _clk_iim_get_rate,
+};
+
+static struct clk i2c_clk[] = {
+       {
+       __INIT_CLK_DEBUG(i2c_clk_0)
+        .id = 0,
+        .parent = &ipg_perclk,
+        .enable_reg = MXC_CCM_CCGR2,
+        .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        },
+       {
+       __INIT_CLK_DEBUG(i2c_clk_1)
+        .id = 1,
+        .parent = &ipg_perclk,
+        .enable_reg = MXC_CCM_CCGR2,
+        .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        },
+       {
+       __INIT_CLK_DEBUG(i2c_clk_2)
+        .id = 2,
+        .parent = &ipg_perclk,
+        .enable_reg = MXC_CCM_CCGR2,
+        .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        },
+};
+
+static int _clk_ipu1_set_parent(struct clk *clk, struct clk *parent)
+{
+       int mux;
+       u32 reg = __raw_readl(MXC_CCM_CSCDR3)
+               & ~MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &osc_clk,
+               &pll2_pfd2_400M, &pll3_120M, &pll3_pfd1_540M, NULL, NULL);
+
+       reg |= (mux << MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCDR3);
+
+       return 0;
+}
+
+static unsigned long _clk_ipu1_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCDR3);
+       div = ((reg & MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK) >>
+                       MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu1_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCDR3);
+       reg &= ~MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR3);
+
+       return 0;
+}
+
+static unsigned long _clk_ipu_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 8)
+               div = 8;
+
+       return parent_rate / div;
+}
+
+static struct clk ipu1_clk = {
+       __INIT_CLK_DEBUG(ipu1_clk)
+       .parent = &pll2_pfd2_400M,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ipu1_set_parent,
+       .round_rate = _clk_ipu_round_rate,
+       .set_rate = _clk_ipu1_set_rate,
+       .get_rate = _clk_ipu1_get_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_ipu2_set_parent(struct clk *clk, struct clk *parent)
+{
+       int mux;
+       u32 reg = __raw_readl(MXC_CCM_CSCDR3)
+               & ~MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+               &pll2_pfd2_400M, &pll3_sw_clk, &pll3_pfd1_540M, NULL, NULL);
+
+       reg |= (mux << MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCDR3);
+
+       return 0;
+}
+
+static unsigned long _clk_ipu2_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCDR3);
+       div = ((reg & MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK) >>
+                       MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu2_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCDR3);
+       reg &= ~MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR3);
+
+       return 0;
+}
+
+static struct clk ipu2_clk = {
+       __INIT_CLK_DEBUG(ipu2_clk)
+       .parent = &pll2_pfd2_400M,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ipu2_set_parent,
+       .round_rate = _clk_ipu_round_rate,
+       .set_rate = _clk_ipu2_set_rate,
+       .get_rate = _clk_ipu2_get_rate,
+       .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk usdhc_dep_clk = {
+       .parent = &mmdc_ch1_axi_clk[0],
+       .secondary = &mx6per1_clk,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       };
+
+static unsigned long _clk_usdhc_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 8)
+               div = 8;
+
+       return parent_rate / div;
+}
+
+static int _clk_usdhc1_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC1_CLK_SEL;
+
+       if (parent == &pll2_pfd0_352M)
+               reg |= (MXC_CCM_CSCMR1_USDHC1_CLK_SEL);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static unsigned long _clk_usdhc1_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       div = ((reg & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
+                       MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc1_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       reg &= ~MXC_CCM_CSCDR1_USDHC1_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR1);
+
+       return 0;
+}
+
+static struct clk usdhc1_clk = {
+       __INIT_CLK_DEBUG(usdhc1_clk)
+       .id = 0,
+       .parent = &pll2_pfd2_400M,
+       .secondary = &usdhc_dep_clk,
+       .enable_reg = MXC_CCM_CCGR6,
+       .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_usdhc1_set_parent,
+       .round_rate = _clk_usdhc_round_rate,
+       .set_rate = _clk_usdhc1_set_rate,
+       .get_rate = _clk_usdhc1_get_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_usdhc2_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC2_CLK_SEL;
+
+       if (parent == &pll2_pfd0_352M)
+               reg |= (MXC_CCM_CSCMR1_USDHC2_CLK_SEL);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static unsigned long _clk_usdhc2_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       div = ((reg & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
+                       MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc2_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       reg &= ~MXC_CCM_CSCDR1_USDHC2_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR1);
+
+       return 0;
+}
+
+static struct clk usdhc2_clk = {
+       __INIT_CLK_DEBUG(usdhc2_clk)
+       .id = 1,
+       .parent = &pll2_pfd2_400M,
+       .secondary = &usdhc_dep_clk,
+       .enable_reg = MXC_CCM_CCGR6,
+       .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_usdhc2_set_parent,
+       .round_rate = _clk_usdhc_round_rate,
+       .set_rate = _clk_usdhc2_set_rate,
+       .get_rate = _clk_usdhc2_get_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_usdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC3_CLK_SEL;
+
+       if (parent == &pll2_pfd0_352M)
+               reg |= (MXC_CCM_CSCMR1_USDHC3_CLK_SEL);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static unsigned long _clk_usdhc3_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       div = ((reg & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
+                       MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc3_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       reg &= ~MXC_CCM_CSCDR1_USDHC3_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR1);
+
+       return 0;
+}
+
+
+static struct clk usdhc3_clk = {
+       __INIT_CLK_DEBUG(usdhc3_clk)
+       .id = 2,
+       .parent = &pll2_pfd2_400M,
+       .secondary = &usdhc_dep_clk,
+       .enable_reg = MXC_CCM_CCGR6,
+       .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_usdhc3_set_parent,
+       .round_rate = _clk_usdhc_round_rate,
+       .set_rate = _clk_usdhc3_set_rate,
+       .get_rate = _clk_usdhc3_get_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_usdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USDHC4_CLK_SEL;
+
+       if (parent == &pll2_pfd0_352M)
+               reg |= (MXC_CCM_CSCMR1_USDHC4_CLK_SEL);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static unsigned long _clk_usdhc4_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       div = ((reg & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
+                       MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usdhc4_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1);
+       reg &= ~MXC_CCM_CSCDR1_USDHC4_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR1);
+
+       return 0;
+}
+
+
+static struct clk usdhc4_clk = {
+       __INIT_CLK_DEBUG(usdhc4_clk)
+       .id = 3,
+       .parent = &pll2_pfd2_400M,
+       .secondary = &usdhc_dep_clk,
+       .enable_reg = MXC_CCM_CCGR6,
+       .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_usdhc4_set_parent,
+       .round_rate = _clk_usdhc_round_rate,
+       .set_rate = _clk_usdhc4_set_rate,
+       .get_rate = _clk_usdhc4_get_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_ssi_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+       u32 div = parent_rate / rate;
+
+       if (parent_rate % rate)
+               div++;
+
+       __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+       return parent_rate / (pre * post);
+}
+
+static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+{
+       u32 reg, prediv, podf;
+
+       reg = __raw_readl(MXC_CCM_CS1CDR);
+
+       prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK)
+               >> MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+       podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK)
+               >> MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi1_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || div > 512)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+       reg = __raw_readl(MXC_CCM_CS1CDR);
+       reg &= ~(MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK |
+                MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK);
+       reg |= (post - 1) << MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET;
+       reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CS1CDR);
+
+       return 0;
+}
+
+static unsigned long _clk_extern_audio_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+       u32 div = parent_rate / rate;
+
+       if (parent_rate % rate)
+               div++;
+
+       __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+       return parent_rate / (pre * post);
+}
+
+static int _clk_extern_audio_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCMR2) & ~MXC_CCM_CSCMR2_ESAI_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll4_audio_main_clk, &pll3_pfd2_508M,
+                       &pll3_pfd3_454M,        &pll3_sw_clk, NULL, NULL);
+       reg |= mux << MXC_CCM_CSCMR2_ESAI_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CSCMR2);
+
+       return 0;
+}
+
+static unsigned long _clk_extern_audio_get_rate(struct clk *clk)
+{
+       u32 reg, pred, podf;
+
+       reg = __raw_readl(MXC_CCM_CS1CDR);
+
+       pred = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK)
+               >> MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET) + 1;
+       podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK)
+               >> MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_extern_audio_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || div > 64)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+       reg = __raw_readl(MXC_CCM_CS1CDR);
+       reg &= ~(MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK|
+                MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK);
+       reg |= (post - 1) << MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET;
+       reg |= (pre - 1) << MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CS1CDR);
+
+       return 0;
+}
+
+static struct clk extern_audio_clk = {
+       __INIT_CLK_DEBUG(extern_audio_clk)
+        .id = 0,
+        .parent = &pll3_sw_clk,
+        .secondary = &spba_clk,
+        .enable_reg = MXC_CCM_CCGR1,
+        .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        .set_rate = _clk_extern_audio_set_rate,
+        .get_rate = _clk_extern_audio_get_rate,
+        .set_parent = _clk_extern_audio_set_parent,
+        .round_rate = _clk_extern_audio_round_rate,
+};
+
+
+static int _clk_ssi1_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1)
+               & ~MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll3_pfd2_508M, &pll3_pfd3_454M,
+                       &pll4_audio_main_clk, NULL, NULL, NULL);
+       reg |= (mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static struct clk ssi1_clk = {
+       __INIT_CLK_DEBUG(ssi1_clk)
+       .parent = &pll3_pfd2_508M,
+       .enable_reg = MXC_CCM_CCGR5,
+       .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ssi1_set_parent,
+       .set_rate = _clk_ssi1_set_rate,
+       .round_rate = _clk_ssi_round_rate,
+       .get_rate = _clk_ssi1_get_rate,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+        .secondary = &ocram_clk,
+#else
+        .secondary = &mmdc_ch1_axi_clk[0],
+#endif
+};
+
+static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+{
+       u32 reg, prediv, podf;
+
+       reg = __raw_readl(MXC_CCM_CS2CDR);
+
+       prediv = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK)
+               >> MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET) + 1;
+       podf = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK)
+               >> MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi2_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || div > 512)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+       reg = __raw_readl(MXC_CCM_CS2CDR);
+       reg &= ~(MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK |
+                MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK);
+       reg |= (post - 1) << MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET;
+       reg |= (pre - 1) << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CS2CDR);
+
+       return 0;
+}
+
+
+static int _clk_ssi2_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1)
+               & ~MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll3_pfd2_508M, &pll3_pfd3_454M,
+                       &pll4_audio_main_clk, NULL, NULL, NULL);
+       reg |= (mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static struct clk ssi2_clk = {
+       __INIT_CLK_DEBUG(ssi2_clk)
+       .parent = &pll3_pfd2_508M,
+       .enable_reg = MXC_CCM_CCGR5,
+       .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ssi2_set_parent,
+       .set_rate = _clk_ssi2_set_rate,
+       .round_rate = _clk_ssi_round_rate,
+       .get_rate = _clk_ssi2_get_rate,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+        .secondary = &ocram_clk,
+#else
+        .secondary = &mmdc_ch1_axi_clk[0],
+#endif
+};
+
+static unsigned long _clk_ssi3_get_rate(struct clk *clk)
+{
+       u32 reg, prediv, podf;
+
+       reg = __raw_readl(MXC_CCM_CS1CDR);
+
+       prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK)
+               >> MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+       podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK)
+               >> MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi3_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || div > 512)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(1 << 6, div, &pre, &post);
+
+       reg = __raw_readl(MXC_CCM_CS1CDR);
+       reg &= ~(MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK|
+                MXC_CCM_CS1CDR_SSI3_CLK_PRED_MASK);
+       reg |= (post - 1) << MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET;
+       reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI3_CLK_PRED_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CS1CDR);
+
+       return 0;
+}
+
+
+static int _clk_ssi3_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll3_pfd2_508M, &pll3_pfd3_454M,
+                               &pll4_audio_main_clk, NULL, NULL, NULL);
+       reg |= (mux << MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static struct clk ssi3_clk = {
+       __INIT_CLK_DEBUG(ssi3_clk)
+       .parent = &pll3_pfd2_508M,
+       .enable_reg = MXC_CCM_CCGR5,
+       .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ssi3_set_parent,
+       .set_rate = _clk_ssi3_set_rate,
+       .round_rate = _clk_ssi_round_rate,
+       .get_rate = _clk_ssi3_get_rate,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+        .secondary = &ocram_clk,
+#else
+        .secondary = &mmdc_ch1_axi_clk[0],
+#endif
+};
+
+static unsigned long _clk_epdc_lcdif_pix_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+       u32 div = parent_rate / rate;
+
+       /* Round to closest divisor */
+       if ((parent_rate % rate) > (rate / 2))
+               div++;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 64)
+               div = 64;
+
+       __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+       printk("round_rate: parent_rate = %d, rate = %d, div = %d, pre = %d, post = %d\n",
+               parent_rate, rate, div, pre, post);
+
+       return parent_rate / (pre * post);
+}
+
+static unsigned long _clk_pxp_epdc_axi_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       /* Round to closest divisor */
+       if ((parent_rate % rate) > (rate / 2))
+               div++;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 8)
+               div = 8;
+
+       return parent_rate / div;
+}
+
+static unsigned long _clk_pxp_axi_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CHSCCDR);
+
+       div = ((reg & MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK) >>
+                        MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_pxp_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CHSCCDR);
+       reg &= ~MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+       return 0;
+}
+
+static int _clk_pxp_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CHSCCDR)
+               & ~MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+                       &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+                       &pll2_pfd0_352M, &pll2_pfd2_400M, &pll3_pfd1_540M);
+       reg |= (mux << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+       /* Derive clock from divided pre-muxed pxp_axi clock.*/
+       mux = 0;
+       reg = __raw_readl(MXC_CCM_CHSCCDR)
+               & ~MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK;
+       __raw_writel(reg | (mux << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET),
+               MXC_CCM_CHSCCDR);
+
+       return 0;
+}
+
+static unsigned long _clk_epdc_axi_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CHSCCDR);
+
+       div = ((reg & MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK)
+                       >> MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_epdc_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CHSCCDR);
+       reg &= ~MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+       return 0;
+}
+
+static int _clk_epdc_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CHSCCDR)
+               & ~MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+                       &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+                       &pll2_pfd0_352M, &pll2_pfd2_400M, &pll3_pfd1_540M);
+       reg |= (mux << MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CHSCCDR);
+
+       /* Derive clock from divided pre-muxed ipu1_di0 clock.*/
+       mux = 0;
+       reg = __raw_readl(MXC_CCM_CHSCCDR)
+               & ~MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK;
+       __raw_writel(reg | (mux << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET),
+               MXC_CCM_CHSCCDR);
+
+       return 0;
+}
+
+static struct clk pxp_axi_clk = {
+        __INIT_CLK_DEBUG(pxp_axi_clk)
+       .id = 0,
+       .parent = &pll5_video_main_clk,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_pxp_axi_set_parent,
+       .set_rate = _clk_pxp_axi_set_rate,
+       .round_rate = _clk_pxp_epdc_axi_round_rate,
+       .get_rate = _clk_pxp_axi_get_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk epdc_axi_clk = {
+        __INIT_CLK_DEBUG(epdc_axi_clk)
+       .id = 0,
+       .parent = &pll5_video_main_clk,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_epdc_axi_set_parent,
+       .set_rate = _clk_epdc_axi_set_rate,
+       .round_rate = _clk_pxp_epdc_axi_round_rate,
+       .get_rate = _clk_epdc_axi_get_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_lcdif_pix_get_rate(struct clk *clk)
+{
+       u32 reg, pre, post;
+
+       reg = __raw_readl(MXC_CCM_CSCDR2);
+
+       pre = ((reg & MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK) >>
+                       MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET) + 1;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       post = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK) >>
+                       MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / (pre * post);
+}
+
+static int _clk_lcdif_pix_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 64))
+               return -EINVAL;
+
+       __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+       reg = __raw_readl(MXC_CCM_CSCDR2);
+       reg &= ~MXC_CCM_CSCDR2_IPU2_DI0_PODF_MASK;
+       reg |= (pre - 1) << MXC_CCM_CSCDR2_IPU2_DI0_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR2);
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK;
+       reg |= (post - 1) << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static int _clk_lcdif_pix_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCDR2)
+               & ~MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+                       &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+                       &pll2_pfd0_352M, &pll3_pfd0_720M, &pll3_pfd1_540M);
+       reg |= (mux << MXC_CCM_CSCDR2_IPU2_DI0_PRE_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCDR2);
+
+       /* Derive clock from divided pre-muxed lcdif_pix clock.*/
+       mux = 0;
+       reg = __raw_readl(MXC_CCM_CSCDR2)
+               & ~MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_MASK;
+       __raw_writel(reg | (mux << MXC_CCM_CSCDR2_IPU2_DI0_CLK_SEL_OFFSET),
+               MXC_CCM_CSCDR2);
+
+       return 0;
+}
+
+static unsigned long _clk_epdc_pix_get_rate(struct clk *clk)
+{
+       u32 reg, pre, post;
+
+       reg = __raw_readl(MXC_CCM_CSCDR2);
+
+       pre = ((reg & MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK) >>
+               MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET) + 1;
+
+       reg = __raw_readl(MXC_CCM_CBCMR);
+       post = ((reg & MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK) >>
+               MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET) + 1;
+
+
+       return clk_get_rate(clk->parent) / (pre * post);
+}
+
+static int _clk_epdc_pix_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+
+       if (((parent_rate / div) != rate) || (div > 64))
+               return -EINVAL;
+
+       __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+       printk("pre %d, post %d\n", pre, post);
+
+       reg = __raw_readl(MXC_CCM_CSCDR2);
+       reg &= ~MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK;
+       reg |= (pre - 1) << MXC_CCM_CSCDR2_IPU2_DI1_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCDR2);
+
+       reg = __raw_readl(MXC_CCM_CBCMR);
+       reg &= ~MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK;
+       reg |= (post - 1) << MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CBCMR);
+
+       return 0;
+}
+
+static int _clk_epdc_pix_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCDR2)
+               & ~MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll2_528_bus_main_clk,
+                       &pll3_usb_otg_main_clk, &pll5_video_main_clk,
+                       &pll2_pfd0_352M, &pll2_pfd1_594M, &pll3_pfd1_540M);
+       reg |= (mux << MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCDR2);
+
+       return 0;
+}
+
+static struct clk lcdif_pix_clk = {
+        __INIT_CLK_DEBUG(lcdif_pix_clk)
+       .id = 0,
+       .parent = &pll5_video_main_clk,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_lcdif_pix_set_parent,
+       .set_rate = _clk_lcdif_pix_set_rate,
+       .round_rate = _clk_epdc_lcdif_pix_round_rate,
+       .get_rate = _clk_lcdif_pix_get_rate,
+       .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk epdc_pix_clk = {
+        __INIT_CLK_DEBUG(epdc_pix_clk)
+       .id = 0,
+       .parent = &pll3_pfd1_540M,
+       .enable_reg = MXC_CCM_CCGR3,
+       .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_epdc_pix_set_parent,
+       .set_rate = _clk_epdc_pix_set_rate,
+       .round_rate = _clk_epdc_lcdif_pix_round_rate,
+       .get_rate = _clk_epdc_pix_get_rate,
+       .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+static unsigned long _clk_spdif_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+       u32 div = parent_rate / rate;
+
+       if (parent_rate % rate)
+               div++;
+
+       __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+       return parent_rate / (pre * post);
+}
+
+static int _clk_spdif0_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CDCDR)
+               & ~MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK;
+
+       mux = _get_mux6(parent, &pll4_audio_main_clk,
+               &pll3_pfd2_508M, &pll3_pfd3_454M,
+               &pll3_sw_clk, NULL, NULL);
+       reg |= mux << MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CDCDR);
+
+       return 0;
+}
+
+static unsigned long _clk_spdif0_get_rate(struct clk *clk)
+{
+       u32 reg, pred, podf;
+
+       reg = __raw_readl(MXC_CCM_CDCDR);
+
+       pred = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK)
+               >> MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET) + 1;
+       podf = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK)
+               >> MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int _clk_spdif0_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div, pre, post;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || div > 64)
+               return -EINVAL;
+
+       __calc_pre_post_dividers(1 << 3, div, &pre, &post);
+
+       reg = __raw_readl(MXC_CCM_CDCDR);
+       reg &= ~(MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK|
+                MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK);
+       reg |= (post - 1) << MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET;
+       reg |= (pre - 1) << MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CDCDR);
+
+       return 0;
+}
+
+static struct clk spdif0_clk[] = {
+       {
+       __INIT_CLK_DEBUG(spdif0_clk_0)
+       .id = 0,
+       .parent = &pll3_sw_clk,
+        .enable = _clk_enable,
+        .enable_reg = MXC_CCM_CCGR5,
+        .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+        .disable = _clk_disable,
+        .secondary = &spdif0_clk[1],
+        .set_rate = _clk_spdif0_set_rate,
+        .get_rate = _clk_spdif0_get_rate,
+        .set_parent = _clk_spdif0_set_parent,
+        .round_rate = _clk_spdif_round_rate,
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       },
+       {
+       __INIT_CLK_DEBUG(spdif0_clk_1)
+        .id = 1,
+        .parent = &ipg_clk,
+        .secondary = &spba_clk,
+        },
+};
+
+static int _clk_ecspi_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCDR2) & ~MXC_CCM_CSCDR2_ECSPI_CLK_SEL_MASK;
+
+       if (parent == &pll3_60M)
+               mux = 0;
+       else
+               mux = 1; /* osc */
+
+       reg |= mux << MXC_CCM_CSCDR2_ECSPI_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CSCDR2);
+
+       return 0;
+}
+
+static int _clk_fec_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int reg, div = 1;
+
+       switch (rate) {
+       case 25000000:
+               div = 0;
+               break;
+       case 50000000:
+               div = 1;
+               break;
+       case 100000000:
+               div = 2;
+               break;
+       case 125000000:
+               div = 3;
+               break;
+       default:
+               return -EINVAL;
+       }
+       reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+       reg &= ~ANADIG_PLL_ENET_DIV_SELECT_MASK;
+       reg |= (div << ANADIG_PLL_ENET_DIV_SELECT_OFFSET);
+       __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+       return 0;
+}
+
+static unsigned long _clk_fec_get_rate(struct clk *clk)
+{
+       unsigned int div;
+
+       div = (__raw_readl(PLL8_ENET_BASE_ADDR))
+               & ANADIG_PLL_ENET_DIV_SELECT_MASK;
+
+       switch (div) {
+       case 0:
+               div = 20;
+               break;
+       case 1:
+               div = 10;
+               break;
+       case 3:
+               div = 5;
+               break;
+       case 4:
+               div = 4;
+               break;
+       }
+
+       return 500000000 / div;
+}
+
+static int _clk_fec_enable(struct clk *clk)
+{
+       unsigned int reg;
+
+       /* Enable ENET ref clock */
+       reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+       reg &= ~ANADIG_PLL_BYPASS;
+       reg |= ANADIG_PLL_ENABLE;
+       __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+
+       _clk_enable(clk);
+       return 0;
+}
+
+static void _clk_fec_disable(struct clk *clk)
+{
+       unsigned int reg;
+
+       _clk_disable(clk);
+
+       /* Enable ENET ref clock */
+       reg = __raw_readl(PLL8_ENET_BASE_ADDR);
+       reg |= ANADIG_PLL_BYPASS;
+       reg &= ~ANADIG_PLL_ENABLE;
+       __raw_writel(reg, PLL8_ENET_BASE_ADDR);
+}
+
+static struct clk fec_clk[] = {
+       {
+       __INIT_CLK_DEBUG(fec_clk)
+       .id = 0,
+       .parent = &pll6_enet_main_clk,
+       .enable_reg = MXC_CCM_CCGR1,
+       .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+       .enable = _clk_fec_enable,
+       .disable = _clk_fec_disable,
+       .set_rate = _clk_fec_set_rate,
+       .get_rate = _clk_fec_get_rate,
+       .secondary = &fec_clk[1],
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       },
+       {
+       .parent = &mmdc_ch1_axi_clk[0],
+       .secondary = &mx6per1_clk,
+       },
+};
+
+static struct clk ecspi_clk[] = {
+       {
+       __INIT_CLK_DEBUG(ecspi0_clk)
+       .id = 0,
+       .parent = &pll3_60M,
+       .secondary = &spba_clk,
+       .enable_reg = MXC_CCM_CCGR1,
+       .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ecspi_set_parent,
+       },
+       {
+       __INIT_CLK_DEBUG(ecspi1_clk)
+       .id = 1,
+       .parent = &pll3_60M,
+       .secondary = &spba_clk,
+       .enable_reg = MXC_CCM_CCGR1,
+       .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ecspi_set_parent,
+       },
+       {
+       __INIT_CLK_DEBUG(ecspi2_clk)
+       .id = 2,
+       .parent = &pll3_60M,
+       .secondary = &spba_clk,
+       .enable_reg = MXC_CCM_CCGR1,
+       .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ecspi_set_parent,
+       },
+       {
+       __INIT_CLK_DEBUG(ecspi3_clk)
+       .id = 3,
+       .parent = &pll3_60M,
+       .secondary = &spba_clk,
+       .enable_reg = MXC_CCM_CCGR1,
+       .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ecspi_set_parent,
+       },
+       {
+       __INIT_CLK_DEBUG(ecspi4_clk)
+       .id = 4,
+       .parent = &pll3_60M,
+       .secondary = &spba_clk,
+       .enable_reg = MXC_CCM_CCGR1,
+       .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable,
+       .set_parent = _clk_ecspi_set_parent,
+       },
+};
+
+static unsigned long _clk_emi_slow_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 8)
+               div = 8;
+
+       return parent_rate / div;
+}
+
+static int _clk_emi_slow_set_parent(struct clk *clk, struct clk *parent)
+{
+       int mux;
+       u32 reg = __raw_readl(MXC_CCM_CSCMR1)
+               & ~MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
+
+       mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk,
+                               &pll2_pfd2_400M, &pll3_pfd0_720M, NULL, NULL);
+       reg |= (mux << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET);
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static unsigned long _clk_emi_slow_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       div = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK) >>
+                       MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET) + 1;
+
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_emi_slow_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCMR1);
+       reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
+       reg |= (div - 1) << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET;
+       __raw_writel(reg, MXC_CCM_CSCMR1);
+
+       return 0;
+}
+
+static struct clk emi_slow_clk = {
+       __INIT_CLK_DEBUG(emi_slow_clk)
+        .id = 0,
+        .parent = &axi_clk,
+        .enable_reg = MXC_CCM_CCGR6,
+        .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        .set_rate = _clk_emi_slow_set_rate,
+        .get_rate = _clk_emi_slow_get_rate,
+        .round_rate = _clk_emi_slow_round_rate,
+        .set_parent = _clk_emi_slow_set_parent,
+};
+
+static unsigned long _clk_uart_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+
+       if (div > 64)
+               div = 64;
+
+       return parent_rate / div;
+}
+
+static int _clk_uart_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg, div;
+       u32 parent_rate = clk_get_rate(clk->parent);
+
+       div = parent_rate / rate;
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 64))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1) & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+       reg |= ((div - 1) << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
+
+       __raw_writel(reg, MXC_CCM_CSCDR1);
+
+       return 0;
+}
+
+static unsigned long _clk_uart_get_rate(struct clk *clk)
+{
+       u32 reg, div;
+       unsigned long val;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1) & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+       div = (reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+       val = clk_get_rate(clk->parent) / div;
+
+       return val;
+}
+
+static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 reg, mux;
+
+       reg = __raw_readl(MXC_CCM_CSCDR1) & ~MXC_CCM_CSCDR1_UART_CLK_SEL_MASK;
+
+       if (parent == &osc_clk)
+               mux = 1;
+       else
+               mux = 0; /* osc */
+
+       reg |= mux << MXC_CCM_CSCDR2_ECSPI_CLK_SEL_OFFSET;
+
+       __raw_writel(reg, MXC_CCM_CSCDR1);
+
+       return 0;
+}
+
+static struct clk uart_clk[] = {
+       {
+       __INIT_CLK_DEBUG(uart_clk)
+        .id = 0,
+        .parent = &pll3_80M,
+        .enable_reg = MXC_CCM_CCGR5,
+        .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        .secondary = &uart_clk[1],
+        .set_rate = _clk_uart_set_rate,
+        .get_rate = _clk_uart_get_rate,
+        .round_rate = _clk_uart_round_rate,
+        .set_parent = _clk_uart_set_parent,
+       },
+       {
+       __INIT_CLK_DEBUG(uart_serial_clk)
+        .id = 1,
+        .enable_reg = MXC_CCM_CCGR5,
+        .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+       },
+};
+
+static struct clk aips_tz2_clk = {
+       __INIT_CLK_DEBUG(aips_tz2_clk)
+       .parent = &ahb_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+static struct clk aips_tz1_clk = {
+       __INIT_CLK_DEBUG(aips_tz1_clk)
+       .parent = &ahb_clk,
+       .enable_reg = MXC_CCM_CCGR0,
+       .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+       .enable = _clk_enable,
+       .disable = _clk_disable_inwait,
+};
+
+/* set the parent by the ipcg table */
+
+static struct clk pwm_clk[] = {
+       {
+       __INIT_CLK_DEBUG(pwm_clk_0)
+        .parent = &ipg_perclk,
+        .id = 0,
+        .enable_reg = MXC_CCM_CCGR4,
+        .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        },
+       {
+       __INIT_CLK_DEBUG(pwm_clk_1)
+        .parent = &ipg_perclk,
+        .id = 1,
+        .enable_reg = MXC_CCM_CCGR4,
+        .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        },
+       {
+       __INIT_CLK_DEBUG(pwm_clk_2)
+        .parent = &ipg_perclk,
+        .id = 2,
+        .enable_reg = MXC_CCM_CCGR4,
+        .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        },
+       {
+       __INIT_CLK_DEBUG(pwm_clk_3)
+        .parent = &ipg_perclk,
+        .id = 3,
+        .enable_reg = MXC_CCM_CCGR4,
+        .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+        .enable = _clk_enable,
+        .disable = _clk_disable,
+        },
+};
+
+static struct clk usboh3_clk[] = {
+       {
+       __INIT_CLK_DEBUG(usboh3_clk)
+       .parent = &ahb_clk,
+       .enable = _clk_enable,
+       .enable_reg = MXC_CCM_CCGR6,
+       .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+       .disable = _clk_disable,
+       .secondary = &usboh3_clk[1],
+       .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       },
+       {
+       .parent = &mmdc_ch1_axi_clk[0],
+       .secondary = &mx6per1_clk,
+       },
+};
+
+static int _clk_enable1(struct clk *clk)
+{
+       u32 reg;
+       reg = __raw_readl(clk->enable_reg);
+       reg |= 1 << clk->enable_shift;
+       __raw_writel(reg, clk->enable_reg);
+
+       return 0;
+}
+
+static void _clk_disable1(struct clk *clk)
+{
+       u32 reg;
+       reg = __raw_readl(clk->enable_reg);
+       reg &= ~(1 << clk->enable_shift);
+       __raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 sel, reg;
+
+       if (parent == &pll3_usb_otg_main_clk)
+               sel = 0;
+       else if (parent == &pll2_528_bus_main_clk)
+               sel = 1;
+       else if (parent == &pll1_sys_main_clk)
+               sel = 2;
+       else if (parent == &pll5_video_main_clk)
+               sel = 3;
+       else if (parent == &axi_clk)
+               sel = 5;
+       else if (parent == &pxp_axi_clk)
+               sel = 7;
+       else if (parent == &epdc_axi_clk)
+               sel = 8;
+       else if (parent == &lcdif_pix_clk)
+               sel = 9;
+       else if (parent == &epdc_pix_clk)
+               sel = 10;
+       else if (parent == &ahb_clk)
+               sel = 11;
+       else if (parent == &ipg_clk)
+               sel = 12;
+       else if (parent == &ipg_perclk)
+               sel = 13;
+       else if (parent == &ckil_clk)
+               sel = 14;
+       else if (parent == &pll4_audio_main_clk)
+               sel = 15;
+       else
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CCOSR);
+       reg &= ~MXC_CCM_CCOSR_CKOL_SEL_MASK;
+       reg |= sel << MXC_CCM_CCOSR_CKOL_SEL_OFFSET;
+       __raw_writel(reg, MXC_CCM_CCOSR);
+       return 0;
+}
+
+static unsigned long _clk_clko_get_rate(struct clk *clk)
+{
+       u32 reg = __raw_readl(MXC_CCM_CCOSR);
+       u32 div = ((reg & MXC_CCM_CCOSR_CKOL_DIV_MASK) >>
+                       MXC_CCM_CCOSR_CKOL_DIV_OFFSET) + 1;
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg;
+       u32 parent_rate = clk_get_rate(clk->parent);
+       u32 div = parent_rate / rate;
+
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CCOSR);
+       reg &= ~MXC_CCM_CCOSR_CKOL_DIV_MASK;
+       reg |= (div - 1) << MXC_CCM_CCOSR_CKOL_DIV_OFFSET;
+       __raw_writel(reg, MXC_CCM_CCOSR);
+       return 0;
+}
+
+static unsigned long _clk_clko_round_rate(struct clk *clk,
+                                               unsigned long rate)
+{
+       u32 parent_rate = clk_get_rate(clk->parent);
+       u32 div = parent_rate / rate;
+
+       /* Make sure rate is not greater than the maximum value for the clock.
+        * Also prevent a div of 0.
+        */
+       if (div == 0)
+               div++;
+       if (div > 8)
+               div = 8;
+       return parent_rate / div;
+}
+
+static int _clk_clko2_set_parent(struct clk *clk, struct clk *parent)
+{
+       u32 sel, reg;
+
+       if (parent == &mmdc_ch1_axi_clk[0])
+               sel = 0;
+       else if (parent == &usdhc4_clk)
+               sel = 2;
+       else if (parent == &usdhc1_clk)
+               sel = 3;
+       else if (parent == &ecspi_clk[0])
+               sel = 6;
+       else if (parent == &usdhc3_clk)
+               sel = 8;
+       else if (parent == &ipu1_clk)
+               sel = 11;
+       else if (parent == &ipu2_clk)
+               sel = 12;
+
+       else if (parent == &osc_clk)
+               sel = 14;
+       else if (parent == &usdhc2_clk)
+               sel = 17;
+       else if (parent == &ssi1_clk)
+               sel = 18;
+       else if (parent == &ssi2_clk)
+               sel = 19;
+       else if (parent == &ssi3_clk)
+               sel = 20;
+       else if (parent == &uart_clk[0])
+               sel = 28;
+       else if (parent == &spdif0_clk[0])
+               sel = 29;
+       else if (parent == &spdif0_clk[1])
+               sel = 30;
+       else
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CCOSR);
+       reg &= ~MXC_CCM_CCOSR_CKO2_SEL_MASK;
+       reg |= sel << MXC_CCM_CCOSR_CKO2_SEL_OFFSET;
+       __raw_writel(reg, MXC_CCM_CCOSR);
+       return 0;
+}
+
+static unsigned long _clk_clko2_get_rate(struct clk *clk)
+{
+       u32 reg = __raw_readl(MXC_CCM_CCOSR);
+       u32 div = ((reg & MXC_CCM_CCOSR_CKO2_DIV_MASK) >>
+                       MXC_CCM_CCOSR_CKO2_DIV_OFFSET) + 1;
+       return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_clko2_set_rate(struct clk *clk, unsigned long rate)
+{
+       u32 reg;
+       u32 parent_rate = clk_get_rate(clk->parent);
+       u32 div = parent_rate / rate;
+
+       if (div == 0)
+               div++;
+       if (((parent_rate / div) != rate) || (div > 8))
+               return -EINVAL;
+
+       reg = __raw_readl(MXC_CCM_CCOSR);
+       reg &= ~MXC_CCM_CCOSR_CKO2_DIV_MASK;
+       reg |= (div - 1) << MXC_CCM_CCOSR_CKO2_DIV_OFFSET;
+       __raw_writel(reg, MXC_CCM_CCOSR);
+       return 0;
+}
+
+static struct clk clko_clk = {
+       __INIT_CLK_DEBUG(clko_clk)
+       .parent = &pll2_528_bus_main_clk,
+       .enable = _clk_enable1,
+       .enable_reg = MXC_CCM_CCOSR,
+       .enable_shift = MXC_CCM_CCOSR_CKOL_EN_OFFSET,
+       .disable = _clk_disable1,
+       .set_parent = _clk_clko_set_parent,
+       .set_rate = _clk_clko_set_rate,
+       .get_rate = _clk_clko_get_rate,
+       .round_rate = _clk_clko_round_rate,
+};
+
+static struct clk clko2_clk = {
+       __INIT_CLK_DEBUG(clko2_clk)
+       .parent = &usdhc4_clk,
+       .enable = _clk_enable1,
+       .enable_reg = MXC_CCM_CCOSR,
+       .enable_shift = MXC_CCM_CCOSR_CKO2_EN_OFFSET,
+       .disable = _clk_disable1,
+       .set_parent = _clk_clko2_set_parent,
+       .set_rate = _clk_clko2_set_rate,
+       .get_rate = _clk_clko2_get_rate,
+       .round_rate = _clk_clko_round_rate,
+};
+
+static struct clk perfmon0_clk = {
+       __INIT_CLK_DEBUG(perfmon0_clk)
+       .parent = &mmdc_ch1_axi_clk[0],
+       .enable = _clk_enable1,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+       .disable = _clk_disable1,
+};
+
+static struct clk perfmon1_clk = {
+       __INIT_CLK_DEBUG(perfmon1_clk)
+       .parent = &ipu1_clk,
+       .enable = _clk_enable1,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+       .disable = _clk_disable1,
+};
+
+static struct clk perfmon2_clk = {
+       __INIT_CLK_DEBUG(perfmon2_clk)
+       .parent = &mmdc_ch1_axi_clk[0],
+       .enable = _clk_enable1,
+       .enable_reg = MXC_CCM_CCGR4,
+       .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+       .disable = _clk_disable1,
+};
+
+static struct clk dummy_clk = {
+       .id = 0,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+       { \
+               .dev_id = d, \
+               .con_id = n, \
+               .clk = &c, \
+       }
+
+
+static struct clk_lookup lookups[] = {
+       _REGISTER_CLOCK(NULL, "osc", osc_clk),
+       _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+       _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk),
+       _REGISTER_CLOCK(NULL, "ckil", ckil_clk),
+       _REGISTER_CLOCK(NULL, "pll1_main_clk", pll1_sys_main_clk),
+       _REGISTER_CLOCK(NULL, "pll1_sw_clk", pll1_sw_clk),
+       _REGISTER_CLOCK(NULL, "pll2", pll2_528_bus_main_clk),
+       _REGISTER_CLOCK(NULL, "pll2_pfd2_400M", pll2_pfd2_400M),
+       _REGISTER_CLOCK(NULL, "pll2_pfd0_352M", pll2_pfd0_352M),
+       _REGISTER_CLOCK(NULL, "pll2_pfd1_594M", pll2_pfd1_594M),
+       _REGISTER_CLOCK(NULL, "pll2_200M", pll2_200M),
+       _REGISTER_CLOCK(NULL, "pll3_main_clk", pll3_usb_otg_main_clk),
+       _REGISTER_CLOCK(NULL, "pll3_pfd2_508M", pll3_pfd2_508M),
+       _REGISTER_CLOCK(NULL, "pll3_pfd3_454M", pll3_pfd3_454M),
+       _REGISTER_CLOCK(NULL, "pll3_pfd0_720M", pll3_pfd0_720M),
+       _REGISTER_CLOCK(NULL, "pll3_pfd1_540M", pll3_pfd1_540M),
+       _REGISTER_CLOCK(NULL, "pll3_sw_clk", pll3_sw_clk),
+       _REGISTER_CLOCK(NULL, "pll3_120M", pll3_120M),
+       _REGISTER_CLOCK(NULL, "pll3_80M", pll3_80M),
+       _REGISTER_CLOCK(NULL, "pll3_60M", pll3_60M),
+       _REGISTER_CLOCK(NULL, "pll4", pll4_audio_main_clk),
+       _REGISTER_CLOCK(NULL, "pll5", pll5_video_main_clk),
+       _REGISTER_CLOCK(NULL, "pll6", pll6_enet_main_clk),
+       _REGISTER_CLOCK(NULL, "extern_audio_clk", extern_audio_clk),
+       _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk),
+       _REGISTER_CLOCK("smp_twd", NULL, twd_clk),
+       _REGISTER_CLOCK(NULL, "periph_clk", periph_clk),
+       _REGISTER_CLOCK(NULL, "axi_clk", axi_clk),
+       _REGISTER_CLOCK(NULL, "mmdc_ch0_axi", mmdc_ch1_axi_clk[0]),
+       _REGISTER_CLOCK(NULL, "ahb", ahb_clk),
+       _REGISTER_CLOCK(NULL, "ipg_clk", ipg_clk),
+       _REGISTER_CLOCK(NULL, "ipg_perclk", ipg_perclk),
+       _REGISTER_CLOCK(NULL, "spba", spba_clk),
+       _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk[0]),
+       _REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+       _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[0]),
+       _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk[1]),
+       _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]),
+       _REGISTER_CLOCK(NULL, "csi_clk", ipu1_clk),
+       _REGISTER_CLOCK(NULL, "elcdif_axi", ipu2_clk),
+       _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, usdhc1_clk),
+       _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, usdhc2_clk),
+       _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, usdhc3_clk),
+       _REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, usdhc4_clk),
+       _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk),
+       _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk),
+       _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk),
+       _REGISTER_CLOCK(NULL, "pxp_axi", pxp_axi_clk),
+       _REGISTER_CLOCK(NULL, "epdc_axi", epdc_axi_clk),
+       _REGISTER_CLOCK(NULL, "epdc_pix", epdc_pix_clk),
+       _REGISTER_CLOCK(NULL, "elcdif_pix", lcdif_pix_clk),
+       _REGISTER_CLOCK("mxc_spdif.0", NULL, spdif0_clk[0]),
+       _REGISTER_CLOCK("imx6q-ecspi.0", NULL, ecspi_clk[0]),
+       _REGISTER_CLOCK("imx6q-ecspi.1", NULL, ecspi_clk[1]),
+       _REGISTER_CLOCK("imx6q-ecspi.2", NULL, ecspi_clk[2]),
+       _REGISTER_CLOCK("imx6q-ecspi.3", NULL, ecspi_clk[3]),
+       _REGISTER_CLOCK("imx6q-ecspi.4", NULL, ecspi_clk[4]),
+       _REGISTER_CLOCK(NULL, "emi_slow_clk", emi_slow_clk),
+       _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0]),
+       _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[0]),
+       _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[0]),
+       _REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[0]),
+       _REGISTER_CLOCK(NULL, "gpt", gpt_clk[0]),
+       _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk[0]),
+       _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm_clk[1]),
+       _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm_clk[2]),
+       _REGISTER_CLOCK("mxc_pwm.3", NULL, pwm_clk[3]),
+       _REGISTER_CLOCK("fec.0", NULL, fec_clk[0]),
+       _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk[0]),
+       _REGISTER_CLOCK(NULL, "usb_phy1_clk", usb_phy1_clk),
+       _REGISTER_CLOCK(NULL, "usb_phy3_clk", usb_phy3_clk),
+       _REGISTER_CLOCK(NULL, "usb_phy4_clk", usb_phy4_clk),
+       _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk),
+       _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk),
+       _REGISTER_CLOCK(NULL, NULL, aips_tz2_clk),
+       _REGISTER_CLOCK(NULL, NULL, aips_tz1_clk),
+       _REGISTER_CLOCK(NULL, "clko_clk", clko_clk),
+       _REGISTER_CLOCK(NULL, "clko2_clk", clko2_clk),
+       _REGISTER_CLOCK("mxs-perfmon.0", "perfmon", perfmon0_clk),
+       _REGISTER_CLOCK("mxs-perfmon.1", "perfmon", perfmon1_clk),
+       _REGISTER_CLOCK("mxs-perfmon.2", "perfmon", perfmon2_clk),
+       _REGISTER_CLOCK(NULL, "anaclk_1", anaclk_1),
+       _REGISTER_CLOCK(NULL, "anaclk_2", anaclk_2),
+};
+
+static void clk_tree_init(void)
+
+{
+       unsigned int reg;
+
+       reg = __raw_readl(MMDC_MDMISC_OFFSET);
+       /*
+        * For lpddr2 board, current freq only support up to 400MHz,
+        * in this case, periph clk will set to 400MHz in uboot,
+        * so in clock init, we need to check whether the ddr clock
+        * is set to 400MHz, if yes, then we should set periph clk
+        * parent to pll2_pfd_400M.
+        */
+       if ((reg & MMDC_MDMISC_DDR_TYPE_MASK) ==
+               (0x1 << MMDC_MDMISC_DDR_TYPE_OFFSET)) {
+               clk_set_parent(&periph_clk, &pll2_pfd2_400M);
+               printk(KERN_INFO "Set periph_clk's parent to pll2_pfd2_400M!\n");
+       }
+}
+
+
+int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc,
+       unsigned long ckih1, unsigned long ckih2)
+{
+       __iomem void *base;
+       int i;
+
+       external_low_reference = ckil;
+       external_high_reference = ckih1;
+       ckih2_reference = ckih2;
+       oscillator_reference = osc;
+
+       apll_base = ioremap(ANATOP_BASE_ADDR, SZ_4K);
+
+       for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+               clkdev_add(&lookups[i]);
+               clk_debug_register(lookups[i].clk);
+       }
+
+       /* Disable un-necessary PFDs & PLLs */
+
+       /* keep correct count. */
+       clk_enable(&cpu_clk);
+       clk_enable(&periph_clk);
+
+       clk_tree_init();
+
+       pll2_pfd0_352M.disable(&pll2_pfd0_352M);
+       pll2_pfd1_594M.disable(&pll2_pfd1_594M);
+
+       pll3_pfd3_454M.disable(&pll3_pfd3_454M);
+       pll3_pfd2_508M.disable(&pll3_pfd2_508M);
+       pll3_pfd1_540M.disable(&pll3_pfd1_540M);
+       pll3_pfd0_720M.disable(&pll3_pfd0_720M);
+
+       pll3_usb_otg_main_clk.disable(&pll3_usb_otg_main_clk);
+       pll4_audio_main_clk.disable(&pll4_audio_main_clk);
+       pll5_video_main_clk.disable(&pll5_video_main_clk);
+       pll6_enet_main_clk.disable(&pll6_enet_main_clk);
+
+       /* Initialize Audio and Video PLLs to valid frequency (650MHz). */
+       clk_set_rate(&pll4_audio_main_clk, 650000000);
+       clk_set_rate(&pll5_video_main_clk, 650000000);
+
+       clk_set_parent(&clko_clk, &ipg_clk);
+
+       mx6_cpu_op_init();
+       cpu_op_tbl = get_cpu_op(&cpu_op_nr);
+
+       /* Gate off all possible clocks */
+       if (mxc_jtag_enabled) {
+               __raw_writel(3 << MXC_CCM_CCGRx_CG11_OFFSET |
+                            3 << MXC_CCM_CCGRx_CG2_OFFSET |
+                            3 << MXC_CCM_CCGRx_CG1_OFFSET |
+                            3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0);
+       } else {
+               __raw_writel(1 << MXC_CCM_CCGRx_CG11_OFFSET |
+                            3 << MXC_CCM_CCGRx_CG2_OFFSET |
+                            3 << MXC_CCM_CCGRx_CG1_OFFSET |
+                            3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0);
+       }
+       __raw_writel(3 << MXC_CCM_CCGRx_CG10_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR1);
+       __raw_writel(1 << MXC_CCM_CCGRx_CG12_OFFSET |
+                    1 << MXC_CCM_CCGRx_CG11_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG10_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG9_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2);
+       __raw_writel(1 << MXC_CCM_CCGRx_CG14_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG13_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG12_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG11_OFFSET |
+                    3 << MXC_CCM_CCGRx_CG10_OFFSET, MXC_CCM_CCGR3);
+       __raw_writel(3 << MXC_CCM_CCGRx_CG7_OFFSET |
+                       1 << MXC_CCM_CCGRx_CG6_OFFSET |
+                       1 << MXC_CCM_CCGRx_CG4_OFFSET, MXC_CCM_CCGR4);
+       __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR5);
+
+       __raw_writel(0, MXC_CCM_CCGR6);
+
+       /* S/PDIF */
+       clk_set_parent(&spdif0_clk[0], &pll3_pfd3_454M);
+
+       /* pxp & epdc axi */
+       clk_set_parent(&pxp_axi_clk, &pll2_pfd2_400M);
+       clk_set_rate(&pxp_axi_clk, 198000000);
+       clk_set_parent(&epdc_axi_clk, &pll2_pfd2_400M);
+       clk_set_rate(&epdc_axi_clk, 198000000);
+
+       /* epdc pix - PLL5 as parent */
+       clk_set_parent(&epdc_pix_clk, &pll5_video_main_clk);
+
+       gpt_clk[0].parent = &ipg_perclk;
+       gpt_clk[0].get_rate = NULL;
+
+       /* GPT will source from perclk, hence ipg_perclk
+        * should be from OSC24M */
+       clk_set_parent(&ipg_perclk, &osc_clk);
+
+       base = ioremap(GPT_BASE_ADDR, SZ_4K);
+       mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT);
+
+       lp_high_freq = 0;
+       lp_med_freq = 0;
+
+       return 0;
+
+}
index 0af4b5bbf04d34e5a9e5860611b2cdadb080b80b..1ae8ac96adbe5d403a98b11d274dbfede31903dd 100644 (file)
 #define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET             (12)
 #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK               (0x3 << 10)
 #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET             (10)
+#define MXC_CCM_CSCMR1_PERCLK_CLK_SEL_MASK             (0x1 << 6)
+#define MXC_CCM_CSCMR1_PERCLK_CLK_SEL_OFFSET   (6)
 #define MXC_CCM_CSCMR1_PERCLK_PODF_MASK                        (0x3F)
 #define MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET              (0)
 
 #define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET          (8)
 #define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK            (0x7 << 8)
 #define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET          (6)
+#define MXC_CCM_CSCDR1_UART_CLK_SEL_MASK               (0x1 << 6)
+#define MXC_CCM_CSCDR1_UART_CLK_SEL_OFFSET             (6)
 #define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK            (0x3 << 6)
 #define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK              (0x3F)
 #define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET            (0)
 /* Define the bits in register CSCDR2 */
 #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK             (0x3F << 19)
 #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET           (19)
+#define MXC_CCM_CSCDR2_ECSPI_CLK_SEL_MASK              (0x1 << 18)
+#define MXC_CCM_CSCDR2_ECSPI_CLK_SEL_OFFSET            (18)
 #define MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_MASK       (0x7 << 15)
 #define MXC_CCM_CSCDR2_IPU2_DI1_PRE_CLK_SEL_OFFSET     (15)
 #define MXC_CCM_CSCDR2_IPU2_DI1_PODF_MASK              (0x7 << 12)
index de91ac7c1e367857b77fd428f8089f77e87c264d..4edcaea09b1463670d65aa161f77fb6a9bcfc22e 100755 (executable)
@@ -74,6 +74,8 @@ extern int mx50_clocks_init(unsigned long ckil, unsigned long osc,
                        unsigned long ckih1);
 extern int mx6_clocks_init(unsigned long ckil, unsigned long osc,
                        unsigned long ckih1, unsigned long ckih2);
+extern int mx6sl_clocks_init(unsigned long ckil, unsigned long osc,
+                       unsigned long ckih1, unsigned long ckih2);
 extern void imx6_init_fec(struct fec_platform_data fec_data);
 extern int mxc91231_clocks_init(unsigned long fref);
 extern int mxc_register_gpios(void);
index bb247b41692e690fe7a6aefb5111202be827fa2d..3f99628a410eb1b0958a3bdbdc468c0efbe3e13c 100644 (file)
@@ -339,7 +339,7 @@ void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
        __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
 
        if (timer_is_v2()) {
-               if (cpu_is_mx5() ||
+               if (cpu_is_mx5() || cpu_is_mx6sl() ||
                        mx6q_revision() == IMX_CHIP_REVISION_1_0)
                        tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR |
                                                V2_TCTL_WAITEN | MXC_TCTL_TEN;