[ARM] MX27 Clock rework
authorSascha Hauer <s.hauer@pengutronix.de>
Mon, 16 Feb 2009 14:13:43 +0000 (15:13 +0100)
committerSascha Hauer <s.hauer@pengutronix.de>
Fri, 13 Mar 2009 09:33:51 +0000 (10:33 +0100)
This changes MX27 to use common clkdev. It also cleans up MX27 clock
support to be more readable.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
arch/arm/mach-mx2/clock_imx27.c
arch/arm/mach-mx2/cpu_imx27.c
arch/arm/mach-mx2/crm_regs.h [deleted file]
arch/arm/plat-mxc/Kconfig

index 700a22f5ae88066cec742635f340a078dacd10a3..3f7280c490f0754c29dc92f78a3e599f169deb37 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
 
-#include <mach/clock.h>
-#include <mach/common.h>
+#include <asm/clkdev.h>
 #include <asm/div64.h>
 
-#include "crm_regs.h"
-
-static struct clk ckil_clk;
-static struct clk mpll_clk;
-static struct clk mpll_main_clk[];
-static struct clk spll_clk;
-
-static int _clk_enable(struct clk *clk)
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+/* Register offsets */
+#define CCM_CSCR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
+#define CCM_MPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
+#define CCM_MPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
+#define CCM_SPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
+#define CCM_SPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
+#define CCM_OSC26MCTL           (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
+#define CCM_PCDR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
+#define CCM_PCDR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
+#define CCM_PCCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
+#define CCM_PCCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
+#define CCM_CCSR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
+#define CCM_PMCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
+#define CCM_PMCOUNT             (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
+#define CCM_WKGDCTL             (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
+
+#define CCM_CSCR_UPDATE_DIS    (1 << 31)
+#define CCM_CSCR_SSI2          (1 << 23)
+#define CCM_CSCR_SSI1          (1 << 22)
+#define CCM_CSCR_VPU           (1 << 21)
+#define CCM_CSCR_MSHC           (1 << 20)
+#define CCM_CSCR_SPLLRES        (1 << 19)
+#define CCM_CSCR_MPLLRES        (1 << 18)
+#define CCM_CSCR_SP             (1 << 17)
+#define CCM_CSCR_MCU            (1 << 16)
+#define CCM_CSCR_OSC26MDIV      (1 << 4)
+#define CCM_CSCR_OSC26M         (1 << 3)
+#define CCM_CSCR_FPM            (1 << 2)
+#define CCM_CSCR_SPEN           (1 << 1)
+#define CCM_CSCR_MPEN           (1 << 0)
+
+/* i.MX27 TO 2+ */
+#define CCM_CSCR_ARM_SRC        (1 << 15)
+
+#define CCM_SPCTL1_LF           (1 << 15)
+#define CCM_SPCTL1_BRMO         (1 << 6)
+
+static struct clk mpll_main1_clk, mpll_main2_clk;
+
+static int clk_pccr_enable(struct clk *clk)
 {
        unsigned long reg;
 
+       if (!clk->enable_reg)
+               return 0;
+
        reg = __raw_readl(clk->enable_reg);
        reg |= 1 << clk->enable_shift;
        __raw_writel(reg, clk->enable_reg);
@@ -44,16 +82,19 @@ static int _clk_enable(struct clk *clk)
        return 0;
 }
 
-static void _clk_disable(struct clk *clk)
+static void clk_pccr_disable(struct clk *clk)
 {
        unsigned long reg;
 
+       if (!clk->enable_reg)
+               return;
+
        reg = __raw_readl(clk->enable_reg);
        reg &= ~(1 << clk->enable_shift);
        __raw_writel(reg, clk->enable_reg);
 }
 
-static int _clk_spll_enable(struct clk *clk)
+static int clk_spll_enable(struct clk *clk)
 {
        unsigned long reg;
 
@@ -61,13 +102,12 @@ static int _clk_spll_enable(struct clk *clk)
        reg |= CCM_CSCR_SPEN;
        __raw_writel(reg, CCM_CSCR);
 
-       while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
-               ;
+       while (!(__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF));
 
        return 0;
 }
 
-static void _clk_spll_disable(struct clk *clk)
+static void clk_spll_disable(struct clk *clk)
 {
        unsigned long reg;
 
@@ -76,192 +116,30 @@ static void _clk_spll_disable(struct clk *clk)
        __raw_writel(reg, CCM_CSCR);
 }
 
-static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
-{
-       unsigned long reg;
-
-       reg = __raw_readl(CCM_PCCR0);
-       reg |= mask0;
-       __raw_writel(reg, CCM_PCCR0);
-
-       reg = __raw_readl(CCM_PCCR1);
-       reg |= mask1;
-       __raw_writel(reg, CCM_PCCR1);
-
-}
-
-static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1)
-{
-       unsigned long reg;
-
-       reg = __raw_readl(CCM_PCCR0);
-       reg &= ~mask0;
-       __raw_writel(reg, CCM_PCCR0);
-
-       reg = __raw_readl(CCM_PCCR1);
-       reg &= ~mask1;
-       __raw_writel(reg, CCM_PCCR1);
-}
-
-static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0)
-{
-       unsigned long reg;
-
-       reg = __raw_readl(CCM_PCCR1);
-       reg |= mask1;
-       __raw_writel(reg, CCM_PCCR1);
-
-       reg = __raw_readl(CCM_PCCR0);
-       reg |= mask0;
-       __raw_writel(reg, CCM_PCCR0);
-}
-
-static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0)
-{
-       unsigned long reg;
-
-       reg = __raw_readl(CCM_PCCR1);
-       reg &= ~mask1;
-       __raw_writel(reg, CCM_PCCR1);
-
-       reg = __raw_readl(CCM_PCCR0);
-       reg &= ~mask0;
-       __raw_writel(reg, CCM_PCCR0);
-}
-
-static int _clk_dma_enable(struct clk *clk)
-{
-       _clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
-
-       return 0;
-}
-
-static void _clk_dma_disable(struct clk *clk)
-{
-       _clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
-}
-
-static int _clk_rtic_enable(struct clk *clk)
-{
-       _clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
-
-       return 0;
-}
-
-static void _clk_rtic_disable(struct clk *clk)
-{
-       _clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
-}
-
-static int _clk_emma_enable(struct clk *clk)
-{
-       _clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
-
-       return 0;
-}
-
-static void _clk_emma_disable(struct clk *clk)
-{
-       _clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
-}
-
-static int _clk_slcdc_enable(struct clk *clk)
-{
-       _clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
-
-       return 0;
-}
-
-static void _clk_slcdc_disable(struct clk *clk)
-{
-       _clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
-}
-
-static int _clk_fec_enable(struct clk *clk)
-{
-       _clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
-
-       return 0;
-}
-
-static void _clk_fec_disable(struct clk *clk)
-{
-       _clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
-}
-
-static int _clk_vpu_enable(struct clk *clk)
-{
-       unsigned long reg;
-
-       reg = __raw_readl(CCM_PCCR1);
-       reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK;
-       __raw_writel(reg, CCM_PCCR1);
-
-       return 0;
-}
-
-static void _clk_vpu_disable(struct clk *clk)
-{
-       unsigned long reg;
-
-       reg = __raw_readl(CCM_PCCR1);
-       reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK);
-       __raw_writel(reg, CCM_PCCR1);
-}
-
-static int _clk_sahara2_enable(struct clk *clk)
-{
-       _clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
-
-       return 0;
-}
-
-static void _clk_sahara2_disable(struct clk *clk)
-{
-       _clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
-}
-
-static int _clk_mstick1_enable(struct clk *clk)
-{
-       _clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
-
-       return 0;
-}
-
-static void _clk_mstick1_disable(struct clk *clk)
+static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
 {
-       _clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
-}
-
-#define CSCR() (__raw_readl(CCM_CSCR))
-#define PCDR0() (__raw_readl(CCM_PCDR0))
-#define PCDR1() (__raw_readl(CCM_PCDR1))
-
-static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent)
-{
-       int cscr = CSCR();
+       int cscr = __raw_readl(CCM_CSCR);
 
        if (clk->parent == parent)
                return 0;
 
        if (mx27_revision() >= CHIP_REV_2_0) {
-               if (parent == &mpll_main_clk[0]) {
+               if (parent == &mpll_main1_clk) {
                        cscr |= CCM_CSCR_ARM_SRC;
                } else {
-                       if (parent == &mpll_main_clk[1])
+                       if (parent == &mpll_main2_clk)
                                cscr &= ~CCM_CSCR_ARM_SRC;
                        else
                                return -EINVAL;
                }
                __raw_writel(cscr, CCM_CSCR);
-       } else
-               return -ENODEV;
-
-       clk->parent = parent;
-       return 0;
+               clk->parent = parent;
+               return 0;
+       }
+       return -ENODEV;
 }
 
-static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
 {
        int div;
        unsigned long parent_rate;
@@ -278,7 +156,7 @@ static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
        return parent_rate / div;
 }
 
