mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2] clk: i.MX: Port Linux clock tree for i.MX51 and i.MX53
@ 2018-08-30  5:02 Andrey Smirnov
  2018-09-04  6:37 ` Sascha Hauer
  2018-09-06  7:48 ` Sascha Hauer
  0 siblings, 2 replies; 4+ messages in thread
From: Andrey Smirnov @ 2018-08-30  5:02 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Existing clock tree code for i.MX5 in Barebox predates DT and is not
aware of it. This results in missing clocks on DT-based boards like
RDU1 and Babbage. Port clock tree from Linux to resolve this
problem. Old non-DT clock code is kept around for the sake of the
boards that were never converted to use DT.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---

Changes since [v1]:

    - Instead of being opt-in patch replaces i.MX51 clock code bound
      to "fsl,imx5*-ccm" compatible properties in DT

    - Code for clocks related to SPDIF and SSI were dropped

[v1] http://lists.infradead.org/pipermail/barebox/2018-August/034423.html

 drivers/clk/imx/Makefile          |   6 +-
 drivers/clk/imx/clk-imx5.c        |  27 --
 drivers/clk/imx/clk-imx51-imx53.c | 492 ++++++++++++++++++++++++++++++
 3 files changed, 495 insertions(+), 30 deletions(-)
 create mode 100644 drivers/clk/imx/clk-imx51-imx53.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 8f441a97e..9d3093c96 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -16,9 +16,9 @@ obj-$(CONFIG_ARCH_IMX21)  += clk-imx21.o
 obj-$(CONFIG_ARCH_IMX27)  += clk-imx27.o
 obj-$(CONFIG_ARCH_IMX31)  += clk-imx31.o
 obj-$(CONFIG_ARCH_IMX35)  += clk-imx35.o
-obj-$(CONFIG_ARCH_IMX50)  += clk-imx5.o
-obj-$(CONFIG_ARCH_IMX51)  += clk-imx5.o
-obj-$(CONFIG_ARCH_IMX53)  += clk-imx5.o
+obj-$(CONFIG_ARCH_IMX50)  += clk-imx5.o clk-imx51-imx53.o
+obj-$(CONFIG_ARCH_IMX51)  += clk-imx5.o clk-imx51-imx53.o
+obj-$(CONFIG_ARCH_IMX53)  += clk-imx5.o clk-imx51-imx53.o
 obj-$(CONFIG_ARCH_IMX6)   += clk-imx6.o
 obj-$(CONFIG_ARCH_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_ARCH_IMX6SL) += clk-imx6sl.o
diff --git a/drivers/clk/imx/clk-imx5.c b/drivers/clk/imx/clk-imx5.c
index edebd25a3..0a5b47e29 100644
--- a/drivers/clk/imx/clk-imx5.c
+++ b/drivers/clk/imx/clk-imx5.c
@@ -333,18 +333,9 @@ static int imx50_ccm_probe(struct device_d *dev)
 	return 0;
 }
 
-static __maybe_unused struct of_device_id imx50_ccm_dt_ids[] = {
-	{
-		.compatible = "fsl,imx50-ccm",
-	}, {
-		/* sentinel */
-	}
-};
-
 static struct driver_d imx50_ccm_driver = {
 	.probe	= imx50_ccm_probe,
 	.name	= "imx50-ccm",
-	.of_compatible = DRV_OF_COMPAT(imx50_ccm_dt_ids),
 };
 
 static void mx51_clocks_ipu_init(void __iomem *regs)
@@ -414,18 +405,9 @@ static int imx51_ccm_probe(struct device_d *dev)
 	return 0;
 }
 
-static __maybe_unused struct of_device_id imx51_ccm_dt_ids[] = {
-	{
-		.compatible = "fsl,imx51-ccm",
-	}, {
-		/* sentinel */
-	}
-};
-
 static struct driver_d imx51_ccm_driver = {
 	.probe	= imx51_ccm_probe,
 	.name	= "imx51-ccm",
-	.of_compatible = DRV_OF_COMPAT(imx51_ccm_dt_ids),
 };
 
 static void mx53_clocks_ipu_init(void __iomem *regs)
@@ -506,18 +488,9 @@ static int imx53_ccm_probe(struct device_d *dev)
 	return 0;
 }
 
-static __maybe_unused struct of_device_id imx53_ccm_dt_ids[] = {
-	{
-		.compatible = "fsl,imx53-ccm",
-	}, {
-		/* sentinel */
-	}
-};
-
 static struct driver_d imx53_ccm_driver = {
 	.probe	= imx53_ccm_probe,
 	.name	= "imx53-ccm",
-	.of_compatible = DRV_OF_COMPAT(imx53_ccm_dt_ids),
 };
 
 static int imx5_ccm_init(void)
diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c
new file mode 100644
index 000000000..16518f0be
--- /dev/null
+++ b/drivers/clk/imx/clk-imx51-imx53.c
@@ -0,0 +1,492 @@
+/*
+ * 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 <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <mach/imx50-regs.h>
+#include <mach/imx51-regs.h>
+#include <mach/imx53-regs.h>
+#include <dt-bindings/clock/imx5-clock.h>
+
+#include "clk.h"
+
+#define MX51_DPLL1_BASE		0x83f80000
+#define MX51_DPLL2_BASE		0x83f84000
+#define MX51_DPLL3_BASE		0x83f88000
+
+#define MX53_DPLL1_BASE		0x63f80000
+#define MX53_DPLL2_BASE		0x63f84000
+#define MX53_DPLL3_BASE		0x63f88000
+#define MX53_DPLL4_BASE		0x63f8c000
+
+#define MXC_CCM_CCR		(ccm_base + 0x00)
+#define MXC_CCM_CCDR		(ccm_base + 0x04)
+#define MXC_CCM_CSR		(ccm_base + 0x08)
+#define MXC_CCM_CCSR		(ccm_base + 0x0c)
+#define MXC_CCM_CACRR		(ccm_base + 0x10)
+#define MXC_CCM_CBCDR		(ccm_base + 0x14)
+#define MXC_CCM_CBCMR		(ccm_base + 0x18)
+#define MXC_CCM_CSCMR1		(ccm_base + 0x1c)
+#define MXC_CCM_CSCMR2		(ccm_base + 0x20)
+#define MXC_CCM_CSCDR1		(ccm_base + 0x24)
+#define MXC_CCM_CS1CDR		(ccm_base + 0x28)
+#define MXC_CCM_CS2CDR		(ccm_base + 0x2c)
+#define MXC_CCM_CDCDR		(ccm_base + 0x30)
+#define MXC_CCM_CHSCDR		(ccm_base + 0x34)
+#define MXC_CCM_CSCDR2		(ccm_base + 0x38)
+#define MXC_CCM_CSCDR3		(ccm_base + 0x3c)
+#define MXC_CCM_CSCDR4		(ccm_base + 0x40)
+#define MXC_CCM_CWDR		(ccm_base + 0x44)
+#define MXC_CCM_CDHIPR		(ccm_base + 0x48)
+#define MXC_CCM_CDCR		(ccm_base + 0x4c)
+#define MXC_CCM_CTOR		(ccm_base + 0x50)
+#define MXC_CCM_CLPCR		(ccm_base + 0x54)
+#define MXC_CCM_CISR		(ccm_base + 0x58)
+#define MXC_CCM_CIMR		(ccm_base + 0x5c)
+#define MXC_CCM_CCOSR		(ccm_base + 0x60)
+#define MXC_CCM_CGPR		(ccm_base + 0x64)
+#define MXC_CCM_CCGR0		(ccm_base + 0x68)
+#define MXC_CCM_CCGR1		(ccm_base + 0x6c)
+#define MXC_CCM_CCGR2		(ccm_base + 0x70)
+#define MXC_CCM_CCGR3		(ccm_base + 0x74)
+#define MXC_CCM_CCGR4		(ccm_base + 0x78)
+#define MXC_CCM_CCGR5		(ccm_base + 0x7c)
+#define MXC_CCM_CCGR6		(ccm_base + 0x80)
+#define MXC_CCM_CCGR7		(ccm_base + 0x84)
+
+/* Low-power Audio Playback Mode clock */
+static const char *lp_apm_sel[] = { "osc", };
+
+/* This is used multiple times */
+static const char *standard_pll_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "lp_apm", };
+static const char *periph_apm_sel[] = { "pll1_sw", "pll3_sw", "lp_apm", };
+static const char *main_bus_sel[] = { "pll2_sw", "periph_apm", };
+static const char *per_lp_apm_sel[] = { "main_bus", "lp_apm", };
+static const char *per_root_sel[] = { "per_podf", "ipg", };
+static const char *esdhc_c_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
+static const char *esdhc_d_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
+static const char *emi_slow_sel[] = { "main_bus", "ahb", };
+static const char *usb_phy_sel_str[] = { "osc", "usb_phy_podf", };
+static const char *mx51_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "tve_di", };
+static const char *mx53_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "di_pll4_podf", "dummy", "ldb_di0_gate", };
+static const char *mx53_ldb_di0_sel[] = { "pll3_sw", "pll4_sw", };
+static const char *mx51_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", };
+static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", "ldb_di1_gate", };
+static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", };
+static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", };
+static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", };
+static const char *mx51_tve_sel[] = { "tve_pred", "tve_ext_sel", };
+static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
+static const char *gpu3d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
+static const char *gpu2d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
+static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
+static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", };
+static const char *mx53_cko1_sel[] = {
+	"cpu_podf", "pll1_sw", "pll2_sw", "pll3_sw",
+	"emi_slow_podf", "pll4_sw", "nfc_podf", "dummy",
+	"di_pred", "dummy", "dummy", "ahb",
+	"ipg", "per_root", "ckil", "dummy",};
+static const char *mx53_cko2_sel[] = {
+	"dummy"/* dptc_core */, "dummy"/* dptc_perich */,
+	"dummy", "esdhc_a_podf",
+	"usboh3_podf", "dummy"/* wrck_clk_root */,
+	"ecspi_podf", "dummy"/* pll1_ref_clk */,
+	"esdhc_b_podf", "dummy"/* ddr_clk_root */,
+	"dummy"/* arm_axi_clk_root */, "dummy"/* usb_phy_out */,
+	"vpu_sel", "ipu_sel",
+	"osc", "ckih1",
+	"dummy", "esdhc_c_sel",
+	"ssi1_root_podf", "ssi2_root_podf",
+	"dummy", "dummy",
+	"dummy"/* lpsr_clk_root */, "dummy"/* pgc_clk_root */,
+	"dummy"/* tve_out */, "usb_phy_sel",
+	"tve_sel", "lp_apm",
+	"uart_root", "dummy"/* spdif0_clk_root */,
+	"dummy", "dummy", };
+static const char *step_sels[] = { "lp_apm", };
+static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
+static const char *ieee1588_sels[] = { "pll3_sw", "pll4_sw", "dummy" /* usbphy2_clk */, "dummy" /* fec_phy_clk */ };
+
+static struct clk *clk[IMX5_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static void __init mx5_clocks_common_init(void __iomem *ccm_base)
+{
+	clk[IMX5_CLK_DUMMY]		= clk_fixed("dummy", 0);
+
+	clk[IMX5_CLK_PERIPH_APM]	= imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
+						periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
+	clk[IMX5_CLK_MAIN_BUS]		= imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
+						main_bus_sel, ARRAY_SIZE(main_bus_sel));
+	clk[IMX5_CLK_PER_LP_APM]	= imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1,
+						per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel));
+	clk[IMX5_CLK_PER_PRED1]		= imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2);
+	clk[IMX5_CLK_PER_PRED2]		= imx_clk_divider("per_pred2", "per_pred1", MXC_CCM_CBCDR, 3, 3);
+	clk[IMX5_CLK_PER_PODF]		= imx_clk_divider("per_podf", "per_pred2", MXC_CCM_CBCDR, 0, 3);
+	clk[IMX5_CLK_PER_ROOT]		= imx_clk_mux("per_root", MXC_CCM_CBCMR, 0, 1,
+						per_root_sel, ARRAY_SIZE(per_root_sel));
+	clk[IMX5_CLK_AHB]		= imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3);
+	clk[IMX5_CLK_AHB_MAX]		= imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28);
+	clk[IMX5_CLK_AIPS_TZ1]		= imx_clk_gate2("aips_tz1", "ahb", MXC_CCM_CCGR0, 24);
+	clk[IMX5_CLK_AIPS_TZ2]		= imx_clk_gate2("aips_tz2", "ahb", MXC_CCM_CCGR0, 26);
+	clk[IMX5_CLK_TMAX1]		= imx_clk_gate2("tmax1", "ahb", MXC_CCM_CCGR1, 0);
+	clk[IMX5_CLK_TMAX2]		= imx_clk_gate2("tmax2", "ahb", MXC_CCM_CCGR1, 2);
+	clk[IMX5_CLK_TMAX3]		= imx_clk_gate2("tmax3", "ahb", MXC_CCM_CCGR1, 4);
+	clk[IMX5_CLK_SPBA]		= imx_clk_gate2("spba", "ipg", MXC_CCM_CCGR5, 0);
+	clk[IMX5_CLK_IPG]		= imx_clk_divider("ipg", "ahb", MXC_CCM_CBCDR, 8, 2);
+	clk[IMX5_CLK_AXI_A]		= imx_clk_divider("axi_a", "main_bus", MXC_CCM_CBCDR, 16, 3);
+	clk[IMX5_CLK_AXI_B]		= imx_clk_divider("axi_b", "main_bus", MXC_CCM_CBCDR, 19, 3);
+	clk[IMX5_CLK_UART_SEL]		= imx_clk_mux("uart_sel", MXC_CCM_CSCMR1, 24, 2,
+						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+	clk[IMX5_CLK_UART_PRED]		= imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3);
+	clk[IMX5_CLK_UART_ROOT]		= imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3);
+
+	clk[IMX5_CLK_ESDHC_A_SEL]	= imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
+						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+	clk[IMX5_CLK_ESDHC_B_SEL]	= imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
+						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+	clk[IMX5_CLK_ESDHC_A_PRED]	= imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3);
+	clk[IMX5_CLK_ESDHC_A_PODF]	= imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3);
+	clk[IMX5_CLK_ESDHC_B_PRED]	= imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3);
+	clk[IMX5_CLK_ESDHC_B_PODF]	= imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3);
+	clk[IMX5_CLK_ESDHC_C_SEL]	= imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
+	clk[IMX5_CLK_ESDHC_D_SEL]	= imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
+
+	clk[IMX5_CLK_EMI_SEL]		= imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1,
+						emi_slow_sel, ARRAY_SIZE(emi_slow_sel));
+	clk[IMX5_CLK_EMI_SLOW_PODF]	= imx_clk_divider("emi_slow_podf", "emi_sel", MXC_CCM_CBCDR, 22, 3);
+	clk[IMX5_CLK_NFC_PODF]		= imx_clk_divider("nfc_podf", "emi_slow_podf", MXC_CCM_CBCDR, 13, 3);
+	clk[IMX5_CLK_ECSPI_SEL]		= imx_clk_mux("ecspi_sel", MXC_CCM_CSCMR1, 4, 2,
+						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+	clk[IMX5_CLK_ECSPI_PRED]	= imx_clk_divider("ecspi_pred", "ecspi_sel", MXC_CCM_CSCDR2, 25, 3);
+	clk[IMX5_CLK_ECSPI_PODF]	= imx_clk_divider("ecspi_podf", "ecspi_pred", MXC_CCM_CSCDR2, 19, 6);
+	clk[IMX5_CLK_USBOH3_SEL]	= imx_clk_mux("usboh3_sel", MXC_CCM_CSCMR1, 22, 2,
+						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+	clk[IMX5_CLK_USBOH3_PRED]	= imx_clk_divider("usboh3_pred", "usboh3_sel", MXC_CCM_CSCDR1, 8, 3);
+	clk[IMX5_CLK_USBOH3_PODF]	= imx_clk_divider("usboh3_podf", "usboh3_pred", MXC_CCM_CSCDR1, 6, 2);
+	clk[IMX5_CLK_USB_PHY_PRED]	= imx_clk_divider("usb_phy_pred", "pll3_sw", MXC_CCM_CDCDR, 3, 3);
+	clk[IMX5_CLK_USB_PHY_PODF]	= imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
+	clk[IMX5_CLK_USB_PHY_SEL]	= imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
+						usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
+	clk[IMX5_CLK_STEP_SEL]		= imx_clk_mux("step_sel", MXC_CCM_CCSR, 7, 2, step_sels, ARRAY_SIZE(step_sels));
+	clk[IMX5_CLK_CPU_PODF_SEL]	= imx_clk_mux("cpu_podf_sel", MXC_CCM_CCSR, 2, 1, cpu_podf_sels, ARRAY_SIZE(cpu_podf_sels));
+	clk[IMX5_CLK_CPU_PODF]		= imx_clk_divider("cpu_podf", "cpu_podf_sel", MXC_CCM_CACRR, 0, 3);
+	clk[IMX5_CLK_DI_PRED]		= imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
+	clk[IMX5_CLK_IIM_GATE]		= imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
+	clk[IMX5_CLK_UART1_IPG_GATE]	= imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
+	clk[IMX5_CLK_UART1_PER_GATE]	= imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8);
+	clk[IMX5_CLK_UART2_IPG_GATE]	= imx_clk_gate2("uart2_ipg_gate", "ipg", MXC_CCM_CCGR1, 10);
+	clk[IMX5_CLK_UART2_PER_GATE]	= imx_clk_gate2("uart2_per_gate", "uart_root", MXC_CCM_CCGR1, 12);
+	clk[IMX5_CLK_UART3_IPG_GATE]	= imx_clk_gate2("uart3_ipg_gate", "ipg", MXC_CCM_CCGR1, 14);
+	clk[IMX5_CLK_UART3_PER_GATE]	= imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16);
+	clk[IMX5_CLK_I2C1_GATE]		= imx_clk_gate2("i2c1_gate", "per_root", MXC_CCM_CCGR1, 18);
+	clk[IMX5_CLK_I2C2_GATE]		= imx_clk_gate2("i2c2_gate", "per_root", MXC_CCM_CCGR1, 20);
+	clk[IMX5_CLK_PWM1_IPG_GATE]	= imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10);
+	clk[IMX5_CLK_PWM1_HF_GATE]	= imx_clk_gate2("pwm1_hf_gate", "per_root", MXC_CCM_CCGR2, 12);
+	clk[IMX5_CLK_PWM2_IPG_GATE]	= imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14);
+	clk[IMX5_CLK_PWM2_HF_GATE]	= imx_clk_gate2("pwm2_hf_gate", "per_root", MXC_CCM_CCGR2, 16);
+	clk[IMX5_CLK_GPT_IPG_GATE]	= imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 18);
+	clk[IMX5_CLK_GPT_HF_GATE]	= imx_clk_gate2("gpt_hf_gate", "per_root", MXC_CCM_CCGR2, 20);
+	clk[IMX5_CLK_FEC_GATE]		= imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24);
+	clk[IMX5_CLK_USBOH3_GATE]	= imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26);
+	clk[IMX5_CLK_USBOH3_PER_GATE]	= imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28);
+	clk[IMX5_CLK_ESDHC1_IPG_GATE]	= imx_clk_gate2("esdhc1_ipg_gate", "ipg", MXC_CCM_CCGR3, 0);
+	clk[IMX5_CLK_ESDHC2_IPG_GATE]	= imx_clk_gate2("esdhc2_ipg_gate", "ipg", MXC_CCM_CCGR3, 4);
+	clk[IMX5_CLK_ESDHC3_IPG_GATE]	= imx_clk_gate2("esdhc3_ipg_gate", "ipg", MXC_CCM_CCGR3, 8);
+	clk[IMX5_CLK_ESDHC4_IPG_GATE]	= imx_clk_gate2("esdhc4_ipg_gate", "ipg", MXC_CCM_CCGR3, 12);
+	clk[IMX5_CLK_ECSPI1_IPG_GATE]	= imx_clk_gate2("ecspi1_ipg_gate", "ipg", MXC_CCM_CCGR4, 18);
+	clk[IMX5_CLK_ECSPI1_PER_GATE]	= imx_clk_gate2("ecspi1_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 20);
+	clk[IMX5_CLK_ECSPI2_IPG_GATE]	= imx_clk_gate2("ecspi2_ipg_gate", "ipg", MXC_CCM_CCGR4, 22);
+	clk[IMX5_CLK_ECSPI2_PER_GATE]	= imx_clk_gate2("ecspi2_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 24);
+	clk[IMX5_CLK_CSPI_IPG_GATE]	= imx_clk_gate2("cspi_ipg_gate", "ipg", MXC_CCM_CCGR4, 26);
+	clk[IMX5_CLK_SDMA_GATE]		= imx_clk_gate2("sdma_gate", "ipg", MXC_CCM_CCGR4, 30);
+	clk[IMX5_CLK_EMI_FAST_GATE]	= imx_clk_gate2("emi_fast_gate", "dummy", MXC_CCM_CCGR5, 14);
+	clk[IMX5_CLK_EMI_SLOW_GATE]	= imx_clk_gate2("emi_slow_gate", "emi_slow_podf", MXC_CCM_CCGR5, 16);
+	clk[IMX5_CLK_IPU_SEL]		= imx_clk_mux("ipu_sel", MXC_CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel));
+	clk[IMX5_CLK_IPU_GATE]		= imx_clk_gate2("ipu_gate", "ipu_sel", MXC_CCM_CCGR5, 10);
+	clk[IMX5_CLK_NFC_GATE]		= imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
+	clk[IMX5_CLK_IPU_DI0_GATE]	= imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
+	clk[IMX5_CLK_IPU_DI1_GATE]	= imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
+	clk[IMX5_CLK_GPU3D_SEL]		= imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel));
+	clk[IMX5_CLK_GPU2D_SEL]		= imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel));
+	clk[IMX5_CLK_GPU3D_GATE]	= imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2);
+	clk[IMX5_CLK_GARB_GATE]		= imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4);
+	clk[IMX5_CLK_GPU2D_GATE]	= imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14);
+	clk[IMX5_CLK_VPU_SEL]		= imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
+	clk[IMX5_CLK_VPU_GATE]		= imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
+	clk[IMX5_CLK_VPU_REFERENCE_GATE] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
+	clk[IMX5_CLK_GPC_DVFS]		= imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
+
+	clk[IMX5_CLK_SRTC_GATE]		= imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28);
+	clk[IMX5_CLK_PATA_GATE]		= imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0);
+	clk[IMX5_CLK_SAHARA_IPG_GATE]	= imx_clk_gate2("sahara_ipg_gate", "ipg", MXC_CCM_CCGR4, 14);
+	clk[IMX5_CLK_SATA_REF]		= imx_clk_fixed_factor("sata_ref", "usb_phy1_gate", 1, 1);
+
+	clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0");
+	clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL);
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
+	clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]);
+
+	/* move usb phy clk to 24MHz */
+	clk_set_parent(clk[IMX5_CLK_USB_PHY_SEL], clk[IMX5_CLK_OSC]);
+
+	clk_enable(clk[IMX5_CLK_GPC_DVFS]);
+	clk_enable(clk[IMX5_CLK_AHB_MAX]); /* esdhc3 */
+	clk_enable(clk[IMX5_CLK_AIPS_TZ1]);
+	clk_enable(clk[IMX5_CLK_AIPS_TZ2]); /* fec */
+	clk_enable(clk[IMX5_CLK_SPBA]);
+	clk_enable(clk[IMX5_CLK_EMI_FAST_GATE]); /* fec */
+	clk_enable(clk[IMX5_CLK_EMI_SLOW_GATE]); /* eim */
+	clk_enable(clk[IMX5_CLK_MIPI_HSC1_GATE]);
+	clk_enable(clk[IMX5_CLK_MIPI_HSC2_GATE]);
+	clk_enable(clk[IMX5_CLK_MIPI_ESC_GATE]);
+	clk_enable(clk[IMX5_CLK_MIPI_HSP_GATE]);
+	clk_enable(clk[IMX5_CLK_TMAX1]);
+	clk_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
+	clk_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
+}
+
+static void __init mx50_clocks_init(struct device_node *np)
+{
+	void __iomem *ccm_base;
+	unsigned long r;
+
+	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", IOMEM(MX53_DPLL1_BASE));
+	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", IOMEM(MX53_DPLL2_BASE));
+	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", IOMEM(MX53_DPLL3_BASE));
+
+	ccm_base = of_iomap(np, 0);
+	WARN_ON(!ccm_base);
+
+	mx5_clocks_common_init(ccm_base);
+
+	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
+						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
+	clk[IMX5_CLK_ESDHC1_PER_GATE]	= imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+	clk[IMX5_CLK_ESDHC2_PER_GATE]	= imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
+	clk[IMX5_CLK_ESDHC3_PER_GATE]	= imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
+	clk[IMX5_CLK_ESDHC4_PER_GATE]	= imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+	clk[IMX5_CLK_USB_PHY1_GATE]	= imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
+	clk[IMX5_CLK_USB_PHY2_GATE]	= imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
+	clk[IMX5_CLK_I2C3_GATE]		= imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
+	clk[IMX5_CLK_UART4_IPG_GATE]	= imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
+	clk[IMX5_CLK_UART4_PER_GATE]	= imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
+	clk[IMX5_CLK_UART5_IPG_GATE]	= imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
+	clk[IMX5_CLK_UART5_PER_GATE]	= imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
+
+	clk[IMX5_CLK_CKO1_SEL]		= imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
+						mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
+	clk[IMX5_CLK_CKO1_PODF]		= imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
+	clk[IMX5_CLK_CKO1]		= imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
+
+	clk[IMX5_CLK_CKO2_SEL]		= imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
+						mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
+	clk[IMX5_CLK_CKO2_PODF]		= imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
+	clk[IMX5_CLK_CKO2]		= imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
+
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
+
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	/* set SDHC root clock to 200MHZ*/
+	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
+	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
+
+	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
+	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
+}
+CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
+
+static void __init mx51_clocks_init(struct device_node *np)
+{
+	void __iomem *ccm_base;
+	u32 val;
+
+	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", IOMEM(MX51_DPLL1_BASE));
+	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", IOMEM(MX51_DPLL2_BASE));
+	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", IOMEM(MX51_DPLL3_BASE));
+
+	ccm_base = of_iomap(np, 0);
+	WARN_ON(!ccm_base);
+
+	mx5_clocks_common_init(ccm_base);
+
+	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
+						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
+	clk[IMX5_CLK_IPU_DI0_SEL]	= imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
+						mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_IPU_DI1_SEL]	= imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
+						mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_TVE_EXT_SEL]	= imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
+						mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_TVE_SEL]		= imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1,
+						mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel));
+	clk[IMX5_CLK_TVE_GATE]		= imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
+	clk[IMX5_CLK_TVE_PRED]		= imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
+	clk[IMX5_CLK_ESDHC1_PER_GATE]	= imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+	clk[IMX5_CLK_ESDHC2_PER_GATE]	= imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6);
+	clk[IMX5_CLK_ESDHC3_PER_GATE]	= imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10);
+	clk[IMX5_CLK_ESDHC4_PER_GATE]	= imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+	clk[IMX5_CLK_USB_PHY_GATE]	= imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
+	clk[IMX5_CLK_HSI2C_GATE]	= imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
+	clk[IMX5_CLK_MIPI_HSC1_GATE]	= imx_clk_gate2("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6);
+	clk[IMX5_CLK_MIPI_HSC2_GATE]	= imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8);
+	clk[IMX5_CLK_MIPI_ESC_GATE]	= imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10);
+	clk[IMX5_CLK_MIPI_HSP_GATE]	= imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12);
+
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
+
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	/* set the usboh3 parent to pll2_sw */
+	clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]);
+
+	/* set SDHC root clock to 166.25MHZ*/
+	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000);
+	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000);
+
+	/*
+	 * Reference Manual says: Functionality of CCDR[18] and CLPCR[23] is no
+	 * longer supported. Set to one for better power saving.
+	 *
+	 * The effect of not setting these bits is that MIPI clocks can't be
+	 * enabled without the IPU clock being enabled aswell.
+	 */
+	val = readl(MXC_CCM_CCDR);
+	val |= 1 << 18;
+	writel(val, MXC_CCM_CCDR);
+
+	val = readl(MXC_CCM_CLPCR);
+	val |= 1 << 23;
+	writel(val, MXC_CCM_CLPCR);
+}
+CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init);
+
+static void __init mx53_clocks_init(struct device_node *np)
+{
+	void __iomem *ccm_base;
+	unsigned long r;
+
+	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", IOMEM(MX53_DPLL1_BASE));
+	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", IOMEM(MX53_DPLL2_BASE));
+	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", IOMEM(MX53_DPLL3_BASE));
+	clk[IMX5_CLK_PLL4_SW]		= imx_clk_pllv2("pll4_sw", "osc", IOMEM(MX53_DPLL4_BASE));
+
+	ccm_base = of_iomap(np, 0);
+	WARN_ON(!ccm_base);
+
+	mx5_clocks_common_init(ccm_base);
+
+	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
+						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
+	clk[IMX5_CLK_LDB_DI1_DIV_3_5]	= imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+	clk[IMX5_CLK_LDB_DI1_DIV]	= imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0);
+	clk[IMX5_CLK_LDB_DI1_SEL]	= imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
+						mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_DI_PLL4_PODF]	= imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
+	clk[IMX5_CLK_LDB_DI0_DIV_3_5]	= imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+	clk[IMX5_CLK_LDB_DI0_DIV]	= imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0);
+	clk[IMX5_CLK_LDB_DI0_SEL]	= imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
+						mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_LDB_DI0_GATE]	= imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
+	clk[IMX5_CLK_LDB_DI1_GATE]	= imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
+	clk[IMX5_CLK_IPU_DI0_SEL]	= imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
+						mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_IPU_DI1_SEL]	= imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
+						mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_TVE_EXT_SEL]	= imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
+						mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
+	clk[IMX5_CLK_TVE_GATE]		= imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
+	clk[IMX5_CLK_TVE_PRED]		= imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
+	clk[IMX5_CLK_ESDHC1_PER_GATE]	= imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+	clk[IMX5_CLK_ESDHC2_PER_GATE]	= imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
+	clk[IMX5_CLK_ESDHC3_PER_GATE]	= imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
+	clk[IMX5_CLK_ESDHC4_PER_GATE]	= imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+	clk[IMX5_CLK_USB_PHY1_GATE]	= imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
+	clk[IMX5_CLK_USB_PHY2_GATE]	= imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
+	clk[IMX5_CLK_CAN_SEL]		= imx_clk_mux("can_sel", MXC_CCM_CSCMR2, 6, 2,
+						mx53_can_sel, ARRAY_SIZE(mx53_can_sel));
+	clk[IMX5_CLK_CAN1_SERIAL_GATE]	= imx_clk_gate2("can1_serial_gate", "can_sel", MXC_CCM_CCGR6, 22);
+	clk[IMX5_CLK_CAN1_IPG_GATE]	= imx_clk_gate2("can1_ipg_gate", "ipg", MXC_CCM_CCGR6, 20);
+	clk[IMX5_CLK_OCRAM]		= imx_clk_gate2("ocram", "ahb", MXC_CCM_CCGR6, 2);
+	clk[IMX5_CLK_CAN2_SERIAL_GATE]	= imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8);
+	clk[IMX5_CLK_CAN2_IPG_GATE]	= imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
+	clk[IMX5_CLK_I2C3_GATE]		= imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
+	clk[IMX5_CLK_SATA_GATE]		= imx_clk_gate2("sata_gate", "ipg", MXC_CCM_CCGR4, 2);
+
+	clk[IMX5_CLK_FIRI_SEL]		= imx_clk_mux("firi_sel", MXC_CCM_CSCMR2, 12, 2,
+						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+	clk[IMX5_CLK_FIRI_PRED]		= imx_clk_divider("firi_pred", "firi_sel", MXC_CCM_CSCDR3, 6, 3);
+	clk[IMX5_CLK_FIRI_PODF]		= imx_clk_divider("firi_podf", "firi_pred", MXC_CCM_CSCDR3, 0, 6);
+	clk[IMX5_CLK_FIRI_SERIAL_GATE]	= imx_clk_gate2("firi_serial_gate", "firi_podf", MXC_CCM_CCGR1, 28);
+	clk[IMX5_CLK_FIRI_IPG_GATE]	= imx_clk_gate2("firi_ipg_gate", "ipg", MXC_CCM_CCGR1, 26);
+
+	clk[IMX5_CLK_CSI0_MCLK1_SEL]	= imx_clk_mux("csi0_mclk1_sel", MXC_CCM_CSCMR2, 22, 2,
+						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+	clk[IMX5_CLK_CSI0_MCLK1_PRED]	= imx_clk_divider("csi0_mclk1_pred", "csi0_mclk1_sel", MXC_CCM_CSCDR4, 6, 3);
+	clk[IMX5_CLK_CSI0_MCLK1_PODF]	= imx_clk_divider("csi0_mclk1_podf", "csi0_mclk1_pred", MXC_CCM_CSCDR4, 0, 6);
+	clk[IMX5_CLK_CSI0_MCLK1_GATE]	= imx_clk_gate2("csi0_mclk1_serial_gate", "csi0_mclk1_podf", MXC_CCM_CCGR6, 4);
+
+	clk[IMX5_CLK_IEEE1588_SEL]	= imx_clk_mux("ieee1588_sel", MXC_CCM_CSCMR2, 14, 2,
+						ieee1588_sels, ARRAY_SIZE(ieee1588_sels));
+	clk[IMX5_CLK_IEEE1588_PRED]	= imx_clk_divider("ieee1588_pred", "ieee1588_sel", MXC_CCM_CSCDR2, 6, 3);
+	clk[IMX5_CLK_IEEE1588_PODF]	= imx_clk_divider("ieee1588_podf", "ieee1588_pred", MXC_CCM_CSCDR2, 0, 6);
+	clk[IMX5_CLK_IEEE1588_GATE]	= imx_clk_gate2("ieee1588_serial_gate", "ieee1588_podf", MXC_CCM_CCGR7, 6);
+	clk[IMX5_CLK_UART4_IPG_GATE]	= imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
+	clk[IMX5_CLK_UART4_PER_GATE]	= imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
+	clk[IMX5_CLK_UART5_IPG_GATE]	= imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
+	clk[IMX5_CLK_UART5_PER_GATE]	= imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
+
+	clk[IMX5_CLK_CKO1_SEL]		= imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
+						mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
+	clk[IMX5_CLK_CKO1_PODF]		= imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
+	clk[IMX5_CLK_CKO1]		= imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
+
+	clk[IMX5_CLK_CKO2_SEL]		= imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
+						mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
+	clk[IMX5_CLK_CKO2_PODF]		= imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
+	clk[IMX5_CLK_CKO2]		= imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
+	clk[IMX5_CLK_ARM]		= imx_clk_cpu("arm", "cpu_podf",
+						clk[IMX5_CLK_CPU_PODF],
+						clk[IMX5_CLK_CPU_PODF_SEL],
+						clk[IMX5_CLK_PLL1_SW],
+						clk[IMX5_CLK_STEP_SEL]);
+
+	imx_check_clocks(clk, ARRAY_SIZE(clk));
+
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	/* set SDHC root clock to 200MHZ*/
+	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
+	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
+
+	/* move can bus clk to 24MHz */
+	clk_set_parent(clk[IMX5_CLK_CAN_SEL], clk[IMX5_CLK_LP_APM]);
+
+	/* make sure step clock is running from 24MHz */
+	clk_set_parent(clk[IMX5_CLK_STEP_SEL], clk[IMX5_CLK_LP_APM]);
+
+	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
+	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
+}
+CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
-- 
2.17.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] clk: i.MX: Port Linux clock tree for i.MX51 and i.MX53
  2018-08-30  5:02 [PATCH v2] clk: i.MX: Port Linux clock tree for i.MX51 and i.MX53 Andrey Smirnov
