diff mbox

[RFC,V1,8/8] ARM i.MX51/53: reimplement clock support

Message ID 1322046755-13511-9-git-send-email-richard.zhao@linaro.org
State RFC
Headers show

Commit Message

Richard Zhao Nov. 23, 2011, 11:12 a.m. UTC
From: Sascha Hauer <s.hauer@pengutronix.de>

Reimplement i.MX51/53 clock support. This is tested with a babbage
board and a loco board up to the point that UARTs, FEC and USB work.
There are surely bugs left in the code, but I found several in the
old code while reimplementing it, so who cares...
The implementation is mostly based on the datasheet and not the old
code.

The old code is left in the tree and removed in the next patch.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/mach-mx5/Kconfig              |   14 +
 arch/arm/mach-mx5/Makefile             |    2 +-
 arch/arm/mach-mx5/clock-imx51-imx53.c  |  636 ++++++++++++++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/clock.h |    3 +
 4 files changed, 654 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-mx5/clock-imx51-imx53.c
diff mbox

Patch

diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index af0c212..924930b 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -31,6 +31,13 @@  config	SOC_IMX51
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
 	select ARCH_MX51
+	select GENERIC_CLK
+	select GENERIC_CLK_FIXED
+	select GENERIC_CLK_DIVIDER
+	select GENERIC_CLK_MUX
+	select GENERIC_CLK_DUMMY
+	select IMX_CLK_PLLV2
+	select IMX_CLK_GATE2B
 
 config	SOC_IMX53
 	bool
@@ -39,6 +46,13 @@  config	SOC_IMX53
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MX53
+	select GENERIC_CLK
+	select GENERIC_CLK_FIXED
+	select GENERIC_CLK_DIVIDER
+	select GENERIC_CLK_MUX
+	select GENERIC_CLK_DUMMY
+	select IMX_CLK_PLLV2
+	select IMX_CLK_GATE2B
 
 #comment "i.MX50 machines:"
 
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 0fc6080..b26438d 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -3,7 +3,7 @@ 
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
+obj-y   := cpu.o mm.o clock-imx51-imx53.o ehci.o system.o
 
 obj-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