-static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+static int set_rate_cpu(struct clk *clk, unsigned long rate)
 {
        unsigned int div;
        uint32_t reg;
@@ -295,19 +173,18 @@ static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
 
        reg = __raw_readl(CCM_CSCR);
        if (mx27_revision() >= CHIP_REV_2_0) {
-               reg &= ~CCM_CSCR_ARM_MASK;
-               reg |= div << CCM_CSCR_ARM_OFFSET;
-               reg &= ~0x06;
-               __raw_writel(reg | 0x80000000, CCM_CSCR);
+               reg &= ~(3 << 12);
+               reg |= div << 12;
+               reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN);
+               __raw_writel(reg | CCM_CSCR_UPDATE_DIS, CCM_CSCR);
        } else {
-               printk(KERN_ERR "Cant set CPU frequency!\n");
+               printk(KERN_ERR "Can't set CPU frequency!\n");
        }
 
        return 0;
 }
 
-static unsigned long _clk_perclkx_round_rate(struct clk *clk,
-                                            unsigned long rate)
+static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
 {
        u32 div;
        unsigned long parent_rate;
@@ -324,7 +201,7 @@ static unsigned long _clk_perclkx_round_rate(struct clk *clk,
        return parent_rate / div;
 }
 
-static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
+static int set_rate_per(struct clk *clk, unsigned long rate)
 {
        u32 reg;
        u32 div;
@@ -340,84 +217,65 @@ static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
                return -EINVAL;
        div--;
 
-       reg =
-           __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
-                                      (clk->id << 3));
+       reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3));
        reg |= div << (clk->id << 3);
        __raw_writel(reg, CCM_PCDR1);
 
        return 0;
 }
 
-static unsigned long _clk_usb_recalc(struct clk *clk)
+static unsigned long get_rate_usb(struct clk *clk)
 {
        unsigned long usb_pdf;
        unsigned long parent_rate;
 
        parent_rate = clk_get_rate(clk->parent);
 
-       usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
+       usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7;
 
        return parent_rate / (usb_pdf + 1U);
 }
 
-static unsigned long _clk_ssi1_recalc(struct clk *clk)
+static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
 {
-       unsigned long ssi1_pdf;
        unsigned long parent_rate;
 
        parent_rate = clk_get_rate(clk->parent);
 
-       ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >>
-                                       CCM_PCDR0_SSI1BAUDDIV_OFFSET;
-
        if (mx27_revision() >= CHIP_REV_2_0)
-               ssi1_pdf += 4;
+               pdf += 4;  /* MX27 TO2+ */
        else
-               ssi1_pdf = (ssi1_pdf < 2) ? 124UL : ssi1_pdf;
+               pdf = (pdf < 2) ? 124UL : pdf;  /* MX21 & MX27 TO1 */
 
-       return 2UL * parent_rate / ssi1_pdf;
+       return 2UL * parent_rate / pdf;
 }
 
-static unsigned long _clk_ssi2_recalc(struct clk *clk)
+static unsigned long get_rate_ssi1(struct clk *clk)
 {
-       unsigned long ssi2_pdf;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
-           CCM_PCDR0_SSI2BAUDDIV_OFFSET;
-
-       if (mx27_revision() >= CHIP_REV_2_0)
-               ssi2_pdf += 4;
-       else
-               ssi2_pdf = (ssi2_pdf < 2) ? 124UL : ssi2_pdf;
+       return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
+}
 
-       return 2UL * parent_rate / ssi2_pdf;
+static unsigned long get_rate_ssi2(struct clk *clk)
+{
+       return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
 }
 