@ 2018-09-04  6:37 ` Sascha Hauer
  2018-09-06  7:48 ` Sascha Hauer
  1 sibling, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2018-09-04  6:37 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

On Wed, Aug 29, 2018 at 10:02:07PM -0700, Andrey Smirnov wrote:
> Existing clock tree code for i.MX5 in Barebox predates DT and is not
> aware of it. This results in missing clocks on DT-based boards like
> RDU1 and Babbage. Port clock tree from Linux to resolve this
> problem. Old non-DT clock code is kept around for the sake of the
> boards that were never converted to use DT.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---

Tested on i.MX53 QSB with no bad effects and applied, thanks

Sascha

> 
> Changes since [v1]:
> 
>     - Instead of being opt-in patch replaces i.MX51 clock code bound
>       to "fsl,imx5*-ccm" compatible properties in DT
> 
>     - Code for clocks related to SPDIF and SSI were dropped
> 
> [v1] http://lists.infradead.org/pipermail/barebox/2018-August/034423.html
> 
>  drivers/clk/imx/Makefile          |   6 +-
>  drivers/clk/imx/clk-imx5.c        |  27 --
>  drivers/clk/imx/clk-imx51-imx53.c | 492 ++++++++++++++++++++++++++++++
>  3 files changed, 495 insertions(+), 30 deletions(-)
>  create mode 100644 drivers/clk/imx/clk-imx51-imx53.c
> 
> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> index 8f441a97e..9d3093c96 100644
> --- a/drivers/clk/imx/Makefile
> +++ b/drivers/clk/imx/Makefile
> @@ -16,9 +16,9 @@ obj-$(CONFIG_ARCH_IMX21)  += clk-imx21.o
>  obj-$(CONFIG_ARCH_IMX27)  += clk-imx27.o
>  obj-$(CONFIG_ARCH_IMX31)  += clk-imx31.o
>  obj-$(CONFIG_ARCH_IMX35)  += clk-imx35.o
> -obj-$(CONFIG_ARCH_IMX50)  += clk-imx5.o
> -obj-$(CONFIG_ARCH_IMX51)  += clk-imx5.o
> -obj-$(CONFIG_ARCH_IMX53)  += clk-imx5.o
> +obj-$(CONFIG_ARCH_IMX50)  += clk-imx5.o clk-imx51-imx53.o
> +obj-$(CONFIG_ARCH_IMX51)  += clk-imx5.o clk-imx51-imx53.o
> +obj-$(CONFIG_ARCH_IMX53)  += clk-imx5.o clk-imx51-imx53.o
>  obj-$(CONFIG_ARCH_IMX6)   += clk-imx6.o
>  obj-$(CONFIG_ARCH_IMX6SX) += clk-imx6sx.o
>  obj-$(CONFIG_ARCH_IMX6SL) += clk-imx6sl.o
> diff --git a/drivers/clk/imx/clk-imx5.c b/drivers/clk/imx/clk-imx5.c
> index edebd25a3..0a5b47e29 100644
> --- a/drivers/clk/imx/clk-imx5.c
> +++ b/drivers/clk/imx/clk-imx5.c
> @@ -333,18 +333,9 @@ static int imx50_ccm_probe(struct device_d *dev)
>  	return 0;
>  }
>  
> -static __maybe_unused struct of_device_id imx50_ccm_dt_ids[] = {
> -	{
> -		.compatible = "fsl,imx50-ccm",
> -	}, {
> -		/* sentinel */
> -	}
> -};
> -
>  static struct driver_d imx50_ccm_driver = {
>  	.probe	= imx50_ccm_probe,
>  	.name	= "imx50-ccm",
> -	.of_compatible = DRV_OF_COMPAT(imx50_ccm_dt_ids),
>  };
>  
>  static void mx51_clocks_ipu_init(void __iomem *regs)
> @@ -414,18 +405,9 @@ static int imx51_ccm_probe(struct device_d *dev)
>  	return 0;
>  }
>  
> -static __maybe_unused struct of_device_id imx51_ccm_dt_ids[] = {
> -	{
> -		.compatible = "fsl,imx51-ccm",
> -	}, {
> -		/* sentinel */
> -	}
> -};
> -
>  static struct driver_d imx51_ccm_driver = {
>  	.probe	= imx51_ccm_probe,
>  	.name	= "imx51-ccm",
> -	.of_compatible = DRV_OF_COMPAT(imx51_ccm_dt_ids),
>  };
>  
>  static void mx53_clocks_ipu_init(void __iomem *regs)
> @@ -506,18 +488,9 @@ static int imx53_ccm_probe(struct device_d *dev)
>  	return 0;
>  }
>  
> -static __maybe_unused struct of_device_id imx53_ccm_dt_ids[] = {
> -	{
> -		.compatible = "fsl,imx53-ccm",
> -	}, {
> -		/* sentinel */
> -	}
> -};
> -
>  static struct driver_d imx53_ccm_driver = {
>  	.probe	= imx53_ccm_probe,
>  	.name	= "imx53-ccm",
> -	.of_compatible = DRV_OF_COMPAT(imx53_ccm_dt_ids),
>  };
>  
>  static int imx5_ccm_init(void)
> diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c
> new file mode 100644
> index 000000000..16518f0be
> --- /dev/null
> +++ b/drivers/clk/imx/clk-imx51-imx53.c
> @@ -0,0 +1,492 @@
> +/*
> + * 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 <common.h>
> +#include <init.h>
> +#include <driver.h>
> +#include <linux/clk.h>
> +#include <io.h>
> +#include <of.h>
> +#include <of_address.h>
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <mach/imx50-regs.h>
> +#include <mach/imx51-regs.h>
> +#include <mach/imx53-regs.h>
> +#include <dt-bindings/clock/imx5-clock.h>
> +
> +#include "clk.h"
> +
> +#define MX51_DPLL1_BASE		0x83f80000
> +#define MX51_DPLL2_BASE		0x83f84000
> +#define MX51_DPLL3_BASE		0x83f88000
> +
> +#define MX53_DPLL1_BASE		0x63f80000
> +#define MX53_DPLL2_BASE		0x63f84000
> +#define MX53_DPLL3_BASE		0x63f88000
> +#define MX53_DPLL4_BASE		0x63f8c000
> +
> +#define MXC_CCM_CCR		(ccm_base + 0x00)
> +#define MXC_CCM_CCDR		(ccm_base + 0x04)
> +#define MXC_CCM_CSR		(ccm_base + 0x08)
> +#define MXC_CCM_CCSR		(ccm_base + 0x0c)
> +#define MXC_CCM_CACRR		(ccm_base + 0x10)
> +#define MXC_CCM_CBCDR		(ccm_base + 0x14)
> +#define MXC_CCM_CBCMR		(ccm_base + 0x18)
> +#define MXC_CCM_CSCMR1		(ccm_base + 0x1c)
> +#define MXC_CCM_CSCMR2		(ccm_base + 0x20)
> +#define MXC_CCM_CSCDR1		(ccm_base + 0x24)
> +#define MXC_CCM_CS1CDR		(ccm_base + 0x28)
> +#define MXC_CCM_CS2CDR		(ccm_base + 0x2c)
> +#define MXC_CCM_CDCDR		(ccm_base + 0x30)
> +#define MXC_CCM_CHSCDR		(ccm_base + 0x34)
> +#define MXC_CCM_CSCDR2		(ccm_base + 0x38)
> +#define MXC_CCM_CSCDR3		(ccm_base + 0x3c)
> +#define MXC_CCM_CSCDR4		(ccm_base + 0x40)
> +#define MXC_CCM_CWDR		(ccm_base + 0x44)
> +#define MXC_CCM_CDHIPR		(ccm_base + 0x48)
> +#define MXC_CCM_CDCR		(ccm_base + 0x4c)
> +#define MXC_CCM_CTOR		(ccm_base + 0x50)
> +#define MXC_CCM_CLPCR		(ccm_base + 0x54)
> +#define MXC_CCM_CISR		(ccm_base + 0x58)
> +#define MXC_CCM_CIMR		(ccm_base + 0x5c)
> +#define MXC_CCM_CCOSR		(ccm_base + 0x60)
> +#define MXC_CCM_CGPR		(ccm_base + 0x64)
> +#define MXC_CCM_CCGR0		(ccm_base + 0x68)
> +#define MXC_CCM_CCGR1		(ccm_base + 0x6c)
> +#define MXC_CCM_CCGR2		(ccm_base + 0x70)
> +#define MXC_CCM_CCGR3		(ccm_base + 0x74)
> +#define MXC_CCM_CCGR4		(ccm_base + 0x78)
> +#define MXC_CCM_CCGR5		(ccm_base + 0x7c)
> +#define MXC_CCM_CCGR6		(ccm_base + 0x80)
> +#define MXC_CCM_CCGR7		(ccm_base + 0x84)
> +
> +/* Low-power Audio Playback Mode clock */
> +static const char *lp_apm_sel[] = { "osc", };
> +
> +/* This is used multiple times */
> +static const char *standard_pll_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "lp_apm", };
> +static const char *periph_apm_sel[] = { "pll1_sw", "pll3_sw", "lp_apm", };
> +static const char *main_bus_sel[] = { "pll2_sw", "periph_apm", };
> +static const char *per_lp_apm_sel[] = { "main_bus", "lp_apm", };
> +static const char *per_root_sel[] = { "per_podf", "ipg", };
> +static const char *esdhc_c_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
> +static const char *esdhc_d_sel[] = { "esdhc_a_podf", "esdhc_b_podf", };
> +static const char *emi_slow_sel[] = { "main_bus", "ahb", };
> +static const char *usb_phy_sel_str[] = { "osc", "usb_phy_podf", };
> +static const char *mx51_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "tve_di", };
> +static const char *mx53_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "di_pll4_podf", "dummy", "ldb_di0_gate", };
> +static const char *mx53_ldb_di0_sel[] = { "pll3_sw", "pll4_sw", };
> +static const char *mx51_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", };
> +static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", "ldb_di1_gate", };
> +static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", };
> +static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", };
> +static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", };
> +static const char *mx51_tve_sel[] = { "tve_pred", "tve_ext_sel", };
> +static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
> +static const char *gpu3d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
> +static const char *gpu2d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
> +static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
> +static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", };
> +static const char *mx53_cko1_sel[] = {
> +	"cpu_podf", "pll1_sw", "pll2_sw", "pll3_sw",
> +	"emi_slow_podf", "pll4_sw", "nfc_podf", "dummy",
> +	"di_pred", "dummy", "dummy", "ahb",
> +	"ipg", "per_root", "ckil", "dummy",};
> +static const char *mx53_cko2_sel[] = {
> +	"dummy"/* dptc_core */, "dummy"/* dptc_perich */,
> +	"dummy", "esdhc_a_podf",
> +	"usboh3_podf", "dummy"/* wrck_clk_root */,
> +	"ecspi_podf", "dummy"/* pll1_ref_clk */,
> +	"esdhc_b_podf", "dummy"/* ddr_clk_root */,
> +	"dummy"/* arm_axi_clk_root */, "dummy"/* usb_phy_out */,
> +	"vpu_sel", "ipu_sel",
> +	"osc", "ckih1",
> +	"dummy", "esdhc_c_sel",
> +	"ssi1_root_podf", "ssi2_root_podf",
> +	"dummy", "dummy",
> +	"dummy"/* lpsr_clk_root */, "dummy"/* pgc_clk_root */,
> +	"dummy"/* tve_out */, "usb_phy_sel",
> +	"tve_sel", "lp_apm",
> +	"uart_root", "dummy"/* spdif0_clk_root */,
> +	"dummy", "dummy", };
> +static const char *step_sels[] = { "lp_apm", };
> +static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
> +static const char *ieee1588_sels[] = { "pll3_sw", "pll4_sw", "dummy" /* usbphy2_clk */, "dummy" /* fec_phy_clk */ };
> +
> +static struct clk *clk[IMX5_CLK_END];
> +static struct clk_onecell_data clk_data;
> +
> +static void __init mx5_clocks_common_init(void __iomem *ccm_base)
> +{
> +	clk[IMX5_CLK_DUMMY]		= clk_fixed("dummy", 0);
> +
> +	clk[IMX5_CLK_PERIPH_APM]	= imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
> +						periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
> +	clk[IMX5_CLK_MAIN_BUS]		= imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
> +						main_bus_sel, ARRAY_SIZE(main_bus_sel));
> +	clk[IMX5_CLK_PER_LP_APM]	= imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1,
> +						per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel));
> +	clk[IMX5_CLK_PER_PRED1]		= imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2);
> +	clk[IMX5_CLK_PER_PRED2]		= imx_clk_divider("per_pred2", "per_pred1", MXC_CCM_CBCDR, 3, 3);
> +	clk[IMX5_CLK_PER_PODF]		= imx_clk_divider("per_podf", "per_pred2", MXC_CCM_CBCDR, 0, 3);
> +	clk[IMX5_CLK_PER_ROOT]		= imx_clk_mux("per_root", MXC_CCM_CBCMR, 0, 1,
> +						per_root_sel, ARRAY_SIZE(per_root_sel));
> +	clk[IMX5_CLK_AHB]		= imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3);
> +	clk[IMX5_CLK_AHB_MAX]		= imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28);
> +	clk[IMX5_CLK_AIPS_TZ1]		= imx_clk_gate2("aips_tz1", "ahb", MXC_CCM_CCGR0, 24);
> +	clk[IMX5_CLK_AIPS_TZ2]		= imx_clk_gate2("aips_tz2", "ahb", MXC_CCM_CCGR0, 26);
> +	clk[IMX5_CLK_TMAX1]		= imx_clk_gate2("tmax1", "ahb", MXC_CCM_CCGR1, 0);
> +	clk[IMX5_CLK_TMAX2]		= imx_clk_gate2("tmax2", "ahb", MXC_CCM_CCGR1, 2);
> +	clk[IMX5_CLK_TMAX3]		= imx_clk_gate2("tmax3", "ahb", MXC_CCM_CCGR1, 4);
> +	clk[IMX5_CLK_SPBA]		= imx_clk_gate2("spba", "ipg", MXC_CCM_CCGR5, 0);
> +	clk[IMX5_CLK_IPG]		= imx_clk_divider("ipg", "ahb", MXC_CCM_CBCDR, 8, 2);
> +	clk[IMX5_CLK_AXI_A]		= imx_clk_divider("axi_a", "main_bus", MXC_CCM_CBCDR, 16, 3);
> +	clk[IMX5_CLK_AXI_B]		= imx_clk_divider("axi_b", "main_bus", MXC_CCM_CBCDR, 19, 3);
> +	clk[IMX5_CLK_UART_SEL]		= imx_clk_mux("uart_sel", MXC_CCM_CSCMR1, 24, 2,
> +						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
> +	clk[IMX5_CLK_UART_PRED]		= imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3);
> +	clk[IMX5_CLK_UART_ROOT]		= imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3);
> +
> +	clk[IMX5_CLK_ESDHC_A_SEL]	= imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
> +						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
> +	clk[IMX5_CLK_ESDHC_B_SEL]	= imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
> +						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
> +	clk[IMX5_CLK_ESDHC_A_PRED]	= imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3);
> +	clk[IMX5_CLK_ESDHC_A_PODF]	= imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3);
> +	clk[IMX5_CLK_ESDHC_B_PRED]	= imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3);
> +	clk[IMX5_CLK_ESDHC_B_PODF]	= imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3);
> +	clk[IMX5_CLK_ESDHC_C_SEL]	= imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
> +	clk[IMX5_CLK_ESDHC_D_SEL]	= imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
> +
> +	clk[IMX5_CLK_EMI_SEL]		= imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1,
> +						emi_slow_sel, ARRAY_SIZE(emi_slow_sel));
> +	clk[IMX5_CLK_EMI_SLOW_PODF]	= imx_clk_divider("emi_slow_podf", "emi_sel", MXC_CCM_CBCDR, 22, 3);
> +	clk[IMX5_CLK_NFC_PODF]		= imx_clk_divider("nfc_podf", "emi_slow_podf", MXC_CCM_CBCDR, 13, 3);
> +	clk[IMX5_CLK_ECSPI_SEL]		= imx_clk_mux("ecspi_sel", MXC_CCM_CSCMR1, 4, 2,
> +						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
> +	clk[IMX5_CLK_ECSPI_PRED]	= imx_clk_divider("ecspi_pred", "ecspi_sel", MXC_CCM_CSCDR2, 25, 3);
> +	clk[IMX5_CLK_ECSPI_PODF]	= imx_clk_divider("ecspi_podf", "ecspi_pred", MXC_CCM_CSCDR2, 19, 6);
> +	clk[IMX5_CLK_USBOH3_SEL]	= imx_clk_mux("usboh3_sel", MXC_CCM_CSCMR1, 22, 2,
> +						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
> +	clk[IMX5_CLK_USBOH3_PRED]	= imx_clk_divider("usboh3_pred", "usboh3_sel", MXC_CCM_CSCDR1, 8, 3);
> +	clk[IMX5_CLK_USBOH3_PODF]	= imx_clk_divider("usboh3_podf", "usboh3_pred", MXC_CCM_CSCDR1, 6, 2);
> +	clk[IMX5_CLK_USB_PHY_PRED]	= imx_clk_divider("usb_phy_pred", "pll3_sw", MXC_CCM_CDCDR, 3, 3);
> +	clk[IMX5_CLK_USB_PHY_PODF]	= imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
> +	clk[IMX5_CLK_USB_PHY_SEL]	= imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
> +						usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
> +	clk[IMX5_CLK_STEP_SEL]		= imx_clk_mux("step_sel", MXC_CCM_CCSR, 7, 2, step_sels, ARRAY_SIZE(step_sels));
> +	clk[IMX5_CLK_CPU_PODF_SEL]	= imx_clk_mux("cpu_podf_sel", MXC_CCM_CCSR, 2, 1, cpu_podf_sels, ARRAY_SIZE(cpu_podf_sels));
> +	clk[IMX5_CLK_CPU_PODF]		= imx_clk_divider("cpu_podf", "cpu_podf_sel", MXC_CCM_CACRR, 0, 3);
> +	clk[IMX5_CLK_DI_PRED]		= imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
> +	clk[IMX5_CLK_IIM_GATE]		= imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
> +	clk[IMX5_CLK_UART1_IPG_GATE]	= imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
> +	clk[IMX5_CLK_UART1_PER_GATE]	= imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8);
> +	clk[IMX5_CLK_UART2_IPG_GATE]	= imx_clk_gate2("uart2_ipg_gate", "ipg", MXC_CCM_CCGR1, 10);
> +	clk[IMX5_CLK_UART2_PER_GATE]	= imx_clk_gate2("uart2_per_gate", "uart_root", MXC_CCM_CCGR1, 12);
> +	clk[IMX5_CLK_UART3_IPG_GATE]	= imx_clk_gate2("uart3_ipg_gate", "ipg", MXC_CCM_CCGR1, 14);
> +	clk[IMX5_CLK_UART3_PER_GATE]	= imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16);
> +	clk[IMX5_CLK_I2C1_GATE]		= imx_clk_gate2("i2c1_gate", "per_root", MXC_CCM_CCGR1, 18);
> +	clk[IMX5_CLK_I2C2_GATE]		= imx_clk_gate2("i2c2_gate", "per_root", MXC_CCM_CCGR1, 20);
> +	clk[IMX5_CLK_PWM1_IPG_GATE]	= imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10);
> +	clk[IMX5_CLK_PWM1_HF_GATE]	= imx_clk_gate2("pwm1_hf_gate", "per_root", MXC_CCM_CCGR2, 12);
> +	clk[IMX5_CLK_PWM2_IPG_GATE]	= imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14);
> +	clk[IMX5_CLK_PWM2_HF_GATE]	= imx_clk_gate2("pwm2_hf_gate", "per_root", MXC_CCM_CCGR2, 16);
> +	clk[IMX5_CLK_GPT_IPG_GATE]	= imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 18);
> +	clk[IMX5_CLK_GPT_HF_GATE]	= imx_clk_gate2("gpt_hf_gate", "per_root", MXC_CCM_CCGR2, 20);
> +	clk[IMX5_CLK_FEC_GATE]		= imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24);
> +	clk[IMX5_CLK_USBOH3_GATE]	= imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26);
> +	clk[IMX5_CLK_USBOH3_PER_GATE]	= imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28);
> +	clk[IMX5_CLK_ESDHC1_IPG_GATE]	= imx_clk_gate2("esdhc1_ipg_gate", "ipg", MXC_CCM_CCGR3, 0);
> +	clk[IMX5_CLK_ESDHC2_IPG_GATE]	= imx_clk_gate2("esdhc2_ipg_gate", "ipg", MXC_CCM_CCGR3, 4);
> +	clk[IMX5_CLK_ESDHC3_IPG_GATE]	= imx_clk_gate2("esdhc3_ipg_gate", "ipg", MXC_CCM_CCGR3, 8);
> +	clk[IMX5_CLK_ESDHC4_IPG_GATE]	= imx_clk_gate2("esdhc4_ipg_gate", "ipg", MXC_CCM_CCGR3, 12);
> +	clk[IMX5_CLK_ECSPI1_IPG_GATE]	= imx_clk_gate2("ecspi1_ipg_gate", "ipg", MXC_CCM_CCGR4, 18);
> +	clk[IMX5_CLK_ECSPI1_PER_GATE]	= imx_clk_gate2("ecspi1_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 20);
> +	clk[IMX5_CLK_ECSPI2_IPG_GATE]	= imx_clk_gate2("ecspi2_ipg_gate", "ipg", MXC_CCM_CCGR4, 22);
> +	clk[IMX5_CLK_ECSPI2_PER_GATE]	= imx_clk_gate2("ecspi2_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 24);
> +	clk[IMX5_CLK_CSPI_IPG_GATE]	= imx_clk_gate2("cspi_ipg_gate", "ipg", MXC_CCM_CCGR4, 26);
> +	clk[IMX5_CLK_SDMA_GATE]		= imx_clk_gate2("sdma_gate", "ipg", MXC_CCM_CCGR4, 30);
> +	clk[IMX5_CLK_EMI_FAST_GATE]	= imx_clk_gate2("emi_fast_gate", "dummy", MXC_CCM_CCGR5, 14);
> +	clk[IMX5_CLK_EMI_SLOW_GATE]	= imx_clk_gate2("emi_slow_gate", "emi_slow_podf", MXC_CCM_CCGR5, 16);
> +	clk[IMX5_CLK_IPU_SEL]		= imx_clk_mux("ipu_sel", MXC_CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel));
> +	clk[IMX5_CLK_IPU_GATE]		= imx_clk_gate2("ipu_gate", "ipu_sel", MXC_CCM_CCGR5, 10);
> +	clk[IMX5_CLK_NFC_GATE]		= imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
> +	clk[IMX5_CLK_IPU_DI0_GATE]	= imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
> +	clk[IMX5_CLK_IPU_DI1_GATE]	= imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
> +	clk[IMX5_CLK_GPU3D_SEL]		= imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel));
> +	clk[IMX5_CLK_GPU2D_SEL]		= imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel));
> +	clk[IMX5_CLK_GPU3D_GATE]	= imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2);
> +	clk[IMX5_CLK_GARB_GATE]		= imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4);
> +	clk[IMX5_CLK_GPU2D_GATE]	= imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14);
> +	clk[IMX5_CLK_VPU_SEL]		= imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
> +	clk[IMX5_CLK_VPU_GATE]		= imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
> +	clk[IMX5_CLK_VPU_REFERENCE_GATE] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
> +	clk[IMX5_CLK_GPC_DVFS]		= imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
> +
> +	clk[IMX5_CLK_SRTC_GATE]		= imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28);
> +	clk[IMX5_CLK_PATA_GATE]		= imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0);
> +	clk[IMX5_CLK_SAHARA_IPG_GATE]	= imx_clk_gate2("sahara_ipg_gate", "ipg", MXC_CCM_CCGR4, 14);
> +	clk[IMX5_CLK_SATA_REF]		= imx_clk_fixed_factor("sata_ref", "usb_phy1_gate", 1, 1);
> +
> +	clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0");
> +	clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL);
> +
> +	/* Set SDHC parents to be PLL2 */
> +	clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
> +	clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]);
> +
> +	/* move usb phy clk to 24MHz */
> +	clk_set_parent(clk[IMX5_CLK_USB_PHY_SEL], clk[IMX5_CLK_OSC]);
> +
> +	clk_enable(clk[IMX5_CLK_GPC_DVFS]);
> +	clk_enable(clk[IMX5_CLK_AHB_MAX]); /* esdhc3 */
> +	clk_enable(clk[IMX5_CLK_AIPS_TZ1]);
> +	clk_enable(clk[IMX5_CLK_AIPS_TZ2]); /* fec */
> +	clk_enable(clk[IMX5_CLK_SPBA]);
> +	clk_enable(clk[IMX5_CLK_EMI_FAST_GATE]); /* fec */
> +	clk_enable(clk[IMX5_CLK_EMI_SLOW_GATE]); /* eim */
> +	clk_enable(clk[IMX5_CLK_MIPI_HSC1_GATE]);
> +	clk_enable(clk[IMX5_CLK_MIPI_HSC2_GATE]);
> +	clk_enable(clk[IMX5_CLK_MIPI_ESC_GATE]);
> +	clk_enable(clk[IMX5_CLK_MIPI_HSP_GATE]);
> +	clk_enable(clk[IMX5_CLK_TMAX1]);
> +	clk_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
> +	clk_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
> +}
> +
> +static void __init mx50_clocks_init(struct device_node *np)
> +{
> +	void __iomem *ccm_base;
> +	unsigned long r;
> +
> +	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", IOMEM(MX53_DPLL1_BASE));
> +	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", IOMEM(MX53_DPLL2_BASE));
> +	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", IOMEM(MX53_DPLL3_BASE));
> +
> +	ccm_base = of_iomap(np, 0);
> +	WARN_ON(!ccm_base);
> +
> +	mx5_clocks_common_init(ccm_base);
> +
> +	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
> +						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
> +	clk[IMX5_CLK_ESDHC1_PER_GATE]	= imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
> +	clk[IMX5_CLK_ESDHC2_PER_GATE]	= imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
> +	clk[IMX5_CLK_ESDHC3_PER_GATE]	= imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
> +	clk[IMX5_CLK_ESDHC4_PER_GATE]	= imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
> +	clk[IMX5_CLK_USB_PHY1_GATE]	= imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
> +	clk[IMX5_CLK_USB_PHY2_GATE]	= imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
> +	clk[IMX5_CLK_I2C3_GATE]		= imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
> +	clk[IMX5_CLK_UART4_IPG_GATE]	= imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
> +	clk[IMX5_CLK_UART4_PER_GATE]	= imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
> +	clk[IMX5_CLK_UART5_IPG_GATE]	= imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
> +	clk[IMX5_CLK_UART5_PER_GATE]	= imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
> +
> +	clk[IMX5_CLK_CKO1_SEL]		= imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
> +						mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
> +	clk[IMX5_CLK_CKO1_PODF]		= imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
> +	clk[IMX5_CLK_CKO1]		= imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
> +
> +	clk[IMX5_CLK_CKO2_SEL]		= imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
> +						mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
> +	clk[IMX5_CLK_CKO2_PODF]		= imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
> +	clk[IMX5_CLK_CKO2]		= imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
> +
> +	imx_check_clocks(clk, ARRAY_SIZE(clk));
> +
> +	clk_data.clks = clk;
> +	clk_data.clk_num = ARRAY_SIZE(clk);
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +
> +	/* set SDHC root clock to 200MHZ*/
> +	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
> +	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
> +
> +	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
> +	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
> +}
> +CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
> +
> +static void __init mx51_clocks_init(struct device_node *np)
> +{
> +	void __iomem *ccm_base;
> +	u32 val;
> +
> +	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", IOMEM(MX51_DPLL1_BASE));
> +	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", IOMEM(MX51_DPLL2_BASE));
> +	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", IOMEM(MX51_DPLL3_BASE));
> +
> +	ccm_base = of_iomap(np, 0);
> +	WARN_ON(!ccm_base);
> +
> +	mx5_clocks_common_init(ccm_base);
> +
> +	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
> +						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
> +	clk[IMX5_CLK_IPU_DI0_SEL]	= imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
> +						mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_IPU_DI1_SEL]	= imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
> +						mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_TVE_EXT_SEL]	= imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
> +						mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_TVE_SEL]		= imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1,
> +						mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel));
> +	clk[IMX5_CLK_TVE_GATE]		= imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
> +	clk[IMX5_CLK_TVE_PRED]		= imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
> +	clk[IMX5_CLK_ESDHC1_PER_GATE]	= imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
> +	clk[IMX5_CLK_ESDHC2_PER_GATE]	= imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6);
> +	clk[IMX5_CLK_ESDHC3_PER_GATE]	= imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10);
> +	clk[IMX5_CLK_ESDHC4_PER_GATE]	= imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
> +	clk[IMX5_CLK_USB_PHY_GATE]	= imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
> +	clk[IMX5_CLK_HSI2C_GATE]	= imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
> +	clk[IMX5_CLK_MIPI_HSC1_GATE]	= imx_clk_gate2("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6);
> +	clk[IMX5_CLK_MIPI_HSC2_GATE]	= imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8);
> +	clk[IMX5_CLK_MIPI_ESC_GATE]	= imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10);
> +	clk[IMX5_CLK_MIPI_HSP_GATE]	= imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12);
> +
> +	imx_check_clocks(clk, ARRAY_SIZE(clk));
> +
> +	clk_data.clks = clk;
> +	clk_data.clk_num = ARRAY_SIZE(clk);
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +
> +	/* set the usboh3 parent to pll2_sw */
> +	clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]);
> +
> +	/* set SDHC root clock to 166.25MHZ*/
> +	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000);
> +	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000);
> +
> +	/*
> +	 * Reference Manual says: Functionality of CCDR[18] and CLPCR[23] is no
> +	 * longer supported. Set to one for better power saving.
> +	 *
> +	 * The effect of not setting these bits is that MIPI clocks can't be
> +	 * enabled without the IPU clock being enabled aswell.
> +	 */
> +	val = readl(MXC_CCM_CCDR);
> +	val |= 1 << 18;
> +	writel(val, MXC_CCM_CCDR);
> +
> +	val = readl(MXC_CCM_CLPCR);
> +	val |= 1 << 23;
> +	writel(val, MXC_CCM_CLPCR);
> +}
> +CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init);
> +
> +static void __init mx53_clocks_init(struct device_node *np)
> +{
> +	void __iomem *ccm_base;
> +	unsigned long r;
> +
> +	clk[IMX5_CLK_PLL1_SW]		= imx_clk_pllv2("pll1_sw", "osc", IOMEM(MX53_DPLL1_BASE));
> +	clk[IMX5_CLK_PLL2_SW]		= imx_clk_pllv2("pll2_sw", "osc", IOMEM(MX53_DPLL2_BASE));
> +	clk[IMX5_CLK_PLL3_SW]		= imx_clk_pllv2("pll3_sw", "osc", IOMEM(MX53_DPLL3_BASE));
> +	clk[IMX5_CLK_PLL4_SW]		= imx_clk_pllv2("pll4_sw", "osc", IOMEM(MX53_DPLL4_BASE));
> +
> +	ccm_base = of_iomap(np, 0);
> +	WARN_ON(!ccm_base);
> +
> +	mx5_clocks_common_init(ccm_base);
> +
> +	clk[IMX5_CLK_LP_APM]		= imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
> +						lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
> +	clk[IMX5_CLK_LDB_DI1_DIV_3_5]	= imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
> +	clk[IMX5_CLK_LDB_DI1_DIV]	= imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0);
> +	clk[IMX5_CLK_LDB_DI1_SEL]	= imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
> +						mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_DI_PLL4_PODF]	= imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
> +	clk[IMX5_CLK_LDB_DI0_DIV_3_5]	= imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
> +	clk[IMX5_CLK_LDB_DI0_DIV]	= imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0);
> +	clk[IMX5_CLK_LDB_DI0_SEL]	= imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
> +						mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_LDB_DI0_GATE]	= imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
> +	clk[IMX5_CLK_LDB_DI1_GATE]	= imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
> +	clk[IMX5_CLK_IPU_DI0_SEL]	= imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
> +						mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_IPU_DI1_SEL]	= imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
> +						mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_TVE_EXT_SEL]	= imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
> +						mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
> +	clk[IMX5_CLK_TVE_GATE]		= imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
> +	clk[IMX5_CLK_TVE_PRED]		= imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
> +	clk[IMX5_CLK_ESDHC1_PER_GATE]	= imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
> +	clk[IMX5_CLK_ESDHC2_PER_GATE]	= imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
> +	clk[IMX5_CLK_ESDHC3_PER_GATE]	= imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
> +	clk[IMX5_CLK_ESDHC4_PER_GATE]	= imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
> +	clk[IMX5_CLK_USB_PHY1_GATE]	= imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
> +	clk[IMX5_CLK_USB_PHY2_GATE]	= imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
> +	clk[IMX5_CLK_CAN_SEL]		= imx_clk_mux("can_sel", MXC_CCM_CSCMR2, 6, 2,
> +						mx53_can_sel, ARRAY_SIZE(mx53_can_sel));
> +	clk[IMX5_CLK_CAN1_SERIAL_GATE]	= imx_clk_gate2("can1_serial_gate", "can_sel", MXC_CCM_CCGR6, 22);
> +	clk[IMX5_CLK_CAN1_IPG_GATE]	= imx_clk_gate2("can1_ipg_gate", "ipg", MXC_CCM_CCGR6, 20);
> +	clk[IMX5_CLK_OCRAM]		= imx_clk_gate2("ocram", "ahb", MXC_CCM_CCGR6, 2);
> +	clk[IMX5_CLK_CAN2_SERIAL_GATE]	= imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8);
> +	clk[IMX5_CLK_CAN2_IPG_GATE]	= imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
> +	clk[IMX5_CLK_I2C3_GATE]		= imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
> +	clk[IMX5_CLK_SATA_GATE]		= imx_clk_gate2("sata_gate", "ipg", MXC_CCM_CCGR4, 2);
> +
> +	clk[IMX5_CLK_FIRI_SEL]		= imx_clk_mux("firi_sel", MXC_CCM_CSCMR2, 12, 2,
> +						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
> +	clk[IMX5_CLK_FIRI_PRED]		= imx_clk_divider("firi_pred", "firi_sel", MXC_CCM_CSCDR3, 6, 3);
> +	clk[IMX5_CLK_FIRI_PODF]		= imx_clk_divider("firi_podf", "firi_pred", MXC_CCM_CSCDR3, 0, 6);
> +	clk[IMX5_CLK_FIRI_SERIAL_GATE]	= imx_clk_gate2("firi_serial_gate", "firi_podf", MXC_CCM_CCGR1, 28);
> +	clk[IMX5_CLK_FIRI_IPG_GATE]	= imx_clk_gate2("firi_ipg_gate", "ipg", MXC_CCM_CCGR1, 26);
> +
> +	clk[IMX5_CLK_CSI0_MCLK1_SEL]	= imx_clk_mux("csi0_mclk1_sel", MXC_CCM_CSCMR2, 22, 2,
> +						standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
> +	clk[IMX5_CLK_CSI0_MCLK1_PRED]	= imx_clk_divider("csi0_mclk1_pred", "csi0_mclk1_sel", MXC_CCM_CSCDR4, 6, 3);
> +	clk[IMX5_CLK_CSI0_MCLK1_PODF]	= imx_clk_divider("csi0_mclk1_podf", "csi0_mclk1_pred", MXC_CCM_CSCDR4, 0, 6);
> +	clk[IMX5_CLK_CSI0_MCLK1_GATE]	= imx_clk_gate2("csi0_mclk1_serial_gate", "csi0_mclk1_podf", MXC_CCM_CCGR6, 4);
> +
> +	clk[IMX5_CLK_IEEE1588_SEL]	= imx_clk_mux("ieee1588_sel", MXC_CCM_CSCMR2, 14, 2,
> +						ieee1588_sels, ARRAY_SIZE(ieee1588_sels));
> +	clk[IMX5_CLK_IEEE1588_PRED]	= imx_clk_divider("ieee1588_pred", "ieee1588_sel", MXC_CCM_CSCDR2, 6, 3);
> +	clk[IMX5_CLK_IEEE1588_PODF]	= imx_clk_divider("ieee1588_podf", "ieee1588_pred", MXC_CCM_CSCDR2, 0, 6);
> +	clk[IMX5_CLK_IEEE1588_GATE]	= imx_clk_gate2("ieee1588_serial_gate", "ieee1588_podf", MXC_CCM_CCGR7, 6);
> +	clk[IMX5_CLK_UART4_IPG_GATE]	= imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
> +	clk[IMX5_CLK_UART4_PER_GATE]	= imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
> +	clk[IMX5_CLK_UART5_IPG_GATE]	= imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
> +	clk[IMX5_CLK_UART5_PER_GATE]	= imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
> +
> +	clk[IMX5_CLK_CKO1_SEL]		= imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
> +						mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
> +	clk[IMX5_CLK_CKO1_PODF]		= imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
> +	clk[IMX5_CLK_CKO1]		= imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
> +
> +	clk[IMX5_CLK_CKO2_SEL]		= imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
> +						mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
> +	clk[IMX5_CLK_CKO2_PODF]		= imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
> +	clk[IMX5_CLK_CKO2]		= imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
> +	clk[IMX5_CLK_ARM]		= imx_clk_cpu("arm", "cpu_podf",
> +						clk[IMX5_CLK_CPU_PODF],
> +						clk[IMX5_CLK_CPU_PODF_SEL],
> +						clk[IMX5_CLK_PLL1_SW],
> +						clk[IMX5_CLK_STEP_SEL]);
> +
> +	imx_check_clocks(clk, ARRAY_SIZE(clk));
> +
> +	clk_data.clks = clk;
> +	clk_data.clk_num = ARRAY_SIZE(clk);
> +	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +
> +	/* set SDHC root clock to 200MHZ*/
> +	clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
> +	clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
> +
> +	/* move can bus clk to 24MHz */
> +	clk_set_parent(clk[IMX5_CLK_CAN_SEL], clk[IMX5_CLK_LP_APM]);
> +
> +	/* make sure step clock is running from 24MHz */
> +	clk_set_parent(clk[IMX5_CLK_STEP_SEL], clk[IMX5_CLK_LP_APM]);
> +
> +	r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
> +	clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
> +}
> +CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
> -- 
> 2.17.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
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 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] clk: i.MX: Port Linux clock tree for i.MX51 and i.MX53
  2018-08-30  5:02 [PATCH v2] clk: i.MX: Port Linux clock tree for i.MX51 and i.MX53 Andrey Smirnov
  2018-09-04  6:37 ` Sascha Hauer
@ 2018-09-06  7:48 ` Sascha Hauer
  2018-09-06 15:59   ` Andrey Smirnov
  1 sibling, 1 reply; 4+ messages in thread
From: Sascha Hauer @ 2018-09-06  7:48 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

On Wed, Aug 29, 2018 at 10:02:07PM -0700, Andrey Smirnov wrote:
> Existing clock tree code for i.MX5 in Barebox predates DT and is not
> aware of it. This results in missing clocks on DT-based boards like
> RDU1 and Babbage. Port clock tree from Linux to resolve this
> problem. Old non-DT clock code is kept around for the sake of the
> boards that were never converted to use DT.

Overall I am not happy with this patch.

With this patch we now have two clock drivers for the i.MX5 - not only
in the source tree but also in the binaries.

Yesterday I tried fleshing out the differences between both drivers. I
renamed "clks" to "clk", adjusted whitespaces, changed register defines
to the pattern "#define MXC_CCM_xxx (ccm_base + 0x*)". What I got was
quite a bit closer to the kernel driver but still not there. It revealed
some bugs in the kernel driver though. There are several differences in
the register layout between the i.MX50 and the i.MX51/53 (See
IMX5_CLK_ESDHC_A_SEL for example, MXC_CCM_CSCMR1[20:21] on i.MX51/53 and
MXC_CCM_CSCMR1[21:22] on the i.MX50). These are correctly abstracted
in the current barebox driver but not in the Linux driver, see
mx5_clocks_mx51_mx53_init() which doesn't exist in the Linux driver.

So by switching to the Kernel clk driver we introduce a bunch of new
bugs into barebox which of course is unfortunate.

Finally your patch does not compile on some configs
(efika-mx-smartbook_defconfig for example) since COMMON_CLK_OF_PROVIDER
is not selected. That's rather simple to fix of course.

Which clocks are you missing? Maybe it would be better to add the
missing clocks to the barebox clock driver instead of adding a new one?

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 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] clk: i.MX: Port Linux clock tree for i.MX51 and i.MX53
  2018-09-06  7:48 ` Sascha Hauer
