[ARM] MX27 Clock rework

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>
diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c
index 700a22f..3f7280c 100644
--- a/arch/arm/mach-mx2/clock_imx27.c
+++ b/arch/arm/mach-mx2/clock_imx27.c
@@ -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
@@ -20,23 +21,60 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
+
+#include <asm/clkdev.h>
+#include <asm/div64.h>
 
 #include <mach/clock.h>
 #include <mach/common.h>
-#include <asm/div64.h>
+#include <mach/hardware.h>
 
-#include "crm_regs.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)
 
-static struct clk ckil_clk;
-static struct clk mpll_clk;
-static struct clk mpll_main_clk[];
-static struct clk spll_clk;
+#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)
 
-static int _clk_enable(struct clk *clk)
+/* 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 @@
 	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 @@
 	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 @@
 	__raw_writel(reg, CCM_CSCR);
 }
 
-static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
+static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
 {
-	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)
-{
-	_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 @@
 	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 @@
 
 	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 @@
 	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 @@
 		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 2UL * parent_rate / ssi2_pdf;
+	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
 }
 
-static unsigned long _clk_nfc_recalc(struct clk *clk)
+static unsigned long get_rate_ssi2(struct clk *clk)
+{
+	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
+}
+
+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 @@
 	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 @@
 /* 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 @@
 	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,
-	},
+/*
+ * 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,
 };
 
-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,
-	},
+static struct clk mpll_clk = {
+	.parent		= &ckih_clk,
+	.get_rate	= get_rate_mpll,
 };
 
-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,
-	},
+/* 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,
 };
 
-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,
-	},
+/* 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,
 };
 
-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,
-	},
+static struct clk ahb_clk = {
+	.parent		= &mpll_main2_clk,
+	.get_rate	= get_rate_ahb,
 };
 
-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,
-	},
+static struct clk ipg_clk = {
+	.parent		= &ahb_clk,
+	.get_rate	= get_rate_ipg,
 };
 
-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 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 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 spll_clk = {
+	.parent = &ckih_clk,
+	.get_rate = get_rate_spll,
+	.enable = clk_spll_enable,
+	.disable = clk_spll_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,
-	},
+/*
+ * 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 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,
-	},
+/* Output of frequency pre multiplier */
+static struct clk fpm_clk = {
+	.parent = &ckil_clk,
+	.get_rate = get_rate_fpm,
 };
 
-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,
-	},
-};
+#define PCCR0 CCM_PCCR0
+#define PCCR1 CCM_PCCR1
 
-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,
-	},
-};
-
-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 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,
-	},
-};
-
-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,
-	},
-};
-
-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 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 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 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 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,
-	},
-};
-
-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,
-	},
-};
-
-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,
-	},
-};
-
-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,
+#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,				\
+	}
+
+/* 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_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)
 };
 
-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,
-};
-
-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,
-	},
-};
-
-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)
+/* Adjust the clock path for TO2 and later */
+static void __init to2_adjust_clocks(void)
 {
-	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;
+	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 @@
 		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 @@
  */
 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;
 }
+
diff --git a/arch/arm/mach-mx2/cpu_imx27.c b/arch/arm/mach-mx2/cpu_imx27.c
index 239308f..d9e3bf9 100644
--- a/arch/arm/mach-mx2/cpu_imx27.c
+++ b/arch/arm/mach-mx2/cpu_imx27.c
@@ -26,11 +26,11 @@
 
 #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
index 94644cd..0000000
--- a/arch/arm/mach-mx2/crm_regs.h
+++ /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__ */
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 9cc2b16..10f65bf 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -15,6 +15,7 @@
 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