-static unsigned long _clk_nfc_recalc(struct clk *clk)
+static unsigned long get_rate_nfc(struct clk *clk)
 {
        unsigned long nfc_pdf;
        unsigned long parent_rate;
 
        parent_rate = clk_get_rate(clk->parent);
 
-       if (mx27_revision() >= CHIP_REV_2_0) {
-               nfc_pdf =
-                   (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >>
-                   CCM_PCDR0_NFCDIV2_OFFSET;
-       } else {
-               nfc_pdf =
-                   (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >>
-                   CCM_PCDR0_NFCDIV_OFFSET;
-       }
+       if (mx27_revision() >= CHIP_REV_2_0)
+               nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
+       else
+               nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf;
 
        return parent_rate / (nfc_pdf + 1);
 }
 
-static unsigned long _clk_vpu_recalc(struct clk *clk)
+static unsigned long get_rate_vpu(struct clk *clk)
 {
        unsigned long vpu_pdf;
        unsigned long parent_rate;
@@ -425,25 +283,27 @@ static unsigned long _clk_vpu_recalc(struct clk *clk)
        parent_rate = clk_get_rate(clk->parent);
 
        if (mx27_revision() >= CHIP_REV_2_0) {
-               vpu_pdf =
-                   (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >>
-                   CCM_PCDR0_VPUDIV2_OFFSET;
+               vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
                vpu_pdf += 4;
        } else {
-               vpu_pdf =
-                   (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >>
-                   CCM_PCDR0_VPUDIV_OFFSET;
+               vpu_pdf = (__raw_readl(CCM_PCDR0) >> 8) & 0xf;
                vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
        }
+
        return 2UL * parent_rate / vpu_pdf;
 }
 
-static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_parent(struct clk *clk, unsigned long rate)
 {
        return clk->parent->round_rate(clk->parent, rate);
 }
 
-static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
+static unsigned long get_rate_parent(struct clk *clk)
+{
+       return clk_get_rate(clk->parent);
+}
+
+static int set_rate_parent(struct clk *clk, unsigned long rate)
 {
        return clk->parent->set_rate(clk->parent, rate);
 }
@@ -451,94 +311,52 @@ static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
 /* in Hz */
 static unsigned long external_high_reference = 26000000;
 
-static unsigned long get_high_reference_clock_rate(struct clk *clk)
+static unsigned long get_rate_high_reference(struct clk *clk)
 {
        return external_high_reference;
 }
 
-/*
- * the high frequency external clock reference
- * Default case is 26MHz. Could be changed at runtime
- * with a call to change_external_high_reference()
- */
-static struct clk ckih_clk = {
-       .name = "ckih",
-       .get_rate = get_high_reference_clock_rate,
-};
-
 /* in Hz */
 static unsigned long external_low_reference = 32768;
 
-static unsigned long get_low_reference_clock_rate(struct clk *clk)
+static unsigned long get_rate_low_reference(struct clk *clk)
 {
        return external_low_reference;
 }
 
-/*
- * the low frequency external clock reference
- * Default case is 32.768kHz Could be changed at runtime
- * with a call to change_external_low_reference()
- */
-static struct clk ckil_clk = {
-       .name = "ckil",
-       .get_rate = get_low_reference_clock_rate,
-};
+static unsigned long get_rate_fpm(struct clk *clk)
+{
+       return clk_get_rate(clk->parent) * 1024;
+}
 
-static unsigned long get_mpll_clk(struct clk *clk)
+static unsigned long get_rate_mpll(struct clk *clk)
 {
        return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
                        clk_get_rate(clk->parent));
 }
 
-static struct clk mpll_clk = {
-       .name = "mpll",
-       .parent = &ckih_clk,
-       .get_rate = get_mpll_clk,
-};
-
-static unsigned long _clk_mpll_main_get_rate(struct clk *clk)
+static unsigned long get_rate_mpll_main(struct clk *clk)
 {
        unsigned long parent_rate;
 
        parent_rate = clk_get_rate(clk->parent);
 
        /* i.MX27 TO2:
-        * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
-        * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
+        * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
+        * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
         */
-
        if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
                return 2UL * parent_rate / 3UL;
 
        return parent_rate;
 }
 
-static struct clk mpll_main_clk[] = {
-       {
-               /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
-                * It provide the clock source whose rate is same as MPLL
-                */
-               .name = "mpll_main",
-               .id = 0,
-               .parent = &mpll_clk,
-               .get_rate = _clk_mpll_main_get_rate
-       }, {
-               /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
-                * It provide the clock source whose rate is same MPLL * 2/3
-                */
-               .name = "mpll_main",
-               .id = 1,
-               .parent = &mpll_clk,
-               .get_rate = _clk_mpll_main_get_rate
-       }
-};
-
-static unsigned long get_spll_clk(struct clk *clk)
+static unsigned long get_rate_spll(struct clk *clk)
 {
        uint32_t reg;
-       unsigned long ref_clk;
+       unsigned long rate;
 
-       ref_clk = clk_get_rate(clk->parent);
+       rate = clk_get_rate(clk->parent);
 
        reg = __raw_readl(CCM_SPCTL0);
 
@@ -548,987 +366,325 @@ static unsigned long get_spll_clk(struct clk *clk)
        if (mx27_revision() >= CHIP_REV_2_0)
                __raw_writel(reg, CCM_SPCTL0);
 
-       return mxc_decode_pll(reg, ref_clk);
+       return mxc_decode_pll(reg, rate);
 }
 
-static struct clk spll_clk = {
-       .name = "spll",
-       .parent = &ckih_clk,
-       .get_rate = get_spll_clk,
-       .enable = _clk_spll_enable,
-       .disable = _clk_spll_disable,
-};
-
-static unsigned long get_cpu_clk(struct clk *clk)
+static unsigned long get_rate_cpu(struct clk *clk)
 {
        u32 div;
        unsigned long rate;
 
        if (mx27_revision() >= CHIP_REV_2_0)
-               div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
+               div = (__raw_readl(CCM_CSCR) >> 12) & 0x3;
        else
-               div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
+               div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
 
        rate = clk_get_rate(clk->parent);
        return rate / (div + 1);
 }
 
-static struct clk cpu_clk = {
-       .name = "cpu_clk",
-       .parent = &mpll_main_clk[1],
-       .set_parent = _clk_cpu_set_parent,
-       .round_rate = _clk_cpu_round_rate,
-       .get_rate = get_cpu_clk,
-       .set_rate = _clk_cpu_set_rate,
-};
-
-static unsigned long get_ahb_clk(struct clk *clk)
+static unsigned long get_rate_ahb(struct clk *clk)
 {
-       unsigned long rate;
-       unsigned long bclk_pdf;
+       unsigned long rate, bclk_pdf;
 
        if (mx27_revision() >= CHIP_REV_2_0)
-               bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK)
-                                       >> CCM_CSCR_AHB_OFFSET;
+               bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3;
        else
-               bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
-                                       >> CCM_CSCR_BCLK_OFFSET;
+               bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
 
        rate = clk_get_rate(clk->parent);
        return rate / (bclk_pdf + 1);
 }
 
-static struct clk ahb_clk = {
-       .name = "ahb_clk",
-       .parent = &mpll_main_clk[1],
-       .get_rate = get_ahb_clk,
-};
-
-static unsigned long get_ipg_clk(struct clk *clk)
+static unsigned long get_rate_ipg(struct clk *clk)
 {
-       unsigned long rate;
-       unsigned long ipg_pdf;
+       unsigned long rate, ipg_pdf;
 
        if (mx27_revision() >= CHIP_REV_2_0)
                return clk_get_rate(clk->parent);
        else
-               ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
+               ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
 
        rate = clk_get_rate(clk->parent);
        return rate / (ipg_pdf + 1);
 }
 
-static struct clk ipg_clk = {
-       .name = "ipg_clk",
-       .parent = &ahb_clk,
-       .get_rate = get_ipg_clk,
-};
-
-static unsigned long _clk_perclkx_recalc(struct clk *clk)
+static unsigned long get_rate_per(struct clk *clk)
 {
-       unsigned long perclk_pdf;
-       unsigned long parent_rate;
+       unsigned long perclk_pdf, parent_rate;
 
        parent_rate = clk_get_rate(clk->parent);
 
        if (clk->id < 0 || clk->id > 3)
                return 0;
 
-       perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
+       perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f;
 
        return parent_rate / (perclk_pdf + 1);
 }
 
-static struct clk per_clk[] = {
-       {
-               .name = "per_clk",
-               .id = 0,
-               .parent = &mpll_main_clk[1],
-               .get_rate = _clk_perclkx_recalc,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "per_clk",
-               .id = 1,
-               .parent = &mpll_main_clk[1],
-               .get_rate = _clk_perclkx_recalc,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "per_clk",
-               .id = 2,
-               .parent = &mpll_main_clk[1],
-               .round_rate = _clk_perclkx_round_rate,
-               .set_rate = _clk_perclkx_set_rate,
-               .get_rate = _clk_perclkx_recalc,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "per_clk",
-               .id = 3,
-               .parent = &mpll_main_clk[1],
-               .round_rate = _clk_perclkx_round_rate,
-               .set_rate = _clk_perclkx_set_rate,
-               .get_rate = _clk_perclkx_recalc,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-struct clk uart1_clk[] = {
-       {
-               .name = "uart",
-               .id = 0,
-               .parent = &per_clk[0],
-               .secondary = &uart1_clk[1],
-       }, {
-               .name = "uart_ipg_clk",
-               .id = 0,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_UART1_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-struct clk uart2_clk[] = {
-       {
-               .name = "uart",
-               .id = 1,
-               .parent = &per_clk[0],
-               .secondary = &uart2_clk[1],
-       }, {
-               .name = "uart_ipg_clk",
-               .id = 1,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_UART2_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-struct clk uart3_clk[] = {
-       {
-               .name = "uart",
-               .id = 2,
-               .parent = &per_clk[0],
-               .secondary = &uart3_clk[1],
-       }, {
-               .name = "uart_ipg_clk",
-               .id = 2,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_UART3_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-struct clk uart4_clk[] = {
-       {
-               .name = "uart",
-               .id = 3,
-               .parent = &per_clk[0],
-               .secondary = &uart4_clk[1],
-       }, {
-               .name = "uart_ipg_clk",
-               .id = 3,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_UART4_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-struct clk uart5_clk[] = {
-       {
-               .name = "uart",
-               .id = 4,
-               .parent = &per_clk[0],
-               .secondary = &uart5_clk[1],
-       }, {
-               .name = "uart_ipg_clk",
-               .id = 4,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_UART5_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-struct clk uart6_clk[] = {
-       {
-               .name = "uart",
-               .id = 5,
-               .parent = &per_clk[0],
-               .secondary = &uart6_clk[1],
-       }, {
-               .name = "uart_ipg_clk",
-               .id = 5,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_UART6_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-static struct clk gpt1_clk[] = {
-       {
-               .name = "gpt_clk",
-               .id = 0,
-               .parent = &per_clk[0],
-               .secondary = &gpt1_clk[1],
-       }, {
-               .name = "gpt_ipg_clk",
-               .id = 0,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_GPT1_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-static struct clk gpt2_clk[] = {
-       {
-               .name = "gpt_clk",
-               .id = 1,
-               .parent = &per_clk[0],
-               .secondary = &gpt2_clk[1],
-       }, {
-               .name = "gpt_ipg_clk",
-               .id = 1,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_GPT2_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-static struct clk gpt3_clk[] = {
-       {
-               .name = "gpt_clk",
-               .id = 2,
-               .parent = &per_clk[0],
-               .secondary = &gpt3_clk[1],
-       }, {
-               .name = "gpt_ipg_clk",
-               .id = 2,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_GPT3_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-static struct clk gpt4_clk[] = {
-       {
-               .name = "gpt_clk",
-               .id = 3,
-               .parent = &per_clk[0],
-               .secondary = &gpt4_clk[1],
-       }, {
-               .name = "gpt_ipg_clk",
-               .id = 3,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_GPT4_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-static struct clk gpt5_clk[] = {
-       {
-               .name = "gpt_clk",
-               .id = 4,
-               .parent = &per_clk[0],
-               .secondary = &gpt5_clk[1],
-       }, {
-               .name = "gpt_ipg_clk",
-               .id = 4,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_GPT5_OFFSET,
-               .disable = _clk_disable,
-       },
+/*
+ * the high frequency external clock reference
+ * Default case is 26MHz. Could be changed at runtime
+ * with a call to change_external_high_reference()
+ */
+static struct clk ckih_clk = {
+       .get_rate       = get_rate_high_reference,
 };
 
-static struct clk gpt6_clk[] = {
-       {
-               .name = "gpt_clk",
-               .id = 5,
-               .parent = &per_clk[0],
-               .secondary = &gpt6_clk[1],
-       }, {
-               .name = "gpt_ipg_clk",
-               .id = 5,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_GPT6_OFFSET,
-               .disable = _clk_disable,
-       },
+static struct clk mpll_clk = {
+       .parent         = &ckih_clk,
+       .get_rate       = get_rate_mpll,
 };
 
-static struct clk pwm_clk[] = {
-       {
-               .name = "pwm_clk",
-               .parent = &per_clk[0],
-               .secondary = &pwm_clk[1],
-       }, {
-               .name = "pwm_clk",
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_PWM_OFFSET,
-               .disable = _clk_disable,
-       },
+/* For i.MX27 TO2, it is the MPLL path 1 of ARM core
+ * It provides the clock source whose rate is same as MPLL
+ */
+static struct clk mpll_main1_clk = {
+       .id             = 0,
+       .parent         = &mpll_clk,
+       .get_rate       = get_rate_mpll_main,
 };
 
-static struct clk sdhc1_clk[] = {
-       {
-               .name = "sdhc_clk",
-               .id = 0,
-               .parent = &per_clk[1],
-               .secondary = &sdhc1_clk[1],
-       }, {
-               .name = "sdhc_ipg_clk",
-               .id = 0,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_SDHC1_OFFSET,
-               .disable = _clk_disable,
-       },
+/* For i.MX27 TO2, it is the MPLL path 2 of ARM core
+ * It provides the clock source whose rate is same MPLL * 2 / 3
+ */
+static struct clk mpll_main2_clk = {
+       .id             = 1,
+       .parent         = &mpll_clk,
+       .get_rate       = get_rate_mpll_main,
 };
 
-static struct clk sdhc2_clk[] = {
-       {
-               .name = "sdhc_clk",
-               .id = 1,
-               .parent = &per_clk[1],
-               .secondary = &sdhc2_clk[1],
-       }, {
-               .name = "sdhc_ipg_clk",
-               .id = 1,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_SDHC2_OFFSET,
-               .disable = _clk_disable,
-       },
+static struct clk ahb_clk = {
+       .parent         = &mpll_main2_clk,
+       .get_rate       = get_rate_ahb,
 };
 
-static struct clk sdhc3_clk[] = {
-       {
-               .name = "sdhc_clk",
-               .id = 2,
-               .parent = &per_clk[1],
-               .secondary = &sdhc3_clk[1],
-       }, {
-               .name = "sdhc_ipg_clk",
-               .id = 2,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_SDHC3_OFFSET,
-               .disable = _clk_disable,
-       },
+static struct clk ipg_clk = {
+       .parent         = &ahb_clk,
+       .get_rate       = get_rate_ipg,
 };
 
-static struct clk cspi1_clk[] = {
-       {
-               .name = "cspi_clk",
-               .id = 0,
-               .parent = &per_clk[1],
-               .secondary = &cspi1_clk[1],
-       }, {
-               .name = "cspi_ipg_clk",
-               .id = 0,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_CSPI1_OFFSET,
-               .disable = _clk_disable,
-       },
+static struct clk cpu_clk = {
+       .parent = &mpll_main2_clk,
+       .set_parent = clk_cpu_set_parent,
+       .round_rate = round_rate_cpu,
+       .get_rate = get_rate_cpu,
+       .set_rate = set_rate_cpu,
 };
 
-static struct clk cspi2_clk[] = {
-       {
-               .name = "cspi_clk",
-               .id = 1,
-               .parent = &per_clk[1],
-               .secondary = &cspi2_clk[1],
-       }, {
-               .name = "cspi_ipg_clk",
-               .id = 1,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_CSPI2_OFFSET,
-               .disable = _clk_disable,
-       },
+static struct clk spll_clk = {
+       .parent = &ckih_clk,
+       .get_rate = get_rate_spll,
+       .enable = clk_spll_enable,
+       .disable = clk_spll_disable,
 };
 
-static struct clk cspi3_clk[] = {
-       {
-               .name = "cspi_clk",
-               .id = 2,
-               .parent = &per_clk[1],
-               .secondary = &cspi3_clk[1],
-       }, {
-               .name = "cspi_ipg_clk",
-               .id = 2,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_CSPI3_OFFSET,
-               .disable = _clk_disable,
-       },
+/*
+ * the low frequency external clock reference
+ * Default case is 32.768kHz.
+ */
+static struct clk ckil_clk = {
+       .get_rate = get_rate_low_reference,
 };
 
-static struct clk lcdc_clk[] = {
-       {
-               .name = "lcdc_clk",
-               .parent = &per_clk[2],
-               .secondary = &lcdc_clk[1],
-               .round_rate = _clk_parent_round_rate,
-               .set_rate = _clk_parent_set_rate,
-       }, {
-               .name = "lcdc_ipg_clk",
-               .parent = &ipg_clk,
-               .secondary = &lcdc_clk[2],
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_LCDC_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "lcdc_ahb_clk",
-               .parent = &ahb_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
-               .disable = _clk_disable,
-       },
+/* Output of frequency pre multiplier */
+static struct clk fpm_clk = {
+       .parent = &ckil_clk,
+       .get_rate = get_rate_fpm,
 };
 
-static struct clk csi_clk[] = {
-       {
-               .name = "csi_perclk",
-               .parent = &per_clk[3],
-               .secondary = &csi_clk[1],
-               .round_rate = _clk_parent_round_rate,
-               .set_rate = _clk_parent_set_rate,
-       }, {
-               .name = "csi_ahb_clk",
-               .parent = &ahb_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
-               .disable = _clk_disable,
-       },
-};
+#define PCCR0 CCM_PCCR0
+#define PCCR1 CCM_PCCR1
 
-static struct clk usb_clk[] = {
-       {
-               .name = "usb_clk",
-               .parent = &spll_clk,
-               .get_rate = _clk_usb_recalc,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_USBOTG_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "usb_ahb_clk",
-               .parent = &ahb_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
-               .disable = _clk_disable,
+#define DEFINE_CLOCK(name, i, er, es, gr, s, p)                \
+       static struct clk name = {                      \
+               .id             = i,                    \
+               .enable_reg     = er,                   \
+               .enable_shift   = es,                   \
+               .get_rate       = gr,                   \
+               .enable         = clk_pccr_enable,      \
+               .disable        = clk_pccr_disable,     \
+               .secondary      = s,                    \
+               .parent         = p,                    \
        }
-};
-
-static struct clk ssi1_clk[] = {
-       {
-               .name = "ssi_clk",
-               .id = 0,
-               .parent = &mpll_main_clk[1],
-               .secondary = &ssi1_clk[1],
-               .get_rate = _clk_ssi1_recalc,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "ssi_ipg_clk",
-               .id = 0,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-static struct clk ssi2_clk[] = {
-       {
-               .name = "ssi_clk",
-               .id = 1,
-               .parent = &mpll_main_clk[1],
-               .secondary = &ssi2_clk[1],
-               .get_rate = _clk_ssi2_recalc,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR1,
-               .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "ssi_ipg_clk",
-               .id = 1,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
-               .disable = _clk_disable,
-       },
-};
-
-static struct clk nfc_clk = {
-       .name = "nfc",
-       .parent = &cpu_clk,
-       .get_rate = _clk_nfc_recalc,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR1,
-       .enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk vpu_clk = {
-       .name = "vpu_clk",
-       .parent = &mpll_main_clk[1],
-       .get_rate = _clk_vpu_recalc,
-       .enable = _clk_vpu_enable,
-       .disable = _clk_vpu_disable,
-};
-
-static struct clk dma_clk = {
-       .name = "dma",
-       .parent = &ahb_clk,
-       .enable = _clk_dma_enable,
-       .disable = _clk_dma_disable,
-};
-
-static struct clk rtic_clk = {
-       .name = "rtic_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_rtic_enable,
-       .disable = _clk_rtic_disable,
-};
 
-static struct clk brom_clk = {
-       .name = "brom_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR1,
-       .enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk emma_clk = {
-       .name = "emma_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_emma_enable,
-       .disable = _clk_emma_disable,
-};
-
-static struct clk slcdc_clk = {
-       .name = "slcdc_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_slcdc_enable,
-       .disable = _clk_slcdc_disable,
-};
-
-static struct clk fec_clk = {
-       .name = "fec_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_fec_enable,
-       .disable = _clk_fec_disable,
-};
-
-static struct clk emi_clk = {
-       .name = "emi_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR1,
-       .enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk sahara2_clk = {
-       .name = "sahara_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_sahara2_enable,
-       .disable = _clk_sahara2_disable,
-};
-
-static struct clk ata_clk = {
-       .name = "ata_clk",
-       .parent = &ahb_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR1,
-       .enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk mstick1_clk = {
-       .name = "mstick1_clk",
-       .parent = &ipg_clk,
-       .enable = _clk_mstick1_enable,
-       .disable = _clk_mstick1_disable,
-};
-
-static struct clk wdog_clk = {
-       .name = "wdog_clk",
-       .parent = &ipg_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR1,
-       .enable_shift = CCM_PCCR1_WDT_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk gpio_clk = {
-       .name = "gpio_clk",
-       .parent = &ipg_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR1,
-       .enable_shift = CCM_PCCR0_GPIO_OFFSET,
-       .disable = _clk_disable,
-};
+#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)      \
+       static struct clk name = {                              \
+               .id             = i,                            \
+               .enable_reg     = er,                           \
+               .enable_shift   = es,                           \
+               .get_rate       = get_rate_##getsetround,       \
+               .set_rate       = set_rate_##getsetround,       \
+               .round_rate     = round_rate_##getsetround,     \
+               .enable         = clk_pccr_enable,              \
+               .disable        = clk_pccr_disable,             \
+               .secondary      = s,                            \
+               .parent         = p,                            \
+       }
 
-static struct clk i2c_clk[] = {
-       {
-               .name = "i2c_clk",
-               .id = 0,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_I2C1_OFFSET,
-               .disable = _clk_disable,
-       }, {
-               .name = "i2c_clk",
-               .id = 1,
-               .parent = &ipg_clk,
-               .enable = _clk_enable,
-               .enable_reg = CCM_PCCR0,
-               .enable_shift = CCM_PCCR0_I2C2_OFFSET,
-               .disable = _clk_disable,
+/* Forward declaration to keep the following list in order */
+static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
+                 dma_clk1, lcdc_clk2, vpu_clk1;
+
+/* All clocks we can gate through PCCRx in the order of PCCRx bits */
+DEFINE_CLOCK(ssi2_clk1,    1, PCCR0,  0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ssi1_clk1,    0, PCCR0,  1, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(slcdc_clk,    0, PCCR0,  2, NULL, &slcdc_clk1, &ahb_clk);
+DEFINE_CLOCK(sdhc3_clk1,   0, PCCR0,  3, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sdhc2_clk1,   0, PCCR0,  4, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sdhc1_clk1,   0, PCCR0,  5, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(scc_clk,      0, PCCR0,  6, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sahara2_clk,  0, PCCR0,  7, NULL, &sahara2_clk1, &ahb_clk);
+DEFINE_CLOCK(rtic_clk,     0, PCCR0,  8, NULL, &rtic_clk1, &ahb_clk);
+DEFINE_CLOCK(rtc_clk,      0, PCCR0,  9, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pwm_clk1,     0, PCCR0, 11, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(owire_clk,    0, PCCR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(mstick_clk1,  0, PCCR0, 13, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(lcdc_clk1,    0, PCCR0, 14, NULL, &lcdc_clk2, &ipg_clk);
+DEFINE_CLOCK(kpp_clk,      0, PCCR0, 15, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(iim_clk,      0, PCCR0, 16, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(i2c2_clk,     1, PCCR0, 17, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(i2c1_clk,     0, PCCR0, 18, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt6_clk1,    0, PCCR0, 29, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt5_clk1,    0, PCCR0, 20, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt4_clk1,    0, PCCR0, 21, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt3_clk1,    0, PCCR0, 22, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt2_clk1,    0, PCCR0, 23, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt1_clk1,    0, PCCR0, 24, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpio_clk,     0, PCCR0, 25, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(fec_clk,      0, PCCR0, 26, NULL, &fec_clk1, &ahb_clk);
+DEFINE_CLOCK(emma_clk,     0, PCCR0, 27, NULL, &emma_clk1, &ahb_clk);
+DEFINE_CLOCK(dma_clk,      0, PCCR0, 28, NULL, &dma_clk1, &ahb_clk);
+DEFINE_CLOCK(cspi13_clk1,  0, PCCR0, 29, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(cspi2_clk1,   0, PCCR0, 30, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(cspi1_clk1,   0, PCCR0, 31, NULL, NULL, &ipg_clk);
+
+DEFINE_CLOCK(mstick_clk,   0, PCCR1,  2, NULL, &mstick_clk1, &ipg_clk);
+DEFINE_CLOCK(nfc_clk,      0, PCCR1,  3, get_rate_nfc, NULL, &cpu_clk);
+DEFINE_CLOCK(ssi2_clk,     1, PCCR1,  4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk);
+DEFINE_CLOCK(ssi1_clk,     0, PCCR1,  5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk);
+DEFINE_CLOCK(vpu_clk,      0, PCCR1,  6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk);
+DEFINE_CLOCK1(per4_clk,    3, PCCR1,  7, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK1(per3_clk,    2, PCCR1,  8, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK1(per2_clk,    1, PCCR1,  9, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK1(per1_clk,    0, PCCR1, 10, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK(usb_clk1,     0, PCCR1, 11, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(slcdc_clk1,   0, PCCR1, 12, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(sahara2_clk1, 0, PCCR1, 13, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(rtic_clk1,    0, PCCR1, 14, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(lcdc_clk2,    0, PCCR1, 15, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(vpu_clk1,     0, PCCR1, 16, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(fec_clk1,     0, PCCR1, 17, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(emma_clk1,    0, PCCR1, 18, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(emi_clk,      0, PCCR1, 19, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(dma_clk1,     0, PCCR1, 20, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(csi_clk1,     0, PCCR1, 21, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(brom_clk,     0, PCCR1, 22, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(ata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(wdog_clk,     0, PCCR1, 24, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(usb_clk,      0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk);
+DEFINE_CLOCK(uart6_clk1,   0, PCCR1, 26, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart5_clk1,   0, PCCR1, 27, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart4_clk1,   0, PCCR1, 28, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart3_clk1,   0, PCCR1, 29, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart2_clk1,   0, PCCR1, 30, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart1_clk1,   0, PCCR1, 31, NULL, NULL, &ipg_clk);
+
+/* Clocks we cannot directly gate, but drivers need their rates */
+DEFINE_CLOCK(cspi1_clk,    0, 0,      0, NULL, &cspi1_clk1, &per2_clk);
+DEFINE_CLOCK(cspi2_clk,    1, 0,      0, NULL, &cspi2_clk1, &per2_clk);
+DEFINE_CLOCK(cspi3_clk,    2, 0,      0, NULL, &cspi13_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc1_clk,    0, 0,      0, NULL, &sdhc1_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc2_clk,    1, 0,      0, NULL, &sdhc2_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc3_clk,    2, 0,      0, NULL, &sdhc3_clk1, &per2_clk);
+DEFINE_CLOCK(pwm_clk,      0, 0,      0, NULL, &pwm_clk1, &per1_clk);
+DEFINE_CLOCK(gpt1_clk,     0, 0,      0, NULL, &gpt1_clk1, &per1_clk);
+DEFINE_CLOCK(gpt2_clk,     1, 0,      0, NULL, &gpt2_clk1, &per1_clk);
+DEFINE_CLOCK(gpt3_clk,     2, 0,      0, NULL, &gpt3_clk1, &per1_clk);
+DEFINE_CLOCK(gpt4_clk,     3, 0,      0, NULL, &gpt4_clk1, &per1_clk);
+DEFINE_CLOCK(gpt5_clk,     4, 0,      0, NULL, &gpt5_clk1, &per1_clk);
+DEFINE_CLOCK(gpt6_clk,     5, 0,      0, NULL, &gpt6_clk1, &per1_clk);
+DEFINE_CLOCK(uart1_clk,    0, 0,      0, NULL, &uart1_clk1, &per1_clk);
+DEFINE_CLOCK(uart2_clk,    1, 0,      0, NULL, &uart2_clk1, &per1_clk);
+DEFINE_CLOCK(uart3_clk,    2, 0,      0, NULL, &uart3_clk1, &per1_clk);
+DEFINE_CLOCK(uart4_clk,    3, 0,      0, NULL, &uart4_clk1, &per1_clk);
+DEFINE_CLOCK(uart5_clk,    4, 0,      0, NULL, &uart5_clk1, &per1_clk);
+DEFINE_CLOCK(uart6_clk,    5, 0,      0, NULL, &uart6_clk1, &per1_clk);
+DEFINE_CLOCK1(lcdc_clk,    0, 0,      0, parent, &lcdc_clk1, &per3_clk);
+DEFINE_CLOCK1(csi_clk,     0, 0,      0, parent, &csi_clk1, &per4_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+       { \
+               .dev_id = d, \
+               .con_id = n, \
+               .clk = &c, \
        },
-};
 
-static struct clk iim_clk = {
-       .name = "iim_clk",
-       .parent = &ipg_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR0,
-       .enable_shift = CCM_PCCR0_IIM_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk kpp_clk = {
-       .name = "kpp_clk",
-       .parent = &ipg_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR0,
-       .enable_shift = CCM_PCCR0_KPP_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk owire_clk = {
-       .name = "owire",
-       .parent = &ipg_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR0,
-       .enable_shift = CCM_PCCR0_OWIRE_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk rtc_clk = {
-       .name = "rtc_clk",
-       .parent = &ipg_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR0,
-       .enable_shift = CCM_PCCR0_RTC_OFFSET,
-       .disable = _clk_disable,
-};
-
-static struct clk scc_clk = {
-       .name = "scc_clk",
-       .parent = &ipg_clk,
-       .enable = _clk_enable,
-       .enable_reg = CCM_PCCR0,
-       .enable_shift = CCM_PCCR0_SCC_OFFSET,
-       .disable = _clk_disable,
-};
-
-static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
-{
-       u32 div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-       div = parent_rate / rate;
-       if (parent_rate % rate)
-               div++;
-
-       if (div > 8)
-               div = 8;
-
-       return parent_rate / div;
-}
-
-static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
-{
-       u32 reg;
-       u32 div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       div = parent_rate / rate;
-
-       if (div > 8 || div < 1 || ((parent_rate / div) != rate))
-               return -EINVAL;
-       div--;
-
-       reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
-       reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
-       __raw_writel(reg, CCM_PCDR0);
-
-       return 0;
-}
-
-static unsigned long _clk_clko_recalc(struct clk *clk)
-{
-       u32 div;
-       unsigned long parent_rate;
-
-       parent_rate = clk_get_rate(clk->parent);
-
-       div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
-               CCM_PCDR0_CLKODIV_OFFSET;
-       div++;
-
-       return parent_rate / div;
-}
-
-static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 reg;
-
-       reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
-
-       if (parent == &ckil_clk)
-               reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &ckih_clk)
-               reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == mpll_clk.parent)
-               reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == spll_clk.parent)
-               reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &mpll_clk)
-               reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &spll_clk)
-               reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &cpu_clk)
-               reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &ahb_clk)
-               reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &ipg_clk)
-               reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &per_clk[0])
-               reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &per_clk[1])
-               reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &per_clk[2])
-               reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &per_clk[3])
-               reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &ssi1_clk[0])
-               reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &ssi2_clk[0])
-               reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &nfc_clk)
-               reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &mstick1_clk)
-               reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &vpu_clk)
-               reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
-       else if (parent == &usb_clk[0])
-               reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
-       else
-               return -EINVAL;
-
-       __raw_writel(reg, CCM_CCSR);
-
-       return 0;
-}
-
-static int _clk_clko_enable(struct clk *clk)
-{
-       u32 reg;
-
-       reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
-       __raw_writel(reg, CCM_PCDR0);
-
-       return 0;
-}
-
-static void _clk_clko_disable(struct clk *clk)
-{
-       u32 reg;
-
-       reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
-       __raw_writel(reg, CCM_PCDR0);
-}
-
-static struct clk clko_clk = {
-       .name = "clko_clk",
-       .get_rate = _clk_clko_recalc,
-       .set_rate = _clk_clko_set_rate,
-       .round_rate = _clk_clko_round_rate,
-       .set_parent = _clk_clko_set_parent,
-       .enable = _clk_clko_enable,
-       .disable = _clk_clko_disable,
-};
-
-static struct clk *mxc_clks[] = {
-       &ckih_clk,
-       &ckil_clk,
-       &mpll_clk,
-       &mpll_main_clk[0],
-       &mpll_main_clk[1],
-       &spll_clk,
-       &cpu_clk,
-       &ahb_clk,
-       &ipg_clk,
-       &per_clk[0],
-       &per_clk[1],
-       &per_clk[2],
-       &per_clk[3],
-       &clko_clk,
-       &uart1_clk[0],
-       &uart1_clk[1],
-       &uart2_clk[0],
-       &uart2_clk[1],
-       &uart3_clk[0],
-       &uart3_clk[1],
-       &uart4_clk[0],
-       &uart4_clk[1],
-       &uart5_clk[0],
-       &uart5_clk[1],
-       &uart6_clk[0],
-       &uart6_clk[1],
-       &gpt1_clk[0],
-       &gpt1_clk[1],
-       &gpt2_clk[0],
-       &gpt2_clk[1],
-       &gpt3_clk[0],
-       &gpt3_clk[1],
-       &gpt4_clk[0],
-       &gpt4_clk[1],
-       &gpt5_clk[0],
-       &gpt5_clk[1],
-       &gpt6_clk[0],
-       &gpt6_clk[1],
-       &pwm_clk[0],
-       &pwm_clk[1],
-       &sdhc1_clk[0],
-       &sdhc1_clk[1],
-       &sdhc2_clk[0],
-       &sdhc2_clk[1],
-       &sdhc3_clk[0],
-       &sdhc3_clk[1],
-       &cspi1_clk[0],
-       &cspi1_clk[1],
-       &cspi2_clk[0],
-       &cspi2_clk[1],
-       &cspi3_clk[0],
-       &cspi3_clk[1],
-       &lcdc_clk[0],
-       &lcdc_clk[1],
-       &lcdc_clk[2],
-       &csi_clk[0],
-       &csi_clk[1],
-       &usb_clk[0],
-       &usb_clk[1],
-       &ssi1_clk[0],
-       &ssi1_clk[1],
-       &ssi2_clk[0],
-       &ssi2_clk[1],
-       &nfc_clk,
-       &vpu_clk,
-       &dma_clk,
-       &rtic_clk,
-       &brom_clk,
-       &emma_clk,
-       &slcdc_clk,
-       &fec_clk,
-       &emi_clk,
-       &sahara2_clk,
-       &ata_clk,
-       &mstick1_clk,
-       &wdog_clk,
-       &gpio_clk,
-       &i2c_clk[0],
-       &i2c_clk[1],
-       &iim_clk,
-       &kpp_clk,
-       &owire_clk,
-       &rtc_clk,
-       &scc_clk,
-};
-
-void __init change_external_low_reference(unsigned long new_ref)
-{
-       external_low_reference = new_ref;
-}
-
-unsigned long __init clk_early_get_timer_rate(void)
-{
-       return clk_get_rate(&per_clk[0]);
-}
-
-static void __init probe_mxc_clocks(void)
-{
-       int i;
+static struct clk_lookup lookups[] __initdata = {
+       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+       _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+       _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+       _REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk)
+       _REGISTER_CLOCK(NULL, "gpt1", gpt1_clk)
+       _REGISTER_CLOCK(NULL, "gpt2", gpt2_clk)
+       _REGISTER_CLOCK(NULL, "gpt3", gpt3_clk)
+       _REGISTER_CLOCK(NULL, "gpt4", gpt4_clk)
+       _REGISTER_CLOCK(NULL, "gpt5", gpt5_clk)
+       _REGISTER_CLOCK(NULL, "gpt6", gpt6_clk)
+       _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk)
+       _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
+       _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
+       _REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk)
+       _REGISTER_CLOCK(NULL, "cspi1", cspi1_clk)
+       _REGISTER_CLOCK(NULL, "cspi2", cspi2_clk)
+       _REGISTER_CLOCK(NULL, "cspi3", cspi3_clk)
+       _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
+       _REGISTER_CLOCK(NULL, "csi", csi_clk)
+       _REGISTER_CLOCK(NULL, "usb", usb_clk)
+       _REGISTER_CLOCK(NULL, "ssi1", ssi1_clk)
+       _REGISTER_CLOCK(NULL, "ssi2", ssi2_clk)
+       _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+       _REGISTER_CLOCK(NULL, "vpu", vpu_clk)
+       _REGISTER_CLOCK(NULL, "dma", dma_clk)
+       _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
+       _REGISTER_CLOCK(NULL, "brom", brom_clk)
+       _REGISTER_CLOCK(NULL, "emma", emma_clk)
+       _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
+       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK(NULL, "emi", emi_clk)
+       _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
+       _REGISTER_CLOCK(NULL, "ata", ata_clk)
+       _REGISTER_CLOCK(NULL, "mstick", mstick_clk)
+       _REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+       _REGISTER_CLOCK(NULL, "gpio", gpio_clk)
+       _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+       _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+       _REGISTER_CLOCK(NULL, "iim", iim_clk)
+       _REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+       _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
+       _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
+       _REGISTER_CLOCK(NULL, "scc", scc_clk)
+};
+
+/* Adjust the clock path for TO2 and later */
+static void __init to2_adjust_clocks(void)
+{
+       unsigned long cscr = __raw_readl(CCM_CSCR);
 
        if (mx27_revision() >= CHIP_REV_2_0) {
-               if (CSCR() & 0x8000)
-                       cpu_clk.parent = &mpll_main_clk[0];
+               if (cscr & CCM_CSCR_ARM_SRC)
+                       cpu_clk.parent = &mpll_main1_clk;
 
-               if (!(CSCR() & 0x00800000))
-                       ssi2_clk[0].parent = &spll_clk;
+               if (!(cscr & CCM_CSCR_SSI2))
+                       ssi1_clk.parent = &spll_clk;
 
-               if (!(CSCR() & 0x00400000))
-                       ssi1_clk[0].parent = &spll_clk;
+               if (!(cscr & CCM_CSCR_SSI1))
+                       ssi1_clk.parent = &spll_clk;
 
-               if (!(CSCR() & 0x00200000))
+               if (!(cscr & CCM_CSCR_VPU))
                        vpu_clk.parent = &spll_clk;
        } else {
                cpu_clk.parent = &mpll_clk;
@@ -1537,11 +693,13 @@ static void __init probe_mxc_clocks(void)
                cpu_clk.set_rate = NULL;
                ahb_clk.parent = &mpll_clk;
 
-               for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++)
-                       per_clk[i].parent = &mpll_clk;
+               per1_clk.parent = &mpll_clk;
+               per2_clk.parent = &mpll_clk;
+               per3_clk.parent = &mpll_clk;
+               per4_clk.parent = &mpll_clk;
 
-               ssi1_clk[0].parent = &mpll_clk;
-               ssi2_clk[0].parent = &mpll_clk;
+               ssi1_clk.parent = &mpll_clk;
+               ssi2_clk.parent = &mpll_clk;
 
                vpu_clk.parent = &mpll_clk;
        }
@@ -1553,48 +711,45 @@ static void __init probe_mxc_clocks(void)
  */
 int __init mx27_clocks_init(unsigned long fref)
 {
-       u32 cscr;
-       struct clk **clkp;
+       u32 cscr = __raw_readl(CCM_CSCR);
+       int i;
 
        external_high_reference = fref;
 
-       /* detect clock reference for both system PLL */
-       cscr = CSCR();
+       /* detect clock reference for both system PLLs */
        if (cscr & CCM_CSCR_MCU)
                mpll_clk.parent = &ckih_clk;
        else
-               mpll_clk.parent = &ckil_clk;
+               mpll_clk.parent = &fpm_clk;
 
        if (cscr & CCM_CSCR_SP)
                spll_clk.parent = &ckih_clk;
        else
-               spll_clk.parent = &ckil_clk;
+               spll_clk.parent = &fpm_clk;
 
-       probe_mxc_clocks();
+       to2_adjust_clocks();
 
-       per_clk[0].enable(&per_clk[0]);
-       gpt1_clk[1].enable(&gpt1_clk[1]);
+       for (i = 0; i < ARRAY_SIZE(lookups); i++)
+               clkdev_add(&lookups[i]);
 
-       for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
-               clk_register(*clkp);
+       /* Turn off all clocks we do not need */
+       __raw_writel(0, CCM_PCCR0);
+       __raw_writel((1 << 10) | (1 << 19), CCM_PCCR1);
 
-       /* Turn off all possible clocks */
-       __raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
-       __raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
-                    CCM_PCCR1);
        spll_clk.disable(&spll_clk);
 
-       /* This will propagate to all children and init all the clock rates */
-
-       clk_enable(&emi_clk);
+       /* enable basic clocks */
+       clk_enable(&per1_clk);
        clk_enable(&gpio_clk);
+       clk_enable(&emi_clk);
        clk_enable(&iim_clk);
-       clk_enable(&gpt1_clk[0]);
+
 #ifdef CONFIG_DEBUG_LL_CONSOLE
-       clk_enable(&uart1_clk[0]);
+       clk_enable(&uart1_clk);
 #endif
 
-       mxc_timer_init(&gpt1_clk[0]);
+       mxc_timer_init(&gpt1_clk);
 
        return 0;
 }
+
index 239308fe6652323bd225a2267c786a21c4a0fe73..d9e3bf9644c9e46aefd629f751c9de15b883dc04 100644 (file)
 
 #include <mach/hardware.h>
 
-#include "crm_regs.h"
-
 static int cpu_silicon_rev = -1;
 static int cpu_partnumber;
 
+#define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
+
 static void query_silicon_parameter(void)
 {
        u32 val;
diff --git a/arch/arm/mach-mx2/crm_regs.h b/arch/arm/mach-mx2/crm_regs.h
deleted file mode 100644 (file)
index 94644cd..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __ARCH_ARM_MACH_MX2_CRM_REGS_H__
-#define __ARCH_ARM_MACH_MX2_CRM_REGS_H__
-
-#include <mach/hardware.h>
-
-/* Register offsets */
-#define CCM_CSCR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
-#define CCM_MPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
-#define CCM_MPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
-#define CCM_SPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
-#define CCM_SPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
-#define CCM_OSC26MCTL           (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
-#define CCM_PCDR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
-#define CCM_PCDR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
-#define CCM_PCCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
-#define CCM_PCCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
-#define CCM_CCSR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
-#define CCM_PMCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
-#define CCM_PMCOUNT             (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
-#define CCM_WKGDCTL             (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
-
-#define CCM_CSCR_USB_OFFSET     28
-#define CCM_CSCR_USB_MASK       (0x7 << 28)
-#define CCM_CSCR_SD_OFFSET      24
-#define CCM_CSCR_SD_MASK        (0x3 << 24)
-#define CCM_CSCR_SSI2           (1 << 23)
-#define CCM_CSCR_SSI2_OFFSET    23
-#define CCM_CSCR_SSI1           (1 << 22)
-#define CCM_CSCR_SSI1_OFFSET    22
-#define CCM_CSCR_VPU           (1 << 21)
-#define CCM_CSCR_VPU_OFFSET    21
-#define CCM_CSCR_MSHC           (1 << 20)
-#define CCM_CSCR_SPLLRES        (1 << 19)
-#define CCM_CSCR_MPLLRES        (1 << 18)
-#define CCM_CSCR_SP             (1 << 17)
-#define CCM_CSCR_MCU            (1 << 16)
-/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
-#define CCM_CSCR_ARM_SRC        (1 << 15)
-#define CCM_CSCR_ARM_OFFSET     12
-#define CCM_CSCR_ARM_MASK       (0x3 << 12)
-/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
-#define CCM_CSCR_PRESC_OFFSET   13
-#define CCM_CSCR_PRESC_MASK     (0x7 << 13)
-#define CCM_CSCR_BCLK_OFFSET    9
-#define CCM_CSCR_BCLK_MASK      (0xf << 9)
-#define CCM_CSCR_IPDIV_OFFSET   8
-#define CCM_CSCR_IPDIV          (1 << 8)
-/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
-#define CCM_CSCR_AHB_OFFSET     8
-#define CCM_CSCR_AHB_MASK       (0x3 << 8)
-/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
-#define CCM_CSCR_OSC26MDIV      (1 << 4)
-#define CCM_CSCR_OSC26M         (1 << 3)
-#define CCM_CSCR_FPM            (1 << 2)
-#define CCM_CSCR_SPEN           (1 << 1)
-#define CCM_CSCR_MPEN           1
-
-#define CCM_MPCTL0_CPLM         (1 << 31)
-#define CCM_MPCTL0_PD_OFFSET    26
-#define CCM_MPCTL0_PD_MASK      (0xf << 26)
-#define CCM_MPCTL0_MFD_OFFSET   16
-#define CCM_MPCTL0_MFD_MASK     (0x3ff << 16)
-#define CCM_MPCTL0_MFI_OFFSET   10
-#define CCM_MPCTL0_MFI_MASK     (0xf << 10)
-#define CCM_MPCTL0_MFN_OFFSET   0
-#define CCM_MPCTL0_MFN_MASK     0x3ff
-
-#define CCM_MPCTL1_LF           (1 << 15)
-#define CCM_MPCTL1_BRMO         (1 << 6)
-
-#define CCM_SPCTL0_CPLM         (1 << 31)
-#define CCM_SPCTL0_PD_OFFSET    26
-#define CCM_SPCTL0_PD_MASK      (0xf << 26)
-#define CCM_SPCTL0_MFD_OFFSET   16
-#define CCM_SPCTL0_MFD_MASK     (0x3ff << 16)
-#define CCM_SPCTL0_MFI_OFFSET   10
-#define CCM_SPCTL0_MFI_MASK     (0xf << 10)
-#define CCM_SPCTL0_MFN_OFFSET   0
-#define CCM_SPCTL0_MFN_MASK     0x3ff
-
-#define CCM_SPCTL1_LF           (1 << 15)
-#define CCM_SPCTL1_BRMO         (1 << 6)
-
-#define CCM_OSC26MCTL_PEAK_OFFSET       16
-#define CCM_OSC26MCTL_PEAK_MASK         (0x3 << 16)
-#define CCM_OSC26MCTL_AGC_OFFSET        8
-#define CCM_OSC26MCTL_AGC_MASK          (0x3f << 8)
-#define CCM_OSC26MCTL_ANATEST_OFFSET    0
-#define CCM_OSC26MCTL_ANATEST_MASK      0x3f
-
-#define CCM_PCDR0_SSI2BAUDDIV_OFFSET    26
-#define CCM_PCDR0_SSI2BAUDDIV_MASK      (0x3f << 26)
-#define CCM_PCDR0_CLKO_EN               25
-#define CCM_PCDR0_CLKODIV_OFFSET        22
-#define CCM_PCDR0_CLKODIV_MASK          (0x7 << 22)
-#define CCM_PCDR0_SSI1BAUDDIV_OFFSET    16
-#define CCM_PCDR0_SSI1BAUDDIV_MASK      (0x3f << 16)
-/*The difinition for i.MX27 TO2*/
-#define CCM_PCDR0_VPUDIV2_OFFSET        10
-#define CCM_PCDR0_VPUDIV2_MASK          (0x3f << 10)
-#define CCM_PCDR0_NFCDIV2_OFFSET         6
-#define CCM_PCDR0_NFCDIV2_MASK           (0xf << 6)
-#define CCM_PCDR0_MSHCDIV2_MASK          0x3f
-/*The difinition for i.MX27 TO2*/
-#define CCM_PCDR0_NFCDIV_OFFSET         12
-#define CCM_PCDR0_NFCDIV_MASK           (0xf << 12)
-#define CCM_PCDR0_VPUDIV_OFFSET        8
-#define CCM_PCDR0_VPUDIV_MASK          (0xf << 8)
-#define CCM_PCDR0_MSHCDIV_OFFSET        0
-#define CCM_PCDR0_MSHCDIV_MASK          0x1f
-
-#define CCM_PCDR1_PERDIV4_OFFSET        24
-#define CCM_PCDR1_PERDIV4_MASK          (0x3f << 24)
-#define CCM_PCDR1_PERDIV3_OFFSET        16
-#define CCM_PCDR1_PERDIV3_MASK          (0x3f << 16)
-#define CCM_PCDR1_PERDIV2_OFFSET        8
-#define CCM_PCDR1_PERDIV2_MASK          (0x3f << 8)
-#define CCM_PCDR1_PERDIV1_OFFSET        0
-#define CCM_PCDR1_PERDIV1_MASK          0x3f
-
-#define CCM_PCCR0_CSPI1_OFFSET          31
-#define CCM_PCCR0_CSPI1_MASK            (1 << 31)
-#define CCM_PCCR0_CSPI2_OFFSET          30
-#define CCM_PCCR0_CSPI2_MASK            (1 << 30)
-#define CCM_PCCR0_CSPI3_OFFSET          29
-#define CCM_PCCR0_CSPI3_MASK            (1 << 29)
-#define CCM_PCCR0_DMA_OFFSET            28
-#define CCM_PCCR0_DMA_MASK              (1 << 28)
-#define CCM_PCCR0_EMMA_OFFSET           27
-#define CCM_PCCR0_EMMA_MASK             (1 << 27)
-#define CCM_PCCR0_FEC_OFFSET            26
-#define CCM_PCCR0_FEC_MASK              (1 << 26)
-#define CCM_PCCR0_GPIO_OFFSET           25
-#define CCM_PCCR0_GPIO_MASK             (1 << 25)
-#define CCM_PCCR0_GPT1_OFFSET           24
-#define CCM_PCCR0_GPT1_MASK             (1 << 24)
-#define CCM_PCCR0_GPT2_OFFSET           23
-#define CCM_PCCR0_GPT2_MASK             (1 << 23)
-#define CCM_PCCR0_GPT3_OFFSET           22
-#define CCM_PCCR0_GPT3_MASK             (1 << 22)
-#define CCM_PCCR0_GPT4_OFFSET           21
-#define CCM_PCCR0_GPT4_MASK             (1 << 21)
-#define CCM_PCCR0_GPT5_OFFSET           20
-#define CCM_PCCR0_GPT5_MASK             (1 << 20)
-#define CCM_PCCR0_GPT6_OFFSET           19
-#define CCM_PCCR0_GPT6_MASK             (1 << 19)
-#define CCM_PCCR0_I2C1_OFFSET           18
-#define CCM_PCCR0_I2C1_MASK             (1 << 18)
-#define CCM_PCCR0_I2C2_OFFSET           17
-#define CCM_PCCR0_I2C2_MASK             (1 << 17)
-#define CCM_PCCR0_IIM_OFFSET            16
-#define CCM_PCCR0_IIM_MASK              (1 << 16)
-#define CCM_PCCR0_KPP_OFFSET            15
-#define CCM_PCCR0_KPP_MASK              (1 << 15)
-#define CCM_PCCR0_LCDC_OFFSET           14
-#define CCM_PCCR0_LCDC_MASK             (1 << 14)
-#define CCM_PCCR0_MSHC_OFFSET           13
-#define CCM_PCCR0_MSHC_MASK             (1 << 13)
-#define CCM_PCCR0_OWIRE_OFFSET          12
-#define CCM_PCCR0_OWIRE_MASK            (1 << 12)
-#define CCM_PCCR0_PWM_OFFSET            11
-#define CCM_PCCR0_PWM_MASK              (1 << 11)
-#define CCM_PCCR0_RTC_OFFSET            9
-#define CCM_PCCR0_RTC_MASK              (1 << 9)
-#define CCM_PCCR0_RTIC_OFFSET           8
-#define CCM_PCCR0_RTIC_MASK             (1 << 8)
-#define CCM_PCCR0_SAHARA_OFFSET         7
-#define CCM_PCCR0_SAHARA_MASK           (1 << 7)
-#define CCM_PCCR0_SCC_OFFSET            6
-#define CCM_PCCR0_SCC_MASK              (1 << 6)
-#define CCM_PCCR0_SDHC1_OFFSET          5
-#define CCM_PCCR0_SDHC1_MASK            (1 << 5)
-#define CCM_PCCR0_SDHC2_OFFSET          4
-#define CCM_PCCR0_SDHC2_MASK            (1 << 4)
-#define CCM_PCCR0_SDHC3_OFFSET          3
-#define CCM_PCCR0_SDHC3_MASK            (1 << 3)
-#define CCM_PCCR0_SLCDC_OFFSET          2
-#define CCM_PCCR0_SLCDC_MASK            (1 << 2)
-#define CCM_PCCR0_SSI1_IPG_OFFSET       1
-#define CCM_PCCR0_SSI1_IPG_MASK         (1 << 1)
-#define CCM_PCCR0_SSI2_IPG_OFFSET       0
-#define CCM_PCCR0_SSI2_IPG_MASK         (1 << 0)
-
-#define CCM_PCCR1_UART1_OFFSET          31
-#define CCM_PCCR1_UART1_MASK            (1 << 31)
-#define CCM_PCCR1_UART2_OFFSET          30
-#define CCM_PCCR1_UART2_MASK            (1 << 30)
-#define CCM_PCCR1_UART3_OFFSET          29
-#define CCM_PCCR1_UART3_MASK            (1 << 29)
-#define CCM_PCCR1_UART4_OFFSET          28
-#define CCM_PCCR1_UART4_MASK            (1 << 28)
-#define CCM_PCCR1_UART5_OFFSET          27
-#define CCM_PCCR1_UART5_MASK            (1 << 27)
-#define CCM_PCCR1_UART6_OFFSET          26
-#define CCM_PCCR1_UART6_MASK            (1 << 26)
-#define CCM_PCCR1_USBOTG_OFFSET         25
-#define CCM_PCCR1_USBOTG_MASK           (1 << 25)
-#define CCM_PCCR1_WDT_OFFSET            24
-#define CCM_PCCR1_WDT_MASK              (1 << 24)
-#define CCM_PCCR1_HCLK_ATA_OFFSET       23
-#define CCM_PCCR1_HCLK_ATA_MASK         (1 << 23)
-#define CCM_PCCR1_HCLK_BROM_OFFSET      22
-#define CCM_PCCR1_HCLK_BROM_MASK        (1 << 22)
-#define CCM_PCCR1_HCLK_CSI_OFFSET       21
-#define CCM_PCCR1_HCLK_CSI_MASK         (1 << 21)
-#define CCM_PCCR1_HCLK_DMA_OFFSET       20
-#define CCM_PCCR1_HCLK_DMA_MASK         (1 << 20)
-#define CCM_PCCR1_HCLK_EMI_OFFSET       19
-#define CCM_PCCR1_HCLK_EMI_MASK         (1 << 19)
-#define CCM_PCCR1_HCLK_EMMA_OFFSET      18
-#define CCM_PCCR1_HCLK_EMMA_MASK        (1 << 18)
-#define CCM_PCCR1_HCLK_FEC_OFFSET       17
-#define CCM_PCCR1_HCLK_FEC_MASK         (1 << 17)
-#define CCM_PCCR1_HCLK_VPU_OFFSET       16
-#define CCM_PCCR1_HCLK_VPU_MASK         (1 << 16)
-#define CCM_PCCR1_HCLK_LCDC_OFFSET      15
-#define CCM_PCCR1_HCLK_LCDC_MASK        (1 << 15)
-#define CCM_PCCR1_HCLK_RTIC_OFFSET      14
-#define CCM_PCCR1_HCLK_RTIC_MASK        (1 << 14)
-#define CCM_PCCR1_HCLK_SAHARA_OFFSET    13
-#define CCM_PCCR1_HCLK_SAHARA_MASK      (1 << 13)
-#define CCM_PCCR1_HCLK_SLCDC_OFFSET     12
-#define CCM_PCCR1_HCLK_SLCDC_MASK       (1 << 12)
-#define CCM_PCCR1_HCLK_USBOTG_OFFSET    11
-#define CCM_PCCR1_HCLK_USBOTG_MASK      (1 << 11)
-#define CCM_PCCR1_PERCLK1_OFFSET        10
-#define CCM_PCCR1_PERCLK1_MASK          (1 << 10)
-#define CCM_PCCR1_PERCLK2_OFFSET        9
-#define CCM_PCCR1_PERCLK2_MASK          (1 << 9)
-#define CCM_PCCR1_PERCLK3_OFFSET        8
-#define CCM_PCCR1_PERCLK3_MASK          (1 << 8)
-#define CCM_PCCR1_PERCLK4_OFFSET        7
-#define CCM_PCCR1_PERCLK4_MASK          (1 << 7)
-#define CCM_PCCR1_VPU_BAUD_OFFSET       6
-#define CCM_PCCR1_VPU_BAUD_MASK         (1 << 6)
-#define CCM_PCCR1_SSI1_BAUD_OFFSET      5
-#define CCM_PCCR1_SSI1_BAUD_MASK        (1 << 5)
-#define CCM_PCCR1_SSI2_BAUD_OFFSET      4
-#define CCM_PCCR1_SSI2_BAUD_MASK        (1 << 4)
-#define CCM_PCCR1_NFC_BAUD_OFFSET       3
-#define CCM_PCCR1_NFC_BAUD_MASK         (1 << 3)
-#define CCM_PCCR1_MSHC_BAUD_OFFSET      2
-#define CCM_PCCR1_MSHC_BAUD_MASK        (1 << 2)
-
-#define CCM_CCSR_32KSR          (1 << 15)
-#define CCM_CCSR_CLKMODE1       (1 << 9)
-#define CCM_CCSR_CLKMODE0       (1 << 8)
-#define CCM_CCSR_CLKOSEL_OFFSET 0
-#define CCM_CCSR_CLKOSEL_MASK   0x1f
-
-#define SYS_FMCR                0x14   /*  Functional Muxing Control Reg */
-#define SYS_CHIP_ID             0x00   /* The offset of CHIP ID register */
-
-#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */
index 9cc2b16fdf793af36302108b4a65588342257e44..10f65bf27b278e002763fbf737e50d01094528f3 100644 (file)
@@ -15,6 +15,7 @@ config ARCH_MX1
 config ARCH_MX2
        bool "MX2-based"
        select CPU_ARM926T
+       select COMMON_CLKDEV
        help
          This enables support for systems based on the Freescale i.MX2 family