@ 2018-09-06 15:59   ` Andrey Smirnov
  0 siblings, 0 replies; 4+ messages in thread
From: Andrey Smirnov @ 2018-09-06 15:59 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Barebox List

On Thu, Sep 6, 2018 at 12:48 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> On Wed, Aug 29, 2018 at 10:02:07PM -0700, Andrey Smirnov wrote:
> > Existing clock tree code for i.MX5 in Barebox predates DT and is not
> > aware of it. This results in missing clocks on DT-based boards like
> > RDU1 and Babbage. Port clock tree from Linux to resolve this
> > problem. Old non-DT clock code is kept around for the sake of the
> > boards that were never converted to use DT.
>
> Overall I am not happy with this patch.
>
> With this patch we now have two clock drivers for the i.MX5 - not only
> in the source tree but also in the binaries.
>
> Yesterday I tried fleshing out the differences between both drivers. I
> renamed "clks" to "clk", adjusted whitespaces, changed register defines
> to the pattern "#define MXC_CCM_xxx (ccm_base + 0x*)". What I got was
> quite a bit closer to the kernel driver but still not there. It revealed
> some bugs in the kernel driver though. There are several differences in
> the register layout between the i.MX50 and the i.MX51/53 (See
> IMX5_CLK_ESDHC_A_SEL for example, MXC_CCM_CSCMR1[20:21] on i.MX51/53 and
> MXC_CCM_CSCMR1[21:22] on the i.MX50). These are correctly abstracted
> in the current barebox driver but not in the Linux driver, see
> mx5_clocks_mx51_mx53_init() which doesn't exist in the Linux driver.
>
> So by switching to the Kernel clk driver we introduce a bunch of new
> bugs into barebox which of course is unfortunate.
>
> Finally your patch does not compile on some configs
> (efika-mx-smartbook_defconfig for example) since COMMON_CLK_OF_PROVIDER
> is not selected. That's rather simple to fix of course.
>
> Which clocks are you missing? Maybe it would be better to add the
> missing clocks to the barebox clock driver instead of adding a new one?
>

There's already a patch for that for original driver:
http://lists.infradead.org/pipermail/barebox/2018-August/034413.html
My hope was to use this as an opportunity to switch to using kernel
code, but if we don't really want to pay the price for that, then I
think Michael's patch should work just fine.

Also, just out of curiosity, are you planning to upstream the fixes
for bugs in kernel driver you found?

Thanks,
Andrey Smirnov

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-09-06 15:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-30  5:02 [PATCH v2] clk: i.MX: Port Linux clock tree for i.MX51 and i.MX53 Andrey Smirnov
2018-09-04  6:37 ` Sascha Hauer
2018-09-06  7:48 ` Sascha Hauer
2018-09-06 15:59   ` Andrey Smirnov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox