devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/6] add full platform dt clock support for mx51 babbage
@ 2011-03-18 18:24 Shawn Guo
       [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Shawn Guo @ 2011-03-18 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

This patch set is to add full platform dt clock support for mx51
babbage, based on Grant's devicetree/test tree.  All mx51 non-dt
clocks in clock-mx51-mx53.c are translated to dt ones.

Regards,
Shawn

Changes since v1:
 * unify the references to clocks that could be created statically
   and dynamically, so that we do not have to duplicate functions
 * use for_each_matching_node suggested by Grant to match clock
   creating functions
 * reserve 'data' of device_node structure and use new one 'clk'
 * change macro ALLOC_CLK_LOOKUP and ADD_CLK_LOOKUP to functions
 * fix codes that will break existing board support
 * use clock provider 'src-clock' and 'dep-clock'
 * fix up aips and spba node name to remove address info (suggestion
   given by Grant on Jason's patch)

Shawn Guo (6):
      arm/dts: babbage: add all available clock nodes
      arm/mxc: add clk member 'rate' to ease dt fixed-clock support
      dt: add new member 'clk' into device_node
      arm/dt: mx51: dynamically add clocks per dt nodes
      arm/dt: mx5: change timer init function to dt clock way
      of/clock: eliminate function __of_clk_get_from_provider

 arch/arm/boot/dts/babbage.dts          |  501 +++++++++++-
 arch/arm/mach-mx5/Makefile             |    2 +-
 arch/arm/mach-mx5/board-dt.c           |    9 +-
 arch/arm/mach-mx5/clock-dt.c           |   52 --
 arch/arm/mach-mx5/clock-mx51-mx53.c    | 1433 +++++++++++++++++++++++++++++++-
 arch/arm/plat-mxc/include/mach/clock.h |    4 +
 drivers/of/clock.c                     |   23 +-
 include/linux/of.h                     |    1 +
 8 files changed, 1913 insertions(+), 112 deletions(-)

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

* [PATCH v2 1/6] arm/dts: babbage: add all available clock nodes
       [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-03-18 18:24   ` Shawn Guo
  2011-03-18 18:24   ` [PATCH v2 2/6] arm/mxc: add clk member 'rate' to ease dt fixed-clock support Shawn Guo
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Shawn Guo @ 2011-03-18 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

The patch is to add all available dt clock nodes for babbage board.
It sticks to the clock name used in clock-mx51-mx53.c, so that
everything gets consistent to Reference Manual.  For example, the
numbering in clock name usually starts from 1, while 'reg' property
numbering starts from 0 to easy clock binding.

Besides the generally used clock bindings, the following clock
providers are proposed in this patch.

* src-clock
This clock provider is added to reflect the parent clock.

* dep-clock
The mxc 'struct clk' has the member 'secondary' to refer to the clock
that the 'clk' has dependency on.  This 'secondary' clock needs to be
turned on whenever the 'clk' is turned on.  This clock provider is
defined to reflect this 'secondary' clock.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/boot/dts/babbage.dts |  501 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 488 insertions(+), 13 deletions(-)

diff --git a/arch/arm/boot/dts/babbage.dts b/arch/arm/boot/dts/babbage.dts
index 8f9b47c..2028290 100644
--- a/arch/arm/boot/dts/babbage.dts
+++ b/arch/arm/boot/dts/babbage.dts
@@ -47,28 +47,503 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		uart0_clk: uart0 {
-			compatible = "clock";
+		ckil_clk: clkil {
+			compatible = "fixed-clock";
+			#frequency-cells = <1>;
+			clock-outputs = "clil";
+			clock-frequency = <32768>;
+		};
+
+		ckih_clk: ckih {
+			compatible = "fixed-clock";
+			#frequency-cells = <1>;
+			clock-outputs = "ckih";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2_clk: ckih2 {
+			compatible = "fixed-clock";
+			#frequency-cells = <1>;
+			clock-outputs = "ckih2";
+			clock-frequency = <0>;
+		};
+
+		osc_clk: soc {
+			compatible = "fixed-clock";
+			#frequency-cells = <1>;
+			clock-outputs = "osc";
+			clock-frequency = <24000000>;
+		};
+
+		pll1_main_clk: pll1_main {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "pll1_main";
+			src-clock = <&osc_clk>, "osc-clk";
+		};
+
+		pll1_sw_clk: pll_switch@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "pll1_sw";
+			src-clock = <&pll1_main_clk>, "pll-clk";
+		};
+
+		pll2_sw_clk: pll_switch@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "pll2_sw";
+			src-clock = <&osc_clk>, "osc-clk";
+		};
+
+		pll3_sw_clk: pll_switch@2 {
+			compatible = "fsl,mxc-clock";
+			reg = <2>;
+			clock-outputs = "pll3_sw";
+			src-clock = <&osc_clk>, "osc-clk";
+		};
+
+		lp_apm_clk: lp_apm {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "lp_apm";
+			src-clock = <&osc_clk>, "osc-clk";
+		};
+
+		ipg_per_clk: ipg_per {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ipg_per";
+			src-clock = <&lp_apm_clk>, "apm-clk";
+		};
+
+		periph_apm_clk: periph_apm {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "periph_apm";
+			src-clock = <&pll1_sw_clk>, "pll-clk";
+		};
+
+		cpu_clk: cpu {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "cpu";
+			src-clock = <&pll1_sw_clk>, "pll-clk";
+		};
+
+		ddr_hf_clk: ddr_hf {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ddr_hf";
+			src-clock = <&pll1_sw_clk>, "pll-clk";
+		};
+
+		ddr_clk: ddr {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ddr";
+			src-clock = <&ddr_hf_clk>, "ddr-hf-clk";
+		};
+
+		emi_fast_clk: emi_fast {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "emi_fast";
+			src-clock = <&ddr_clk>, "ddr-clk";
+		};
+
+		main_bus_clk: main_bus {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "main_bus";
+			src-clock = <&pll2_sw_clk>, "pll-clk";
+		};
+
+		emi_slow_clk: emi_slow {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "emi_slow";
+			src-clock = <&pll2_sw_clk>, "pll-clk";
+		};
+
+		ahb_clk: ahb {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ahb";
+			src-clock = <&main_bus_clk>, "bus-clk";
+		};
+
+		ipg_clk: ipg {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ipg";
+			src-clock = <&ahb_clk>, "ahb-clk";
+		};
+
+		spba_clk: spba {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "spba";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		iim_clk: iim {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "iim";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		ahb_max_clk: ahb_max {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ahb_max";
+			src-clock = <&ahb_clk>, "ahb-clk";
+		};
+
+		aips_tz1_clk: aips_tz@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "aips_tz1";
+			src-clock = <&ahb_clk>, "ahb-clk";
+			dep-clock = <&ahb_max_clk>, "max-clk";
+		};
+
+		aips_tz2_clk: aips_tz@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "aips_tz2";
+			src-clock = <&ahb_clk>, "ahb-clk";
+			dep-clock = <&ahb_max_clk>, "max-clk";
+		};
+
+		ahbmux1_clk: ahbmux1 {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ahbmux1";
+			src-clock = <&ahb_clk>, "ahb-clk";
+			dep-clock = <&ahb_max_clk>, "max-clk";
+		};
+
+		gpt_ipg_clk: gpt_ipg {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "gpt_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		gpt_clk: gpt {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "gpt";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&gpt_ipg_clk>, "gpt-ipg-clk";
+		};
+
+		gpt_32k_clk: gpt_32k {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "gpt_32k";
+			src-clock = <&ckil_clk>, "ckil-clk";
+		};
+
+		uart1_ipg_clk: uart_ipg@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "uart1_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&aips_tz1_clk>, "aips-clk";
+		};
+
+		uart2_ipg_clk: uart_ipg@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "uart2_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&aips_tz1_clk>, "aips-clk";
+		};
+
+		uart3_ipg_clk: uart_ipg@2 {
+			compatible = "fsl,mxc-clock";
+			reg = <2>;
+			clock-outputs = "uart3_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&spba_clk>, "spba-clk";
+		};
+
+		uart_root_clk: uart_root {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "uart_root";
+			src-clock = <&pll2_sw_clk>, "pll-clk";
+		};
+
+		uart1_clk: uart@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
 			clock-outputs = "imx-uart.0";
+			src-clock = <&uart_root_clk>, "uart-root-clk";
+			dep-clock = <&uart1_ipg_clk>, "uart-ipg-clk";
 		};
 
-		uart1_clk: uart1 {
-			compatible = "clock";
+		uart2_clk: uart@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
 			clock-outputs = "imx-uart.1";
+			src-clock = <&uart_root_clk>, "uart-root-clk";
+			dep-clock = <&uart2_ipg_clk>, "uart-ipg-clk";
 		};
 
-		uart2_clk: uart2 {
-			compatible = "clock";
+		uart3_clk: uart@2 {
+			compatible = "fsl,mxc-clock";
+			reg = <2>;
 			clock-outputs = "imx-uart.2";
+			src-clock = <&uart_root_clk>, "uart-root-clk";
+			dep-clock = <&uart3_ipg_clk>, "uart-ipg-clk";
 		};
 
 		fec_clk: fec {
-			compatible = "clock";
+			compatible = "fsl,mxc-clock";
 			clock-outputs = "fec.0";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		pwm1_clk: pwm@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "mxc-pwm.0";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		pwm2_clk: pwm@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "mxc-pwm.1";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		i2c1_clk: i2c@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "imx-i2c.0";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		i2c2_clk: i2c@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "imx-i2c.1";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		hsi2c_clk: i2c@2 {
+			compatible = "fsl,mxc-clock";
+			reg = <2>;
+			clock-outputs = "imx-i2c.2";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		nfc_clk: nfc {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "mxs_nand";
+			src-clock = <&emi_slow_clk>, "emi-clk";
+		};
+
+		ssi1_ipg_clk: ssi_ipg@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "ssi1_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		ssi2_ipg_clk: ssi_ipg@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "ssi2_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		ssi3_ipg_clk: ssi_ipg@2 {
+			compatible = "fsl,mxc-clock";
+			reg = <2>;
+			clock-outputs = "ssi3_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		ssi1_clk: ssi@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "imx-ssi.0";
+			src-clock = <&pll3_sw_clk>, "pll-clk";
+			dep-clock = <&ssi1_ipg_clk>, "ssi-ipg-clk";
+		};
+
+		ssi2_clk: ssi@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "imx-ssi.1";
+			src-clock = <&pll3_sw_clk>, "pll-clk";
+			dep-clock = <&ssi2_ipg_clk>, "ssi-ipg-clk";
+		};
+
+		ssi3_clk: ssi@2 {
+			compatible = "fsl,mxc-clock";
+			reg = <2>;
+			clock-outputs = "imx-ssi.2";
+			src-clock = <&pll3_sw_clk>, "pll-clk";
+			dep-clock = <&ssi3_ipg_clk>, "ssi-ipg-clk";
+		};
+
+		cspi_ipg_clk: cspi_ipg {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "cspi_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&aips_tz2_clk>, "aips-clk";
+		};
+
+		cspi_clk: cspi {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "imx51-cspi.0";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&cspi_ipg_clk>, "cspi-ipg-clk";
+		};
+
+		ecspi1_ipg_clk: ecspi_ipg@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "ecspi1_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&spba_clk>, "spba-clk";
+		};
+
+		ecspi2_ipg_clk: ecspi_ipg@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "ecspi2_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+			dep-clock = <&aips_tz2_clk>, "aips-clk";
+		};
+
+		ecspi_main_clk: ecspi_main {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ecspi_main";
+			src-clock = <&pll3_sw_clk>, "pll-clk";
+		};
+
+		ecspi1_clk: ecspi@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "imx51-ecspi.0";
+			src-clock = <&ecspi_main_clk>, "ecspi-main-clk";
+			dep-clock = <&ecspi1_ipg_clk>, "ecspi-ipg-clk";
+		};
+
+		ecspi2_clk: ecspi@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "imx51-ecspi.1";
+			src-clock = <&ecspi_main_clk>, "ecspi-main-clk";
+			dep-clock = <&ecspi2_ipg_clk>, "ecspi-ipg-clk";
+		};
+
+		sdma_clk: sdma {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "imx-sdma";
+			src-clock = <&ahb_clk>, "ahb-clk";
+		};
+
+		esdhc1_ipg_clk: esdhc_ipg@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "esdhc1_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		esdhc2_ipg_clk: esdhc_ipg@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "esdhc2_ipg";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		esdhc1_clk: esdhc@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "sdhci-esdhc-imx.0";
+			src-clock = <&pll2_sw_clk>, "pll-clk";
+			dep-clock = <&esdhc1_ipg_clk>, "esdhc-ipg-clk";
+		};
+
+		esdhc2_clk: esdhc@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "sdhci-esdhc-imx.1";
+			src-clock = <&pll2_sw_clk>, "pll-clk";
+			dep-clock = <&esdhc2_ipg_clk>, "esdhc-ipg-clk";
+		};
+
+		mipi_esc_clk: mipi_esc {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "mipi_esc";
+			dep-clock = <&pll2_sw_clk>, "pll-clk";
+		};
+
+		mipi_hsc1_clk: mipi_hsc@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "mipi_hsc1";
+			src-clock = <&mipi_hsc2_clk>, "mipi-hsc-clk";
+			dep-clock = <&pll2_sw_clk>, "pll-clk";
+		};
+
+		mipi_hsc2_clk: mipi_hsc@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "mipi_hsc2";
+			src-clock = <&mipi_esc_clk>, "mipi-esc-clk";
+			dep-clock = <&pll2_sw_clk>, "pll-clk";
+		};
+
+		ipu_sec_clk: ipu_sec {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "ipu_sec";
+			src-clock = <&emi_fast_clk>, "emi-clk";
+			dep-clock = <&ahbmux1_clk>, "ahbmux-clk";
+		};
+
+		ipu_clk: ipu {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "imx-ipuv3";
+			src-clock = <&ahb_clk>, "ahb-clk";
+			dep-clock = <&ipu_sec_clk>, "ipu-sec-clk";
+		};
+
+		ipu_di0_clk: ipu_di@0 {
+			compatible = "fsl,mxc-clock";
+			reg = <0>;
+			clock-outputs = "imx-ipuv3-di0";
+			src-clock = <&pll3_sw_clk>, "pll-clk";
+		};
+
+		ipu_di1_clk: ipu_di@1 {
+			compatible = "fsl,mxc-clock";
+			reg = <1>;
+			clock-outputs = "imx-ipuv3-di1";
+			src-clock = <&pll3_sw_clk>, "pll-clk";
+		};
+
+		mipi_hsp_clk: mipi_hsp {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "mipi_hsp";
+			src-clock = <&ipu_clk>, "ipu-clk";
+			dep-clock = <&mipi_hsc1_clk>, "mipi-hsc-clk";
+		};
+
+		usboh3_clk: usboh3 {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "mxc-ehci";
+			src-clock = <&pll2_sw_clk>, "pll-clk";
+		};
+
+		usb_ahb_clk: usb_ahb {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "mxc-ehci-ahb";
+			src-clock = <&ipg_clk>, "ipg-clk";
+		};
+
+		usb_phy1_clk: usb_phy1 {
+			compatible = "fsl,mxc-clock";
+			clock-outputs = "usb_phy1";
+			src-clock = <&pll3_sw_clk>, "pll-clk";
+		};
+
+		dummy_clk: dummy {
+			compatible = "fsl,mxc-clock";
 		};
 	};
 
-	aips@73f00000 {
+	aips1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
@@ -79,7 +554,7 @@
 			reg = <0xbc000 0x1000>;
 			interrupts = <0x1f>;
 			fsl,has-rts-cts;
-			uart-clock = <&uart0_clk>, "uart";
+			uart-clock = <&uart1_clk>, "uart";
 		};
 
 		imx-uart@c0000 {
@@ -87,11 +562,11 @@
 			reg = <0xc0000 0x1000>;
 			interrupts = <0x20>;
 			fsl,has-rts-cts;
-			uart-clock = <&uart1_clk>, "uart";
+			uart-clock = <&uart2_clk>, "uart";
 		};
 	};
 
-	spba@70000000 {
+	spba {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
@@ -102,11 +577,11 @@
 			reg = <0xc000 0x1000>;
 			interrupts = <0x21>;
 			fsl,has-rts-cts;
-			uart-clock = <&uart2_clk>, "uart";
+			uart-clock = <&uart3_clk>, "uart";
 		};
 	};
 
