diff mbox

[32/40] ARM i.MX5: implement clocks using common clock framework

Message ID 1334065553-7565-33-git-send-email-s.hauer@pengutronix.de
State New
Headers show

Commit Message

Sascha Hauer April 10, 2012, 1:45 p.m. UTC
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/Kconfig           |    1 +
 arch/arm/mach-imx/Makefile          |    2 +-
 arch/arm/mach-imx/clk-imx51-imx53.c |  414 +++++++++++++++++++++++++++++++++++
 3 files changed, 416 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx51-imx53.c

Comments

Richard Zhao April 23, 2012, 6:39 a.m. UTC | #1
Hello Sascha,

I saw some code removed from clk init code. For example:
mx51_clocks_init:
clk_enable(&cpu_clk);
clk_enable(&main_bus_clk);
/* move usb_phy_clk to 24MHz */
clk_set_parent(&usb_phy1_clk, &osc_clk);
/* set the usboh3_clk parent to pll2_sw_clk */
clk_set_parent(&usboh3_clk, &pll2_sw_clk);

mx53_clocks_init:
clk_set_parent(&uart_root_clk, &pll3_sw_clk);

Could you explain why you remove them?
If it has reasonable purpose, do you think it's better to put
them in a seperate patch? It makes everyone clear what it changed.
 
Thanks
Richard
Sascha Hauer April 23, 2012, 6:54 a.m. UTC | #2
On Mon, Apr 23, 2012 at 02:39:50PM +0800, Richard Zhao wrote:
> Hello Sascha,
> 
> I saw some code removed from clk init code. For example:
> mx51_clocks_init:
> clk_enable(&cpu_clk);
> clk_enable(&main_bus_clk);
> /* move usb_phy_clk to 24MHz */
> clk_set_parent(&usb_phy1_clk, &osc_clk);
> /* set the usboh3_clk parent to pll2_sw_clk */
> clk_set_parent(&usboh3_clk, &pll2_sw_clk);
> 
> mx53_clocks_init:
> clk_set_parent(&uart_root_clk, &pll3_sw_clk);
> 
> Could you explain why you remove them?
> If it has reasonable purpose, do you think it's better to put
> them in a seperate patch? It makes everyone clear what it changed.

I can readd most of them, the setup simply got lost. BTW what is the
reason for reparenting the uart clock in the i.MX53 setup? This will
break early console support if the bootloader didn't setup the uart
clock in the same way already.

Sascha
Richard Zhao April 23, 2012, 7:28 a.m. UTC | #3
On Mon, Apr 23, 2012 at 08:54:19AM +0200, Sascha Hauer wrote:
> On Mon, Apr 23, 2012 at 02:39:50PM +0800, Richard Zhao wrote:
> > Hello Sascha,
> > 
> > I saw some code removed from clk init code. For example:
> > mx51_clocks_init:
> > clk_enable(&cpu_clk);
> > clk_enable(&main_bus_clk);
> > /* move usb_phy_clk to 24MHz */
> > clk_set_parent(&usb_phy1_clk, &osc_clk);
> > /* set the usboh3_clk parent to pll2_sw_clk */
> > clk_set_parent(&usboh3_clk, &pll2_sw_clk);
> > 
> > mx53_clocks_init:
> > clk_set_parent(&uart_root_clk, &pll3_sw_clk);
> > 
> > Could you explain why you remove them?
> > If it has reasonable purpose, do you think it's better to put
> > them in a seperate patch? It makes everyone clear what it changed.
> 
> I can readd most of them, the setup simply got lost. BTW what is the
> reason for reparenting the uart clock in the i.MX53 setup? This will
> break early console support if the bootloader didn't setup the uart
> clock in the same way already.
I think you can remove the uart reparent. The original aim is to avoid
use the same pll as display/ipu. Dispaly requires precise clk which sometimes
change pll rate.

You might need also check other platforms wheter they lost setup code.

Thanks
Richard
> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>
diff mbox

Patch

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 692de7b..eb14ae9 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -82,6 +82,7 @@  config SOC_IMX35
 config SOC_IMX5
 	select CPU_V7
 	select MXC_TZIC