diff --git a/arch/arm/mach-mx5/clock-imx51-imx53.c b/arch/arm/mach-mx5/clock-imx51-imx53.c
new file mode 100644
index 0000000..ba02c46
--- /dev/null
+++ b/arch/arm/mach-mx5/clock-imx51-imx53.c
@@ -0,0 +1,636 @@ 
+/*
+ * Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <asm/div64.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "crm_regs.h"
+
+struct clk_dummy {
+	struct clk clk;
+};
+
+static struct clk_hw_ops dumy_ops;
+static struct clk_dummy dummy = {
+	.clk = {
+		.name = "dummy",
+		.ops = &dumy_ops,
+	},
+};
+
+static DEFINE_CLK_FIXED(ckil, 0);
+static DEFINE_CLK_FIXED(osc, 0);
+static DEFINE_CLK_FIXED(ckih1, 0);
+static DEFINE_CLK_FIXED(ckih2, 0);
+
+static DEFINE_CLK_PLLV2(pll1, &osc.clk, MX51_DPLL1_BASE);
+static DEFINE_CLK_PLLV2(pll2, &osc.clk, MX51_DPLL2_BASE);
+static DEFINE_CLK_PLLV2(pll3, &osc.clk, MX51_DPLL3_BASE);
+static DEFINE_CLK_PLLV2(pll4, &osc.clk, MX53_DPLL4_BASE);
+
+static struct clk_dummy dummy;
+
+/* Low-power Audio Playback Mode clock */
+static struct clk *lp_apm_sel[] = {
+	&osc.clk,
+	NULL,
+};
+static DEFINE_CLK_MUX(lp_apm, MXC_CCM_CCSR, 9, 1, lp_apm_sel);
+
+static DEFINE_CLK_DIVIDER(step_pll2_div, &pll2.clk, 0, MXC_CCM_CCSR, 5, 2);
+
+static DEFINE_CLK_DIVIDER(step_pll3_div, &pll3.clk, 0, MXC_CCM_CCSR, 3, 2);
+
+static struct clk *step_clk_sel[] = {
+	&lp_apm.clk,
+	NULL,
+	&step_pll2_div.clk,
+	&step_pll3_div.clk,
+};
+static DEFINE_CLK_MUX(step_clk, MXC_CCM_CCSR, 7, 2, step_clk_sel);
+
+static struct clk *pll1_sw_sel[] = {
+	&pll1.clk,
+	&step_clk.clk,
+};
+static DEFINE_CLK_MUX(pll1_sw, MXC_CCM_CCSR, 2, 1, pll1_sw_sel);
+
+static struct clk *pll2_sw_sel[] = {
+	&pll2.clk,
+	NULL,
+};
+static DEFINE_CLK_MUX(pll2_sw, MXC_CCM_CCSR, 1, 1, pll2_sw_sel);
+
+static struct clk *pll3_sw_sel[] = {
+	&pll3.clk,
+	NULL,
+};
+static DEFINE_CLK_MUX(pll3_sw, MXC_CCM_CCSR, 0, 1, pll3_sw_sel);
+
+static struct clk *pll4_sw_sel[] = {
+	&pll4.clk,
+	NULL,
+};
+static DEFINE_CLK_MUX(pll4_sw, MXC_CCM_CCSR, 9, 1, pll4_sw_sel);
+
+
+/* This is used multiple times */
+static struct clk *standard_pll_sel_clks[] = {
+	&pll1_sw.clk,
+	&pll2_sw.clk,
+	&pll3_sw.clk,
+	&lp_apm.clk,
+};
+
+static struct clk *periph_apm_sel[] = {
+	&pll1_sw.clk,
+	&pll3_sw.clk,
+	&lp_apm.clk,
+};
+static DEFINE_CLK_MUX(periph_apm, MXC_CCM_CBCMR, 12, 2, periph_apm_sel);
+
+static struct clk *main_bus_sel[] = {
+	&pll2_sw.clk,
+	&periph_apm.clk,
+};
+static DEFINE_CLK_MUX(main_bus, MXC_CCM_CBCDR, 25, 1, main_bus_sel);
+
+static DEFINE_CLK_DIVIDER(ahb_root, &main_bus.clk, 0, MXC_CCM_CBCDR, 10, 3);
+static DEFINE_CLK_DIVIDER(ipg, &ahb_root.clk, 0, MXC_CCM_CBCDR, 8, 2);
+
+static struct clk *perclk_lp_apm_sel[] = {
+	&main_bus.clk,
+	&lp_apm.clk,
+};
+static DEFINE_CLK_MUX(perclk_lp_apm, MXC_CCM_CBCMR, 1, 1, perclk_lp_apm_sel);
+
+static DEFINE_CLK_DIVIDER(perclk_pred1, &perclk_lp_apm.clk, 0, MXC_CCM_CBCDR, 6, 2);
+static DEFINE_CLK_DIVIDER(perclk_pred2, &perclk_pred1.clk, 0, MXC_CCM_CBCDR, 3, 3);
+static DEFINE_CLK_DIVIDER(perclk_podf, &perclk_pred2.clk, CLK_PARENT_SET_RATE, MXC_CCM_CBCDR, 0, 3);
+
+static struct clk *ipg_perclk_sel[] = {
+	&perclk_podf.clk,
+	&ipg.clk,
+};
+static DEFINE_CLK_MUX(ipg_perclk, MXC_CCM_CBCMR, 0, 1, ipg_perclk_sel);
+
+static DEFINE_CLK_DIVIDER(axi_a, &main_bus.clk, 0, MXC_CCM_CBCDR, 16, 3);
+static DEFINE_CLK_DIVIDER(axi_b, &main_bus.clk, 0, MXC_CCM_CBCDR, 19, 3);
+
+static struct clk *emi_slow_sel_clks[] = {
+	&main_bus.clk,
+	&ahb_root.clk,
+};
+static DEFINE_CLK_MUX(emi_sel, MXC_CCM_CBCDR, 26, 1, emi_slow_sel_clks);
+static DEFINE_CLK_DIVIDER(emi_slow_podf, &emi_sel.clk, 0, MXC_CCM_CBCDR, 22, 3);
+static DEFINE_CLK_DIVIDER(nfc_podf, &emi_slow_podf.clk, 0, MXC_CCM_CBCDR, 13, 3);
+
+static struct clk *xpu_sel[] = {
+	&axi_a.clk,
+	&axi_b.clk,
+	&emi_slow_podf.clk,
+	&ahb_root.clk,
+};
+static DEFINE_CLK_MUX(gpu2d, MXC_CCM_CBCMR, 16, 2, xpu_sel);
+static DEFINE_CLK_MUX(arm_axi, MXC_CCM_CBCMR, 8, 2, xpu_sel);
+static DEFINE_CLK_MUX(ipu_hsp, MXC_CCM_CBCMR, 6, 2, xpu_sel);
+static DEFINE_CLK_MUX(gpu, MXC_CCM_CBCMR, 4, 2, xpu_sel);
+static DEFINE_CLK_MUX(vpu_axi_root, MXC_CCM_CBCMR, 14, 2, xpu_sel);
+static DEFINE_CLK_MUX(ddr_root, MXC_CCM_CBCMR, 10, 2, xpu_sel);
+
+static DEFINE_CLK_DIVIDER(ddr_hf_mx51, &pll1_sw.clk, 0, MXC_CCM_CBCDR, 27, 3);
+static struct clk *ddr_hf_sel[] = {
+	&ddr_root.clk,
+	&ddr_hf_mx51.clk,
+};
+static DEFINE_CLK_MUX(ddr_root_mx51, MXC_CCM_CBCDR, 30, 1, ddr_hf_sel);
+
+static DEFINE_CLK_MUX(uart_sel, MXC_CCM_CSCMR1, 24, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(uart_pred, &uart_sel.clk, 0, MXC_CCM_CSCDR1, 3, 3);
+static DEFINE_CLK_DIVIDER(uart_root, &uart_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CSCDR1, 0, 3);
+
+static DEFINE_CLK_MUX(esdhc1_sel, MXC_CCM_CSCMR1, 20, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(esdhc1_pred, &esdhc1_sel.clk, 0, MXC_CCM_CSCDR1, 16, 3);
+static DEFINE_CLK_DIVIDER(esdhc1_podf, &esdhc1_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CSCDR1, 11, 3);
+
+/* This is routed to esdhc3 in the i.MX53 datasheet */
+static DEFINE_CLK_MUX(esdhc2_sel, MXC_CCM_CSCMR1, 16, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(esdhc2_pred, &esdhc2_sel.clk, 0, MXC_CCM_CSCDR1, 22, 3);
+static DEFINE_CLK_DIVIDER(esdhc2_podf, &esdhc2_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CSCDR1, 19, 3);
+
+static struct clk *esdhc3_sel_clks[] = {
+	&esdhc1_podf.clk,
+	&esdhc2_podf.clk,
+};
+static DEFINE_CLK_MUX(esdhc3_sel, MXC_CCM_CSCMR1, 19, 1, esdhc3_sel_clks);
+
+static struct clk *esdhc4_sel_clks[] = {
+	&esdhc1_podf.clk,
+	&esdhc2_podf.clk,
+};
+static DEFINE_CLK_MUX(esdhc4_sel, MXC_CCM_CSCMR1, 18, 1, esdhc4_sel_clks);
+
+static struct clk *ssi_apm_sel[] = {
+	&ckih1.clk,
+	&lp_apm.clk,
+	&ckih2.clk,
+};
+static DEFINE_CLK_MUX(ssi_lp_apm, MXC_CCM_CSCMR1, 8, 2, ssi_apm_sel);
+static DEFINE_CLK_MUX(ssi1_clk_sel, MXC_CCM_CSCMR1, 14, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(ssi1_clk_pred, &ssi1_clk_sel.clk, 0, MXC_CCM_CS1CDR, 6, 3);
+static DEFINE_CLK_DIVIDER(ssi1_clk, &ssi1_clk_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CS1CDR, 0, 6);
+static DEFINE_CLK_MUX(ssi2_clk_sel, MXC_CCM_CSCMR1, 12, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(ssi2_clk_pred, &ssi2_clk_sel.clk, 0, MXC_CCM_CS2CDR, 6, 3);
+static DEFINE_CLK_DIVIDER(ssi2_clk, &ssi2_clk_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CS2CDR, 0, 6);
+static struct clk *ssi3_clk_sel[] = {
+	&ssi1_clk.clk,
+	&ssi2_clk.clk,
+};
+static DEFINE_CLK_MUX(ssi3_clk, MXC_CCM_CSCMR1, 11, 1, ssi3_clk_sel);
+
+static DEFINE_CLK_MUX(ecspi_sel, MXC_CCM_CSCMR1, 4, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(ecspi_pred, &ecspi_sel.clk, 0, MXC_CCM_CSCDR2, 25, 3);
+static DEFINE_CLK_DIVIDER(ecspi_podf, &ecspi_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CSCDR2, 19, 6);
+
+static DEFINE_CLK_MUX(usboh3_sel, MXC_CCM_CSCMR1, 22, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(usboh3_pred, &usboh3_sel.clk, 0, MXC_CCM_CSCDR1, 8, 3);
+static DEFINE_CLK_DIVIDER(usboh3_podf, &usboh3_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CSCDR1, 6, 2);
+
+static DEFINE_CLK_DIVIDER(usb_phy_pred, &pll3_sw.clk, 0, MXC_CCM_CDCDR, 3, 3);
+static DEFINE_CLK_DIVIDER(usb_phy_podf, &usb_phy_pred.clk, CLK_PARENT_SET_RATE, MXC_CCM_CDCDR, 0, 3);
+static struct clk *usb_phy_sel_clks[] = {
+	&osc.clk,
+	&usb_phy_podf.clk,
+};
+static DEFINE_CLK_MUX(usb_phy_sel, MXC_CCM_CSCMR1, 26, 1, usb_phy_sel_clks);
+
+static DEFINE_CLK_DIVIDER(cpu_podf, &pll1_sw.clk, 0, MXC_CCM_CACRR, 0, 3);
+
+static struct clk *ipu_di0_sel_clks[] = {
+	&pll3_sw.clk,
+	&osc.clk,
+	&ckih1.clk,
+	NULL, /* &tve_di.clk */
+	NULL, /* ipp di0 (iomux) */
+	NULL, /* ldp di0 */
+};
+static DEFINE_CLK_MUX(ipu_di0_sel, MXC_CCM_CSCMR2, 26, 3, ipu_di0_sel_clks);
+
+static struct clk *ipu_di1_sel_clks[] = {
+	&pll3_sw.clk,
+	&osc.clk,
+	&ckih1.clk,
+	NULL, /* &tve_di.clk */
+	NULL, /* ipp di1 (iomux) */
+	NULL, /* ldp di1 */
+};
+static DEFINE_CLK_MUX(ipu_di1_sel, MXC_CCM_CSCMR2, 29, 3, ipu_di1_sel_clks);
+
+static struct clk *tve_ext_sel_clks[] = {
+	&osc.clk,
+	&ckih1.clk,
+};
+static DEFINE_CLK_MUX(tve_ext_sel, MXC_CCM_CSCMR1, 6, 1, tve_ext_sel_clks);
+
+static DEFINE_CLK_DIVIDER(tve_pred, &pll3_sw.clk, 0, MXC_CCM_CDCDR, 28, 3);
+
+static struct clk *tve_sel_clks[] = {
+	&tve_pred.clk,
+	&tve_ext_sel.clk,
+};
+static DEFINE_CLK_MUX(tve_sel, MXC_CCM_CSCMR1, 7, 1, tve_sel_clks);
+
+static DEFINE_CLK_GATE2B(ahbmux1, &ipg.clk, MXC_CCM_CCGR0, 8);
+static DEFINE_CLK_GATE2B(aips_tz1, &ipg.clk, MXC_CCM_CCGR0, 12);
+static DEFINE_CLK_GATE2B(aips_tz2, &ipg.clk, MXC_CCM_CCGR0, 13);
+static DEFINE_CLK_GATE2B(ahb_max, &ipg.clk, MXC_CCM_CCGR0, 14);
+static DEFINE_CLK_GATE2B(iim_gate, &ipg.clk, MXC_CCM_CCGR0, 15);
+
+static DEFINE_CLK_GATE2B(uart1_ipg_gate, &ipg.clk, MXC_CCM_CCGR1, 3);
+static DEFINE_CLK_GATE2B(uart1_per_gate, &uart_root.clk, MXC_CCM_CCGR1, 4);
+static DEFINE_CLK_GATE2B(uart2_ipg_gate, &ipg.clk, MXC_CCM_CCGR1, 5);
+static DEFINE_CLK_GATE2B(uart2_per_gate, &uart_root.clk, MXC_CCM_CCGR1, 6);
+static DEFINE_CLK_GATE2B(uart3_ipg_gate, &ipg.clk, MXC_CCM_CCGR1, 7);
+static DEFINE_CLK_GATE2B(uart3_per_gate, &uart_root.clk, MXC_CCM_CCGR1, 8);
+static DEFINE_CLK_GATE2B(i2c1_gate, &ipg_perclk.clk, MXC_CCM_CCGR1, 9);
+static DEFINE_CLK_GATE2B(i2c2_gate, &ipg_perclk.clk, MXC_CCM_CCGR1, 10);
+static DEFINE_CLK_GATE2B(hsi2c_gate, &ipg.clk, MXC_CCM_CCGR1, 11);
+
+static DEFINE_CLK_GATE2B(mx51_usb_phy_gate, &usb_phy_sel.clk, MXC_CCM_CCGR2, 0);
+static DEFINE_CLK_GATE2B(gpt_ipg_gate, &ipg.clk, MXC_CCM_CCGR2, 10);
+static DEFINE_CLK_GATE2B(pwm1_ipg_gate, &ipg.clk, MXC_CCM_CCGR2, 5);
+static DEFINE_CLK_GATE2B(pwm1_hf_gate, &ipg_perclk.clk, MXC_CCM_CCGR2, 6);
+static DEFINE_CLK_GATE2B(pwm2_ipg_gate, &ipg.clk, MXC_CCM_CCGR2, 7);
+static DEFINE_CLK_GATE2B(pwm2_hf_gate, &ipg_perclk.clk, MXC_CCM_CCGR2, 8);
+static DEFINE_CLK_GATE2B(gpt_gate, &ipg.clk, MXC_CCM_CCGR2, 9);
+static DEFINE_CLK_GATE2B(fec_gate, &ipg.clk, MXC_CCM_CCGR2, 12);
+static DEFINE_CLK_GATE2B(usboh3_ahb_gate, &ipg.clk, MXC_CCM_CCGR2, 13);
+static DEFINE_CLK_GATE2B(usboh3_gate, &usboh3_podf.clk, MXC_CCM_CCGR2, 14);
+static DEFINE_CLK_GATE2B(tve_gate, &tve_sel.clk, MXC_CCM_CCGR2, 15);
+
+static DEFINE_CLK_GATE2B(esdhc1_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 0);
+static DEFINE_CLK_GATE2B(esdhc1_per_gate, &esdhc1_podf.clk, MXC_CCM_CCGR3, 1);
+static DEFINE_CLK_GATE2B(esdhc2_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 2);
+static DEFINE_CLK_GATE2B(esdhc2_per_gate, &esdhc2_podf.clk, MXC_CCM_CCGR3, 3);
+static DEFINE_CLK_GATE2B(esdhc3_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 4);
+static DEFINE_CLK_GATE2B(esdhc3_per_gate, &esdhc3_sel.clk, MXC_CCM_CCGR3, 5);
+static DEFINE_CLK_GATE2B(esdhc4_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 6);
+static DEFINE_CLK_GATE2B(esdhc4_per_gate, &esdhc4_sel.clk, MXC_CCM_CCGR3, 7);
+static DEFINE_CLK_GATE2B(ssi1_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 8);
+static DEFINE_CLK_GATE2B(ssi1_gate, &ssi1_clk.clk, MXC_CCM_CCGR3, 9);
+static DEFINE_CLK_GATE2B(ssi2_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 10);
+static DEFINE_CLK_GATE2B(ssi2_gate, &ssi2_clk.clk, MXC_CCM_CCGR3, 11);
+static DEFINE_CLK_GATE2B(ssi3_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 12);
+static DEFINE_CLK_GATE2B(ssi3_gate, &ssi3_clk.clk, MXC_CCM_CCGR3, 13);
+
+static DEFINE_CLK_GATE2B(mx51_mipi_hsc1_gate, &ipg.clk, MXC_CCM_CCGR4, 3);
+static DEFINE_CLK_GATE2B(mx51_mipi_hsc2_gate, &ipg.clk, MXC_CCM_CCGR4, 4);
+static DEFINE_CLK_GATE2B(mx51_mipi_esc_gate, &ipg.clk, MXC_CCM_CCGR4, 5);
+static DEFINE_CLK_GATE2B(mx51_mipi_hsp_gate, &ipg.clk, MXC_CCM_CCGR4, 6);
+
+static DEFINE_CLK_GATE2B(mx53_usb_phy1_gate, &usb_phy_sel.clk, MXC_CCM_CCGR4, 5);
+static DEFINE_CLK_GATE2B(mx53_usb_phy2_gate, &usb_phy_sel.clk, MXC_CCM_CCGR4, 6);
+static DEFINE_CLK_GATE2B(ecspi1_ipg_gate, &ipg.clk, MXC_CCM_CCGR4, 9);
+static DEFINE_CLK_GATE2B(ecspi1_per_gate, &ecspi_podf.clk, MXC_CCM_CCGR4, 10);
+static DEFINE_CLK_GATE2B(ecspi2_ipg_gate, &ipg.clk, MXC_CCM_CCGR4, 11);
+static DEFINE_CLK_GATE2B(ecspi2_per_gate, &ecspi_podf.clk, MXC_CCM_CCGR4, 12);
+static DEFINE_CLK_GATE2B(cspi_ipg_gate, &ipg.clk, MXC_CCM_CCGR4, 13);
+static DEFINE_CLK_GATE2B(sdma_gate, &ipg.clk, MXC_CCM_CCGR4, 15);
+
+static DEFINE_CLK_GATE2B(ipu_gate, &ipu_hsp.clk, MXC_CCM_CCGR5, 5);
+static DEFINE_CLK_GATE2B(emi_fast_gate, &dummy.clk, MXC_CCM_CCGR5, 7);
+static DEFINE_CLK_GATE2B(emi_slow_gate, &emi_slow_podf.clk, MXC_CCM_CCGR5, 8);
+static DEFINE_CLK_GATE2B(nfc_gate, &nfc_podf.clk, MXC_CCM_CCGR5, 10);
+
+static DEFINE_CLK_GATE2B(ipu_di0_gate, &ipu_di0_sel.clk, MXC_CCM_CCGR6, 5);
+static DEFINE_CLK_GATE2B(ipu_di1_gate, &ipu_di1_sel.clk, MXC_CCM_CCGR6, 6);
+
+#define _REGISTER_CLKDEV(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = c,   \
+	},
+
+static struct clk_lookup mx5_lookups[] = {
+	_REGISTER_CLKDEV("imx21-uart.0", NULL, &uart1_per_gate.clk)
+	_REGISTER_CLKDEV("imx21-uart.1", NULL, &uart2_per_gate.clk)
+	_REGISTER_CLKDEV("imx21-uart.2", NULL, &uart3_per_gate.clk)
+	_REGISTER_CLKDEV("mxc_pwm.0", "pwm", &pwm1_ipg_gate.clk)
+	_REGISTER_CLKDEV("mxc_pwm.1", "pwm", &pwm2_ipg_gate.clk)
+	_REGISTER_CLKDEV("imx-i2c.0", NULL, &i2c1_gate.clk)
+	_REGISTER_CLKDEV("imx-i2c.1", NULL, &i2c2_gate.clk)
+	_REGISTER_CLKDEV("mxc-ehci.0", "usb", &usboh3_gate.clk)
+	_REGISTER_CLKDEV("mxc-ehci.0", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLKDEV("mxc-ehci.0", "usb_phy1", &mx53_usb_phy1_gate.clk)
+	_REGISTER_CLKDEV("mxc-ehci.1", "usb", &usboh3_gate.clk)
+	_REGISTER_CLKDEV("mxc-ehci.1", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLKDEV("mxc-ehci.2", "usb", &usboh3_gate.clk)
+	_REGISTER_CLKDEV("mxc-ehci.2", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLKDEV("fsl-usb2-udc", "usb", &usboh3_gate.clk)
+	_REGISTER_CLKDEV("fsl-usb2-udc", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLKDEV("mxc_nand", NULL, &nfc_gate.clk)
+	_REGISTER_CLKDEV("imx-ssi.0", NULL, &ssi1_gate.clk)
+	_REGISTER_CLKDEV("imx-ssi.1", NULL, &ssi2_gate.clk)
+	_REGISTER_CLKDEV("imx-ssi.2", NULL, &ssi3_gate.clk)
+	_REGISTER_CLKDEV("imx-sdma", NULL, &sdma_gate.clk)
+	_REGISTER_CLKDEV("imx51-ecspi.0", NULL, &ecspi1_per_gate.clk)
+	_REGISTER_CLKDEV("imx51-ecspi.1", NULL, &ecspi2_per_gate.clk)
+	_REGISTER_CLKDEV("imx51-cspi.0", NULL, &cspi_ipg_gate.clk)
+	_REGISTER_CLKDEV(NULL, "cpu", &cpu_podf.clk)
+	_REGISTER_CLKDEV(NULL, "iim", &iim_gate.clk)
+	_REGISTER_CLKDEV("sdhci-esdhc-imx.0", NULL, &esdhc1_per_gate.clk)
+	_REGISTER_CLKDEV("sdhci-esdhc-imx.1", NULL, &esdhc2_per_gate.clk)
+	_REGISTER_CLKDEV("sdhci-esdhc-imx.2", NULL, &esdhc3_per_gate.clk)
+	_REGISTER_CLKDEV("sdhci-esdhc-imx.3", NULL, &esdhc4_per_gate.clk)
+	_REGISTER_CLKDEV("imx-ipuv3", NULL, &ipu_gate.clk)
+	_REGISTER_CLKDEV("imx-ipuv3", "di0", &ipu_di0_gate.clk)
+	_REGISTER_CLKDEV("imx-ipuv3", "di1", &ipu_di1_gate.clk)
+	_REGISTER_CLKDEV("imx2-wdt.0", NULL, &dummy.clk)
+	_REGISTER_CLKDEV("imx2-wdt.1", NULL, &dummy.clk)
+	_REGISTER_CLKDEV("imx-keypad", NULL, &dummy.clk)
+};
+
+static struct clk_lookup mx51_lookups[] = {
+	_REGISTER_CLKDEV("imx-i2c.2", NULL, &hsi2c_gate.clk)
+	_REGISTER_CLKDEV("imx27-fec.0", NULL, &fec_gate.clk)
+	_REGISTER_CLKDEV(NULL, "mipi_hsp", &mx51_mipi_hsp_gate.clk)
+};
+
+static struct clk_lookup mx53_lookups[] = {
+	_REGISTER_CLKDEV("imx25-fec.0", NULL, &fec_gate.clk)
+};
+
+struct clk *mx5_on_clocks[] = {
+	&uart1_ipg_gate.clk,
+	&uart2_ipg_gate.clk,
+	&uart3_ipg_gate.clk,
+	&gpt_ipg_gate.clk,
+	&esdhc1_ipg_gate.clk,
+	&esdhc2_ipg_gate.clk,
+	&esdhc3_ipg_gate.clk,
+	&esdhc4_ipg_gate.clk,
+	&ecspi1_ipg_gate.clk,
+	&ecspi2_ipg_gate.clk,
+	&cspi_ipg_gate.clk,
+};
+
+#define _REGISTER_CLK(_clk, _ops, _flags) \
+		&(_clk).clk,
+
+struct clk *mx5_clk_array[] = {
+	_REGISTER_CLK(ckil, &clk_fixed_ops, CLK_IS_ROOT)
+	_REGISTER_CLK(osc, &clk_fixed_ops, CLK_IS_ROOT)
+	_REGISTER_CLK(ckih1, &clk_fixed_ops, CLK_IS_ROOT)
+	_REGISTER_CLK(ckih2, &clk_fixed_ops, CLK_IS_ROOT)
+	_REGISTER_CLK(pll1, &clk_pllv2_ops, 0)
+	_REGISTER_CLK(pll2, &clk_pllv2_ops, 0)
+	_REGISTER_CLK(pll3, &clk_pllv2_ops, 0)
+	/*
+	 * pll4 is only used by mx53. we put it here because
+	 * tve_ext_sel use it early
+	*/
+	_REGISTER_CLK(pll4, &clk_pllv2_ops, 0)
+	_REGISTER_CLK(pll4_sw, &clk_mux_ops, 0)
+	_REGISTER_CLK(dummy, &clk_dummy_ops, CLK_IS_ROOT)
+	_REGISTER_CLK(lp_apm, &clk_mux_ops, 0)
+	_REGISTER_CLK(step_pll2_div, &clk_divider_ops, 0)
+	_REGISTER_CLK(step_pll3_div, &clk_divider_ops, 0)
+	_REGISTER_CLK(step_clk, &clk_mux_ops, 0)
+	_REGISTER_CLK(pll1_sw, &clk_mux_ops, 0)
+	_REGISTER_CLK(pll2_sw, &clk_mux_ops, 0)
+	_REGISTER_CLK(pll3_sw, &clk_mux_ops, 0)
+	_REGISTER_CLK(periph_apm, &clk_mux_ops, 0)
+	_REGISTER_CLK(main_bus, &clk_mux_ops, 0)
+	_REGISTER_CLK(ahb_root, &clk_divider_ops, 0)
+	_REGISTER_CLK(ipg, &clk_divider_ops, 0)
+	_REGISTER_CLK(perclk_lp_apm, &clk_mux_ops, 0)
+	_REGISTER_CLK(perclk_pred1, &clk_divider_ops, 0)
+	_REGISTER_CLK(perclk_pred2, &clk_divider_ops, 0)
+	_REGISTER_CLK(perclk_podf, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(ipg_perclk, &clk_mux_ops, 0)
+	_REGISTER_CLK(axi_a, &clk_divider_ops, 0)
+	_REGISTER_CLK(axi_b, &clk_divider_ops, 0)
+	_REGISTER_CLK(gpu2d, &clk_mux_ops, 0)
+	_REGISTER_CLK(arm_axi, &clk_mux_ops, 0)
+	_REGISTER_CLK(ipu_hsp, &clk_mux_ops, 0)
+	_REGISTER_CLK(gpu, &clk_mux_ops, 0)
+	_REGISTER_CLK(vpu_axi_root, &clk_mux_ops, 0)
+	_REGISTER_CLK(ddr_root, &clk_mux_ops, 0)
+	_REGISTER_CLK(uart_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(uart_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(uart_root, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(esdhc1_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(esdhc1_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(esdhc1_podf, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(esdhc2_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(esdhc2_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(esdhc2_podf, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(esdhc3_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(esdhc4_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(emi_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(emi_slow_podf, &clk_divider_ops, 0)
+	_REGISTER_CLK(nfc_podf, &clk_divider_ops, 0)
+	_REGISTER_CLK(ssi_lp_apm, &clk_mux_ops, 0)
+	_REGISTER_CLK(ssi1_clk_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(ssi1_clk_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(ssi1_clk, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(ssi2_clk_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(ssi2_clk_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(ssi2_clk, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(ssi3_clk, &clk_mux_ops, 0)
+	_REGISTER_CLK(ecspi_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(ecspi_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(ecspi_podf, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(usboh3_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(usboh3_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(usboh3_podf, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(usb_phy_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(usb_phy_podf, &clk_divider_ops, HINT_PARENT_RATE_CHANGE)
+	_REGISTER_CLK(usb_phy_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(cpu_podf, &clk_divider_ops, 0)
+	_REGISTER_CLK(ipu_di0_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(ipu_di1_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(tve_ext_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(tve_pred, &clk_divider_ops, 0)
+	_REGISTER_CLK(tve_sel, &clk_mux_ops, 0)
+	_REGISTER_CLK(ahbmux1, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(aips_tz1, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(aips_tz2, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ahb_max, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(iim_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(uart1_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(uart1_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(uart2_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(uart2_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(uart3_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(uart3_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(i2c1_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(i2c2_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(gpt_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(pwm1_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(pwm1_hf_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(pwm2_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(pwm2_hf_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(gpt_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(fec_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(usboh3_ahb_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(usboh3_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(tve_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc1_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc1_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc2_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc2_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc3_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc3_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc4_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(esdhc4_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ssi1_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ssi1_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ssi2_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ssi2_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ssi3_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ssi3_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ecspi1_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ecspi1_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ecspi2_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ecspi2_per_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(cspi_ipg_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(sdma_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ipu_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(emi_fast_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(emi_slow_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(nfc_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ipu_di0_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(ipu_di1_gate, &clk_gate2b_ops, 0)
+};
+
+struct clk *mx51_clk_array[] = {
+	_REGISTER_CLK(ddr_hf_mx51, &clk_divider_ops, 0)
+	_REGISTER_CLK(ddr_root_mx51, &clk_mux_ops, 0)
+	_REGISTER_CLK(hsi2c_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(mx51_usb_phy_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(mx51_mipi_hsc1_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(mx51_mipi_hsc2_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(mx51_mipi_esc_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(mx51_mipi_hsp_gate, &clk_gate2b_ops, 0)
+};
+
+struct clk *mx53_clk_array[] = {
+	_REGISTER_CLK(mx53_usb_phy1_gate, &clk_gate2b_ops, 0)
+	_REGISTER_CLK(mx53_usb_phy2_gate, &clk_gate2b_ops, 0)
+};
+
+static void clk_register_array(struct clk **clks, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		clk_init(NULL, clks[i]);
+}
+
+static void clkdev_add_array(struct clk_lookup *lookup, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		clkdev_add(&lookup[i]);
+}
+
+static void mx5_clocks_common_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	int i;
+
+	ckil.fixed_rate = rate_ckil;
+	osc.fixed_rate = rate_osc;
+	ckih1.fixed_rate = rate_ckih1;
+	ckih2.fixed_rate = rate_ckih2;
+
+	clk_register_array(mx5_clk_array, ARRAY_SIZE(mx5_clk_array));
+	clkdev_add_array(mx5_lookups, ARRAY_SIZE(mx5_lookups));
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_sel.clk, &pll2_sw.clk);
+	clk_set_parent(&esdhc2_sel.clk, &pll2_sw.clk);
+
+	/* keep device ipg clocks on until drivers handle it */
+	for (i = 0; i < ARRAY_SIZE(mx5_on_clocks); i++) {
+		clk_prepare(mx5_on_clocks[i]);
+		clk_enable(mx5_on_clocks[i]);
+	}
+}
+
+int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	/* Clock tree has i.MX51 layout. i.MX53 needs some fixups */
+	pll1.base = MX53_DPLL1_BASE;
+	pll2.base = MX53_DPLL2_BASE;
+	pll3.base = MX53_DPLL3_BASE;
+	esdhc3_per_gate.clk.parent = &esdhc2_podf.clk;
+	esdhc2_per_gate.clk.parent = &esdhc3_sel.clk;
+	tve_gate.clk.parent = &tve_pred.clk;
+	tve_pred.clk.parent = &tve_ext_sel.clk;
+	tve_ext_sel_clks[0] = &pll4_sw.clk;
+	tve_ext_sel_clks[1] = &ckih1.clk;
+
+	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
+	clk_register_array(mx53_clk_array, ARRAY_SIZE(mx53_clk_array));
+	clkdev_add_array(mx53_lookups, ARRAY_SIZE(mx53_lookups));
+
+	/* set SDHC root clock to 200MHZ*/
+	clk_set_rate(&esdhc1_podf.clk, 200000000);
+	clk_set_rate(&esdhc2_podf.clk, 200000000);
+
+	/* System timer */
+	mxc_timer_init(&gpt_gate.clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+		MX53_INT_GPT);
+
+	clk_prepare(&iim_gate.clk);
+	clk_enable(&iim_gate.clk);
+	imx_print_silicon_rev("i.MX53", mx53_revision());
+	clk_disable(&iim_gate.clk);
+	clk_unprepare(&iim_gate.clk);
+
+	return 0;
+}
+
+int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
+	clk_register_array(mx51_clk_array, ARRAY_SIZE(mx5_clk_array));
+	clkdev_add_array(mx51_lookups, ARRAY_SIZE(mx51_lookups));
+
+	/* set SDHC root clock to 166.25MHZ*/
+	clk_set_rate(&esdhc1_podf.clk, 166250000);
+	clk_set_rate(&esdhc2_podf.clk, 166250000);
+
+	/* System timer */
+	mxc_timer_init(&gpt_gate.clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+		MX51_INT_GPT);
+
+	clk_prepare(&iim_gate.clk);
+	clk_enable(&iim_gate.clk);
+	imx_print_silicon_rev("i.MX51", mx51_revision());
+	clk_disable(&iim_gate.clk);
+
+	return 0;
+}
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index b9cfb46..2258807 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -26,6 +26,8 @@ 
 #ifndef CONFIG_GENERIC_CLK
 struct module;
 
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+#else
 struct clk {
 	int id;
 	/* Source clock this clk depends on */
@@ -57,6 +59,7 @@  struct clk {
 	/* Function ptr to set the parent clock of the clock. */
 	int (*set_parent) (struct clk *, struct clk *);
 };
+#endif
 
 int clk_register(struct clk *clk);
 void clk_unregister(struct clk *clk);