-	aips@83f00000 {
+	aips2 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
-- 
1.7.1

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

* [PATCH v2 2/6] arm/mxc: add clk member 'rate' to ease dt fixed-clock support
       [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2011-03-18 18:24   ` [PATCH v2 1/6] arm/dts: babbage: add all available clock nodes Shawn Guo
@ 2011-03-18 18:24   ` Shawn Guo
  2011-03-18 18:24   ` [PATCH v2 3/6] dt: add new member 'clk' into device_node Shawn Guo
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Shawn Guo @ 2011-03-18 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

This new member is not necessary to support dt clock, but it can
simplified the code a lot in terms of those fixed rate clocks.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/plat-mxc/include/mach/clock.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 753a598..e688b49 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -38,6 +38,10 @@ struct clk {
 	/* Register address for clock's enable/disable control. */
 	void __iomem *enable_reg;
 	u32 flags;
+#ifdef CONFIG_OF
+	/* clock rate used by fixed-clock */
+	unsigned long rate;
+#endif
 	/* get the current clock rate (always a fresh value) */
 	unsigned long (*get_rate) (struct clk *);
 	/* Function ptr to set the clock to a new rate. The rate must match a
-- 
1.7.1

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

* [PATCH v2 3/6] dt: add new member 'clk' into device_node
       [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2011-03-18 18:24   ` [PATCH v2 1/6] arm/dts: babbage: add all available clock nodes Shawn Guo
  2011-03-18 18:24   ` [PATCH v2 2/6] arm/mxc: add clk member 'rate' to ease dt fixed-clock support Shawn Guo
@ 2011-03-18 18:24   ` Shawn Guo
       [not found]     ` <1300472672-13392-4-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2011-03-18 18:24   ` [PATCH v2 4/6] arm/dt: mx51: dynamically add clocks per dt nodes Shawn Guo
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Shawn Guo @ 2011-03-18 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

This pointer to 'struct clk' is added to save the reference to 'clk'
which is dynamically created per dt clock node, so that clkdev API
like clk_get can work with dt based device driver.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 include/linux/of.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/of.h b/include/linux/of.h
index d9dd664..e621295 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -54,6 +54,7 @@ struct device_node {
 	struct	device_node *allnext;	/* next in list of all nodes */
 	struct	proc_dir_entry *pde;	/* this node's proc directory */
 	struct	kref kref;
+	struct	clk *clk;
 	unsigned long _flags;
 	void	*data;
 #if defined(CONFIG_SPARC)
-- 
1.7.1

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

* [PATCH v2 4/6] arm/dt: mx51: dynamically add clocks per dt nodes
       [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
                     ` (2 preceding siblings ...)
  2011-03-18 18:24   ` [PATCH v2 3/6] dt: add new member 'clk' into device_node Shawn Guo
@ 2011-03-18 18:24   ` Shawn Guo
       [not found]     ` <1300472672-13392-5-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2011-03-18 18:24   ` [PATCH v2 5/6] arm/dt: mx5: change timer init function to dt clock way Shawn Guo
  2011-03-18 18:24   ` [PATCH v2 6/6] of/clock: eliminate function __of_clk_get_from_provider Shawn Guo
  5 siblings, 1 reply; 10+ messages in thread
From: Shawn Guo @ 2011-03-18 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

This patch is to change the static clock creating and registering to
the dynamic way, which scans dt clock nodes, associate clk with
device_node, and then add them to clkdev accordingly.

It's a pretty straight translation from non-dt clock code to dt one,
and it does not really change any actual clock implementation.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/mach-mx5/Makefile          |    2 +-
 arch/arm/mach-mx5/clock-dt.c        |   52 --
 arch/arm/mach-mx5/clock-mx51-mx53.c | 1433 ++++++++++++++++++++++++++++++++++-
 3 files changed, 1410 insertions(+), 77 deletions(-)
 delete mode 100644 arch/arm/mach-mx5/clock-dt.c

diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index bd4542d..540697e 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -18,4 +18,4 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
 obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
-obj-$(CONFIG_MACH_MX51_DT) += board-dt.o clock-dt.o
+obj-$(CONFIG_MACH_MX51_DT) += board-dt.o
diff --git a/arch/arm/mach-mx5/clock-dt.c b/arch/arm/mach-mx5/clock-dt.c
deleted file mode 100644
index 9c04475..0000000
--- a/arch/arm/mach-mx5/clock-dt.c
+++ /dev/null
@@ -1,52 +0,0 @@
-
-/*
- * Copyright 2011 Linaro Ltd.
- * Jason Liu <jason.hui-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_clk.h>
-
-static struct clk *mx5_dt_clk_get(struct device_node *np,
-					const char *output_id, void *data)
-{
-	return data;
-}
-
-static __init void mx5_dt_scan_clks(void)
-{
-	struct device_node *node;
-	struct clk *clk;
-	const char *id;
-	int rc;
-
-	for_each_compatible_node(node, NULL, "clock") {
-		id = of_get_property(node, "clock-outputs", NULL);
-		if (!id)
-			continue;
-
-		clk = clk_get_sys(id, NULL);
-		if (IS_ERR(clk))
-			continue;
-
-		rc = of_clk_add_provider(node, mx5_dt_clk_get, clk);
-		if (rc)
-			pr_err("error adding fixed clk %s\n", node->name);
-	}
-}
-
-void __init mx5_clk_dt_init(void)
-{
-	mx5_dt_scan_clks();
-}
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 0a19e75..f5fdded 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -15,6 +15,10 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_clk.h>
 
 #include <asm/div64.h>
 
@@ -43,6 +47,28 @@ static struct clk emi_fast_clk;
 static struct clk ipu_clk;
 static struct clk mipi_hsc1_clk;
 
+/*
+ * The pointers are defined to unify the references to clocks, as clocks
+ * could also be created by dt code in a dynamic way besides the static
+ * way used in existing non-dt clock code.
+ */
+static struct clk *osc_clk_ptr;
+static struct clk *pll1_main_clk_ptr;
+static struct clk *pll1_sw_clk_ptr;
+static struct clk *pll2_sw_clk_ptr;
+static struct clk *pll3_sw_clk_ptr;
+static struct clk *lp_apm_clk_ptr;
+static struct clk *periph_apm_clk_ptr;
+static struct clk *main_bus_clk_ptr;
+static struct clk *ipg_clk_ptr;
+static struct clk *ipg_per_clk_ptr;
+static struct clk *cpu_clk_ptr;
+static struct clk *iim_clk_ptr;
+static struct clk *usboh3_clk_ptr;
+static struct clk *usb_phy1_clk_ptr;
+static struct clk *esdhc1_clk_ptr;
+static struct clk *esdhc2_clk_ptr;
+
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
 /* calculate best pre and post dividers to get the required divider */
@@ -129,11 +155,11 @@ static inline u32 _get_mux(struct clk *parent, struct clk *m0,
 
 static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
 {
-	if (pll == &pll1_main_clk)
+	if (pll == pll1_main_clk_ptr)
 		return MX51_DPLL1_BASE;
-	else if (pll == &pll2_sw_clk)
+	else if (pll == pll2_sw_clk_ptr)
 		return MX51_DPLL2_BASE;
-	else if (pll == &pll3_sw_clk)
+	else if (pll == pll3_sw_clk_ptr)
 		return MX51_DPLL3_BASE;
 	else
 		BUG();
@@ -310,7 +336,7 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
 	 *
 	 * When switching back, do it in reverse order
 	 */
-	if (parent == &pll1_main_clk) {
+	if (parent == pll1_main_clk_ptr) {
 		/* Switch to pll1_main_clk */
 		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
 		__raw_writel(reg, MXC_CCM_CCSR);
@@ -320,11 +346,11 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
 		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
 				MXC_CCM_CCSR_STEP_SEL_OFFSET);
 	} else {
-		if (parent == &lp_apm_clk) {
+		if (parent == lp_apm_clk_ptr) {
 			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
-		} else  if (parent == &pll2_sw_clk) {
+		} else  if (parent == pll2_sw_clk_ptr) {
 			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
-		} else  if (parent == &pll3_sw_clk) {
+		} else  if (parent == pll3_sw_clk_ptr) {
 			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
 		} else
 			return -EINVAL;
@@ -350,10 +376,10 @@ static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
 
 	reg = __raw_readl(MXC_CCM_CCSR);
 
-	if (clk->parent == &pll2_sw_clk) {
+	if (clk->parent == pll2_sw_clk_ptr) {
 		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
 		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
-	} else if (clk->parent == &pll3_sw_clk) {
+	} else if (clk->parent == pll3_sw_clk_ptr) {
 		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
 		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
 	} else
@@ -367,7 +393,7 @@ static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
 
 	reg = __raw_readl(MXC_CCM_CCSR);
 
-	if (parent == &pll2_sw_clk)
+	if (parent == pll2_sw_clk_ptr)
 		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
 	else
 		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
@@ -380,7 +406,7 @@ static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
 {
 	u32 reg;
 
-	if (parent == &osc_clk)
+	if (parent == osc_clk_ptr)
 		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
 	else
 		return -EINVAL;
@@ -423,7 +449,8 @@ static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
 	u32 reg, mux;
 	int i = 0;
 
-	mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+	mux = _get_mux(parent, pll1_sw_clk_ptr, pll3_sw_clk_ptr,
+			lp_apm_clk_ptr, NULL);
 
 	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
 	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
@@ -452,9 +479,9 @@ static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
 
 	reg = __raw_readl(MXC_CCM_CBCDR);
 
-	if (parent == &pll2_sw_clk)
+	if (parent == pll2_sw_clk_ptr)
 		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else if (parent == &periph_apm_clk)
+	else if (parent == periph_apm_clk_ptr)
 		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
 	else
 		return -EINVAL;
@@ -587,7 +614,7 @@ static unsigned long clk_ipg_per_get_rate(struct clk *clk)
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+	if (clk->parent == main_bus_clk_ptr || clk->parent == lp_apm_clk_ptr) {
 		/* the main_bus_clk is the one before the DVFS engine */
 		reg = __raw_readl(MXC_CCM_CBCDR);
 		prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
@@ -597,7 +624,7 @@ static unsigned long clk_ipg_per_get_rate(struct clk *clk)
 		podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
 			MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
 		return parent_rate / (prediv1 * prediv2 * podf);
-	} else if (clk->parent == &ipg_clk)
+	} else if (clk->parent == ipg_clk_ptr)
 		return parent_rate;
 	else
 		BUG();
@@ -612,11 +639,11 @@ static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
 	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
 	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
 
-	if (parent == &ipg_clk)
+	if (parent == ipg_clk_ptr)
 		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-	else if (parent == &lp_apm_clk)
+	else if (parent == lp_apm_clk_ptr)
 		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	else if (parent != &main_bus_clk)
+	else if (parent != main_bus_clk_ptr)
 		return -EINVAL;
 
 	__raw_writel(reg, MXC_CCM_CBCMR);
@@ -830,7 +857,7 @@ static struct clk ipg_clk = {
 	.get_rate = clk_ipg_get_rate,
 };
 
-static struct clk ipg_perclk = {
+static struct clk ipg_per_clk = {
 	.parent = &lp_apm_clk,
 	.get_rate = clk_ipg_per_get_rate,
 	.set_parent = _clk_ipg_per_set_parent,
@@ -1036,8 +1063,9 @@ static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
 {									\
 	u32 reg, mux;							\
 									\
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
-			&pll3_sw_clk, &lp_apm_clk);			\
+	mux = _get_mux(parent, pll1_sw_clk_ptr, pll2_sw_clk_ptr,	\
+			pll3_sw_clk_ptr, lp_apm_clk_ptr);		\
+									\
 	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
 		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
 	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
@@ -1115,7 +1143,7 @@ static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
 
 	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
 
-	if (parent == &pll3_sw_clk)
+	if (parent == pll3_sw_clk_ptr)
 		reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
 
 	__raw_writel(reg, MXC_CCM_CSCMR1);
@@ -1346,7 +1374,7 @@ static void clk_tree_init(void)
 {
 	u32 reg;
 
-	ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+	clk_set_parent(ipg_per_clk_ptr, lp_apm_clk_ptr);
 
 	/*
 	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
@@ -1367,6 +1395,27 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 {
 	int i;
 
+	/*
+	 * Save the clock pointers that could be referenced by
+	 * both non-dt and dt clock codes later in this file.
+	 */
+	osc_clk_ptr		= &osc_clk;
+	pll1_main_clk_ptr	= &pll1_main_clk;
+	pll1_sw_clk_ptr		= &pll1_sw_clk;
+	pll2_sw_clk_ptr		= &pll2_sw_clk;
+	pll3_sw_clk_ptr		= &pll3_sw_clk;
+	lp_apm_clk_ptr		= &lp_apm_clk;
+	periph_apm_clk_ptr	= &periph_apm_clk;
+	main_bus_clk_ptr	= &main_bus_clk;
+	ipg_clk_ptr		= &ipg_clk;
+	ipg_per_clk_ptr		= &ipg_per_clk;
+	cpu_clk_ptr		= &cpu_clk;
+	iim_clk_ptr		= &iim_clk;
+	usboh3_clk_ptr		= &usboh3_clk;
+	usb_phy1_clk_ptr	= &usb_phy1_clk;
+	esdhc1_clk_ptr		= &esdhc1_clk;
+	esdhc2_clk_ptr		= &esdhc2_clk;
+
 	external_low_reference = ckil;
 	external_high_reference = ckih1;
 	ckih2_reference = ckih2;
@@ -1432,3 +1481,1339 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 		MX53_INT_GPT);
 	return 0;
 }
+
+/*
+ * Dynamically create and register clks per dt nodes
+ */
+#ifdef CONFIG_OF
+static unsigned long get_fixed_clk_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static __init int mx5_scan_fixed_clks(void)
+{
+	struct device_node *node;
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *rate;
+	const char *dev_id;
+	int ret = 0;
+
+	for_each_compatible_node(node, NULL, "fixed-clock") {
+		cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+		if (!cl) {
+			ret = -ENOMEM;
+			break;
+		}
+		clk = (struct clk *) (cl + 1);
+
+		dev_id = of_get_property(node, "clock-outputs", NULL);
+		if (!dev_id) {
+			kfree(cl);
+			continue;
+		}
+
+		rate = of_get_property(node, "clock-frequency", NULL);
+		if (!rate) {
+			kfree(cl);
+			continue;
+		}
+		clk->rate = be32_to_cpu(*rate);
+		clk->get_rate = get_fixed_clk_rate;
+
+		if (!strcmp(node->name, "osc"))
+			osc_clk_ptr = clk;
+
+		node->clk = clk;
+
+		cl->dev_id = dev_id;
+		cl->clk = clk;
+		clkdev_add(cl);
+	}
+
+	return ret;
+}
+
+static struct clk *mx5_prop_name_to_clk(struct device_node *node,
+		const char *prop_name)
+{
+	struct device_node *provnode;
+	struct clk *clk;
+	const void *prop;
+	u32 provhandle;
+	int sz;
+
+	prop = of_get_property(node, prop_name, &sz);
+	if (!prop || sz < 4)
+		goto out;
+
+	/* Extract the phandle from the start of the property value */
+	provhandle = be32_to_cpup(prop);
+	prop += 4;
+	sz -= 4;
+
+	/*
+	 * Make sure the clock name is properly terminated and within the
+	 * size of the property.
+	 */
+	if (strlen(prop) + 1 > sz)
+		goto out;
+
+	provnode = of_find_node_by_phandle(provhandle);
+	if (!provnode)
+		goto out;
+
+	clk = provnode->clk;
+
+	of_node_put(provnode);
+
+	return clk;
+
+out:
+	pr_err("%s: failed to get %s of %s\n", __func__, prop_name, node->name);
+	return NULL;
+}
+
+static inline struct clk *mx5_get_source_clk(struct device_node *node)
+{
+	return mx5_prop_name_to_clk(node, "src-clock");
+}
+
+static inline struct clk *mx5_get_depend_clk(struct device_node *node)
+{
+	return mx5_prop_name_to_clk(node, "dep-clock");
+}
+
+static __init struct clk_lookup *mx5_pre_clk_lookup(struct device_node * node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+	if (cl) {
+		clk = (struct clk *) (cl + 1);
+		clk->parent = mx5_get_source_clk(node);
+		clk->secondary = mx5_get_source_clk(node);
+	}
+
+	return cl;
+}
+
+static __init int mx5_post_clk_lookup(struct clk_lookup *cl,
+				      struct device_node *node)
+{
+	struct clk *clk;
+	const char *dev_id;
+
+	dev_id = of_get_property(node, "clock-outputs", NULL);
+	if (!dev_id) {
+		kfree(cl);
+		return -EINVAL;
+	}
+
+	clk = (struct clk *) (cl + 1);
+	node->clk = clk;
+
+	cl->dev_id = dev_id;
+	cl->clk = clk;
+	clkdev_add(cl);
+
+	return 0;
+}
+
+static __init int mx5_add_dummy_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	node->clk = clk;
+
+	cl->clk = clk;
+	clkdev_add(cl);
+
+	return 0;
+}
+
+static __init int mx5_add_usb_phy1_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+	clk->set_parent = clk_usb_phy1_set_parent;
+
+	usb_phy1_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_usb_ahb_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_usboh3_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_usboh3_get_rate;
+	clk->set_parent = clk_usboh3_set_parent;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+
+	usboh3_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_hsp_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_hsc_enable;
+	clk->disable = _clk_hsc_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_di_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR6;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG5_OFFSET :
+					MXC_CCM_CCGRx_CG6_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = clk_ipu_enable;
+	clk->disable = clk_ipu_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_sec_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_hsc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG3_OFFSET :
+					MXC_CCM_CCGRx_CG4_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_esc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_esdhc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	if (id == 0) {
+		clk->enable_shift = MXC_CCM_CCGRx_CG1_OFFSET;
+		clk->get_rate = clk_esdhc1_get_rate;
+		clk->set_rate = clk_esdhc1_set_rate;
+		clk->set_parent = clk_esdhc1_set_parent;
+		esdhc1_clk_ptr = clk;
+	} else {
+		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
+		clk->get_rate = clk_esdhc2_get_rate;
+		clk->set_rate = clk_esdhc2_set_rate;
+		clk->set_parent = clk_esdhc2_set_parent;
+		esdhc2_clk_ptr = clk;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_esdhc_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG0_OFFSET :
+					MXC_CCM_CCGRx_CG2_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_sdma_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG10_OFFSET :
+					MXC_CCM_CCGRx_CG12_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable_inrun;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG9_OFFSET :
+					MXC_CCM_CCGRx_CG11_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_main_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ecspi_get_rate;
+	clk->set_parent = clk_ecspi_set_parent;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cspi_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cspi_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ssi_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ssi_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_nfc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+	clk->get_rate = clk_nfc_get_rate;
+	clk->set_rate = clk_nfc_set_rate;
+	clk->round_rate = clk_nfc_round_rate;
+	clk->set_parent = clk_nfc_set_parent;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_i2c_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pwm_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG6_OFFSET :
+					MXC_CCM_CCGRx_CG8_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_fec_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG4_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_root_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_uart_get_rate;
+	clk->set_parent = clk_uart_set_parent;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_32k_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahbmux1_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_aips_tz_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG12_OFFSET :
+					MXC_CCM_CCGRx_CG13_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahb_max_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_iim_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+	iim_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_spba_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ipg_get_rate;
+
+	ipg_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahb_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ahb_get_rate;
+	clk->set_rate = _clk_ahb_set_rate;
+	clk->round_rate = _clk_ahb_round_rate;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_emi_slow_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+	clk->get_rate = clk_emi_slow_get_rate;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_main_bus_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->set_parent = _clk_main_bus_set_parent;
+
+	main_bus_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_emi_fast_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ddr_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ddr_hf_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = _clk_ddr_hf_get_rate;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cpu_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_cpu_get_rate;
+	clk->set_rate = clk_cpu_set_rate;
+
+	cpu_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipg_per_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ipg_per_get_rate;
+	clk->set_parent = _clk_ipg_per_set_parent;
+
+	ipg_per_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_periph_apm_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->set_parent = _clk_periph_apm_set_parent;
+
+	periph_apm_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_lp_apm_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->set_parent = _clk_lp_apm_set_parent;
+
+	lp_apm_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pll_switch_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+
+	switch (id) {
+	case 0:
+		clk->get_rate = clk_pll1_sw_get_rate;
+		clk->set_parent = _clk_pll1_sw_set_parent;
+		pll1_sw_clk_ptr = clk;
+		break;
+	case 1:
+		clk->get_rate = clk_pll_get_rate;
+		clk->set_rate = _clk_pll_set_rate;
+		clk->enable = _clk_pll_enable;
+		clk->disable = _clk_pll_disable;
+		clk->set_parent = _clk_pll2_sw_set_parent;
+		pll2_sw_clk_ptr = clk;
+		break;
+	case 2:
+		clk->get_rate = clk_pll_get_rate;
+		clk->set_rate = _clk_pll_set_rate;
+		clk->enable = _clk_pll_enable;
+		clk->disable = _clk_pll_disable;
+		pll3_sw_clk_ptr = clk;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pll1_main_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_pll_get_rate;
+	clk->enable = _clk_pll_enable;
+	clk->disable = _clk_pll_disable;
+
+	pll1_main_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+#define MX5_CLK_COMP	"fsl,mxc-clock"
+
+static const struct of_device_id mx5_dt_mxc_clock_ids[] = {
+	{ .name = "pll1_main",	.compatible = MX5_CLK_COMP, .data = mx5_add_pll1_main_clk },
+	{ .name = "pll_switch", .compatible = MX5_CLK_COMP, .data = mx5_add_pll_switch_clk },
+	{ .name = "lp_apm",	.compatible = MX5_CLK_COMP, .data = mx5_add_lp_apm_clk },
+	{ .name = "periph_apm", .compatible = MX5_CLK_COMP, .data = mx5_add_periph_apm_clk },
+	{ .name = "ipg_per",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipg_per_clk },
+	{ .name = "cpu",	.compatible = MX5_CLK_COMP, .data = mx5_add_cpu_clk },
+	{ .name = "ddr_hf",	.compatible = MX5_CLK_COMP, .data = mx5_add_ddr_hf_clk },
+	{ .name = "ddr",	.compatible = MX5_CLK_COMP, .data = mx5_add_ddr_clk },
+	{ .name = "emi_fast",	.compatible = MX5_CLK_COMP, .data = mx5_add_emi_fast_clk },
+	{ .name = "main_bus",	.compatible = MX5_CLK_COMP, .data = mx5_add_main_bus_clk },
+	{ .name = "emi_slow",	.compatible = MX5_CLK_COMP, .data = mx5_add_emi_slow_clk },
+	{ .name = "ahb",	.compatible = MX5_CLK_COMP, .data = mx5_add_ahb_clk },
+	{ .name = "ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipg_clk },
+	{ .name = "spba",	.compatible = MX5_CLK_COMP, .data = mx5_add_spba_clk },
+	{ .name = "iim",	.compatible = MX5_CLK_COMP, .data = mx5_add_iim_clk },
+	{ .name = "ahb_max",	.compatible = MX5_CLK_COMP, .data = mx5_add_ahb_max_clk },
+	{ .name = "aips_tz",	.compatible = MX5_CLK_COMP, .data = mx5_add_aips_tz_clk },
+	{ .name = "ahbmux1",	.compatible = MX5_CLK_COMP, .data = mx5_add_ahbmux1_clk },
+	{ .name = "gpt_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_gpt_ipg_clk },
+	{ .name = "gpt",	.compatible = MX5_CLK_COMP, .data = mx5_add_gpt_clk },
+	{ .name = "gpt_32k",	.compatible = MX5_CLK_COMP, .data = mx5_add_gpt_32k_clk },
+	{ .name = "uart_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_uart_ipg_clk },
+	{ .name = "uart_root",	.compatible = MX5_CLK_COMP, .data = mx5_add_uart_root_clk },
+	{ .name = "uart",	.compatible = MX5_CLK_COMP, .data = mx5_add_uart_clk },
+	{ .name = "fec",	.compatible = MX5_CLK_COMP, .data = mx5_add_fec_clk },
+	{ .name = "pwm",	.compatible = MX5_CLK_COMP, .data = mx5_add_pwm_clk },
+	{ .name = "i2c",	.compatible = MX5_CLK_COMP, .data = mx5_add_i2c_clk },
+	{ .name = "nfc",	.compatible = MX5_CLK_COMP, .data = mx5_add_nfc_clk },
+	{ .name = "ssi_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_ssi_ipg_clk },
+	{ .name = "ssi",	.compatible = MX5_CLK_COMP, .data = mx5_add_ssi_clk },
+	{ .name = "cspi_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_cspi_ipg_clk },
+	{ .name = "cspi",	.compatible = MX5_CLK_COMP, .data = mx5_add_cspi_clk },
+	{ .name = "ecspi_main",	.compatible = MX5_CLK_COMP, .data = mx5_add_ecspi_main_clk },
+	{ .name = "ecspi_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_ecspi_ipg_clk },
+	{ .name = "ecspi",	.compatible = MX5_CLK_COMP, .data = mx5_add_ecspi_clk },
+	{ .name = "sdma",	.compatible = MX5_CLK_COMP, .data = mx5_add_sdma_clk },
+	{ .name = "esdhc_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_esdhc_ipg_clk },
+	{ .name = "esdhc",	.compatible = MX5_CLK_COMP, .data = mx5_add_esdhc_clk },
+	{ .name = "mipi_esc",	.compatible = MX5_CLK_COMP, .data = mx5_add_mipi_esc_clk },
+	{ .name = "mipi_hsc",	.compatible = MX5_CLK_COMP, .data = mx5_add_mipi_hsc_clk },
+	{ .name = "ipu_sec",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipu_sec_clk },
+	{ .name = "ipu",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipu_clk },
+	{ .name = "ipu_di",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipu_di_clk },
+	{ .name = "mipi_hsp",	.compatible = MX5_CLK_COMP, .data = mx5_add_mipi_hsp_clk },
+	{ .name = "usboh3",	.compatible = MX5_CLK_COMP, .data = mx5_add_usboh3_clk },
+	{ .name = "usb_ahb",	.compatible = MX5_CLK_COMP, .data = mx5_add_usb_ahb_clk },
+	{ .name = "usb_phy1",	.compatible = MX5_CLK_COMP, .data = mx5_add_usb_phy1_clk },
+	{ .name = "dummy",	.compatible = MX5_CLK_COMP, .data = mx5_add_dummy_clk },
+	{ /* sentinel */ }
+};
+
+static __init int mx5_dt_scan_clks(void)
+{
+	struct device_node *np;
+	const struct of_device_id *dt_clk_id;
+	int (*mx5_add_clk)(struct device_node *);
+	int ret;
+
+	ret = mx5_scan_fixed_clks();
+	if (ret) {
+		pr_err("%s: fixed-clock failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	for_each_matching_node(np, mx5_dt_mxc_clock_ids) {
+		dt_clk_id = of_match_node(mx5_dt_mxc_clock_ids, np);
+		mx5_add_clk = dt_clk_id->data;
+		ret = mx5_add_clk(np);
+		if (ret) {
+			pr_err("%s: clock %s failed %d\n",
+				__func__, np->name, ret);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+void __init mx5_clk_dt_init(void)
+{
+	mx5_dt_scan_clks();
+
+	clk_tree_init();
+
+	clk_enable(cpu_clk_ptr);
+	clk_enable(main_bus_clk_ptr);
+
+	clk_enable(iim_clk_ptr);
+	mx51_revision();
+	clk_disable(iim_clk_ptr);
+
+	/* move usb_phy_clk to 24MHz */
+	clk_set_parent(usb_phy1_clk_ptr, osc_clk_ptr);
+
+	/* set the usboh3_clk parent to pll2_sw_clk */
+	clk_set_parent(usboh3_clk_ptr, pll2_sw_clk_ptr);
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(esdhc1_clk_ptr, pll2_sw_clk_ptr);
+	clk_set_parent(esdhc2_clk_ptr, pll2_sw_clk_ptr);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(esdhc1_clk_ptr, 166250000);
+	clk_set_rate(esdhc2_clk_ptr, 166250000);
+}
+#endif
-- 
1.7.1

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

* [PATCH v2 5/6] arm/dt: mx5: change timer init function to dt clock way
       [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
                     ` (3 preceding siblings ...)
  2011-03-18 18:24   ` [PATCH v2 4/6] arm/dt: mx51: dynamically add clocks per dt nodes Shawn Guo
@ 2011-03-18 18:24   ` Shawn Guo
  2011-03-18 18:24   ` [PATCH v2 6/6] of/clock: eliminate function __of_clk_get_from_provider Shawn Guo
  5 siblings, 0 replies; 10+ messages in thread
From: Shawn Guo @ 2011-03-18 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

The big deal here is that it removes the call to mx51_clocks_init,
where all the possible clocks are added to clkdev in static way.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/mach-mx5/board-dt.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-mx5/board-dt.c b/arch/arm/mach-mx5/board-dt.c
index 62ca693..f620ded 100644
--- a/arch/arm/mach-mx5/board-dt.c
+++ b/arch/arm/mach-mx5/board-dt.c
@@ -16,6 +16,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
+#include <linux/clk.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -42,8 +43,14 @@ static void __init mx51_dt_board_init(void)
 
 static void __init mx51_dt_timer_init(void)
 {
-	mx51_clocks_init(32768, 24000000, 22579200, 0);
+	struct clk *clk;
+
 	mx5_clk_dt_init();
+
+	clk = clk_get_sys("gpt", NULL);
+	if (!IS_ERR(clk))
+		mxc_timer_init(clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+				MX51_MXC_INT_GPT);
 }
 
 static struct sys_timer mxc_timer = {
-- 
1.7.1

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

* [PATCH v2 6/6] of/clock: eliminate function __of_clk_get_from_provider
       [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
                     ` (4 preceding siblings ...)
  2011-03-18 18:24   ` [PATCH v2 5/6] arm/dt: mx5: change timer init function to dt clock way Shawn Guo
@ 2011-03-18 18:24   ` Shawn Guo
       [not found]     ` <1300472672-13392-7-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  5 siblings, 1 reply; 10+ messages in thread
From: Shawn Guo @ 2011-03-18 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

With the platform clock support, the 'struct clk' should have been
associated with device_node->data.  So the use of function
__of_clk_get_from_provider can be eliminated.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/of/clock.c |   23 ++---------------------
 1 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/drivers/of/clock.c b/drivers/of/clock.c
index 7b5ea67..1b34937 100644
--- a/drivers/of/clock.c
+++ b/drivers/of/clock.c
@@ -71,24 +71,6 @@ void of_clk_del_provider(struct device_node *np,
 	mutex_unlock(&of_clk_lock);
 }
 
-static struct clk *__of_clk_get_from_provider(struct device_node *np, const char *clk_output)
-{
-	struct of_clk_provider *provider;
-	struct clk *clk = NULL;
-
-	/* Check if we have such a provider in our array */
-	mutex_lock(&of_clk_lock);
-	list_for_each_entry(provider, &of_clk_providers, link) {
-		if (provider->node == np)
-			clk = provider->get(np, clk_output, provider->data);
-		if (clk)
-			break;
-	}
-	mutex_unlock(&of_clk_lock);
-
-	return clk;
-}
-
 struct clk *of_clk_get(struct device *dev, const char *id)
 {
 	struct device_node *provnode;
@@ -123,9 +105,8 @@ struct clk *of_clk_get(struct device *dev, const char *id)
 			__func__, prop_name, dev->of_node->full_name);
 		return NULL;
 	}
-	clk = __of_clk_get_from_provider(provnode, prop);
-	if (clk)
-		dev_dbg(dev, "Using clock from %s\n", provnode->full_name);
+
+	clk = provnode->clk;
 
 	of_node_put(provnode);
 
-- 
1.7.1

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

* Re: [PATCH v2 3/6] dt: add new member 'clk' into device_node
       [not found]     ` <1300472672-13392-4-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-03-31 19:59       ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-03-31 19:59 UTC (permalink / raw)
  To: Shawn Guo
  Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

On Sat, Mar 19, 2011 at 02:24:29AM +0800, Shawn Guo wrote:
> This pointer to 'struct clk' is added to save the reference to 'clk'
> which is dynamically created per dt clock node, so that clkdev API
> like clk_get can work with dt based device driver.
> 
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  include/linux/of.h |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/of.h b/include/linux/of.h
> index d9dd664..e621295 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -54,6 +54,7 @@ struct device_node {
>  	struct	device_node *allnext;	/* next in list of all nodes */
>  	struct	proc_dir_entry *pde;	/* this node's proc directory */
>  	struct	kref kref;
> +	struct	clk *clk;

The dt clock support code can already translate from dt node to a
clock provider, and each clock provider should provide a .get() hook
to return the correct struct clk.  of_clk_add_provider() inserts a
mapping into the of_clk_providers() list, and clk_get() calls
of_clk_get() which will process a devicenode->clk provider mapping.

Adding a struct clk pointer to the device node isn't sufficient since
a single clock provider node can provide multiple clock outputs.

g.

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

* Re: [PATCH v2 4/6] arm/dt: mx51: dynamically add clocks per dt nodes
       [not found]     ` <1300472672-13392-5-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-03-31 20:40       ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-03-31 20:40 UTC (permalink / raw)
  To: Shawn Guo
  Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

On Sat, Mar 19, 2011 at 02:24:30AM +0800, Shawn Guo wrote:
> This patch is to change the static clock creating and registering to
> the dynamic way, which scans dt clock nodes, associate clk with
> device_node, and then add them to clkdev accordingly.
> 
> It's a pretty straight translation from non-dt clock code to dt one,
> and it does not really change any actual clock implementation.
> 
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hey Shawn,

As you and I discussed earlier, I'm backing off from the encoding all
clock information in the device tree for the time being so that dt and
non-dt use cases will continue to share the same clock setup code.
Clock bindings are still important to get right, particularly for
off-chip connections, but they aren't as critical for getting basic
device tree support up and running.

Regardless, here are my comments on this patch which we can revisit
again later.

> ---
>  arch/arm/mach-mx5/Makefile          |    2 +-
>  arch/arm/mach-mx5/clock-dt.c        |   52 --
>  arch/arm/mach-mx5/clock-mx51-mx53.c | 1433 ++++++++++++++++++++++++++++++++++-
>  3 files changed, 1410 insertions(+), 77 deletions(-)
>  delete mode 100644 arch/arm/mach-mx5/clock-dt.c
> 
> diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
> index bd4542d..540697e 100644
> --- a/arch/arm/mach-mx5/Makefile
> +++ b/arch/arm/mach-mx5/Makefile
> @@ -18,4 +18,4 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
>  obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
>  obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
>  obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
> -obj-$(CONFIG_MACH_MX51_DT) += board-dt.o clock-dt.o
> +obj-$(CONFIG_MACH_MX51_DT) += board-dt.o
> diff --git a/arch/arm/mach-mx5/clock-dt.c b/arch/arm/mach-mx5/clock-dt.c
> deleted file mode 100644
> index 9c04475..0000000
> --- a/arch/arm/mach-mx5/clock-dt.c
> +++ /dev/null
> @@ -1,52 +0,0 @@
> -
> -/*
> - * Copyright 2011 Linaro Ltd.
> - * Jason Liu <jason.hui-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> - *
> - * The code contained herein is licensed under the GNU General Public
> - * License. You may obtain a copy of the GNU General Public License
> - * Version 2 or later at the following locations:
> - *
> - * http://www.opensource.org/licenses/gpl-license.html
> - * http://www.gnu.org/copyleft/gpl.html
> - */
> -
> -#include <linux/err.h>
> -#include <linux/init.h>
> -#include <linux/clk.h>
> -#include <linux/of.h>
> -#include <linux/of_address.h>
> -#include <linux/of_clk.h>
> -
> -static struct clk *mx5_dt_clk_get(struct device_node *np,
> -					const char *output_id, void *data)
> -{
> -	return data;
> -}
> -
> -static __init void mx5_dt_scan_clks(void)
> -{
> -	struct device_node *node;
> -	struct clk *clk;
> -	const char *id;
> -	int rc;
> -
> -	for_each_compatible_node(node, NULL, "clock") {
> -		id = of_get_property(node, "clock-outputs", NULL);
> -		if (!id)
> -			continue;
> -
> -		clk = clk_get_sys(id, NULL);
> -		if (IS_ERR(clk))
> -			continue;
> -
> -		rc = of_clk_add_provider(node, mx5_dt_clk_get, clk);
> -		if (rc)
> -			pr_err("error adding fixed clk %s\n", node->name);
> -	}
> -}
> -
> -void __init mx5_clk_dt_init(void)
> -{
> -	mx5_dt_scan_clks();
> -}
> diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
> index 0a19e75..f5fdded 100644
> --- a/arch/arm/mach-mx5/clock-mx51-mx53.c
> +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
> @@ -15,6 +15,10 @@
>  #include <linux/clk.h>
>  #include <linux/io.h>
>  #include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_clk.h>
>  
>  #include <asm/div64.h>
>  
> @@ -43,6 +47,28 @@ static struct clk emi_fast_clk;
>  static struct clk ipu_clk;
>  static struct clk mipi_hsc1_clk;
>  
> +/*
> + * The pointers are defined to unify the references to clocks, as clocks
> + * could also be created by dt code in a dynamic way besides the static
> + * way used in existing non-dt clock code.
> + */
> +static struct clk *osc_clk_ptr;
> +static struct clk *pll1_main_clk_ptr;
> +static struct clk *pll1_sw_clk_ptr;
> +static struct clk *pll2_sw_clk_ptr;
> +static struct clk *pll3_sw_clk_ptr;
> +static struct clk *lp_apm_clk_ptr;
> +static struct clk *periph_apm_clk_ptr;
> +static struct clk *main_bus_clk_ptr;
> +static struct clk *ipg_clk_ptr;
> +static struct clk *ipg_per_clk_ptr;
> +static struct clk *cpu_clk_ptr;
> +static struct clk *iim_clk_ptr;
> +static struct clk *usboh3_clk_ptr;
> +static struct clk *usb_phy1_clk_ptr;
> +static struct clk *esdhc1_clk_ptr;
> +static struct clk *esdhc2_clk_ptr;
> +

I think it's possible to match up device tree nodes with the existing
struct clks.  Its a big change in model from the direction I sent you
on when you worked on this patch, but it is probably the right thing
to di.  That would minimize the impact on the imx clock
definitions by eliminating the _clk --> &_clk_ptr conversions.  It
would also allow for the dt to sparsely define clock nodes.  ie.  only
define the nodes that external devices actually need to reference.

> +static __init int mx5_scan_fixed_clks(void)
> +{
> +	struct device_node *node;
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *rate;
> +	const char *dev_id;
> +	int ret = 0;
> +
> +	for_each_compatible_node(node, NULL, "fixed-clock") {
> +		cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
> +		if (!cl) {
> +			ret = -ENOMEM;
> +			break;
> +		}
> +		clk = (struct clk *) (cl + 1);
> +
> +		dev_id = of_get_property(node, "clock-outputs", NULL);
> +		if (!dev_id) {
> +			kfree(cl);
> +			continue;
> +		}
> +
> +		rate = of_get_property(node, "clock-frequency", NULL);
> +		if (!rate) {
> +			kfree(cl);
> +			continue;
> +		}
> +		clk->rate = be32_to_cpu(*rate);
> +		clk->get_rate = get_fixed_clk_rate;
> +
> +		if (!strcmp(node->name, "osc"))
> +			osc_clk_ptr = clk;
> +
> +		node->clk = clk;
> +
> +		cl->dev_id = dev_id;
> +		cl->clk = clk;
> +		clkdev_add(cl);

Should use of_clk_add_provider() here.

> +	}
> +
> +	return ret;
> +}
> +
> +static struct clk *mx5_prop_name_to_clk(struct device_node *node,
> +		const char *prop_name)
> +{
> +	struct device_node *provnode;
> +	struct clk *clk;
> +	const void *prop;
> +	u32 provhandle;
> +	int sz;
> +
> +	prop = of_get_property(node, prop_name, &sz);
> +	if (!prop || sz < 4)
> +		goto out;
> +
> +	/* Extract the phandle from the start of the property value */
> +	provhandle = be32_to_cpup(prop);
> +	prop += 4;
> +	sz -= 4;
> +
> +	/*
> +	 * Make sure the clock name is properly terminated and within the
> +	 * size of the property.
> +	 */
> +	if (strlen(prop) + 1 > sz)
> +		goto out;
> +
> +	provnode = of_find_node_by_phandle(provhandle);
> +	if (!provnode)
> +		goto out;
> +
> +	clk = provnode->clk;
> +
> +	of_node_put(provnode);
> +
> +	return clk;
> +
> +out:
> +	pr_err("%s: failed to get %s of %s\n", __func__, prop_name, node->name);
> +	return NULL;
> +}
> +
> +static inline struct clk *mx5_get_source_clk(struct device_node *node)
> +{
> +	return mx5_prop_name_to_clk(node, "src-clock");
> +}
> +
> +static inline struct clk *mx5_get_depend_clk(struct device_node *node)
> +{
> +	return mx5_prop_name_to_clk(node, "dep-clock");
> +}
> +
> +static __init struct clk_lookup *mx5_pre_clk_lookup(struct device_node * node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
> +	if (cl) {
> +		clk = (struct clk *) (cl + 1);

I've been spanked for this construct before because you can't
guarantee that gcc won't put any padding at the end of the first
structure.  Better to define holding structure and get the two
pointers from it instead:

struct clk_lookup_priv {
	struct clk_lookup cl;
	struct clk clk;
} *clp;

clp = kzalloc(sizeof(*clp), GFP_KERNEL);
cl = &clp->cl;
clk = &clp->clk;

> +		clk->parent = mx5_get_source_clk(node);
> +		clk->secondary = mx5_get_source_clk(node);
> +	}
> +
> +	return cl;
> +}
> +
> +static __init int mx5_post_clk_lookup(struct clk_lookup *cl,
> +				      struct device_node *node)
> +{
> +	struct clk *clk;
> +	const char *dev_id;
> +
> +	dev_id = of_get_property(node, "clock-outputs", NULL);
> +	if (!dev_id) {
> +		kfree(cl);
> +		return -EINVAL;
> +	}
> +
> +	clk = (struct clk *) (cl + 1);

Ewwh!  Definitely use a private structure and the container_of() macro
to resolve it from struct clk.

> +	node->clk = clk;
> +
> +	cl->dev_id = dev_id;
> +	cl->clk = clk;
> +	clkdev_add(cl);

Ditto here, use of_clk_add_provider()

> +
> +	return 0;
> +}
> +
> +static __init int mx5_add_dummy_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	node->clk = clk;
> +
> +	cl->clk = clk;
> +	clkdev_add(cl);
> +
> +	return 0;
> +}
> +
> +static __init int mx5_add_usb_phy1_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR2;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
> +	clk->set_parent = clk_usb_phy1_set_parent;
> +
> +	usb_phy1_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_usb_ahb_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR2;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_usboh3_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_usboh3_get_rate;
> +	clk->set_parent = clk_usboh3_set_parent;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR2;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
> +
> +	usboh3_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_mipi_hsp_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_hsc_enable;
> +	clk->disable = _clk_hsc_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ipu_di_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR6;
> +	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG5_OFFSET :
> +					MXC_CCM_CCGRx_CG6_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ipu_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = clk_ipu_enable;
> +	clk->disable = clk_ipu_disable;
> +	clk->enable_reg = MXC_CCM_CCGR5;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ipu_sec_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_mipi_hsc_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG3_OFFSET :
> +					MXC_CCM_CCGRx_CG4_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_mipi_esc_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_esdhc_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_max_enable;
> +	clk->disable = _clk_max_disable;
> +	clk->enable_reg = MXC_CCM_CCGR3;
> +
> +	if (id == 0) {
> +		clk->enable_shift = MXC_CCM_CCGRx_CG1_OFFSET;
> +		clk->get_rate = clk_esdhc1_get_rate;
> +		clk->set_rate = clk_esdhc1_set_rate;
> +		clk->set_parent = clk_esdhc1_set_parent;
> +		esdhc1_clk_ptr = clk;
> +	} else {
> +		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
> +		clk->get_rate = clk_esdhc2_get_rate;
> +		clk->set_rate = clk_esdhc2_set_rate;
> +		clk->set_parent = clk_esdhc2_set_parent;
> +		esdhc2_clk_ptr = clk;
> +	}
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_esdhc_ipg_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_max_enable;
> +	clk->disable = _clk_max_disable;
> +	clk->enable_reg = MXC_CCM_CCGR3;
> +	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG0_OFFSET :
> +					MXC_CCM_CCGRx_CG2_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_sdma_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ecspi_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG10_OFFSET :
> +					MXC_CCM_CCGRx_CG12_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ecspi_ipg_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable_inrun;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG9_OFFSET :
> +					MXC_CCM_CCGRx_CG11_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ecspi_main_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_ecspi_get_rate;
> +	clk->set_parent = clk_ecspi_set_parent;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_cspi_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_cspi_ipg_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR4;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ssi_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 2)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR3;
> +
> +	switch (id) {
> +	case 0:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
> +		break;
> +	case 1:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
> +		break;
> +	case 2:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
> +	}
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ssi_ipg_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 2)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR3;
> +
> +	switch (id) {
> +	case 0:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
> +		break;
> +	case 1:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
> +		break;
> +	case 2:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
> +	}
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_nfc_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR5;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
> +	clk->get_rate = clk_nfc_get_rate;
> +	clk->set_rate = clk_nfc_set_rate;
> +	clk->round_rate = clk_nfc_round_rate;
> +	clk->set_parent = clk_nfc_set_parent;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_i2c_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 2)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR1;
> +
> +	switch (id) {
> +	case 0:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
> +		break;
> +	case 1:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
> +		break;
> +	case 2:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
> +	}
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_pwm_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR2;
> +	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG6_OFFSET :
> +					MXC_CCM_CCGRx_CG8_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_fec_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR2;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_uart_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 2)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR1;
> +
> +	switch (id) {
> +	case 0:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG4_OFFSET;
> +		break;
> +	case 1:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
> +		break;
> +	case 2:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
> +	}
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_uart_root_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_uart_get_rate;
> +	clk->set_parent = clk_uart_set_parent;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_uart_ipg_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 2)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR1;
> +
> +	switch (id) {
> +	case 0:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
> +		break;
> +	case 1:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
> +		break;
> +	case 2:
> +		clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
> +	}
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_gpt_32k_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_gpt_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR2;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_gpt_ipg_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR2;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ahbmux1_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable_inwait;
> +	clk->enable_reg = MXC_CCM_CCGR0;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_aips_tz_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 1)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable_inwait;
> +	clk->enable_reg = MXC_CCM_CCGR0;
> +	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG12_OFFSET :
> +					MXC_CCM_CCGRx_CG13_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ahb_max_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_max_enable;
> +	clk->disable = _clk_max_disable;
> +	clk->enable_reg = MXC_CCM_CCGR0;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_iim_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable_reg = MXC_CCM_CCGR0;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
> +
> +	iim_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_spba_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable;
> +	clk->enable_reg = MXC_CCM_CCGR5;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ipg_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_ipg_get_rate;
> +
> +	ipg_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ahb_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_ahb_get_rate;
> +	clk->set_rate = _clk_ahb_set_rate;
> +	clk->round_rate = _clk_ahb_round_rate;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_emi_slow_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable_inwait;
> +	clk->enable_reg = MXC_CCM_CCGR5;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
> +	clk->get_rate = clk_emi_slow_get_rate;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_main_bus_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->set_parent = _clk_main_bus_set_parent;
> +
> +	main_bus_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_emi_fast_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->enable = _clk_ccgr_enable;
> +	clk->disable = _clk_ccgr_disable_inwait;
> +	clk->enable_reg = MXC_CCM_CCGR5;
> +	clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ddr_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ddr_hf_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = _clk_ddr_hf_get_rate;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_cpu_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_cpu_get_rate;
> +	clk->set_rate = clk_cpu_set_rate;
> +
> +	cpu_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_ipg_per_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_ipg_per_get_rate;
> +	clk->set_parent = _clk_ipg_per_set_parent;
> +
> +	ipg_per_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_periph_apm_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->set_parent = _clk_periph_apm_set_parent;
> +
> +	periph_apm_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_lp_apm_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->set_parent = _clk_lp_apm_set_parent;
> +
> +	lp_apm_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_pll_switch_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +	const __be32 *reg;
> +	int id;
> +
> +	reg = of_get_property(node, "reg", NULL);
> +	if (!reg)
> +		return -ENOENT;
> +
> +	id = be32_to_cpu(*reg);
> +	if (id < 0 || id > 2)
> +		return -EINVAL;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->id = id;
> +
> +	switch (id) {
> +	case 0:
> +		clk->get_rate = clk_pll1_sw_get_rate;
> +		clk->set_parent = _clk_pll1_sw_set_parent;
> +		pll1_sw_clk_ptr = clk;
> +		break;
> +	case 1:
> +		clk->get_rate = clk_pll_get_rate;
> +		clk->set_rate = _clk_pll_set_rate;
> +		clk->enable = _clk_pll_enable;
> +		clk->disable = _clk_pll_disable;
> +		clk->set_parent = _clk_pll2_sw_set_parent;
> +		pll2_sw_clk_ptr = clk;
> +		break;
> +	case 2:
> +		clk->get_rate = clk_pll_get_rate;
> +		clk->set_rate = _clk_pll_set_rate;
> +		clk->enable = _clk_pll_enable;
> +		clk->disable = _clk_pll_disable;
> +		pll3_sw_clk_ptr = clk;
> +	}
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}
> +
> +static __init int mx5_add_pll1_main_clk(struct device_node *node)
> +{
> +	struct clk_lookup *cl;
> +	struct clk *clk;
> +
> +	cl = mx5_pre_clk_lookup(node);
> +	if (!cl)
> +		return -ENOMEM;
> +	clk = (struct clk *) (cl + 1);
> +
> +	clk->get_rate = clk_pll_get_rate;
> +	clk->enable = _clk_pll_enable;
> +	clk->disable = _clk_pll_disable;
> +
> +	pll1_main_clk_ptr = clk;
> +
> +	return mx5_post_clk_lookup(cl, node);
> +}


Hmmm, this ends up being a lot of functions that largely do the same
thing.  /me wonders if it could be more data driven.

g.

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

* Re: [PATCH v2 6/6] of/clock: eliminate function __of_clk_get_from_provider
       [not found]     ` <1300472672-13392-7-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-03-31 20:41       ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-03-31 20:41 UTC (permalink / raw)
  To: Shawn Guo
  Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A

On Sat, Mar 19, 2011 at 02:24:32AM +0800, Shawn Guo wrote:
> With the platform clock support, the 'struct clk' should have been
> associated with device_node->data.  So the use of function
> __of_clk_get_from_provider can be eliminated.
> 
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Not really true since a device node describes a clock provider which
may be able to provide more than one clock output.

g.

> ---
>  drivers/of/clock.c |   23 ++---------------------
>  1 files changed, 2 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/of/clock.c b/drivers/of/clock.c
> index 7b5ea67..1b34937 100644
> --- a/drivers/of/clock.c
> +++ b/drivers/of/clock.c
> @@ -71,24 +71,6 @@ void of_clk_del_provider(struct device_node *np,
>  	mutex_unlock(&of_clk_lock);
>  }
>  
> -static struct clk *__of_clk_get_from_provider(struct device_node *np, const char *clk_output)
> -{
> -	struct of_clk_provider *provider;
> -	struct clk *clk = NULL;
> -
> -	/* Check if we have such a provider in our array */
> -	mutex_lock(&of_clk_lock);
> -	list_for_each_entry(provider, &of_clk_providers, link) {
> -		if (provider->node == np)
> -			clk = provider->get(np, clk_output, provider->data);
> -		if (clk)
> -			break;
> -	}
> -	mutex_unlock(&of_clk_lock);
> -
> -	return clk;
> -}
> -
>  struct clk *of_clk_get(struct device *dev, const char *id)
>  {
>  	struct device_node *provnode;
> @@ -123,9 +105,8 @@ struct clk *of_clk_get(struct device *dev, const char *id)
>  			__func__, prop_name, dev->of_node->full_name);
>  		return NULL;
>  	}
> -	clk = __of_clk_get_from_provider(provnode, prop);
> -	if (clk)
> -		dev_dbg(dev, "Using clock from %s\n", provnode->full_name);
> +
> +	clk = provnode->clk;
>  
>  	of_node_put(provnode);
>  
> -- 
> 1.7.1
> 

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

end of thread, other threads:[~2011-03-31 20:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-18 18:24 [PATCH v2 0/6] add full platform dt clock support for mx51 babbage Shawn Guo
     [not found] ` <1300472672-13392-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-18 18:24   ` [PATCH v2 1/6] arm/dts: babbage: add all available clock nodes Shawn Guo
2011-03-18 18:24   ` [PATCH v2 2/6] arm/mxc: add clk member 'rate' to ease dt fixed-clock support Shawn Guo
2011-03-18 18:24   ` [PATCH v2 3/6] dt: add new member 'clk' into device_node Shawn Guo
     [not found]     ` <1300472672-13392-4-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-31 19:59       ` Grant Likely
2011-03-18 18:24   ` [PATCH v2 4/6] arm/dt: mx51: dynamically add clocks per dt nodes Shawn Guo
     [not found]     ` <1300472672-13392-5-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-31 20:40       ` Grant Likely
2011-03-18 18:24   ` [PATCH v2 5/6] arm/dt: mx5: change timer init function to dt clock way Shawn Guo
2011-03-18 18:24   ` [PATCH v2 6/6] of/clock: eliminate function __of_clk_get_from_provider Shawn Guo
     [not found]     ` <1300472672-13392-7-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-31 20:41       ` Grant Likely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).