+	select COMMON_CLK
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_HAS_CPUFREQ
 	select ARCH_MX5
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index fdad8f4..adf2e4f 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -9,7 +9,7 @@  obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-imx3.o
 
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
 			    clk-pfd.o clk-busy.o
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
new file mode 100644
index 0000000..5b5d7a0
--- /dev/null
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -0,0 +1,414 @@ 
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+
+#include "crm-regs-imx5.h"
+#include "clk.h"
+
+/* Low-power Audio Playback Mode clock */
+static char *lp_apm_sel[] = { "osc", };
+
+/* This is used multiple times */
+static char *standard_pll_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "lp_apm", };
+static char *periph_apm_sel[] = { "pll1_sw", "pll3_sw", "lp_apm", };
+static char *main_bus_sel[] = { "pll2_sw", "periph_apm", };
+static char *esdhc_c_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
+static char *esdhc_d_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
+static char *emi_slow_sel[] = { "main_bus", "ahb", };
+static char *usb_phy_sel[] = { "osc", "usb_phy_podf", };
+static char *mx51_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "tve_di", };
+static char *mx53_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "di_pll4_podf", "dummy", "ldb_di0", };
+static char *mx53_ldb_di0_sel[] = { "pll3_sw", "pll4_sw", };
+static char *mx51_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", };
+static char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", "ldb_di1", };
+static char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", };
+static char *mx51_tve_ext_sel[] = { "osc", "ckih1", };
+static char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", };
+static char *tve_sel[] = { "tve_pred", "tve_ext_sel", };
+static char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
+static char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
+
+#define clkdev(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clkname = c, \
+	},
+
+static struct clk_lookup mx5_lookups[] = {
+	clkdev("imx-gpt.0", "per", "gpt_gate")
+	clkdev("imx-gpt.0", "ipg", "gpt_ipg_gate")
+	clkdev("imx21-uart.0", "per", "uart1_per_gate")
+	clkdev("imx21-uart.0", "ipg", "uart1_ipg_gate")
+	clkdev("imx21-uart.1", "per", "uart2_per_gate")
+	clkdev("imx21-uart.1", "ipg", "uart2_ipg_gate")
+	clkdev("imx21-uart.2", "per", "uart3_per_gate")
+	clkdev("imx21-uart.2", "ipg", "uart3_ipg_gate")
+	clkdev("imx21-uart.3", "per", "uart4_per_gate")
+	clkdev("imx21-uart.3", "ipg", "uart4_ipg_gate")
+	clkdev("imx21-uart.4", "per", "uart5_per_gate")
+	clkdev("imx21-uart.4", "ipg", "uart5_ipg_gate")
+	clkdev("imx51-ecspi.0", "per", "ecspi1_per_gate")
+	clkdev("imx51-ecspi.0", "ipg", "ecspi1_ipg_gate")
+	clkdev("imx51-ecspi.1", "per", "ecspi2_per_gate")
+	clkdev("imx51-ecspi.1", "ipg", "ecspi2_ipg_gate")
+	clkdev("imx51-cspi.0", NULL, "cspi_ipg_gate")
+	clkdev("mxc_pwm.0", "pwm", "pwm1_ipg_gate")
+	clkdev("mxc_pwm.1", "pwm", "pwm2_ipg_gate")
+	clkdev("imx-i2c.0", NULL, "i2c1_gate")
+	clkdev("imx-i2c.1", NULL, "i2c2_gate")
+	clkdev("mxc-ehci.0", "per", "usboh3_per_gate")
+	clkdev("mxc-ehci.0", "ipg", "usboh3_gate")
+	clkdev("mxc-ehci.0", "ahb", "usboh3_gate")
+	clkdev("mxc-ehci.1", "per", "usboh3_per_gate")
+	clkdev("mxc-ehci.1", "ipg", "usboh3_gate")
+	clkdev("mxc-ehci.1", "ahb", "usboh3_gate")
+	clkdev("mxc-ehci.2", "per", "usboh3_per_gate")
+	clkdev("mxc-ehci.2", "ipg", "usboh3_gate")
+	clkdev("mxc-ehci.2", "ahb", "usboh3_gate")
+	clkdev("fsl-usb2-udc", "per", "usboh3_per_gate")
+	clkdev("fsl-usb2-udc", "ipg", "usboh3_gate")
+	clkdev("fsl-usb2-udc", "ahb", "usboh3_gate")
+	clkdev("mxc_nand", NULL, "nfc_gate")
+	clkdev("imx-ssi.0", NULL, "ssi1_ipg_gate")
+	clkdev("imx-ssi.1", NULL, "ssi1_ipg_gate")
+	clkdev("imx-ssi.2", NULL, "ssi1_ipg_gate")
+	clkdev("imx35-sdma", NULL, "sdma_gate")
+	clkdev(NULL, "cpu", "cpu_podf")
+	clkdev(NULL, "iim", "iim_gate")
+	clkdev("imx2-wdt.0", NULL, "dummy")
+	clkdev("imx2-wdt.1", NULL, "dummy")
+	clkdev("imx-keypad", NULL, "dummy")
+	clkdev("imx-tve.0", NULL, "tve_gate")
+	clkdev("imx-tve.0", "di1", "ipu_di1_gate")
+};
+
+static struct clk_lookup mx51_lookups[] = {
+	clkdev("imx-i2c.2", NULL, "hsi2c_gate")
+	clkdev(NULL, "mipi_hsp", "mx51_mipi")
+	clkdev("imx51-vpu.0", NULL, "vpu")
+	clkdev("imx27-fec.0", NULL, "fec_gate")
+	clkdev(NULL, "gpc_dvfs", "gpc_dvfs")
+	clkdev("imx51-ipu", NULL, "ipu")
+	clkdev("imx51-ipu", "di0", "ipu_di0_gate")
+	clkdev("imx51-ipu", "di1", "ipu_di1_gate")
+	clkdev("imx51-ipu", "hsp", "ipu_gate")
+	clkdev("mxc-ehci.0", "usb_phy1", "usb_phy_gate")
+	clkdev("sdhci-esdhc-imx51.0", "ipg", "esdhc1_ipg_gate")
+	clkdev("sdhci-esdhc-imx51.0", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx51.0", "per", "esdhc1_per_gate")
+	clkdev("sdhci-esdhc-imx51.1", "ipg", "esdhc2_ipg_gate")
+	clkdev("sdhci-esdhc-imx51.1", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx51.1", "per", "esdhc2_per_gate")
+	clkdev("sdhci-esdhc-imx51.2", "ipg", "esdhc3_ipg_gate")
+	clkdev("sdhci-esdhc-imx51.2", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx51.2", "per", "esdhc3_per_gate")
+	clkdev("sdhci-esdhc-imx51.3", "ipg", "esdhc4_ipg_gate")
+	clkdev("sdhci-esdhc-imx51.3", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx51.3", "per", "esdhc4_per_gate")
+};
+
+static struct clk_lookup mx53_lookups[] = {
+	clkdev("imx53-vpu.0", NULL, "vpu")
+	clkdev("imx-i2c.2", NULL, "i2c3_gate")
+	clkdev("imx25-fec.0", NULL, "fec_gate")
+	clkdev("imx53-ipu", NULL, "ipu")
+	clkdev("imx53-ipu", "di0", "ipu_di0_gate")
+	clkdev("imx53-ipu", "di1", "ipu_di1_gate")
+	clkdev("imx53-ipu", "hsp", "ipu_gate")
+	clkdev("mxc-ehci.0", "usb_phy1", "usb_phy1_gate")
+	clkdev("sdhci-esdhc-imx53.0", "ipg", "esdhc1_ipg_gate")
+	clkdev("sdhci-esdhc-imx53.0", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx53.0", "per", "esdhc1_per_gate")
+	clkdev("sdhci-esdhc-imx53.1", "ipg", "esdhc2_ipg_gate")
+	clkdev("sdhci-esdhc-imx53.1", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx53.1", "per", "esdhc2_per_gate")
+	clkdev("sdhci-esdhc-imx53.2", "ipg", "esdhc3_ipg_gate")
+	clkdev("sdhci-esdhc-imx53.2", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx53.2", "per", "esdhc3_per_gate")
+	clkdev("sdhci-esdhc-imx53.3", "ipg", "esdhc4_ipg_gate")
+	clkdev("sdhci-esdhc-imx53.3", "ahb", "dummy")
+	clkdev("sdhci-esdhc-imx53.3", "per", "esdhc4_per_gate")
+};
+
+static struct clk *pll1, *pll2, *pll3, *pll4, *iim,
+		  *emi_fast, *ahb_max, *aips_tz1, *aips_tz2,
+		  *spba, *tmax1, *tmax2, *tmax3, *esdhc_a_sel, *esdhc_b_sel,
+		  *esdhc_a_podf, *esdhc_b_podf;
+
+static void __init mx5_clocks_common_init(unsigned long rate_ckil,
+		unsigned long rate_osc, unsigned long rate_ckih1,
+		unsigned long rate_ckih2)
+{
+	imx_clk_fixed("dummy", 0);
+	imx_clk_fixed("ckil", rate_ckil);
+	imx_clk_fixed("osc", rate_osc);
+	imx_clk_fixed("ckih1", rate_ckih1);
+	imx_clk_fixed("ckih2", rate_ckih2);
+
+	imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1, lp_apm_sel,
+			ARRAY_SIZE(lp_apm_sel));
+	imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2, periph_apm_sel,
+			ARRAY_SIZE(periph_apm_sel));
+	imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1, main_bus_sel,
+			ARRAY_SIZE(main_bus_sel));
+	imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3);
+	ahb_max = imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28);
+	aips_tz1 = imx_clk_gate2("aips_tz1", "ahb", MXC_CCM_CCGR0, 24);
+	aips_tz2 = imx_clk_gate2("aips_tz2", "ahb", MXC_CCM_CCGR0, 26);
+	tmax1 = imx_clk_gate2("tmax1", "ahb", MXC_CCM_CCGR1, 0);
+	tmax2 = imx_clk_gate2("tmax2", "ahb", MXC_CCM_CCGR1, 2);
+	tmax3 = imx_clk_gate2("tmax3", "ahb", MXC_CCM_CCGR1, 4);
+	spba = imx_clk_gate2("spba", "ipg", MXC_CCM_CCGR5, 0);
+	imx_clk_divider("ipg", "ahb", MXC_CCM_CBCDR, 8, 2);
+	imx_clk_divider("axi_a", "main_bus", MXC_CCM_CBCDR, 16, 3);
+	imx_clk_divider("axi_b", "main_bus", MXC_CCM_CBCDR, 19, 3);
+	imx_clk_mux("uart_sel", MXC_CCM_CSCMR1, 24, 2, standard_pll_sel,
+			ARRAY_SIZE(standard_pll_sel));
+	imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3);
+	imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3);
+
+	esdhc_a_sel = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2, standard_pll_sel,
+			ARRAY_SIZE(standard_pll_sel));
+	esdhc_b_sel = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2, standard_pll_sel,
+			ARRAY_SIZE(standard_pll_sel));
+	imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3);
+	esdhc_a_podf = imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3);
+	imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3);
+	esdhc_b_podf = imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3);
+	imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
+	imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
+
+	imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1, emi_slow_sel, ARRAY_SIZE(emi_slow_sel));
+	imx_clk_divider("emi_slow_podf", "emi_sel", MXC_CCM_CBCDR, 22, 3);
+	imx_clk_divider("nfc_podf", "emi_slow_podf", MXC_CCM_CBCDR, 13, 3);
+	imx_clk_mux("ecspi_sel", MXC_CCM_CSCMR1, 4, 2, standard_pll_sel,
+			ARRAY_SIZE(standard_pll_sel));
+	imx_clk_divider("ecspi_pred", "ecspi_sel", MXC_CCM_CSCDR2, 25, 3);
+	imx_clk_divider("ecspi_podf", "ecspi_pred", MXC_CCM_CSCDR2, 19, 6);
+	imx_clk_mux("usboh3_sel", MXC_CCM_CSCMR1, 22, 2, standard_pll_sel,
+			ARRAY_SIZE(standard_pll_sel));
+	imx_clk_divider("usboh3_pred", "usboh3_sel", MXC_CCM_CSCDR1, 8, 3);
+	imx_clk_divider("usboh3_podf", "usboh3_pred", MXC_CCM_CSCDR1, 6, 2);
+	imx_clk_divider("usb_phy_pred", "pll3_sw", MXC_CCM_CDCDR, 3, 3);
+	imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
+	imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1, usb_phy_sel,
+			ARRAY_SIZE(usb_phy_sel));
+	imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
+	imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
+	imx_clk_fixed("tve_di", 65000000); /* FIXME */
+	imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, tve_sel, ARRAY_SIZE(tve_sel));
+	iim = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
+	imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
+	imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8);
+	imx_clk_gate2("uart2_ipg_gate", "ipg", MXC_CCM_CCGR1, 10);
+	imx_clk_gate2("uart2_per_gate", "uart_root", MXC_CCM_CCGR1, 12);
+	imx_clk_gate2("uart3_ipg_gate", "ipg", MXC_CCM_CCGR1, 14);
+	imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16);
+	imx_clk_gate2("i2c1_gate", "ipg", MXC_CCM_CCGR1, 18);
+	imx_clk_gate2("i2c2_gate", "ipg", MXC_CCM_CCGR1, 20);
+	imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 20);
+	imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10);
+	imx_clk_gate2("pwm1_hf_gate", "ipg", MXC_CCM_CCGR2, 12);
+	imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14);
+	imx_clk_gate2("pwm2_hf_gate", "ipg", MXC_CCM_CCGR2, 16);
+	imx_clk_gate2("gpt_gate", "ipg", MXC_CCM_CCGR2, 18);
+	imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24);
+	imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26);
+	imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28);
+	imx_clk_gate2("esdhc1_ipg_gate", "ipg", MXC_CCM_CCGR3, 0);
+	imx_clk_gate2("esdhc2_ipg_gate", "ipg", MXC_CCM_CCGR3, 4);
+	imx_clk_gate2("esdhc3_ipg_gate", "ipg", MXC_CCM_CCGR3, 8);
+	imx_clk_gate2("esdhc4_ipg_gate", "ipg", MXC_CCM_CCGR3, 12);
+	imx_clk_gate2("ssi1_ipg_gate", "ipg", MXC_CCM_CCGR3, 16);
+	imx_clk_gate2("ssi2_ipg_gate", "ipg", MXC_CCM_CCGR3, 18);
+	imx_clk_gate2("ssi3_ipg_gate", "ipg", MXC_CCM_CCGR3, 20);
+	imx_clk_gate2("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6);
+	imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8);
+	imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10);
+	imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12);
+	imx_clk_gate2("ecspi1_ipg_gate", "ipg", MXC_CCM_CCGR4, 18);
+	imx_clk_gate2("ecspi1_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 20);
+	imx_clk_gate2("ecspi2_ipg_gate", "ipg", MXC_CCM_CCGR4, 22);
+	imx_clk_gate2("ecspi2_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 24);
+	imx_clk_gate2("cspi_ipg_gate", "ipg", MXC_CCM_CCGR4, 26);
+	imx_clk_gate2("sdma_gate", "ipg", MXC_CCM_CCGR4, 30);
+	emi_fast = imx_clk_gate2("emi_fast_gate", "dummy", MXC_CCM_CCGR5, 14);
+	imx_clk_gate2("emi_slow_gate", "emi_slow_podf", MXC_CCM_CCGR5, 16);
+	imx_clk_mux("ipu_sel", MXC_CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel));
+	imx_clk_gate2("ipu_gate", "ipu_sel", MXC_CCM_CCGR5, 10);
+	imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
+	imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
+	imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
+	imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
+	imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
+	imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
+	imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
+	imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
+	imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
+	imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
+	imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
+
+	clkdev_add_table(mx5_lookups, ARRAY_SIZE(mx5_lookups));
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(esdhc_a_sel, pll2);
+	clk_set_parent(esdhc_b_sel, pll2);
+
+	clk_prepare_enable(ahb_max); /* esdhc3 */
+	clk_prepare_enable(aips_tz1);
+	clk_prepare_enable(aips_tz2); /* fec */
+	clk_prepare_enable(spba);
+	clk_prepare_enable(emi_fast); /* fec */
+	clk_prepare_enable(tmax1);
+	clk_prepare_enable(tmax2); /* esdhc2, fec */
+	clk_prepare_enable(tmax3); /* esdhc1, esdhc4 */
+}
+
+int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	pll1 = imx_clk_pllv2("pll1_sw", "osc", MX51_DPLL1_BASE);
+	pll2 = imx_clk_pllv2("pll2_sw", "osc", MX51_DPLL2_BASE);
+	pll3 = imx_clk_pllv2("pll3_sw", "osc", MX51_DPLL3_BASE);
+	imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, mx51_ipu_di0_sel,
+			ARRAY_SIZE(mx51_ipu_di0_sel));
+	imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, mx51_ipu_di1_sel,
+			ARRAY_SIZE(mx51_ipu_di1_sel));
+	imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, mx51_tve_ext_sel,
+			ARRAY_SIZE(mx51_tve_ext_sel));
+	imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
+	imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
+	imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+	imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6);
+	imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10);
+	imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+	imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
+	imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
+
+	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
+
+	clkdev_add_table(mx51_lookups, ARRAY_SIZE(mx51_lookups));
+
+	/* set SDHC root clock to 166.25MHZ*/
+	clk_set_rate(esdhc_a_podf, 166250000);
+	clk_set_rate(esdhc_b_podf, 166250000);
+
+	/* System timer */
+	mxc_timer_init(NULL, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+		MX51_INT_GPT);
+
+	clk_prepare_enable(iim);
+	imx_print_silicon_rev("i.MX51", mx51_revision());
+	clk_disable_unprepare(iim);
+
+	return 0;
+}
+
+int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	pll1 = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
+	pll2 = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
+	pll3 = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
+	pll4 = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
+
+	imx_clk_mux("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1, mx53_ldb_di1_sel,
+			ARRAY_SIZE(mx53_ldb_di1_sel));
+	imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+	imx_clk_divider("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1);
+	imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
+	imx_clk_mux("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1, mx53_ldb_di0_sel,
+			ARRAY_SIZE(mx53_ldb_di0_sel));
+	imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+	imx_clk_divider("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1);
+	imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
+	imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
+	imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, mx53_ipu_di0_sel,
+			ARRAY_SIZE(mx53_ipu_di0_sel));
+	imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, mx53_ipu_di1_sel,
+			ARRAY_SIZE(mx53_ipu_di1_sel));
+	imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, mx53_tve_ext_sel,
+			ARRAY_SIZE(mx53_tve_ext_sel));
+	imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
+	imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
+	imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+	imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
+	imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
+	imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+	imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
+	imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
+	imx_clk_gate2("i2c3_gate", "ipg", MXC_CCM_CCGR1, 22);
+
+	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
+
+	clkdev_add_table(mx53_lookups, ARRAY_SIZE(mx53_lookups));
+
+	/* set SDHC root clock to 200MHZ*/
+	clk_set_rate(esdhc_a_podf, 200000000);
+	clk_set_rate(esdhc_b_podf, 200000000);
+
+	/* System timer */
+	mxc_timer_init(NULL, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+		MX53_INT_GPT);
+
+	clk_prepare_enable(iim);
+	imx_print_silicon_rev("i.MX53", mx53_revision());
+	clk_disable_unprepare(iim);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+				   unsigned long *ckih1, unsigned long *ckih2)
+{
+	struct device_node *np;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			*ckil = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			*osc = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			*ckih1 = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+			*ckih2 = rate;
+	}
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
+#endif