[RFC PATCH] arm/imx6: convert clock to device tree
Shawn Guo
shawn.guo at linaro.org
Tue Nov 22 03:41:43 EST 2011
It converts imx6 clock code to common clock frame and device tree.
Signed-off-by: Shawn Guo <shawn.guo at linaro.org>
---
As I promised to Arnd, I will convert imx6 clock code to common clock
frame and in turn device tree. Here it is.
It's based on Mike's common-clk pre-v3 and Grant's clock device tree
binding series.
Along with the conversion to device tree, I feel it's a great idea to
introduce '#clock-cells'. With adopting it, I'm using 70 nodes to
describe 110 clocks (~35% nodes reduced). However, the current design
of '#clock-cells' makes the user a little difficult. For example, when
a consumer node references to provider node which is a blob of 4 clocks,
it has to fill 4 parameters into the phandle.
usdhc at 02198000 { /* uSDHC3 */
compatible = "fsl,imx6q-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 0x04>;
clock-input = <&usdhc_clk 2 0 0 0>; <--
clock-input-name = "usdhc3";
};
But we actually need to pass only one parameter to point out the index
of the clock in the blob. It's a little silly to put a number of
meaningless 0 there to fill the length of the phandle parameters. Can
we rework the dt core code to make the following one work?
usdhc at 02198000 { /* uSDHC3 */
compatible = "fsl,imx6q-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 0x04>;
clock-input = <&usdhc_clk 2>; <--
clock-input-name = "usdhc3";
};
Regards,
Shawn
.../devicetree/bindings/clock/clock-imx.txt | 124 ++
arch/arm/boot/dts/imx6q.dtsi | 943 +++++++++-
arch/arm/mach-imx/Kconfig | 5 +
arch/arm/mach-imx/Makefile | 1 +
arch/arm/mach-imx/clock-imx6q.c | 2135 ++++----------------
arch/arm/mach-imx/clock.c | 222 ++
arch/arm/mach-imx/clock.h | 64 +
7 files changed, 1734 insertions(+), 1760 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/clock-imx.txt
create mode 100644 arch/arm/mach-imx/clock.c
create mode 100644 arch/arm/mach-imx/clock.h
diff --git a/Documentation/devicetree/bindings/clock/clock-imx.txt b/Documentation/devicetree/bindings/clock/clock-imx.txt
new file mode 100644
index 0000000..5c597d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clock-imx.txt
@@ -0,0 +1,124 @@
+* Device Tree Bindings for Freescale i.MX Clock
+
+== Clock Gate ==
+
+Required properties:
+- imx,clock-gate: It's a two 32-bit integers array. The first
+ integer specifies the offset of the gate register, and the second
+ one specifies the bit mask of the gate for this clock.
+
+== Clock Divider ==
+
+Required properties:
+- imx,clock-divider: It's a five 32-bit integers array. The first
+ integer specifies the offset of the divider register. The second
+ and the third one specify the shift and width of the pre-divider
+ bits for the clock, which is not necessarily present and the values
+ can just be 0. The last two specify the shift and width of the
+ post-divider bits.
+
+Optional properties:
+- imx,busy-divider: Some imx clocks needs to wait for a busy status
+ cleared when the clock rate gets changed. This property is a two
+ 32-bit integers array. The first integer specifies the offset of
+ the busy register, and the second one specifies the busy bit mask.
+
+== Clock Multiplexer ==
+
+Required properties:
+- imx,clock-multiplexer: It's a three 32-bit integers array. The
+ first integer specifies the offset of the multiplexer register.
+ The second and the third one specify the shift and width of the
+ multiplexer bits for this clock.
+
+Optional properties:
+- imx,busy-multiplexer: Some imx clocks needs to wait for a busy
+ status cleared when the parent gets changed. This property is a two
+ 32-bit integers array. The first integer specifies the offset of
+ the busy register, and the second one specifies the busy bit mask.
+
+A typical imx clock could have gate, divider, multiplexer, but it's
+also very true that a imx clock just has the subset of these three
+properties.
+
+When #clock-cells > 1, this single clock node actually describes
+multiple clocks. Thus all the properties under the node should
+contains the description for all of the clocks, except properties
+clock-input and clock-input-name which are used to describe the
+parents of the clock. That means only the clocks sharing the exactly
+same parents could possible described by single node.
+
+Examples:
+
+pll2_pfd_clk: pll2-pfd {
+ compatible = "fsl,imx6q-pfd";
+ #clock-cells = <3>;
+ imx,clock-gate = <0x100 0x80>,
+ <0x100 0x8000>,
+ <0x100 0x800000>;
+ imx,clock-divider = <0x100 0 0 0 6>,
+ <0x100 0 0 8 6>,
+ <0x100 0 0 16 6>;
+ clock-input = <&pll_bus_clk 0>;
+ clock-input-name = "pll2-bus";
+ clock-output-name = "pll2-pfd-352m",
+ "pll2-pfd-594m",
+ "pll2-pfd-400m";
+};
+
+usdhc_clk: usdhc {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <4>;
+ imx,clock-gate = <0x80 0xc>,
+ <0x80 0x30>,
+ <0x80 0xc0>,
+ <0x80 0x300>;
+ imx,clock-divider = <0x24 0 0 11 3>,
+ <0x24 0 0 16 3>,
+ <0x24 0 0 19 3>,
+ <0x24 0 0 22 3>;
+ imx,clock-multiplexer = <0x1c 16 1>,
+ <0x1c 17 1>,
+ <0x1c 18 1>,
+ <0x1c 19 1>;
+ clock-input = <&pll2_pfd_clk 2 0 0>,
+ <&pll2_pfd_clk 0 0 0>;
+ clock-input-name = "pll2-pfd-400m",
+ "pll2-pfd-352m";
+ clock-output-name = "usdhc1",
+ "usdhc2",
+ "usdhc3",
+ "usdhc3";
+};
+
+usdhc at 02190000 { /* uSDHC1 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02190000 0x4000>;
+ interrupts = <0 22 0x04>;
+ clock-input = <&usdhc_clk 0 0 0 0>;
+ clock-input-name = "usdhc1";
+};
+
+usdhc at 02194000 { /* uSDHC2 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02194000 0x4000>;
+ interrupts = <0 23 0x04>;
+ clock-input = <&usdhc_clk 1 0 0 0>;
+ clock-input-name = "usdhc2";
+};
+
+usdhc at 02198000 { /* uSDHC3 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x02198000 0x4000>;
+ interrupts = <0 24 0x04>;
+ clock-input = <&usdhc_clk 2 0 0 0>;
+ clock-input-name = "usdhc3";
+};
+
+usdhc at 0219c000 { /* uSDHC4 */
+ compatible = "fsl,imx6q-usdhc";
+ reg = <0x0219c000 0x4000>;
+ interrupts = <0 25 0x04>;
+ clock-input = <&usdhc_clk 3 0 0 0>;
+ clock-input-name = "usdhc4";
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 7dda599..a5b9c5e 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -64,19 +64,922 @@
#address-cells = <1>;
#size-cells = <0>;
- ckil {
- compatible = "fsl,imx-ckil", "fixed-clock";
- clock-frequency = <32768>;
+ dummy_clk: dummy {
+ compatible = "dummy-clock";
+ #clock-cells = <1>;
+ clock-output-name = "dummy";
};
- ckih1 {
- compatible = "fsl,imx-ckih1", "fixed-clock";
- clock-frequency = <0>;
+ ref_clk: ref {
+ compatible = "fixed-clock";
+ #clock-cells = <3>;
+ clock-frequency = <24000000 32768 0>;
+ clock-output-name = "osc",
+ "ckil",
+ "ckih";
};
- osc {
- compatible = "fsl,imx-osc", "fixed-clock";
- clock-frequency = <24000000>;
+ pll_sys_clk: pll-sys {
+ compatible = "fsl,imx6q-pll-sys";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x0 0x2000>;
+ imx,clock-divider = <0x0 0 0 0 7>;
+ clock-input = <&ref_clk 0 0 0>;
+ clock-input-name = "osc";
+ clock-output-name = "pll1-sys";
+ };
+
+ pll_bus_clk: pll-bus {
+ compatible = "fsl,imx6q-pll";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x30 0x2000>;
+ imx,clock-divider = <0x30 0 0 0 1>;
+ clock-input = <&ref_clk 0 0 0>;
+ clock-input-name = "osc";
+ clock-output-name = "pll2-bus";
+ };
+
+ pll_usb_clk: pll-usb {
+ compatible = "fsl,imx6q-pll-usb";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x10 0x2000>,
+ <0x20 0x2000>;
+ imx,clock-divider = <0x10 0 0 0 2>,
+ <0x20 0 0 0 2>;
+ clock-input = <&ref_clk 0 0 0>;
+ clock-input-name = "osc";
+ clock-output-name = "pll3-usb-otg",
+ "pll7-usb-host";
+ };
+
+ pll_av_clk: pll-av {
+ compatible = "fsl,imx6q-pll-av";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x70 0x2000>,
+ <0xa0 0x2000>;
+ imx,clock-divider = <0x70 0 0 0 7>,
+ <0xa0 0 0 0 7>;
+ clock-input = <&ref_clk 0 0 0>;
+ clock-input-name = "osc";
+ clock-output-name = "pll4-audio",
+ "pll5-video";
+ };
+
+ pll_mlb_clk: pll-mlb {
+ compatible = "fsl,imx6q-pll";
+ #clock-cells = <1>;
+ imx,clock-gate = <0xd0 0x2000>;
+ clock-input = <&ref_clk 0 0 0>;
+ clock-input-name = "osc";
+ clock-output-name = "pll6-mlb";
+ };
+
+ pll_enet_clk: pll-enet {
+ compatible = "fsl,imx6q-pll-enet";
+ #clock-cells = <1>;
+ imx,clock-gate = <0xe0 0x182000>;
+ imx,clock-divider = <0xe0 0 0 0 2>;
+ clock-input = <&ref_clk 0 0 0>;
+ clock-input-name = "osc";
+ clock-output-name = "pll8-enet";
+ };
+
+ pll2_pfd_clk: pll2-pfd {
+ compatible = "fsl,imx6q-pfd";
+ #clock-cells = <3>;
+ imx,clock-gate = <0x100 0x80>,
+ <0x100 0x8000>,
+ <0x100 0x800000>;
+ imx,clock-divider = <0x100 0 0 0 6>,
+ <0x100 0 0 8 6>,
+ <0x100 0 0 16 6>;
+ clock-input = <&pll_bus_clk 0>;
+ clock-input-name = "pll2-bus";
+ clock-output-name = "pll2-pfd-352m",
+ "pll2-pfd-594m",
+ "pll2-pfd-400m";
+ };
+
+ pll3_pfd_clk: pll3-pfd {
+ compatible = "fsl,imx6q-pfd";
+ #clock-cells = <4>;
+ imx,clock-gate = <0xf0 0x80>,
+ <0xf0 0x8000>,
+ <0xf0 0x800000>,
+ <0xf0 0x80000000>;
+ imx,clock-divider = <0xf0 0 0 0 6>,
+ <0xf0 0 0 8 6>,
+ <0xf0 0 0 16 6>,
+ <0xf0 0 0 24 6>;
+ clock-input = <&pll_usb_clk 0 0>;
+ clock-input-name = "pll3-usb-otg";
+ clock-output-name = "pll3-pfd-720m",
+ "pll3-pfd-540m",
+ "pll3-pfd-508m",
+ "pll3-pfd-454m";
+ };
+
+ pll2_div_clk: pll2-200m {
+ compatible = "divider-fixed-clock";
+ #clock-cells = <1>;
+ clock-divider = <2>;
+ clock-input = <&pll2_pfd_clk 2 0 0>;
+ clock-input-name = "pll2-pfd-400m";
+ clock-output-name = "pll2-200m";
+ };
+
+ pll3_div_clk: pll3-div {
+ compatible = "divider-fixed-clock";
+ #clock-cells = <3>;
+ clock-divider = <4 6 8>;
+ clock-input = <&pll_usb_clk 0 0>;
+ clock-input-name = "pll3-usb";
+ clock-output-name = "pll3-120m",
+ "pll3-80m",
+ "pll3-60m";
+ };
+
+ step_clk: step {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-multiplexer = <0xc 8 1>;
+ clock-input = <&ref_clk 0 0 0>,
+ <&pll2_pfd_clk 2 0 0>;
+ clock-input-name = "osc",
+ "pll2-pfd-400m";
+ clock-output-name = "step";
+ };
+
+ pll1_sw_clk: pll1-sw {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-multiplexer = <0xc 2 1>;
+ clock-input = <&pll_sys_clk 0>,
+ <&step_clk 0>;
+ clock-input-name = "pll1-sys",
+ "step";
+ clock-output-name = "pll1-sw";
+ };
+
+ periph_pre_clk: periph-pre {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-multiplexer = <0x18 18 2>,
+ <0x18 21 2>;
+ clock-input = <&pll_bus_clk 0>,
+ <&pll2_pfd_clk 2 0 0>,
+ <&pll2_pfd_clk 0 0 0>,
+ <&pll2_div_clk 0>;
+ clock-input-name = "pll2-bus",
+ "pll2-pfd-400m",
+ "pll2-pfd-352m",
+ "pll2-200m";
+ clock-output-name = "periph-pre",
+ "periph2-pre";
+ };
+
+ periph_clk2_clk: periph-clk2 {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-divider = <0x14 0 0 27 3>,
+ <0x14 0 0 0 3>;
+ imx,clock-multiplexer = <0x18 12 1>,
+ <0x18 20 1>;
+ clock-input = <&pll_usb_clk 0 0>,
+ <&ref_clk 0 0 0>;
+ clock-input-name = "pll3-usb-otg",
+ "osc";
+ clock-output-name = "periph-clk2",
+ "periph2-clk2";
+ };
+
+ periph_clk: periph {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-multiplexer = <0x14 25 1>;
+ imx,busy-multiplexer = <0x48 0x20>;
+ clock-input = <&periph_pre_clk 0 0>,
+ <&periph_clk2_clk 0 0>;
+ clock-input-name = "periph-pre",
+ "periph-clk2";
+ clock-output-name = "periph";
+ };
+
+ periph2_clk: periph2 {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-multiplexer = <0x14 26 1>;
+ imx,busy-multiplexer = <0x48 0x8>;
+ clock-input = <&periph_pre_clk 1 0>,
+ <&periph_clk2_clk 1 0>;
+ clock-input-name = "periph2-pre",
+ "periph2-clk2";
+ clock-output-name = "periph2";
+ };
+
+ axi_clk: axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x14 0 0 16 3>;
+ imx,busy-divider = <0x48 0x1>;
+ imx,clock-multiplexer = <0x14 6 2>;
+ clock-input = <&periph_clk 0>,
+ <&pll2_pfd_clk 2 0 0>,
+ <&pll3_pfd_clk 1 0 0 0>;
+ clock-input-name = "periph",
+ "pll2-pfd-400m",
+ "pll3-pfd-540m";
+ clock-output-name = "axi";
+ };
+
+ mmdc_ch0_axi_clk: mmdc-ch0-axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0x300000>;
+ imx,clock-divider = <0x14 0 0 19 3>;
+ imx,busy-divider = <0x48 0x10>;
+ clock-input = <&periph_clk 0>;
+ clock-input-name = "periph";
+ clock-output-name = "mmdc-ch0-axi";
+ };
+
+ mmdc_ch1_axi_clk: mmdc-ch1-axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0xc00000>;
+ imx,clock-divider = <0x14 0 0 3 3>;
+ imx,busy-divider = <0x48 0x4>;
+ clock-input = <&periph2_clk 0>;
+ clock-input-name = "periph2";
+ clock-output-name = "mmdc-ch1-axi";
+ };
+
+ arm_clk: arm {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x10 0 0 0 3>;
+ imx,busy-divider = <0x48 0x10000>;
+ clock-input = <&pll1_sw_clk 0>;
+ clock-input-name = "pll1-sw";
+ clock-output-name = "arm";
+ };
+
+ ahb_clk: ahb {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x14 0 0 10 3>;
+ imx,busy-divider = <0x48 0x2>;
+ clock-input = <&periph_clk 0>;
+ clock-input-name = "periph";
+ clock-output-name = "ahb";
+ };
+
+ ipg_clk: ipg {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x14 0 0 8 2>;
+ clock-input = <&ahb_clk 0>;
+ clock-input-name = "ahb";
+ clock-output-name = "ipg";
+ };
+
+ ipg_per_clk: ipg-per {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x1c 0 0 0 6>;
+ clock-input = <&ipg_clk 0>;
+ clock-input-name = "ipg";
+ clock-output-name = "ipg-per";
+ };
+
+ aips_tz_clk: aips-tz {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x68 0x3>,
+ <0x68 0xc>;
+ clock-input = <&ahb_clk 0>;
+ clock-input-name = "ahb";
+ clock-output-name = "aips-tz1",
+ "aips-tz2";
+ };
+
+ apbh_dma_clk: apbh-dma {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x68 0x30>;
+ clock-input = <&ahb_clk 0>;
+ clock-input-name = "ahb";
+ clock-output-name = "apbh-dma";
+ };
+
+ audio_clk: audio {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <3>;
+ imx,clock-gate = <0x6c 0x30000>,
+ <0x68 0xc0>,
+ <0x7c 0xc000>;
+ imx,clock-divider = <0x28 9 3 25 3>,
+ <0x30 12 3 9 3>,
+ <0x30 25 3 22 3>;
+ imx,clock-multiplexer = <0x20 19 2>,
+ <0x30 7 2>,
+ <0x30 20 2>;
+ clock-input = <&pll_av_clk 0 0>,
+ <&pll3_pfd_clk 2 0 0 0>,
+ <&pll3_pfd_clk 3 0 0 0>,
+ <&pll_usb_clk 0 0>;
+ clock-input-name = "pll4-audio",
+ "pll3-pfd-508m",
+ "pll3-pfd-454m",
+ "pll3-usb-otg";
+ clock-output-name = "esai",
+ "asrc",
+ "spdif";
+ };
+
+ can_root_clk: can-root {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x20 0 0 2 6>;
+ clock-input = <&pll_usb_clk 0 0>;
+ clock-input-name = "pll3-usb-otg";
+ clock-output-name = "can-root";
+ };
+
+ can_clk: can {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <4>;
+ imx,clock-gate = <0x68 0xc000>,
+ <0x68 0x30000>,
+ <0x68 0xc0000>,
+ <0x68 0x300000>;
+ clock-input = <&can_root_clk 0>;
+ clock-input-name = "can-root";
+ clock-output-name = "can1",
+ "can1-serial",
+ "can2",
+ "can2-serial";
+ };
+
+ ecspi_root_clk: ecspi-root {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x38 0 0 19 6>;
+ clock-input = <&pll3_div_clk 2 0 0>;
+ clock-input-name = "pll3-60m";
+ clock-output-name = "ecspi-root";
+ };
+
+ ecspi_clk: ecspi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <5>;
+ imx,clock-gate = <0x6c 0x3>,
+ <0x6c 0xc>,
+ <0x6c 0x30>,
+ <0x6c 0xc0>,
+ <0x6c 0x300>;
+ clock-input = <&ecspi_root_clk 0>;
+ clock-input-name = "ecspi-root";
+ clock-output-name = "ecspi1",
+ "ecspi2",
+ "ecspi3",
+ "ecspi4",
+ "ecspi5";
+ };
+
+ enet_clk: enet {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x6c 0xc00>;
+ clock-input = <&ipg_clk 0>;
+ clock-input-name = "ipg";
+ clock-output-name = "enet";
+ };
+
+ gpt_clk: gpt {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x6c 0x300000>,
+ <0x6c 0xc00000>;
+ clock-input = <&ipg_per_clk 0>;
+ clock-input-name = "ipg-per";
+ clock-output-name = "gpt",
+ "gpt-serial";
+ };
+
+ gpu_axi_clk: gpu-axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-multiplexer = <0x18 0 1>,
+ <0x18 1 1>;
+ clock-input = <&axi_clk 0>,
+ <&ahb_clk 0>;
+ clock-input-name = "axi",
+ "ahb";
+ clock-output-name = "gpu2d-axi",
+ "gpu3d-axi";
+ };
+
+ gpu2d_core_clk: gpu2d-core {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x6c 0x3000000>;
+ imx,clock-divider = <0x18 0 0 23 3>;
+ imx,clock-multiplexer = <0x18 16 2>;
+ clock-input = <&axi_clk 0>,
+ <&pll_usb_clk 0 0>,
+ <&pll2_pfd_clk 0 0 0>,
+ <&pll2_pfd_clk 2 0 0>;
+ clock-input-name = "axi",
+ "pll3-usb-otg",
+ "pll2-pfd-352m",
+ "pll2-pfd-400m";
+ clock-output-name = "gpu2d-core";
+ };
+
+ gpu3d_core_clk: gpu3d-core {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x6c 0xc000000>;
+ imx,clock-divider = <0x18 0 0 26 3>;
+ imx,clock-multiplexer = <0x18 4 2>;
+ clock-input = <&mmdc_ch0_axi_clk 0>,
+ <&pll_usb_clk 0 0>,
+ <&pll2_pfd_clk 1 0 0>,
+ <&pll2_pfd_clk 2 0 0>;
+ clock-input-name = "mmdc-ch0-axi",
+ "pll3-usb-otg",
+ "pll2-pfd-594m",
+ "pll2-pfd-400m";
+ clock-output-name = "gpu3d-core";
+ };
+
+ gpu3d_shader_clk: gpu3d-shader {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-divider = <0x18 0 0 29 3>;
+ imx,clock-multiplexer = <0x18 8 2>;
+ clock-input = <&mmdc_ch0_axi_clk 0>,
+ <&pll_usb_clk 0 0>,
+ <&pll2_pfd_clk 1 0 0>,
+ <&pll3_pfd_clk 0 0 0 0>;
+ clock-input-name = "mmdc-ch0-axi",
+ "pll3-usb-otg",
+ "pll2-pfd-594m",
+ "pll3-pfd-720m";
+ clock-output-name = "gpu3d-shader";
+ };
+
+ hdmi_iahb_clk: hdmi-iahb {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x70 0x3>;
+ clock-input = <&ahb_clk 0>;
+ clock-input-name = "ahb";
+ clock-output-name = "hdmi-iahb";
+ };
+
+ hdmi_isfr_clk: hdmi-isfr {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x70 0x3>;
+ clock-input = <&pll3_pfd_clk 1 0 0 0>;
+ clock-input-name = "pll3-pfd-540m";
+ clock-output-name = "hdmi-isfr";
+ };
+
+ i2c_clk: i2c {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <3>;
+ imx,clock-gate = <0x70 0xc0>,
+ <0x70 0x300>,
+ <0x70 0xc00>;
+ clock-input = <&ipg_per_clk 0>;
+ clock-input-name = "ipg-per";
+ clock-output-name = "i2c1",
+ "i2c2",
+ "i2c3";
+ };
+
+ iim_clk: iim {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x70 0x3000>;
+ clock-input = <&ipg_clk 0>;
+ clock-input-name = "ipg";
+ clock-output-name = "iim";
+ };
+
+ ipu_clk: ipu {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x74 0x3>,
+ <0x74 0xc0>;
+ imx,clock-divider = <0x3c 0 0 11 3>,
+ <0x3c 0 0 16 3>;
+ imx,clock-multiplexer = <0x3c 9 2>,
+ <0x3c 14 2>;
+ clock-input = <&mmdc_ch0_axi_clk 0>,
+ <&pll2_pfd_clk 2 0 0>,
+ <&pll3_div_clk 0 0 0>,
+ <&pll3_pfd_clk 1 0 0 0>;
+ clock-input-name = "mmdc-ch0-axi",
+ "pll2-pfd-400m",
+ "pll3-120m",
+ "pll3-pfd-540m";
+ clock-output-name = "ipu1",
+ "ipu2";
+ };
+
+ ldb_di_clk: ldb-di {
+ compatible = "fsl,imx6q-ldb-di-clock";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x74 0x3000>,
+ <0x74 0xc000>;
+ imx,clock-divider = <0x20 0 0 10 1>,
+ <0x20 0 0 11 1>;
+ imx,clock-multiplexer = <0x2c 9 3>,
+ <0x2c 12 3>;
+ clock-input = <&pll_av_clk 1 0>,
+ <&pll2_pfd_clk 0 0 0>,
+ <&pll2_pfd_clk 2 0 0>,
+ <&pll3_pfd_clk 1 0 0 0>,
+ <&pll_usb_clk 0 0>;
+ clock-input-name = "pll5-video",
+ "pll2-pfd-352m",
+ "pll2-pfd-400m",
+ "pll3-pfd-540m",
+ "pll3-usb-otg";
+ clock-output-name = "ldb-di0",
+ "ldb-di1";
+ };
+
+ ipu_di_pre_clk: ipu-di-pre {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <4>;
+ imx,clock-divider = <0x34 0 0 3 3>,
+ <0x34 0 0 12 3>,
+ <0x38 0 0 3 3>,
+ <0x38 0 0 12 3>;
+ imx,clock-multiplexer = <0x34 6 3>,
+ <0x34 15 3>,
+ <0x38 6 3>,
+ <0x38 15 3>;
+ clock-input = <&mmdc_ch0_axi_clk 0>,
+ <&pll_usb_clk 0 0>,
+ <&pll_av_clk 1 0>,
+ <&pll2_pfd_clk 0 0 0>,
+ <&pll2_pfd_clk 2 0 0>,
+ <&pll3_pfd_clk 1 0 0 0>;
+ clock-input-name = "mmdc-ch0-axi",
+ "pll3-usb-otg",
+ "pll5-video",
+ "pll2-pfd-352m",
+ "pll2-pfd-400m",
+ "pll3-pfd-540m";
+ clock-output-name = "ipu1-di0-pre",
+ "ipu1-di1-pre",
+ "ipu2-di0-pre",
+ "ipu2-di1-pre";
+ };
+
+ ipu1_di0_clk: ipu1-di0 {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0xc>;
+ imx,clock-multiplexer = <0x34 0 3>;
+ clock-input = <&ipu_di_pre_clk 0 0 0 0>,
+ <&dummy_clk 0>,
+ <&dummy_clk 0>,
+ <&ldb_di_clk 0 0>,
+ <&ldb_di_clk 1 0>;
+ clock-input-name = "ipu1-di0-pre",
+ "dummy",
+ "dummy",
+ "ldb-di0",
+ "ldb-di1";
+ clock-output-name = "ipu1-di0";
+ };
+
+ ipu1_di1_clk: ipu1-di1 {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0x30>;
+ imx,clock-multiplexer = <0x34 9 3>;
+ clock-input = <&ipu_di_pre_clk 1 0 0 0>,
+ <&dummy_clk 0>,
+ <&dummy_clk 0>,
+ <&ldb_di_clk 0 0>,
+ <&ldb_di_clk 1 0>;
+ clock-input-name = "ipu1-di1-pre",
+ "dummy",
+ "dummy",
+ "ldb-di0",
+ "ldb-di1";
+ clock-output-name = "ipu1-di1";
+ };
+
+ ipu2_di0_clk: ipu2-di0 {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0x300>;
+ imx,clock-multiplexer = <0x38 0 3>;
+ clock-input = <&ipu_di_pre_clk 2 0 0 0>,
+ <&dummy_clk 0>,
+ <&dummy_clk 0>,
+ <&ldb_di_clk 0 0>,
+ <&ldb_di_clk 1 0>;
+ clock-input-name = "ipu2-di0-pre",
+ "dummy",
+ "dummy",
+ "ldb-di0",
+ "ldb-di1";
+ clock-output-name = "ipu2-di0";
+ };
+
+ ipu2_di1_clk: ipu2-di1 {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0xc00>;
+ imx,clock-multiplexer = <0x38 9 3>;
+ clock-input = <&ipu_di_pre_clk 3 0 0 0>,
+ <&dummy_clk 0>,
+ <&dummy_clk 0>,
+ <&ldb_di_clk 0 0>,
+ <&ldb_di_clk 1 0>;
+ clock-input-name = "ipu2-di1-pre",
+ "dummy",
+ "dummy",
+ "ldb-di0",
+ "ldb-di1";
+ clock-output-name = "ipu2-di1";
+ };
+
+ hsi_tx_clk: hsi-tx {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0x30000>;
+ imx,clock-divider = <0x30 0 0 29 3>;
+ imx,clock-multiplexer = <0x30 28 1>;
+ clock-input = <&pll3_div_clk 0 0 0>,
+ <&pll2_pfd_clk 2 0 0>;
+ clock-input-name = "pll3-120m",
+ "pll2-pfd-400m";
+ clock-output-name = "hsi-tx";
+ };
+
+ mlb_clk: mlb {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0xc0000>;
+ clock-input = <&pll_mlb_clk 0>;
+ clock-input-name = "pll6-mlb";
+ clock-output-name = "mlb";
+ };
+
+ mmdc_ipg_clk: mmdc-ipg {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x74 0x3000000>,
+ <0x74 0xc000000>;
+ clock-input = <&ipg_clk 0>;
+ clock-input-name = "ipg";
+ clock-output-name = "mmdc-ch0-ipg",
+ "mmdc-ch1-ipg";
+ };
+
+ openvg_axi_clk: openvg-axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x74 0xc000000>;
+ clock-input = <&axi_clk 0>;
+ clock-input-name = "axi";
+ clock-output-name = "openvg-axi";
+ };
+
+ pcie_axi_clk: pcie-axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x78 0x3>;
+ imx,clock-multiplexer = <0x18 10 1>;
+ clock-input = <&axi_clk 0>,
+ <&ahb_clk 0>;
+ clock-input-name = "axi",
+ "ahb";
+ clock-output-name = "pcie-axi";
+ };
+
+ pwm_clk: pwm {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <4>;
+ imx,clock-gate = <0x78 0x30000>,
+ <0x78 0xc0000>,
+ <0x78 0x300000>,
+ <0x78 0xc00000>;
+ clock-input = <&ipg_per_clk 0>;
+ clock-input-name = "ipg-per";
+ clock-output-name = "pwm1",
+ "pwm2",
+ "pwm3",
+ "pwm4";
+ };
+
+ sata_clk: sata {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x7c 0x30>;
+ clock-input = <&ipg_clk 0>;
+ clock-input-name = "ipg";
+ clock-output-name = "sata";
+ };
+
+ sdma_clk: sdma {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x7c 0xc0>;
+ clock-input = <&ahb_clk 0>;
+ clock-input-name = "ahb";
+ clock-output-name = "sdma";
+ };
+
+ spba_clk: spba {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x7c 0x3000>;
+ clock-input = <&ipg_clk 0>;
+ clock-input-name = "ipg";
+ clock-output-name = "spba";
+ };
+
+ ssi_clk: ssi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <3>;
+ imx,clock-gate = <0x7c 0xc0000>,
+ <0x7c 0x300000>,
+ <0x7c 0xc00000>;
+ imx,clock-divider = <0x28 6 3 0 6>,
+ <0x2c 6 3 0 6>,
+ <0x28 6 3 0 6>;
+ imx,clock-multiplexer = <0x1c 10 2>,
+ <0x1c 12 2>,
+ <0x1c 14 2>;
+ clock-input = <&pll3_pfd_clk 2 0 0 0>,
+ <&pll3_pfd_clk 3 0 0 0>,
+ <&pll_av_clk 0 0>;
+ clock-input-name = "pll3-pfd-508m",
+ "pll3-pfd-454m",
+ "pll4-audio";
+ clock-output-name = "ssi1",
+ "ssi2",
+ "ssi3";
+ };
+
+ uart_clk: uart {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x7c 0x3000000>,
+ <0x7c 0xc000000>;
+ imx,clock-divider = <0x24 0 0 0 6>,
+ <0x24 0 0 0 6>;
+ clock-input = <&pll3_div_clk 1 0 0>;
+ clock-input-name = "pll3-80m";
+ clock-output-name = "uart",
+ "uart-serial";
+ };
+
+ usboh3_clk: usboh3 {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x80 0x3>;
+ clock-input = <&ipg_clk 0>;
+ clock-input-name = "ipg";
+ clock-output-name = "usboh3";
+ };
+
+ usdhc_clk: usdhc {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <4>;
+ imx,clock-gate = <0x80 0xc>,
+ <0x80 0x30>,
+ <0x80 0xc0>,
+ <0x80 0x300>;
+ imx,clock-divider = <0x24 0 0 11 3>,
+ <0x24 0 0 16 3>,
+ <0x24 0 0 19 3>,
+ <0x24 0 0 22 3>;
+ imx,clock-multiplexer = <0x1c 16 1>,
+ <0x1c 17 1>,
+ <0x1c 18 1>,
+ <0x1c 19 1>;
+ clock-input = <&pll2_pfd_clk 2 0 0>,
+ <&pll2_pfd_clk 0 0 0>;
+ clock-input-name = "pll2-pfd-400m",
+ "pll2-pfd-352m";
+ clock-output-name = "usdhc1",
+ "usdhc2",
+ "usdhc3",
+ "usdhc3";
+ };
+
+ enfc_clk: enfc {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x70 0xc000>;
+ imx,clock-divider = <0x2c 18 3 21 6>;
+ imx,clock-multiplexer = <0x2c 16 2>;
+ clock-input = <&pll2_pfd_clk 0 0 0>,
+ <&pll_bus_clk 0>,
+ <&pll_usb_clk 0 0>,
+ <&pll2_pfd_clk 2 0 0>;
+ clock-input-name = "pll2-pfd-352m",
+ "pll2-bus",
+ "pll3-usb-otg",
+ "pll2-pfd-400m";
+ clock-output-name = "enfc";
+ };
+
+ gpmi_bch_apb_clk: gpmi-bch-apb {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x78 0x3000000>;
+ clock-input = <&usdhc_clk 2 0 0 0>;
+ clock-input-name = "usdhc3";
+ clock-output-name = "gpmi-bch-apb";
+ };
+
+ gpmi_bch_clk: gpmi-bch {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x78 0xc000000>;
+ clock-input = <&usdhc_clk 3 0 0 0>;
+ clock-input-name = "usdhc4";
+ clock-output-name = "gpmi-bch";
+ };
+
+ gpmi_io_clk: gpmi-io {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x78 0x30000000>;
+ clock-input = <&enfc_clk 0>;
+ clock-input-name = "enfc";
+ clock-output-name = "gpmi-io";
+ };
+
+ gpmi_apb_clk: gpmi-apb {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x78 0xc0000000>;
+ clock-input = <&usdhc_clk 2 0 0 0>;
+ clock-input-name = "usdhc3";
+ clock-output-name = "gpmi-apb";
+ };
+
+ emi_clk: emi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <2>;
+ imx,clock-gate = <0x80 0xc00>,
+ <0x80 0xc00>;
+ imx,clock-divider = <0x1c 0 0 20 3>,
+ <0x1c 0 0 23 3>;
+ imx,clock-multiplexer = <0x1c 27 2>,
+ <0x1c 29 2>;
+ clock-input = <&axi_clk 0>,
+ <&pll_usb_clk 0 0>,
+ <&pll2_pfd_clk 2 0 0>,
+ <&pll2_pfd_clk 0 0 0>;
+ clock-input-name = "axi",
+ "pll3-usb-otg",
+ "pll2-pfd-400m",
+ "pll2-pfd-352m";
+ clock-output-name = "emi",
+ "emi-slow";
+ };
+
+ vdo_axi_clk: vdo-axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x80 0x3000>;
+ imx,clock-multiplexer = <0x18 11 1>;
+ clock-input = <&axi_clk 0>,
+ <&ahb_clk 0>;
+ clock-input-name = "axi",
+ "ahb";
+ clock-output-name = "vdo-axi";
+ };
+
+ vpu_axi_clk: vpu-axi {
+ compatible = "fsl,imx6q-clock";
+ #clock-cells = <1>;
+ imx,clock-gate = <0x80 0xc000>;
+ imx,clock-divider = <0x24 0 0 25 3>;
+ imx,clock-multiplexer = <0x18 14 2>;
+ clock-input = <&axi_clk 0>,
+ <&pll2_pfd_clk 2 0 0>,
+ <&pll2_pfd_clk 0 0 0>;
+ clock-input-name = "axi",
+ "pll2-pfd-400m",
+ "pll2-pfd-352m";
+ clock-output-name = "vpu-axi";
};
};
@@ -169,6 +1072,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>;
interrupts = <0 26 0x04>;
+ clock-input = <&uart_clk 0 0>;
+ clock-input-name = "uart";
status = "disabled";
};
@@ -245,6 +1150,8 @@
compatible = "fsl,imx6q-gpt";
reg = <0x02098000 0x4000>;
interrupts = <0 55 0x04>;
+ clock-input = <&gpt_clk 0 0>,
+ <&gpt_clk 1 0>;
};
gpio0: gpio at 0209c000 { /* GPIO1 */
@@ -426,6 +1333,8 @@
compatible = "fsl,imx6q-fec";
reg = <0x02188000 0x4000>;
interrupts = <0 118 0x04 0 119 0x04>;
+ clock-input = <&enet_clk 0>;
+ clock-input-name = "enet";
status = "disabled";
};
@@ -438,6 +1347,8 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x02190000 0x4000>;
interrupts = <0 22 0x04>;
+ clock-input = <&usdhc_clk 0 0 0 0>;
+ clock-input-name = "usdhc1";
status = "disabled";
};
@@ -445,6 +1356,8 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x02194000 0x4000>;
interrupts = <0 23 0x04>;
+ clock-input = <&usdhc_clk 1 0 0 0>;
+ clock-input-name = "usdhc2";
status = "disabled";
};
@@ -452,6 +1365,8 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 0x04>;
+ clock-input = <&usdhc_clk 2 0 0 0>;
+ clock-input-name = "usdhc3";
status = "disabled";
};
@@ -459,6 +1374,8 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x0219c000 0x4000>;
interrupts = <0 25 0x04>;
+ clock-input = <&usdhc_clk 3 0 0 0>;
+ clock-input-name = "usdhc4";
status = "disabled";
};
@@ -547,6 +1464,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021e8000 0x4000>;
interrupts = <0 27 0x04>;
+ clock-input = <&uart_clk 0 0>;
+ clock-input-name = "uart";
status = "disabled";
};
@@ -554,6 +1473,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021ec000 0x4000>;
interrupts = <0 28 0x04>;
+ clock-input = <&uart_clk 0 0>;
+ clock-input-name = "uart";
status = "disabled";
};
@@ -561,6 +1482,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f0000 0x4000>;
interrupts = <0 29 0x04>;
+ clock-input = <&uart_clk 0 0>;
+ clock-input-name = "uart";
status = "disabled";
};
@@ -568,6 +1491,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f4000 0x4000>;
interrupts = <0 30 0x04>;
+ clock-input = <&uart_clk 0 0>;
+ clock-input-name = "uart";
status = "disabled";
};
};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index d281035..d30501a 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,6 +1,9 @@
config IMX_HAVE_DMA_V1
bool
+config HAVE_IMX_CLOCK
+ bool
+
config HAVE_IMX_GPC
bool
@@ -614,7 +617,9 @@ config SOC_IMX6Q
select GENERIC_CLK
select GENERIC_CLK_DUMMY
select GENERIC_CLK_FIXED
+ select GENERIC_CLK_DIVIDER_FIXED
select HAVE_ARM_SCU
+ select HAVE_IMX_CLOCK
select HAVE_IMX_GPC
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index aba7321..efd18b9 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_HAVE_IMX_CLOCK) += clock.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
index 4bcaa3e..79d5bf3 100644
--- a/arch/arm/mach-imx/clock-imx6q.c
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -18,493 +18,69 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_clk.h>
#include <linux/of_irq.h>
#include <asm/div64.h>
-#include <asm/mach/map.h>
#include <mach/common.h>
-#include <mach/hardware.h>
-
-#define PLL_BASE IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
-#define PLL1_SYS (PLL_BASE + 0x000)
-#define PLL2_BUS (PLL_BASE + 0x030)
-#define PLL3_USB_OTG (PLL_BASE + 0x010)
-#define PLL4_AUDIO (PLL_BASE + 0x070)
-#define PLL5_VIDEO (PLL_BASE + 0x0a0)
-#define PLL6_MLB (PLL_BASE + 0x0d0)
-#define PLL7_USB_HOST (PLL_BASE + 0x020)
-#define PLL8_ENET (PLL_BASE + 0x0e0)
-#define PFD_480 (PLL_BASE + 0x0f0)
-#define PFD_528 (PLL_BASE + 0x100)
-#define PLL_NUM_OFFSET 0x010
-#define PLL_DENOM_OFFSET 0x020
-
-#define PFD0 7
-#define PFD1 15
-#define PFD2 23
-#define PFD3 31
-#define PFD_FRAC_MASK 0x3f
+#include "clock.h"
+#define PLL_NUM_OFFSET 0x010
+#define PLL_DENOM_OFFSET 0x020
#define BM_PLL_BYPASS (0x1 << 16)
-#define BM_PLL_ENABLE (0x1 << 13)
-#define BM_PLL_POWER_DOWN (0x1 << 12)
+#define BM_PLL_POWER (0x1 << 12)
#define BM_PLL_LOCK (0x1 << 31)
-#define BP_PLL_SYS_DIV_SELECT 0
-#define BM_PLL_SYS_DIV_SELECT (0x7f << 0)
-#define BP_PLL_BUS_DIV_SELECT 0
-#define BM_PLL_BUS_DIV_SELECT (0x1 << 0)
-#define BP_PLL_USB_DIV_SELECT 0
-#define BM_PLL_USB_DIV_SELECT (0x3 << 0)
-#define BP_PLL_AV_DIV_SELECT 0
-#define BM_PLL_AV_DIV_SELECT (0x7f << 0)
-#define BP_PLL_ENET_DIV_SELECT 0
-#define BM_PLL_ENET_DIV_SELECT (0x3 << 0)
-#define BM_PLL_ENET_EN_PCIE (0x1 << 19)
-#define BM_PLL_ENET_EN_SATA (0x1 << 20)
-
-#define CCM_BASE IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
-#define CCR (CCM_BASE + 0x00)
-#define CCDR (CCM_BASE + 0x04)
-#define CSR (CCM_BASE + 0x08)
-#define CCSR (CCM_BASE + 0x0c)
-#define CACRR (CCM_BASE + 0x10)
-#define CBCDR (CCM_BASE + 0x14)
-#define CBCMR (CCM_BASE + 0x18)
-#define CSCMR1 (CCM_BASE + 0x1c)
-#define CSCMR2 (CCM_BASE + 0x20)
-#define CSCDR1 (CCM_BASE + 0x24)
-#define CS1CDR (CCM_BASE + 0x28)
-#define CS2CDR (CCM_BASE + 0x2c)
-#define CDCDR (CCM_BASE + 0x30)
-#define CHSCCDR (CCM_BASE + 0x34)
-#define CSCDR2 (CCM_BASE + 0x38)
-#define CSCDR3 (CCM_BASE + 0x3c)
-#define CSCDR4 (CCM_BASE + 0x40)
-#define CWDR (CCM_BASE + 0x44)
-#define CDHIPR (CCM_BASE + 0x48)
-#define CDCR (CCM_BASE + 0x4c)
-#define CTOR (CCM_BASE + 0x50)
-#define CLPCR (CCM_BASE + 0x54)
-#define CISR (CCM_BASE + 0x58)
-#define CIMR (CCM_BASE + 0x5c)
-#define CCOSR (CCM_BASE + 0x60)
-#define CGPR (CCM_BASE + 0x64)
-#define CCGR0 (CCM_BASE + 0x68)
-#define CCGR1 (CCM_BASE + 0x6c)
-#define CCGR2 (CCM_BASE + 0x70)
-#define CCGR3 (CCM_BASE + 0x74)
-#define CCGR4 (CCM_BASE + 0x78)
-#define CCGR5 (CCM_BASE + 0x7c)
-#define CCGR6 (CCM_BASE + 0x80)
-#define CCGR7 (CCM_BASE + 0x84)
-#define CMEOR (CCM_BASE + 0x88)
-
-#define CG0 0
-#define CG1 2
-#define CG2 4
-#define CG3 6
-#define CG4 8
-#define CG5 10
-#define CG6 12
-#define CG7 14
-#define CG8 16
-#define CG9 18
-#define CG10 20
-#define CG11 22
-#define CG12 24
-#define CG13 26
-#define CG14 28
-#define CG15 30
-
-#define BP_CCSR_PLL1_SW_CLK_SEL 2
-#define BM_CCSR_PLL1_SW_CLK_SEL (0x1 << 2)
-#define BP_CCSR_STEP_SEL 8
-#define BM_CCSR_STEP_SEL (0x1 << 8)
-
-#define BP_CACRR_ARM_PODF 0
-#define BM_CACRR_ARM_PODF (0x7 << 0)
-
-#define BP_CBCDR_PERIPH2_CLK2_PODF 0
-#define BM_CBCDR_PERIPH2_CLK2_PODF (0x7 << 0)
-#define BP_CBCDR_MMDC_CH1_AXI_PODF 3
-#define BM_CBCDR_MMDC_CH1_AXI_PODF (0x7 << 3)
-#define BP_CBCDR_AXI_SEL 6
-#define BM_CBCDR_AXI_SEL (0x3 << 6)
-#define BP_CBCDR_IPG_PODF 8
-#define BM_CBCDR_IPG_PODF (0x3 << 8)
-#define BP_CBCDR_AHB_PODF 10
-#define BM_CBCDR_AHB_PODF (0x7 << 10)
-#define BP_CBCDR_AXI_PODF 16
-#define BM_CBCDR_AXI_PODF (0x7 << 16)
-#define BP_CBCDR_MMDC_CH0_AXI_PODF 19
-#define BM_CBCDR_MMDC_CH0_AXI_PODF (0x7 << 19)
-#define BP_CBCDR_PERIPH_CLK_SEL 25
-#define BM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
-#define BP_CBCDR_PERIPH2_CLK_SEL 26
-#define BM_CBCDR_PERIPH2_CLK_SEL (0x1 << 26)
-#define BP_CBCDR_PERIPH_CLK2_PODF 27
-#define BM_CBCDR_PERIPH_CLK2_PODF (0x7 << 27)
-
-#define BP_CBCMR_GPU2D_AXI_SEL 0
-#define BM_CBCMR_GPU2D_AXI_SEL (0x1 << 0)
-#define BP_CBCMR_GPU3D_AXI_SEL 1
-#define BM_CBCMR_GPU3D_AXI_SEL (0x1 << 1)
-#define BP_CBCMR_GPU3D_CORE_SEL 4
-#define BM_CBCMR_GPU3D_CORE_SEL (0x3 << 4)
-#define BP_CBCMR_GPU3D_SHADER_SEL 8
-#define BM_CBCMR_GPU3D_SHADER_SEL (0x3 << 8)
-#define BP_CBCMR_PCIE_AXI_SEL 10
-#define BM_CBCMR_PCIE_AXI_SEL (0x1 << 10)
-#define BP_CBCMR_VDO_AXI_SEL 11
-#define BM_CBCMR_VDO_AXI_SEL (0x1 << 11)
-#define BP_CBCMR_PERIPH_CLK2_SEL 12
-#define BM_CBCMR_PERIPH_CLK2_SEL (0x3 << 12)
-#define BP_CBCMR_VPU_AXI_SEL 14
-#define BM_CBCMR_VPU_AXI_SEL (0x3 << 14)
-#define BP_CBCMR_GPU2D_CORE_SEL 16
-#define BM_CBCMR_GPU2D_CORE_SEL (0x3 << 16)
-#define BP_CBCMR_PRE_PERIPH_CLK_SEL 18
-#define BM_CBCMR_PRE_PERIPH_CLK_SEL (0x3 << 18)
-#define BP_CBCMR_PERIPH2_CLK2_SEL 20
-#define BM_CBCMR_PERIPH2_CLK2_SEL (0x1 << 20)
-#define BP_CBCMR_PRE_PERIPH2_CLK_SEL 21
-#define BM_CBCMR_PRE_PERIPH2_CLK_SEL (0x3 << 21)
-#define BP_CBCMR_GPU2D_CORE_PODF 23
-#define BM_CBCMR_GPU2D_CORE_PODF (0x7 << 23)
-#define BP_CBCMR_GPU3D_CORE_PODF 26
-#define BM_CBCMR_GPU3D_CORE_PODF (0x7 << 26)
-#define BP_CBCMR_GPU3D_SHADER_PODF 29
-#define BM_CBCMR_GPU3D_SHADER_PODF (0x7 << 29)
-
-#define BP_CSCMR1_PERCLK_PODF 0
-#define BM_CSCMR1_PERCLK_PODF (0x3f << 0)
-#define BP_CSCMR1_SSI1_SEL 10
-#define BM_CSCMR1_SSI1_SEL (0x3 << 10)
-#define BP_CSCMR1_SSI2_SEL 12
-#define BM_CSCMR1_SSI2_SEL (0x3 << 12)
-#define BP_CSCMR1_SSI3_SEL 14
-#define BM_CSCMR1_SSI3_SEL (0x3 << 14)
-#define BP_CSCMR1_USDHC1_SEL 16
-#define BM_CSCMR1_USDHC1_SEL (0x1 << 16)
-#define BP_CSCMR1_USDHC2_SEL 17
-#define BM_CSCMR1_USDHC2_SEL (0x1 << 17)
-#define BP_CSCMR1_USDHC3_SEL 18
-#define BM_CSCMR1_USDHC3_SEL (0x1 << 18)
-#define BP_CSCMR1_USDHC4_SEL 19
-#define BM_CSCMR1_USDHC4_SEL (0x1 << 19)
-#define BP_CSCMR1_EMI_PODF 20
-#define BM_CSCMR1_EMI_PODF (0x7 << 20)
-#define BP_CSCMR1_EMI_SLOW_PODF 23
-#define BM_CSCMR1_EMI_SLOW_PODF (0x7 << 23)
-#define BP_CSCMR1_EMI_SEL 27
-#define BM_CSCMR1_EMI_SEL (0x3 << 27)
-#define BP_CSCMR1_EMI_SLOW_SEL 29
-#define BM_CSCMR1_EMI_SLOW_SEL (0x3 << 29)
-
-#define BP_CSCMR2_CAN_PODF 2
-#define BM_CSCMR2_CAN_PODF (0x3f << 2)
-#define BM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10)
-#define BM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11)
-#define BP_CSCMR2_ESAI_SEL 19
-#define BM_CSCMR2_ESAI_SEL (0x3 << 19)
-
-#define BP_CSCDR1_UART_PODF 0
-#define BM_CSCDR1_UART_PODF (0x3f << 0)
-#define BP_CSCDR1_USDHC1_PODF 11
-#define BM_CSCDR1_USDHC1_PODF (0x7 << 11)
-#define BP_CSCDR1_USDHC2_PODF 16
-#define BM_CSCDR1_USDHC2_PODF (0x7 << 16)
-#define BP_CSCDR1_USDHC3_PODF 19
-#define BM_CSCDR1_USDHC3_PODF (0x7 << 19)
-#define BP_CSCDR1_USDHC4_PODF 22
-#define BM_CSCDR1_USDHC4_PODF (0x7 << 22)
-#define BP_CSCDR1_VPU_AXI_PODF 25
-#define BM_CSCDR1_VPU_AXI_PODF (0x7 << 25)
-
-#define BP_CS1CDR_SSI1_PODF 0
-#define BM_CS1CDR_SSI1_PODF (0x3f << 0)
-#define BP_CS1CDR_SSI1_PRED 6
-#define BM_CS1CDR_SSI1_PRED (0x7 << 6)
-#define BP_CS1CDR_ESAI_PRED 9
-#define BM_CS1CDR_ESAI_PRED (0x7 << 9)
-#define BP_CS1CDR_SSI3_PODF 16
-#define BM_CS1CDR_SSI3_PODF (0x3f << 16)
-#define BP_CS1CDR_SSI3_PRED 22
-#define BM_CS1CDR_SSI3_PRED (0x7 << 22)
-#define BP_CS1CDR_ESAI_PODF 25
-#define BM_CS1CDR_ESAI_PODF (0x7 << 25)
-
-#define BP_CS2CDR_SSI2_PODF 0
-#define BM_CS2CDR_SSI2_PODF (0x3f << 0)
-#define BP_CS2CDR_SSI2_PRED 6
-#define BM_CS2CDR_SSI2_PRED (0x7 << 6)
-#define BP_CS2CDR_LDB_DI0_SEL 9
-#define BM_CS2CDR_LDB_DI0_SEL (0x7 << 9)
-#define BP_CS2CDR_LDB_DI1_SEL 12
-#define BM_CS2CDR_LDB_DI1_SEL (0x7 << 12)
-#define BP_CS2CDR_ENFC_SEL 16
-#define BM_CS2CDR_ENFC_SEL (0x3 << 16)
-#define BP_CS2CDR_ENFC_PRED 18
-#define BM_CS2CDR_ENFC_PRED (0x7 << 18)
-#define BP_CS2CDR_ENFC_PODF 21
-#define BM_CS2CDR_ENFC_PODF (0x3f << 21)
-
-#define BP_CDCDR_ASRC_SERIAL_SEL 7
-#define BM_CDCDR_ASRC_SERIAL_SEL (0x3 << 7)
-#define BP_CDCDR_ASRC_SERIAL_PODF 9
-#define BM_CDCDR_ASRC_SERIAL_PODF (0x7 << 9)
-#define BP_CDCDR_ASRC_SERIAL_PRED 12
-#define BM_CDCDR_ASRC_SERIAL_PRED (0x7 << 12)
-#define BP_CDCDR_SPDIF_SEL 20
-#define BM_CDCDR_SPDIF_SEL (0x3 << 20)
-#define BP_CDCDR_SPDIF_PODF 22
-#define BM_CDCDR_SPDIF_PODF (0x7 << 22)
-#define BP_CDCDR_SPDIF_PRED 25
-#define BM_CDCDR_SPDIF_PRED (0x7 << 25)
-#define BP_CDCDR_HSI_TX_PODF 29
-#define BM_CDCDR_HSI_TX_PODF (0x7 << 29)
-#define BP_CDCDR_HSI_TX_SEL 28
-#define BM_CDCDR_HSI_TX_SEL (0x1 << 28)
-
-#define BP_CHSCCDR_IPU1_DI0_SEL 0
-#define BM_CHSCCDR_IPU1_DI0_SEL (0x7 << 0)
-#define BP_CHSCCDR_IPU1_DI0_PRE_PODF 3
-#define BM_CHSCCDR_IPU1_DI0_PRE_PODF (0x7 << 3)
-#define BP_CHSCCDR_IPU1_DI0_PRE_SEL 6
-#define BM_CHSCCDR_IPU1_DI0_PRE_SEL (0x7 << 6)
-#define BP_CHSCCDR_IPU1_DI1_SEL 9
-#define BM_CHSCCDR_IPU1_DI1_SEL (0x7 << 9)
-#define BP_CHSCCDR_IPU1_DI1_PRE_PODF 12
-#define BM_CHSCCDR_IPU1_DI1_PRE_PODF (0x7 << 12)
-#define BP_CHSCCDR_IPU1_DI1_PRE_SEL 15
-#define BM_CHSCCDR_IPU1_DI1_PRE_SEL (0x7 << 15)
-
-#define BP_CSCDR2_IPU2_DI0_SEL 0
-#define BM_CSCDR2_IPU2_DI0_SEL (0x7)
-#define BP_CSCDR2_IPU2_DI0_PRE_PODF 3
-#define BM_CSCDR2_IPU2_DI0_PRE_PODF (0x7 << 3)
-#define BP_CSCDR2_IPU2_DI0_PRE_SEL 6
-#define BM_CSCDR2_IPU2_DI0_PRE_SEL (0x7 << 6)
-#define BP_CSCDR2_IPU2_DI1_SEL 9
-#define BM_CSCDR2_IPU2_DI1_SEL (0x7 << 9)
-#define BP_CSCDR2_IPU2_DI1_PRE_PODF 12
-#define BM_CSCDR2_IPU2_DI1_PRE_PODF (0x7 << 12)
-#define BP_CSCDR2_IPU2_DI1_PRE_SEL 15
-#define BM_CSCDR2_IPU2_DI1_PRE_SEL (0x7 << 15)
-#define BP_CSCDR2_ECSPI_CLK_PODF 19
-#define BM_CSCDR2_ECSPI_CLK_PODF (0x3f << 19)
-
-#define BP_CSCDR3_IPU1_HSP_SEL 9
-#define BM_CSCDR3_IPU1_HSP_SEL (0x3 << 9)
-#define BP_CSCDR3_IPU1_HSP_PODF 11
-#define BM_CSCDR3_IPU1_HSP_PODF (0x7 << 11)
-#define BP_CSCDR3_IPU2_HSP_SEL 14
-#define BM_CSCDR3_IPU2_HSP_SEL (0x3 << 14)
-#define BP_CSCDR3_IPU2_HSP_PODF 16
-#define BM_CSCDR3_IPU2_HSP_PODF (0x7 << 16)
-
-#define BM_CDHIPR_AXI_PODF_BUSY (0x1 << 0)
-#define BM_CDHIPR_AHB_PODF_BUSY (0x1 << 1)
-#define BM_CDHIPR_MMDC_CH1_PODF_BUSY (0x1 << 2)
-#define BM_CDHIPR_PERIPH2_SEL_BUSY (0x1 << 3)
-#define BM_CDHIPR_MMDC_CH0_PODF_BUSY (0x1 << 4)
-#define BM_CDHIPR_PERIPH_SEL_BUSY (0x1 << 5)
-#define BM_CDHIPR_ARM_PODF_BUSY (0x1 << 16)
-
-#define BP_CLPCR_LPM 0
-#define BM_CLPCR_LPM (0x3 << 0)
-#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
-#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
-#define BM_CLPCR_SBYOS (0x1 << 6)
-#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
-#define BM_CLPCR_VSTBY (0x1 << 8)
-#define BP_CLPCR_STBY_COUNT 9
-#define BM_CLPCR_STBY_COUNT (0x3 << 9)
-#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
-#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
-#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
-#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
-#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
-#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
-#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
-#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
-#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
-#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
-#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
-
-#define FREQ_480M 480000000
-#define FREQ_528M 528000000
-#define FREQ_594M 594000000
-#define FREQ_650M 650000000
-#define FREQ_1300M 1300000000
-
-struct clk_gate {
- void __iomem *reg;
- u32 bm;
-};
-
-struct clk_div {
- void __iomem *reg;
- u32 bp_pred;
- u32 bm_pred;
- u32 bp_podf;
- u32 bm_podf;
-};
-
-struct clk_mux {
- void __iomem *reg;
- u32 bp;
- u32 bm;
- struct clk_hw **parents;
-};
-
-struct clk_hw_imx {
- const char *name;
- struct clk_hw hw;
- struct clk_gate *gate;
- struct clk_div *div;
- struct clk_mux *mux;
- struct clk_hw *parent;
- const struct clk_hw_ops *ops;
-};
-
-#define to_clk_imx(c) container_of(c, struct clk_hw_imx, hw)
-
-/* Declaration */
-static struct clk_hw_imx step_clk;
-static struct clk_hw_imx pll1_sw_clk;
-static struct clk_hw_imx arm_clk;
-static struct clk_hw_imx ahb_clk;
-static struct clk_hw_imx axi_clk;
-static struct clk_hw_imx ipg_clk;
-static struct clk_hw_imx ipg_perclk;
-static struct clk_hw_imx mmdc_ch0_axi_clk;
-static struct clk_hw_imx periph_clk;
-static struct clk_hw_imx periph_pre_clk;
-static struct clk_hw_imx periph_clk2_clk;
-static struct clk_hw_imx periph2_pre_clk;
-static struct clk_hw_imx periph2_clk2_clk;
-static struct clk_hw_imx ldb_di0_clk;
-static struct clk_hw_imx ldb_di1_clk;
-static struct clk_hw_imx ipu1_di0_pre_clk;
-static struct clk_hw_imx ipu1_di1_pre_clk;
-static struct clk_hw_imx ipu2_di0_pre_clk;
-static struct clk_hw_imx ipu2_di1_pre_clk;
-static struct clk_hw_imx usdhc3_clk;
-static struct clk_hw_imx usdhc4_clk;
-static struct clk_hw_imx enfc_clk;
-
-/* Dummy clock */
-static struct clk_dummy dummy_clk;
-
-/* Fixed clocks */
-static struct clk_hw_fixed ckil_clk;
-static struct clk_hw_fixed ckih_clk;
-static struct clk_hw_fixed osc_clk;
-
-/*
- * Common functions
- */
-static struct clk *_clk_get_parent(struct clk_hw *hw)
-{
- struct clk_mux *m = to_clk_imx(hw)->mux;
- u32 i;
-
- if (!m)
- return to_clk_imx(hw)->parent->clk;
-
- i = (readl_relaxed(m->reg) & m->bm) >> m->bp;
-
- return m->parents[i]->clk;
-}
-
-/*
-static int _clk_set_parent(struct clk_hw *hw, struct clk *parent)
-{
- struct clk_mux *m = to_clk_imx(hw)->mux;
- struct clk_hw **parents = m->parents;
- int i = 0;
- u32 val;
-
- while (parents[i]) {
- if (parent == parents[i]->clk)
- break;
- i++;
- }
- if (!parents[i])
- return -EINVAL;
-
- val = readl_relaxed(m->reg);
- val &= ~m->bm;
- val |= i << m->bp;
- writel_relaxed(val, m->reg);
-
- if (hw == &periph_clk.hw)
- return clk_busy_wait(hw);
-
- return 0;
-}
-*/
-
-static unsigned long _clk_recalc_rate(struct clk_hw *hw)
-{
- struct clk_div *d = to_clk_imx(hw)->div;
- u32 val, pred, podf;
-
- if (!d)
- return clk_get_rate(clk_get_parent(hw->clk));
-
- val = readl_relaxed(d->reg);
- pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
- podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
-
- return clk_get_rate(clk_get_parent(hw->clk)) / (pred * podf);
-}
-
-/*
- * PLL
- */
-#define DEF_PLL_GATE(c, r) \
-static struct clk_gate c##_gate = { \
- .reg = r, \
- .bm = BM_PLL_ENABLE, \
-}
-DEF_PLL_GATE(pll1_sys, PLL1_SYS);
-DEF_PLL_GATE(pll2_bus, PLL2_BUS);
-DEF_PLL_GATE(pll3_usb_otg, PLL3_USB_OTG);
-DEF_PLL_GATE(pll4_audio, PLL4_AUDIO);
-DEF_PLL_GATE(pll5_video, PLL5_VIDEO);
-DEF_PLL_GATE(pll6_mlb, PLL6_MLB);
-DEF_PLL_GATE(pll7_usb_host, PLL7_USB_HOST);
-DEF_PLL_GATE(pll8_enet, PLL8_ENET);
-
-#define DEF_PLL_DIV(c, r, b) \
-static struct clk_div c##_div = { \
- .reg = r, \
- .bp_podf = BP_PLL_##b##_DIV_SELECT, \
- .bm_podf = BM_PLL_##b##_DIV_SELECT, \
-}
-
-DEF_PLL_DIV(pll1_sys, PLL1_SYS, SYS);
-DEF_PLL_DIV(pll2_bus, PLL2_BUS, BUS);
-DEF_PLL_DIV(pll3_usb_otg, PLL3_USB_OTG, USB);
-DEF_PLL_DIV(pll4_audio, PLL4_AUDIO, AV);
-DEF_PLL_DIV(pll5_video, PLL5_VIDEO, AV);
-DEF_PLL_DIV(pll7_usb_host, PLL7_USB_HOST, AV);
-DEF_PLL_DIV(pll8_enet, PLL8_ENET, ENET);
+#define CLPCR 0x54
+#define BP_CLPCR_LPM 0
+#define BM_CLPCR_LPM (0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
+#define BM_CLPCR_SBYOS (0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
+#define BM_CLPCR_VSTBY (0x1 << 8)
+#define BP_CLPCR_STBY_COUNT 9
+#define BM_CLPCR_STBY_COUNT (0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
+#define CCGR0 0x68
+#define CCGR1 0x6c
+#define CCGR2 0x70
+#define CCGR3 0x74
+#define CCGR4 0x78
+#define CCGR5 0x7c
+#define CCGR6 0x80
+#define CCGR7 0x84
+
+#define FREQ_480M 480000000
+#define FREQ_528M 528000000
+#define FREQ_594M 594000000
+#define FREQ_650M 650000000
+#define FREQ_1300M 1300000000
+
+static void __iomem *ccm_base;
+static void __iomem *anatop_base;
static int pll_enable(struct clk_hw *hw)
{
- struct clk_gate *g = to_clk_imx(hw)->gate;
+ struct clk_imx_gate *g = to_clk_imx(hw)->gate;
int timeout = 0x100000;
u32 val;
val = readl_relaxed(g->reg);
val &= ~BM_PLL_BYPASS;
- val &= ~BM_PLL_POWER_DOWN;
- /* 480MHz PLLs have the opposite definition for power bit */
- if (g->reg == PLL3_USB_OTG || g->reg == PLL7_USB_HOST)
- val |= BM_PLL_POWER_DOWN;
+ if (g->powerup_set_bit)
+ val |= BM_PLL_POWER;
+ else
+ val &= ~BM_PLL_POWER;
writel_relaxed(val, g->reg);
/* Wait for PLL to lock */
@@ -516,7 +92,7 @@ static int pll_enable(struct clk_hw *hw)
/* Enable the PLL output now */
val = readl_relaxed(g->reg);
- val |= g->bm;
+ val |= g->mask;
writel_relaxed(val, g->reg);
return 0;
@@ -524,102 +100,110 @@ static int pll_enable(struct clk_hw *hw)
static void pll_disable(struct clk_hw *hw)
{
- struct clk_gate *g = to_clk_imx(hw)->gate;
+ struct clk_imx_gate *g = to_clk_imx(hw)->gate;
u32 val;
val = readl_relaxed(g->reg);
- val &= ~g->bm;
+ val &= ~g->mask;
val |= BM_PLL_BYPASS;
- val |= BM_PLL_POWER_DOWN;
- if (g->reg == PLL3_USB_OTG || g->reg == PLL7_USB_HOST)
- val &= ~BM_PLL_POWER_DOWN;
+ if (g->powerup_set_bit)
+ val &= ~BM_PLL_POWER;
+ else
+ val |= BM_PLL_POWER;
writel_relaxed(val, g->reg);
}
-static unsigned long pll1_sys_recalc_rate(struct clk_hw *hw)
+static unsigned long pll_recalc_rate(struct clk_hw *hw)
{
- struct clk_div *d = to_clk_imx(hw)->div;
- u32 div = (readl_relaxed(d->reg) & d->bm_podf) >> d->bp_podf;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 div;
- return clk_get_rate(clk_get_parent(hw->clk)) * div / 2;
+ if (!d)
+ return clk_get_rate(clk_get_parent(hw->clk));
+
+ div = readl_relaxed(d->reg) >> d->shift_podf &
+ ((1 << d->width_podf) - 1);
+
+ return (div == 1) ? clk_get_rate(clk_get_parent(hw->clk)) * 22 :
+ clk_get_rate(clk_get_parent(hw->clk)) * 20;
}
-static int pll1_sys_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
{
- struct clk_div *d = to_clk_imx(hw)->div;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
u32 val, div;
- if (rate < FREQ_650M || rate > FREQ_1300M)
+ if (!d)
+ return -EINVAL;
+
+ if (rate == FREQ_528M)
+ div = 1;
+ else if (rate == FREQ_480M)
+ div = 0;
+ else
return -EINVAL;
- *parent_rate = clk_get_rate(clk_get_parent(hw->clk));
- div = rate * 2 / *parent_rate;
val = readl_relaxed(d->reg);
- val &= ~d->bm_podf;
- val |= div << d->bp_podf;
+ val &= ~(((1 << d->width_podf) - 1) << d->shift_podf);
+ val |= div << d->shift_podf;
writel_relaxed(val, d->reg);
return 0;
}
-static unsigned long pll8_enet_recalc_rate(struct clk_hw *hw)
-{
- struct clk_div *d = to_clk_imx(hw)->div;
- u32 div = (readl_relaxed(d->reg) & d->bm_podf) >> d->bp_podf;
+static const struct clk_hw_ops pll_ops = {
+ .enable = pll_enable,
+ .disable = pll_disable,
+ .recalc_rate = pll_recalc_rate,
+ .set_rate = pll_set_rate,
+ .get_parent = clk_imx_get_parent,
+};
- switch (div) {
- case 0:
- return 25000000;
- case 1:
- return 50000000;
- case 2:
- return 100000000;
- case 3:
- return 125000000;
- }
+static unsigned long pll_sys_recalc_rate(struct clk_hw *hw)
+{
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 div = readl_relaxed(d->reg) >> d->shift_podf &
+ ((1 << d->width_podf) - 1);
- return 0;
+ return clk_get_rate(clk_get_parent(hw->clk)) * div / 2;
}
-static int pll8_enet_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int pll_sys_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
{
- struct clk_div *d = to_clk_imx(hw)->div;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
u32 val, div;
- switch (rate) {
- case 25000000:
- div = 0;
- break;
- case 50000000:
- div = 1;
- break;
- case 100000000:
- div = 2;
- break;
- case 125000000:
- div = 3;
- break;
- default:
+ if (rate < FREQ_650M || rate > FREQ_1300M)
return -EINVAL;
- }
+ *parent_rate = clk_get_rate(clk_get_parent(hw->clk));
+ div = rate * 2 / *parent_rate;
val = readl_relaxed(d->reg);
- val &= ~d->bm_podf;
- val |= div << d->bp_podf;
+ val &= ~(((1 << d->width_podf) - 1) << d->shift_podf);
+ val |= div << d->shift_podf;
writel_relaxed(val, d->reg);
return 0;
}
+static const struct clk_hw_ops pll_sys_ops = {
+ .enable = pll_enable,
+ .disable = pll_disable,
+ .recalc_rate = pll_sys_recalc_rate,
+ .set_rate = pll_sys_set_rate,
+ .get_parent = clk_imx_get_parent,
+};
+
static unsigned long pll_av_recalc_rate(struct clk_hw *hw)
{
- struct clk_div *d = to_clk_imx(hw)->div;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
unsigned long parent_rate = clk_get_rate(clk_get_parent(hw->clk));
u32 mfn = readl_relaxed(d->reg + PLL_NUM_OFFSET);
u32 mfd = readl_relaxed(d->reg + PLL_DENOM_OFFSET);
- u32 div = (readl_relaxed(d->reg) & d->bm_podf) >> d->bp_podf;
+ u32 div = readl_relaxed(d->reg) >> d->shift_podf &
+ ((1 << d->width_podf) - 1);
return (parent_rate * div) + ((parent_rate / mfd) * mfn);
}
@@ -627,7 +211,7 @@ static unsigned long pll_av_recalc_rate(struct clk_hw *hw)
static int pll_av_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- struct clk_div *d = to_clk_imx(hw)->div;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
u32 val, div;
u32 mfn, mfd = 1000000;
s64 temp64;
@@ -644,8 +228,8 @@ static int pll_av_set_rate(struct clk_hw *hw, unsigned long rate,
mfn = temp64;
val = readl_relaxed(d->reg);
- val &= ~d->bm_podf;
- val |= div << d->bp_podf;
+ val &= ~(((1 << d->width_podf) - 1) << d->shift_podf);
+ val |= div << d->shift_podf;
writel_relaxed(val, d->reg);
writel_relaxed(mfn, d->reg + PLL_NUM_OFFSET);
writel_relaxed(mfd, d->reg + PLL_DENOM_OFFSET);
@@ -653,154 +237,80 @@ static int pll_av_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
-static unsigned long pll_recalc_rate(struct clk_hw *hw)
-{
- struct clk_div *d = to_clk_imx(hw)->div;
- u32 div;
+static const struct clk_hw_ops pll_av_ops = {
+ .enable = pll_enable,
+ .disable = pll_disable,
+ .recalc_rate = pll_av_recalc_rate,
+ .set_rate = pll_av_set_rate,
+ .get_parent = clk_imx_get_parent,
+};
- if (d->reg == PLL1_SYS)
- return pll1_sys_recalc_rate(hw);
- else if (d->reg == PLL4_AUDIO || d->reg == PLL5_VIDEO)
- return pll_av_recalc_rate(hw);
- else if (d->reg == PLL8_ENET)
- return pll8_enet_recalc_rate(hw);
+static unsigned long pll_enet_recalc_rate(struct clk_hw *hw)
+{
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 div = readl_relaxed(d->reg) >> d->shift_podf &
+ ((1 << d->width_podf) - 1);
- /* fall into generic case */
- div = (readl_relaxed(d->reg) & d->bm_podf) >> d->bp_podf;
+ switch (div) {
+ case 0:
+ return 25000000;
+ case 1:
+ return 50000000;
+ case 2:
+ return 100000000;
+ case 3:
+ return 125000000;
+ }
- return (div == 1) ? clk_get_rate(clk_get_parent(hw->clk)) * 22 :
- clk_get_rate(clk_get_parent(hw->clk)) * 20;
+ return 0;
}
-static int pll_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int pll_enet_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
{
- struct clk_div *d = to_clk_imx(hw)->div;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
u32 val, div;
- if (d->reg == PLL1_SYS)
- return pll1_sys_set_rate(hw, rate, parent_rate);
- else if (d->reg == PLL4_AUDIO || d->reg == PLL5_VIDEO)
- return pll_av_set_rate(hw, rate, parent_rate);
- else if (d->reg == PLL8_ENET)
- return pll8_enet_set_rate(hw, rate, parent_rate);
-
- /* fall into generic case */
- if (rate == FREQ_528M)
- div = 1;
- else if (rate == FREQ_480M)
+ switch (rate) {
+ case 25000000:
div = 0;
- else
+ break;
+ case 50000000:
+ div = 1;
+ break;
+ case 100000000:
+ div = 2;
+ break;
+ case 125000000:
+ div = 3;
+ break;
+ default:
return -EINVAL;
+ }
val = readl_relaxed(d->reg);
- val &= ~d->bm_podf;
- val |= div << d->bp_podf;
+ val &= ~(((1 << d->width_podf) - 1) << d->shift_podf);
+ val |= div << d->shift_podf;
writel_relaxed(val, d->reg);
return 0;
}
-static const struct clk_hw_ops clk_pll_ops = {
+static const struct clk_hw_ops pll_enet_ops = {
.enable = pll_enable,
.disable = pll_disable,
- .recalc_rate = pll_recalc_rate,
- .set_rate = pll_set_rate,
- .get_parent = _clk_get_parent,
-};
-
-#define DEF_PLL(c) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .gate = &c##_gate, \
- .div = &c##_div, \
- .parent = &osc_clk.hw, \
- .ops = &clk_pll_ops, \
-}
-
-DEF_PLL(pll1_sys);
-DEF_PLL(pll2_bus);
-DEF_PLL(pll3_usb_otg);
-DEF_PLL(pll4_audio);
-DEF_PLL(pll5_video);
-DEF_PLL(pll7_usb_host);
-DEF_PLL(pll8_enet);
-
-/* pll6_mlb: no divider */
-static const struct clk_hw_ops pll6_mlb_ops = {
- .enable = pll_enable,
- .disable = pll_disable,
- .recalc_rate = _clk_recalc_rate,
- .get_parent = _clk_get_parent,
-};
-
-static struct clk_hw_imx pll6_mlb = {
- .gate = &pll6_mlb_gate,
- .parent = &osc_clk.hw,
- .ops = &pll6_mlb_ops,
+ .recalc_rate = pll_enet_recalc_rate,
+ .set_rate = pll_enet_set_rate,
+ .get_parent = clk_imx_get_parent,
};
-/*
- * PFD
- */
-#define DEF_PFD_GATE(c, r, bp) \
-static struct clk_gate c##_gate = { \
- .reg = r, \
- .bm = 1 << bp, \
-}
-
-DEF_PFD_GATE(pll2_pfd_352m, PFD_528, PFD0);
-DEF_PFD_GATE(pll2_pfd_594m, PFD_528, PFD1);
-DEF_PFD_GATE(pll2_pfd_400m, PFD_528, PFD2);
-DEF_PFD_GATE(pll3_pfd_720m, PFD_480, PFD0);
-DEF_PFD_GATE(pll3_pfd_540m, PFD_480, PFD1);
-DEF_PFD_GATE(pll3_pfd_508m, PFD_480, PFD2);
-DEF_PFD_GATE(pll3_pfd_454m, PFD_480, PFD3);
-
-#define DEF_PFD_DIV(c, r, bp) \
-static struct clk_div c##_div = { \
- .reg = r, \
- .bp_podf = bp - 7, \
- .bm_podf = PFD_FRAC_MASK << (bp - 7), \
-}
-
-DEF_PFD_DIV(pll2_pfd_352m, PFD_528, PFD0);
-DEF_PFD_DIV(pll2_pfd_594m, PFD_528, PFD1);
-DEF_PFD_DIV(pll2_pfd_400m, PFD_528, PFD2);
-DEF_PFD_DIV(pll3_pfd_720m, PFD_480, PFD0);
-DEF_PFD_DIV(pll3_pfd_540m, PFD_480, PFD1);
-DEF_PFD_DIV(pll3_pfd_508m, PFD_480, PFD2);
-DEF_PFD_DIV(pll3_pfd_454m, PFD_480, PFD3);
-
-static int pfd_enable(struct clk_hw *hw)
-{
- struct clk_gate *g = to_clk_imx(hw)->gate;
- u32 val;
-
- val = readl_relaxed(g->reg);
- val &= ~g->bm;
- writel_relaxed(val, g->reg);
-
- return 0;
-}
-
-static void pfd_disable(struct clk_hw *hw)
-{
- struct clk_gate *g = to_clk_imx(hw)->gate;
- u32 val;
-
- val = readl_relaxed(g->reg);
- val |= g->bm;
- writel_relaxed(val, g->reg);
-}
-
static unsigned long pfd_recalc_rate(struct clk_hw *hw)
{
- struct clk_div *d = to_clk_imx(hw)->div;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
u64 tmp = (u64) clk_get_rate(clk_get_parent(hw->clk)) * 18;
- u32 frac;
+ u32 frac = readl_relaxed(d->reg) >> d->shift_podf &
+ ((1 << d->width_podf) - 1);
- frac = (readl_relaxed(d->reg) & d->bm_podf) >> d->bp_podf;
do_div(tmp, frac);
return tmp;
@@ -809,7 +319,7 @@ static unsigned long pfd_recalc_rate(struct clk_hw *hw)
static int pfd_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *pprate)
{
- struct clk_div *d = to_clk_imx(hw)->div;
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
u64 tmp = (u64) clk_get_rate(clk_get_parent(hw->clk)) * 18;
u32 val, frac;
@@ -824,8 +334,8 @@ static int pfd_set_rate(struct clk_hw *hw, unsigned long rate,
frac = (frac > 35) ? 35 : frac;
val = readl_relaxed(d->reg);
- val &= ~d->bm_podf;
- val |= frac << d->bp_podf;
+ val &= ~(((1 << d->width_podf) - 1) << d->shift_podf);
+ val |= frac << d->shift_podf;
writel_relaxed(val, d->reg);
tmp = (u64) clk_get_rate(clk_get_parent(hw->clk)) * 18;
@@ -851,815 +361,22 @@ static long pfd_round_rate(struct clk_hw *hw, unsigned long rate)
return tmp;
}
-static const struct clk_hw_ops clk_pfd_ops = {
- .enable = pfd_enable,
- .disable = pfd_disable,
+static const struct clk_hw_ops pfd_ops = {
+ .enable = clk_imx_enable,
+ .disable = clk_imx_disable,
.recalc_rate = pfd_recalc_rate,
.round_rate = pfd_round_rate,
.set_rate = pfd_set_rate,
- .get_parent = _clk_get_parent,
-};
-
-#define DEF_PFD(c, p) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .gate = &c##_gate, \
- .div = &c##_div, \
- .parent = p, \
- .ops = &clk_pfd_ops, \
-}
-
-DEF_PFD(pll2_pfd_352m, &pll2_bus.hw);
-DEF_PFD(pll2_pfd_594m, &pll2_bus.hw);
-DEF_PFD(pll2_pfd_400m, &pll2_bus.hw);
-DEF_PFD(pll3_pfd_720m, &pll3_usb_otg.hw);
-DEF_PFD(pll3_pfd_540m, &pll3_usb_otg.hw);
-DEF_PFD(pll3_pfd_508m, &pll3_usb_otg.hw);
-DEF_PFD(pll3_pfd_454m, &pll3_usb_otg.hw);
-
-/*
- * Clocks with only fixed divider
- */
-struct clk_div_fixed {
- struct clk_hw hw;
- unsigned int div;
- struct clk_hw *parent;
+ .get_parent = clk_imx_get_parent,
};
-#define to_clk_div_fixed(c) container_of(c, struct clk_div_fixed, hw)
-
-#define DEF_CLK_DIV_FIXED(c, d, p) \
-static struct clk_div_fixed c = { \
- .div = d, \
- .parent = p, \
-}
-
-DEF_CLK_DIV_FIXED(pll2_200m, 2, &pll2_pfd_400m.hw);
-DEF_CLK_DIV_FIXED(pll3_120m, 4, &pll3_usb_otg.hw);
-DEF_CLK_DIV_FIXED(pll3_80m, 6, &pll3_usb_otg.hw);
-DEF_CLK_DIV_FIXED(pll3_60m, 8, &pll3_usb_otg.hw);
-
-static unsigned long clk_div_fixed_recalc_rate(struct clk_hw *hw)
-{
- return clk_get_rate(clk_get_parent(hw->clk)) /
- to_clk_div_fixed(hw)->div;
-}
-
-static struct clk *clk_div_fixed_get_parent(struct clk_hw *hw)
-{
- return to_clk_div_fixed(hw)->parent->clk;
-}
-
-static const struct clk_hw_ops clk_div_fixed_ops = {
- .recalc_rate = clk_div_fixed_recalc_rate,
- .get_parent = clk_div_fixed_get_parent,
-};
-
-/*
- * Generic clocks
- */
-#define DEF_CLK_GATE(c, r, bp) \
-static struct clk_gate c##_gate = { \
- .reg = r, \
- .bm = 0x3 << bp, \
-}
-
-DEF_CLK_GATE(aips_tz1_clk, CCGR0, CG0);
-DEF_CLK_GATE(aips_tz2_clk, CCGR0, CG1);
-DEF_CLK_GATE(apbh_dma_clk, CCGR0, CG2);
-DEF_CLK_GATE(asrc_clk, CCGR0, CG3);
-DEF_CLK_GATE(can1_serial_clk, CCGR0, CG8);
-DEF_CLK_GATE(can1_clk, CCGR0, CG7);
-DEF_CLK_GATE(can2_serial_clk, CCGR0, CG10);
-DEF_CLK_GATE(can2_clk, CCGR0, CG9);
-DEF_CLK_GATE(ecspi1_clk, CCGR1, CG0);
-DEF_CLK_GATE(ecspi2_clk, CCGR1, CG1);
-DEF_CLK_GATE(ecspi3_clk, CCGR1, CG2);
-DEF_CLK_GATE(ecspi4_clk, CCGR1, CG3);
-DEF_CLK_GATE(ecspi5_clk, CCGR1, CG4);
-DEF_CLK_GATE(enet_clk, CCGR1, CG5);
-DEF_CLK_GATE(esai_clk, CCGR1, CG8);
-DEF_CLK_GATE(gpt_serial_clk, CCGR1, CG11);
-DEF_CLK_GATE(gpt_clk, CCGR1, CG10);
-DEF_CLK_GATE(gpu2d_core_clk, CCGR1, CG12);
-DEF_CLK_GATE(gpu3d_core_clk, CCGR1, CG13);
-DEF_CLK_GATE(gpu3d_shader_clk, CCGR1, CG13);
-DEF_CLK_GATE(hdmi_iahb_clk, CCGR2, CG0);
-DEF_CLK_GATE(hdmi_isfr_clk, CCGR2, CG2);
-DEF_CLK_GATE(i2c1_clk, CCGR2, CG3);
-DEF_CLK_GATE(i2c2_clk, CCGR2, CG4);
-DEF_CLK_GATE(i2c3_clk, CCGR2, CG5);
-DEF_CLK_GATE(iim_clk, CCGR2, CG6);
-DEF_CLK_GATE(enfc_clk, CCGR2, CG7);
-DEF_CLK_GATE(ipu1_clk, CCGR3, CG0);
-DEF_CLK_GATE(ipu1_di0_clk, CCGR3, CG1);
-DEF_CLK_GATE(ipu1_di1_clk, CCGR3, CG2);
-DEF_CLK_GATE(ipu2_clk, CCGR3, CG3);
-DEF_CLK_GATE(ipu2_di0_clk, CCGR3, CG4);
-DEF_CLK_GATE(ipu2_di1_clk, CCGR3, CG5);
-DEF_CLK_GATE(ldb_di0_clk, CCGR3, CG6);
-DEF_CLK_GATE(ldb_di1_clk, CCGR3, CG7);
-DEF_CLK_GATE(hsi_tx_clk, CCGR3, CG8);
-DEF_CLK_GATE(mlb_clk, CCGR3, CG9);
-DEF_CLK_GATE(mmdc_ch0_ipg_clk, CCGR3, CG12);
-DEF_CLK_GATE(mmdc_ch0_axi_clk, CCGR3, CG10);
-DEF_CLK_GATE(mmdc_ch1_ipg_clk, CCGR3, CG13);
-DEF_CLK_GATE(mmdc_ch1_axi_clk, CCGR3, CG11);
-DEF_CLK_GATE(openvg_axi_clk, CCGR3, CG13);
-DEF_CLK_GATE(pcie_axi_clk, CCGR4, CG0);
-DEF_CLK_GATE(pwm1_clk, CCGR4, CG8);
-DEF_CLK_GATE(pwm2_clk, CCGR4, CG9);
-DEF_CLK_GATE(pwm3_clk, CCGR4, CG10);
-DEF_CLK_GATE(pwm4_clk, CCGR4, CG11);
-DEF_CLK_GATE(gpmi_bch_apb_clk, CCGR4, CG12);
-DEF_CLK_GATE(gpmi_bch_clk, CCGR4, CG13);
-DEF_CLK_GATE(gpmi_apb_clk, CCGR4, CG15);
-DEF_CLK_GATE(gpmi_io_clk, CCGR4, CG14);
-DEF_CLK_GATE(sata_clk, CCGR5, CG2);
-DEF_CLK_GATE(sdma_clk, CCGR5, CG3);
-DEF_CLK_GATE(spba_clk, CCGR5, CG6);
-DEF_CLK_GATE(spdif_clk, CCGR5, CG7);
-DEF_CLK_GATE(ssi1_clk, CCGR5, CG9);
-DEF_CLK_GATE(ssi2_clk, CCGR5, CG10);
-DEF_CLK_GATE(ssi3_clk, CCGR5, CG11);
-DEF_CLK_GATE(uart_serial_clk, CCGR5, CG13);
-DEF_CLK_GATE(uart_clk, CCGR5, CG12);
-DEF_CLK_GATE(usboh3_clk, CCGR6, CG0);
-DEF_CLK_GATE(usdhc1_clk, CCGR6, CG1);
-DEF_CLK_GATE(usdhc2_clk, CCGR6, CG2);
-DEF_CLK_GATE(usdhc3_clk, CCGR6, CG3);
-DEF_CLK_GATE(usdhc4_clk, CCGR6, CG4);
-DEF_CLK_GATE(emi_slow_clk, CCGR6, CG5);
-DEF_CLK_GATE(vdo_axi_clk, CCGR6, CG6);
-DEF_CLK_GATE(vpu_axi_clk, CCGR6, CG7);
-
-#define DEF_CLK_DIV1(c, r, b) \
-static struct clk_div c##_div = { \
- .reg = r, \
- .bp_podf = BP_##r##_##b##_PODF, \
- .bm_podf = BM_##r##_##b##_PODF, \
-}
-
-DEF_CLK_DIV1(arm_clk, CACRR, ARM);
-DEF_CLK_DIV1(ipg_clk, CBCDR, IPG);
-DEF_CLK_DIV1(ahb_clk, CBCDR, AHB);
-DEF_CLK_DIV1(axi_clk, CBCDR, AXI);
-DEF_CLK_DIV1(mmdc_ch0_axi_clk, CBCDR, MMDC_CH0_AXI);
-DEF_CLK_DIV1(mmdc_ch1_axi_clk, CBCDR, MMDC_CH1_AXI);
-DEF_CLK_DIV1(periph_clk2_clk, CBCDR, PERIPH_CLK2);
-DEF_CLK_DIV1(periph2_clk2_clk, CBCDR, PERIPH2_CLK2);
-DEF_CLK_DIV1(gpu2d_core_clk, CBCMR, GPU2D_CORE);
-DEF_CLK_DIV1(gpu3d_core_clk, CBCMR, GPU3D_CORE);
-DEF_CLK_DIV1(gpu3d_shader_clk, CBCMR, GPU3D_SHADER);
-DEF_CLK_DIV1(ipg_perclk, CSCMR1, PERCLK);
-DEF_CLK_DIV1(emi_clk, CSCMR1, EMI);
-DEF_CLK_DIV1(emi_slow_clk, CSCMR1, EMI_SLOW);
-DEF_CLK_DIV1(can1_clk, CSCMR2, CAN);
-DEF_CLK_DIV1(uart_clk, CSCDR1, UART);
-DEF_CLK_DIV1(usdhc1_clk, CSCDR1, USDHC1);
-DEF_CLK_DIV1(usdhc2_clk, CSCDR1, USDHC2);
-DEF_CLK_DIV1(usdhc3_clk, CSCDR1, USDHC3);
-DEF_CLK_DIV1(usdhc4_clk, CSCDR1, USDHC4);
-DEF_CLK_DIV1(vpu_axi_clk, CSCDR1, VPU_AXI);
-DEF_CLK_DIV1(hsi_tx_clk, CDCDR, HSI_TX);
-DEF_CLK_DIV1(ipu1_di0_pre_clk, CHSCCDR, IPU1_DI0_PRE);
-DEF_CLK_DIV1(ipu1_di1_pre_clk, CHSCCDR, IPU1_DI1_PRE);
-DEF_CLK_DIV1(ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE);
-DEF_CLK_DIV1(ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE);
-DEF_CLK_DIV1(ipu1_clk, CSCDR3, IPU1_HSP);
-DEF_CLK_DIV1(ipu2_clk, CSCDR3, IPU2_HSP);
-
-#define DEF_CLK_DIV2(c, r, b) \
-static struct clk_div c##_div = { \
- .reg = r, \
- .bp_pred = BP_##r##_##b##_PRED, \
- .bm_pred = BM_##r##_##b##_PRED, \
- .bp_podf = BP_##r##_##b##_PODF, \
- .bm_podf = BM_##r##_##b##_PODF, \
-}
-
-DEF_CLK_DIV2(ssi1_clk, CS1CDR, SSI1);
-DEF_CLK_DIV2(ssi3_clk, CS1CDR, SSI3);
-DEF_CLK_DIV2(esai_clk, CS1CDR, ESAI);
-DEF_CLK_DIV2(ssi2_clk, CS2CDR, SSI2);
-DEF_CLK_DIV2(enfc_clk, CS2CDR, ENFC);
-DEF_CLK_DIV2(spdif_clk, CDCDR, SPDIF);
-DEF_CLK_DIV2(asrc_serial_clk, CDCDR, ASRC_SERIAL);
-
-static struct clk_hw *step_clk_parents[] = {
- &osc_clk.hw,
- &pll2_pfd_400m.hw,
- NULL
-};
-
-static struct clk_hw *pll1_sw_clk_parents[] = {
- &pll1_sys.hw,
- &step_clk.hw,
- NULL
-};
-
-static struct clk_hw *axi_clk_parents[] = {
- &periph_clk.hw,
- &pll2_pfd_400m.hw,
- &pll3_pfd_540m.hw,
- NULL
-};
-
-static struct clk_hw *periph_clk_parents[] = {
- &periph_pre_clk.hw,
- &periph_clk2_clk.hw,
- NULL
-};
-
-static struct clk_hw *periph_pre_clk_parents[] = {
- &pll2_bus.hw,
- &pll2_pfd_400m.hw,
- &pll2_pfd_352m.hw,
- &pll2_200m.hw,
- NULL
-};
-
-static struct clk_hw *periph_clk2_clk_parents[] = {
- &pll3_usb_otg.hw,
- &osc_clk.hw,
- NULL
-};
-
-static struct clk_hw *periph2_clk_parents[] = {
- &periph2_pre_clk.hw,
- &periph2_clk2_clk.hw,
- NULL
-};
-
-static struct clk_hw *periph2_pre_clk_parents[] = {
- &pll2_bus.hw,
- &pll2_pfd_400m.hw,
- &pll2_pfd_352m.hw,
- &pll2_200m.hw,
- NULL
-};
-
-static struct clk_hw *periph2_clk2_clk_parents[] = {
- &pll3_usb_otg.hw,
- &osc_clk.hw,
- NULL
-};
-
-static struct clk_hw *gpu2d_axi_clk_parents[] = {
- &axi_clk.hw,
- &ahb_clk.hw,
- NULL
-};
-
-#define gpu3d_axi_clk_parents gpu2d_axi_clk_parents
-#define pcie_axi_clk_parents gpu2d_axi_clk_parents
-#define vdo_axi_clk_parents gpu2d_axi_clk_parents
-
-static struct clk_hw *gpu3d_core_clk_parents[] = {
- &mmdc_ch0_axi_clk.hw,
- &pll3_usb_otg.hw,
- &pll2_pfd_594m.hw,
- &pll2_pfd_400m.hw,
- NULL
-};
-
-static struct clk_hw *gpu3d_shader_clk_parents[] = {
- &mmdc_ch0_axi_clk.hw,
- &pll3_usb_otg.hw,
- &pll2_pfd_594m.hw,
- &pll3_pfd_720m.hw,
- NULL
-};
-
-static struct clk_hw *vpu_axi_clk_parents[] = {
- &axi_clk.hw,
- &pll2_pfd_400m.hw,
- &pll2_pfd_352m.hw,
- NULL
-};
-
-static struct clk_hw *gpu2d_core_clk_parents[] = {
- &axi_clk.hw,
- &pll3_usb_otg.hw,
- &pll2_pfd_352m.hw,
- &pll2_pfd_400m.hw,
- NULL
-};
-
-static struct clk_hw *ssi1_clk_parents[] = {
- &pll3_pfd_508m.hw,
- &pll3_pfd_454m.hw,
- &pll4_audio.hw,
- NULL
-};
-
-#define ssi2_clk_parents ssi1_clk_parents
-#define ssi3_clk_parents ssi1_clk_parents
-
-static struct clk_hw *usdhc1_clk_parents[] = {
- &pll2_pfd_400m.hw,
- &pll2_pfd_352m.hw,
- NULL
-};
-
-#define usdhc2_clk_parents usdhc1_clk_parents
-#define usdhc3_clk_parents usdhc1_clk_parents
-#define usdhc4_clk_parents usdhc1_clk_parents
-
-static struct clk_hw *emi_clk_parents[] = {
- &axi_clk.hw,
- &pll3_usb_otg.hw,
- &pll2_pfd_400m.hw,
- &pll2_pfd_352m.hw,
- NULL
-};
-
-#define emi_slow_clk_parents emi_clk_parents
-
-static struct clk_hw *esai_clk_parents[] = {
- &pll4_audio.hw,
- &pll3_pfd_508m.hw,
- &pll3_pfd_454m.hw,
- &pll3_usb_otg.hw,
- NULL
-};
-
-#define spdif_clk_parents esai_clk_parents
-#define asrc_serial_clk_parents esai_clk_parents
-
-static struct clk_hw *ldb_di0_clk_parents[] = {
- &pll5_video.hw,
- &pll2_pfd_352m.hw,
- &pll2_pfd_400m.hw,
- &pll3_pfd_540m.hw,
- &pll3_usb_otg.hw,
- NULL
-};
-
-#define ldb_di1_clk_parents ldb_di0_clk_parents
-
-static struct clk_hw *enfc_clk_parents[] = {
- &pll2_pfd_352m.hw,
- &pll2_bus.hw,
- &pll3_usb_otg.hw,
- &pll2_pfd_400m.hw,
- NULL
-};
-
-static struct clk_hw *hsi_tx_clk_parents[] = {
- &pll3_120m.hw,
- &pll2_pfd_400m.hw,
- NULL
-};
-
-static struct clk_hw *ipu1_di0_pre_clk_parents[] = {
- &mmdc_ch0_axi_clk.hw,
- &pll3_usb_otg.hw,
- &pll5_video.hw,
- &pll2_pfd_352m.hw,
- &pll2_pfd_400m.hw,
- &pll3_pfd_540m.hw,
- NULL
-};
-
-#define ipu1_di1_pre_clk_parents ipu1_di0_pre_clk_parents
-#define ipu2_di0_pre_clk_parents ipu1_di0_pre_clk_parents
-#define ipu2_di1_pre_clk_parents ipu1_di0_pre_clk_parents
-
-#define DEF_IPU_DI_PARENTS(i, d) \
-static struct clk_hw *ipu##i##_di##d##_clk_parents[] = { \
- &ipu##i##_di##d##_pre_clk.hw, \
- &dummy_clk.hw, \
- &dummy_clk.hw, \
- &ldb_di0_clk.hw, \
- &ldb_di1_clk.hw, \
- NULL \
-}
-
-DEF_IPU_DI_PARENTS(1, 0);
-DEF_IPU_DI_PARENTS(1, 1);
-DEF_IPU_DI_PARENTS(2, 0);
-DEF_IPU_DI_PARENTS(2, 1);
-
-static struct clk_hw *ipu1_clk_parents[] = {
- &mmdc_ch0_axi_clk.hw,
- &pll2_pfd_400m.hw,
- &pll3_120m.hw,
- &pll3_pfd_540m.hw,
- NULL
-};
-
-#define ipu2_clk_parents ipu1_clk_parents
-
-#define DEF_CLK_MUX(c, r, b) \
-static struct clk_mux c##_mux = { \
- .reg = r, \
- .bp = BP_##r##_##b##_SEL, \
- .bm = BM_##r##_##b##_SEL, \
- .parents = &c##_parents[0], \
-}
-
-DEF_CLK_MUX(step_clk, CCSR, STEP);
-DEF_CLK_MUX(pll1_sw_clk, CCSR, PLL1_SW_CLK);
-DEF_CLK_MUX(axi_clk, CBCDR, AXI);
-DEF_CLK_MUX(periph_clk, CBCDR, PERIPH_CLK);
-DEF_CLK_MUX(periph_pre_clk, CBCMR, PRE_PERIPH_CLK);
-DEF_CLK_MUX(periph_clk2_clk, CBCMR, PERIPH_CLK2);
-DEF_CLK_MUX(periph2_clk, CBCDR, PERIPH2_CLK);
-DEF_CLK_MUX(periph2_pre_clk, CBCMR, PRE_PERIPH2_CLK);
-DEF_CLK_MUX(periph2_clk2_clk, CBCMR, PERIPH2_CLK2);
-DEF_CLK_MUX(gpu2d_axi_clk, CBCMR, GPU2D_AXI);
-DEF_CLK_MUX(gpu3d_axi_clk, CBCMR, GPU3D_AXI);
-DEF_CLK_MUX(gpu3d_core_clk, CBCMR, GPU3D_CORE);
-DEF_CLK_MUX(gpu3d_shader_clk, CBCMR, GPU3D_SHADER);
-DEF_CLK_MUX(pcie_axi_clk, CBCMR, PCIE_AXI);
-DEF_CLK_MUX(vdo_axi_clk, CBCMR, VDO_AXI);
-DEF_CLK_MUX(vpu_axi_clk, CBCMR, VPU_AXI);
-DEF_CLK_MUX(gpu2d_core_clk, CBCMR, GPU2D_CORE);
-DEF_CLK_MUX(ssi1_clk, CSCMR1, SSI1);
-DEF_CLK_MUX(ssi2_clk, CSCMR1, SSI2);
-DEF_CLK_MUX(ssi3_clk, CSCMR1, SSI3);
-DEF_CLK_MUX(usdhc1_clk, CSCMR1, USDHC1);
-DEF_CLK_MUX(usdhc2_clk, CSCMR1, USDHC2);
-DEF_CLK_MUX(usdhc3_clk, CSCMR1, USDHC3);
-DEF_CLK_MUX(usdhc4_clk, CSCMR1, USDHC4);
-DEF_CLK_MUX(emi_clk, CSCMR1, EMI);
-DEF_CLK_MUX(emi_slow_clk, CSCMR1, EMI_SLOW);
-DEF_CLK_MUX(esai_clk, CSCMR2, ESAI);
-DEF_CLK_MUX(ldb_di0_clk, CS2CDR, LDB_DI0);
-DEF_CLK_MUX(ldb_di1_clk, CS2CDR, LDB_DI1);
-DEF_CLK_MUX(enfc_clk, CS2CDR, ENFC);
-DEF_CLK_MUX(spdif_clk, CDCDR, SPDIF);
-DEF_CLK_MUX(asrc_serial_clk, CDCDR, ASRC_SERIAL);
-DEF_CLK_MUX(hsi_tx_clk, CDCDR, HSI_TX);
-DEF_CLK_MUX(ipu1_di0_pre_clk, CHSCCDR, IPU1_DI0_PRE);
-DEF_CLK_MUX(ipu1_di1_pre_clk, CHSCCDR, IPU1_DI1_PRE);
-DEF_CLK_MUX(ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE);
-DEF_CLK_MUX(ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE);
-DEF_CLK_MUX(ipu1_di0_clk, CHSCCDR, IPU1_DI0);
-DEF_CLK_MUX(ipu1_di1_clk, CHSCCDR, IPU1_DI1);
-DEF_CLK_MUX(ipu2_di0_clk, CSCDR2, IPU2_DI0);
-DEF_CLK_MUX(ipu2_di1_clk, CSCDR2, IPU2_DI1);
-DEF_CLK_MUX(ipu1_clk, CSCDR3, IPU1_HSP);
-DEF_CLK_MUX(ipu2_clk, CSCDR3, IPU2_HSP);
-
-static int _clk_enable(struct clk_hw *hw)
-{
- struct clk_gate *g = to_clk_imx(hw)->gate;
- u32 val;
-
- val = readl_relaxed(g->reg);
- val |= g->bm;
- writel_relaxed(val, g->reg);
-
- return 0;
-}
-
-static void _clk_disable(struct clk_hw *hw)
-{
- struct clk_gate *g = to_clk_imx(hw)->gate;
- u32 val;
-
- val = readl_relaxed(g->reg);
- val &= ~g->bm;
- writel_relaxed(val, g->reg);
-}
-
-static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
-{
- u32 min_pred, temp_pred, old_err, err;
-
- if (div >= 512) {
- *pred = 8;
- *podf = 64;
- } else if (div >= 8) {
- min_pred = (div - 1) / 64 + 1;
- old_err = 8;
- for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
- err = div % temp_pred;
- if (err == 0) {
- *pred = temp_pred;
- break;
- }
- err = temp_pred - err;
- if (err < old_err) {
- old_err = err;
- *pred = temp_pred;
- }
- }
- *podf = (div + *pred - 1) / *pred;
- } else if (div < 8) {
- *pred = div;
- *podf = 1;
- }
-}
-
-static int clk_busy_wait(struct clk_hw *hw)
-{
- int timeout = 0x100000;
- u32 bm;
-
- if (hw == &axi_clk.hw)
- bm = BM_CDHIPR_AXI_PODF_BUSY;
- else if (hw == &ahb_clk.hw)
- bm = BM_CDHIPR_AHB_PODF_BUSY;
- else if (hw == &mmdc_ch0_axi_clk.hw)
- bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
- else if (hw == &periph_clk.hw)
- bm = BM_CDHIPR_PERIPH_SEL_BUSY;
- else if (hw == &arm_clk.hw)
- bm = BM_CDHIPR_ARM_PODF_BUSY;
- else
- return -EINVAL;
-
- while ((readl_relaxed(CDHIPR) & bm) && --timeout)
- cpu_relax();
-
- if (unlikely(!timeout))
- return -EBUSY;
-
- return 0;
-}
-
-static int _clk_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
-{
- struct clk_div *d = to_clk_imx(hw)->div;
- u32 max_div = ((d->bm_pred >> d->bp_pred) + 1) *
- ((d->bm_podf >> d->bp_podf) + 1);
- u32 val, div, pred = 0, podf;
-
- *parent_rate = clk_get_rate(clk_get_parent(hw->clk));
-
- div = *parent_rate / rate;
- if (div == 0)
- div++;
-
- if ((*parent_rate / div != rate) || div > max_div)
- return -EINVAL;
-
- if (d->bm_pred) {
- calc_pred_podf_dividers(div, &pred, &podf);
- } else {
- pred = 1;
- podf = div;
- }
-
- val = readl_relaxed(d->reg);
- val &= ~(d->bm_pred | d->bm_podf);
- val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
- writel_relaxed(val, d->reg);
-
- if (hw == &axi_clk.hw || hw == &ahb_clk.hw ||
- hw == &mmdc_ch0_axi_clk.hw || hw == &arm_clk.hw)
- return clk_busy_wait(hw);
-
- return 0;
-}
-
-static long _clk_round_rate(struct clk_hw *hw, unsigned long rate)
-{
- struct clk_div *d = to_clk_imx(hw)->div;
- u32 div, div_max, pred = 0, podf;
- unsigned long parent_rate = clk_get_rate(clk_get_parent(hw->clk));
-
- div = parent_rate / rate;
- if (div == 0 || parent_rate % rate)
- div++;
-
- if (d->bm_pred) {
- calc_pred_podf_dividers(div, &pred, &podf);
- div = pred * podf;
- } else {
- div_max = (d->bm_podf >> d->bp_podf) + 1;
- if (div > div_max)
- div = div_max;
- }
-
- return parent_rate / div;
-}
-
-/* Clocks with only gate */
-static const struct clk_hw_ops clk_og_imx_ops = {
- .enable = _clk_enable,
- .disable = _clk_disable,
- .recalc_rate = _clk_recalc_rate,
- .get_parent = _clk_get_parent,
-};
-
-#define DEF_OG_CLK(c, p) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .gate = &c##_gate, \
- .parent = p, \
- .ops = &clk_og_imx_ops, \
-}
-
-DEF_OG_CLK(aips_tz1_clk, &ahb_clk.hw);
-DEF_OG_CLK(aips_tz2_clk, &ahb_clk.hw);
-DEF_OG_CLK(apbh_dma_clk, &ahb_clk.hw);
-DEF_OG_CLK(asrc_clk, &pll4_audio.hw);
-DEF_OG_CLK(can1_serial_clk, &pll3_usb_otg.hw);
-DEF_OG_CLK(can2_serial_clk, &pll3_usb_otg.hw);
-DEF_OG_CLK(can2_clk, &pll3_usb_otg.hw);
-DEF_OG_CLK(ecspi1_clk, &pll3_60m.hw);
-DEF_OG_CLK(ecspi2_clk, &pll3_60m.hw);
-DEF_OG_CLK(ecspi3_clk, &pll3_60m.hw);
-DEF_OG_CLK(ecspi4_clk, &pll3_60m.hw);
-DEF_OG_CLK(ecspi5_clk, &pll3_60m.hw);
-DEF_OG_CLK(enet_clk, &ipg_clk.hw);
-DEF_OG_CLK(gpt_serial_clk, &ipg_perclk.hw);
-DEF_OG_CLK(gpt_clk, &ipg_perclk.hw);
-DEF_OG_CLK(hdmi_iahb_clk, &ahb_clk.hw);
-DEF_OG_CLK(hdmi_isfr_clk, &pll3_pfd_540m.hw);
-DEF_OG_CLK(i2c1_clk, &ipg_perclk.hw);
-DEF_OG_CLK(i2c2_clk, &ipg_perclk.hw);
-DEF_OG_CLK(i2c3_clk, &ipg_perclk.hw);
-DEF_OG_CLK(iim_clk, &ipg_clk.hw);
-DEF_OG_CLK(mlb_clk, &pll6_mlb.hw);
-DEF_OG_CLK(mmdc_ch0_ipg_clk, &ipg_clk.hw);
-DEF_OG_CLK(mmdc_ch1_ipg_clk, &ipg_clk.hw);
-DEF_OG_CLK(openvg_axi_clk, &axi_clk.hw);
-DEF_OG_CLK(pwm1_clk, &ipg_perclk.hw);
-DEF_OG_CLK(pwm2_clk, &ipg_perclk.hw);
-DEF_OG_CLK(pwm3_clk, &ipg_perclk.hw);
-DEF_OG_CLK(pwm4_clk, &ipg_perclk.hw);
-DEF_OG_CLK(gpmi_bch_apb_clk, &usdhc3_clk.hw);
-DEF_OG_CLK(gpmi_bch_clk, &usdhc4_clk.hw);
-DEF_OG_CLK(gpmi_apb_clk, &usdhc3_clk.hw);
-DEF_OG_CLK(gpmi_io_clk, &enfc_clk.hw);
-DEF_OG_CLK(sdma_clk, &ahb_clk.hw);
-DEF_OG_CLK(spba_clk, &ipg_clk.hw);
-DEF_OG_CLK(uart_serial_clk, &pll3_usb_otg.hw);
-DEF_OG_CLK(usboh3_clk, &ipg_clk.hw);
-
-/* Clocks with only divider */
-static const struct clk_hw_ops clk_od_imx_ops = {
- .recalc_rate = _clk_recalc_rate,
- .round_rate = _clk_round_rate,
- .set_rate = _clk_set_rate,
- .get_parent = _clk_get_parent,
-};
-
-#define DEF_OD_CLK(c, p) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .div = &c##_div, \
- .parent = p, \
- .ops = &clk_od_imx_ops, \
-}
-
-DEF_OD_CLK(arm_clk, &pll1_sw_clk.hw);
-DEF_OD_CLK(ahb_clk, &periph_clk.hw);
-DEF_OD_CLK(ipg_clk, &ahb_clk.hw);
-DEF_OD_CLK(ipg_perclk, &ipg_clk.hw);
-
-/* Clocks with only multiplexer */
-static const struct clk_hw_ops clk_om_imx_ops = {
- .recalc_rate = _clk_recalc_rate,
- .get_parent = _clk_get_parent,
- /* .set_parent = _clk_set_parent, */
-};
-
-#define DEF_OM_CLK(c) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .mux = &c##_mux, \
- .ops = &clk_om_imx_ops, \
-}
-
-DEF_OM_CLK(step_clk);
-DEF_OM_CLK(pll1_sw_clk);
-DEF_OM_CLK(periph_pre_clk);
-DEF_OM_CLK(periph2_pre_clk);
-DEF_OM_CLK(periph2_clk);
-DEF_OM_CLK(periph_clk);
-DEF_OM_CLK(gpu2d_axi_clk);
-DEF_OM_CLK(gpu3d_axi_clk);
-
-/* Clocks without gate */
-static const struct clk_hw_ops clk_ng_imx_ops = {
- .recalc_rate = _clk_recalc_rate,
- .round_rate = _clk_round_rate,
- .set_rate = _clk_set_rate,
- .get_parent = _clk_get_parent,
- /* .set_parent = _clk_set_parent, */
-};
-
-#define DEF_NG_CLK(c) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .div = &c##_div, \
- .mux = &c##_mux, \
- .ops = &clk_ng_imx_ops, \
-}
-
-DEF_NG_CLK(periph_clk2_clk);
-DEF_NG_CLK(periph2_clk2_clk);
-DEF_NG_CLK(axi_clk);
-DEF_NG_CLK(emi_clk);
-DEF_NG_CLK(ipu1_di0_pre_clk);
-DEF_NG_CLK(ipu1_di1_pre_clk);
-DEF_NG_CLK(ipu2_di0_pre_clk);
-DEF_NG_CLK(ipu2_di1_pre_clk);
-DEF_NG_CLK(asrc_serial_clk);
-
-/* Clocks without divider */
-static const struct clk_hw_ops clk_nd_imx_ops = {
- .enable = _clk_enable,
- .disable = _clk_disable,
- .recalc_rate = _clk_recalc_rate,
- .get_parent = _clk_get_parent,
- /* .set_parent = _clk_set_parent, */
-};
-
-#define DEF_ND_CLK(c) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .gate = &c##_gate, \
- .mux = &c##_mux, \
- .ops = &clk_nd_imx_ops, \
-}
-
-DEF_ND_CLK(ipu1_di0_clk);
-DEF_ND_CLK(ipu1_di1_clk);
-DEF_ND_CLK(ipu2_di0_clk);
-DEF_ND_CLK(ipu2_di1_clk);
-DEF_ND_CLK(vdo_axi_clk);
-
-/* Clocks without multiplexer */
-static const struct clk_hw_ops clk_nm_imx_ops = {
- .enable = _clk_enable,
- .disable = _clk_disable,
- .recalc_rate = _clk_recalc_rate,
- .round_rate = _clk_round_rate,
- .set_rate = _clk_set_rate,
- .get_parent = _clk_get_parent,
-};
-
-#define DEF_NM_CLK(c, p) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .gate = &c##_gate, \
- .div = &c##_div, \
- .parent = p, \
- .ops = &clk_nm_imx_ops, \
-}
-
-DEF_NM_CLK(can1_clk, &pll3_usb_otg.hw);
-DEF_NM_CLK(mmdc_ch0_axi_clk, &periph_clk.hw);
-DEF_NM_CLK(mmdc_ch1_axi_clk, &periph2_clk.hw);
-DEF_NM_CLK(uart_clk, &pll3_80m.hw);
-
-/* Clocks with all of gate, divider and multiplexer */
-static const struct clk_hw_ops clk_imx_ops = {
- .enable = _clk_enable,
- .disable = _clk_disable,
- .recalc_rate = _clk_recalc_rate,
- .round_rate = _clk_round_rate,
- .set_rate = _clk_set_rate,
- .get_parent = _clk_get_parent,
- /* .set_parent = _clk_set_parent, */
-};
-
-#define DEF_CLK(c) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .gate = &c##_gate, \
- .div = &c##_div, \
- .mux = &c##_mux, \
- .ops = &clk_imx_ops, \
-}
-
-DEF_CLK(esai_clk);
-DEF_CLK(gpu2d_core_clk);
-DEF_CLK(gpu3d_core_clk);
-DEF_CLK(gpu3d_shader_clk);
-DEF_CLK(enfc_clk);
-DEF_CLK(ipu1_clk);
-DEF_CLK(ipu2_clk);
-DEF_CLK(hsi_tx_clk);
-DEF_CLK(spdif_clk);
-DEF_CLK(ssi1_clk);
-DEF_CLK(ssi2_clk);
-DEF_CLK(ssi3_clk);
-DEF_CLK(usdhc1_clk);
-DEF_CLK(usdhc2_clk);
-DEF_CLK(usdhc3_clk);
-DEF_CLK(usdhc4_clk);
-DEF_CLK(emi_slow_clk);
-DEF_CLK(vpu_axi_clk);
-
-/*
- * ldb_di_clk
- */
static unsigned long ldb_di_clk_recalc_rate(struct clk_hw *hw)
{
- u32 val = readl_relaxed(CSCMR2);
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 mask = ((1 << d->width_podf) - 1) << d->shift_podf;
+ u32 val = readl_relaxed(d->reg);
- val &= (hw == &ldb_di0_clk.hw) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
- BM_CSCMR2_LDB_DI1_IPU_DIV;
- if (val)
+ if (val & mask)
return clk_get_rate(clk_get_parent(hw->clk)) / 7;
else
return clk_get_rate(clk_get_parent(hw->clk)) * 2 / 7;
@@ -1668,16 +385,18 @@ static unsigned long ldb_di_clk_recalc_rate(struct clk_hw *hw)
static int ldb_di_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- u32 val = readl_relaxed(CSCMR2);
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 mask = ((1 << d->width_podf) - 1) << d->shift_podf;
+ u32 val = readl_relaxed(d->reg);
*parent_rate = clk_get_rate(clk_get_parent(hw->clk));
if (rate * 7 <= *parent_rate + *parent_rate / 20)
- val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
+ val |= mask;
else
- val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
+ val &= ~mask;
- writel_relaxed(val, CSCMR2);
+ writel_relaxed(val, d->reg);
return 0;
}
@@ -1693,218 +412,17 @@ static long ldb_di_clk_round_rate(struct clk_hw *hw, unsigned long rate)
}
static const struct clk_hw_ops ldb_di_clk_ops = {
- .enable = _clk_enable,
- .disable = _clk_disable,
+ .enable = clk_imx_enable,
+ .disable = clk_imx_disable,
.recalc_rate = ldb_di_clk_recalc_rate,
.round_rate = ldb_di_clk_round_rate,
.set_rate = ldb_di_clk_set_rate,
- .get_parent = _clk_get_parent,
-};
-
-#define DEF_LDB_DI_CLK(c) \
-static struct clk_hw_imx c = { \
- .name = #c, \
- .gate = &c##_gate, \
- .mux = &c##_mux, \
- .ops = &ldb_di_clk_ops, \
-}
-
-DEF_LDB_DI_CLK(ldb_di0_clk);
-DEF_LDB_DI_CLK(ldb_di1_clk);
-
-/*
- * pcie_axi_clk
- */
-static int pcie_axi_clk_enable(struct clk_hw *hw)
-{
- u32 val;
-
- val = readl_relaxed(PLL8_ENET);
- val |= BM_PLL_ENET_EN_PCIE;
- writel_relaxed(val, PLL8_ENET);
-
- return _clk_enable(hw);
-}
-
-static void pcie_axi_clk_disable(struct clk_hw *hw)
-{
- u32 val;
-
- _clk_disable(hw);
-
- val = readl_relaxed(PLL8_ENET);
- val &= BM_PLL_ENET_EN_PCIE;
- writel_relaxed(val, PLL8_ENET);
-}
-
-static const struct clk_hw_ops pcie_axi_clk_ops = {
- .enable = pcie_axi_clk_enable,
- .disable = pcie_axi_clk_disable,
- .recalc_rate = _clk_recalc_rate,
- .get_parent = _clk_get_parent,
-};
-
-static struct clk_hw_imx pcie_axi_clk = {
- .name = "pcie_axi_clk",
- .gate = &pcie_axi_clk_gate,
- .mux = &pcie_axi_clk_mux,
- .ops = &pcie_axi_clk_ops,
-};
-
-/*
- * pcie_axi_clk
- */
-static int sata_clk_enable(struct clk_hw *hw)
-{
- u32 val;
-
- val = readl_relaxed(PLL8_ENET);
- val |= BM_PLL_ENET_EN_SATA;
- writel_relaxed(val, PLL8_ENET);
-
- return _clk_enable(hw);
-}
-
-static void sata_clk_disable(struct clk_hw *hw)
-{
- u32 val;
-
- _clk_disable(hw);
-
- val = readl_relaxed(PLL8_ENET);
- val &= BM_PLL_ENET_EN_SATA;
- writel_relaxed(val, PLL8_ENET);
-}
-
-static const struct clk_hw_ops sata_clk_ops = {
- .enable = sata_clk_enable,
- .disable = sata_clk_disable,
- .recalc_rate = _clk_recalc_rate,
- .get_parent = _clk_get_parent,
-};
-
-static struct clk_hw_imx sata_clk = {
- .name = "sata_clk",
- .gate = &sata_clk_gate,
- .ops = &sata_clk_ops,
- .parent = &ipg_clk.hw,
-};
-
-/*
- * clk_hw_imx arrays
- */
-static struct clk_hw_imx *imx_clks_1[] = {
- &pll1_sys,
- &pll2_bus,
- &pll3_usb_otg,
- &pll4_audio,
- &pll5_video,
- &pll7_usb_host,
- &pll8_enet,
- &pll2_pfd_352m,
- &pll2_pfd_594m,
- &pll2_pfd_400m,
- &pll3_pfd_720m,
- &pll3_pfd_540m,
- &pll3_pfd_508m,
- &pll3_pfd_454m,
- &step_clk,
- &pll1_sw_clk,
-};
-
-static struct clk_hw_imx *imx_clks_2[] = {
- &arm_clk,
- &periph_pre_clk,
- &periph_clk2_clk,
- &periph2_pre_clk,
- &periph2_clk2_clk,
- &periph_clk,
- &periph2_clk,
- &ahb_clk,
- &ipg_clk,
- &ipg_perclk,
- &axi_clk,
- &emi_clk,
- &emi_slow_clk,
- &mmdc_ch0_axi_clk,
- &mmdc_ch1_axi_clk,
- &mmdc_ch0_ipg_clk,
- &mmdc_ch1_ipg_clk,
- &gpu2d_axi_clk,
- &gpu3d_axi_clk,
- &openvg_axi_clk,
- &gpu2d_core_clk,
- &gpu3d_core_clk,
- &gpu3d_shader_clk,
- &vdo_axi_clk,
- &vpu_axi_clk,
- &pcie_axi_clk,
- &aips_tz1_clk,
- &aips_tz2_clk,
- &apbh_dma_clk,
- &can1_serial_clk,
- &can2_serial_clk,
- &can1_clk,
- &can2_clk,
- &ecspi1_clk,
- &ecspi2_clk,
- &ecspi3_clk,
- &ecspi4_clk,
- &ecspi5_clk,
- &enet_clk,
- &gpt_serial_clk,
- &gpt_clk,
- &i2c1_clk,
- &i2c2_clk,
- &i2c3_clk,
- &iim_clk,
- &mlb_clk,
- &pwm1_clk,
- &pwm2_clk,
- &pwm3_clk,
- &pwm4_clk,
- &sdma_clk,
- &spba_clk,
- &uart_serial_clk,
- &usboh3_clk,
- &ldb_di0_clk,
- &ldb_di1_clk,
- &ipu1_di0_pre_clk,
- &ipu1_di1_pre_clk,
- &ipu2_di0_pre_clk,
- &ipu2_di1_pre_clk,
- &ipu1_di0_clk,
- &ipu1_di1_clk,
- &ipu2_di0_clk,
- &ipu2_di1_clk,
- &ipu1_clk,
- &ipu2_clk,
- &hdmi_iahb_clk,
- &hdmi_isfr_clk,
- &uart_clk,
- &hsi_tx_clk,
- &ssi1_clk,
- &ssi2_clk,
- &ssi3_clk,
- &esai_clk,
- &spdif_clk,
- &asrc_serial_clk,
- &asrc_clk,
- &enfc_clk,
- &usdhc1_clk,
- &usdhc2_clk,
- &usdhc3_clk,
- &usdhc4_clk,
- &gpmi_bch_apb_clk,
- &gpmi_bch_clk,
- &gpmi_apb_clk,
- &gpmi_io_clk,
- &sata_clk,
+ .get_parent = clk_imx_get_parent,
};
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
{
- u32 val = readl_relaxed(CLPCR);
+ u32 val = readl_relaxed(ccm_base + CLPCR);
val &= ~BM_CLPCR_LPM;
switch (mode) {
@@ -1932,94 +450,211 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
default:
return -EINVAL;
}
- writel_relaxed(val, CLPCR);
+ writel_relaxed(val, ccm_base + CLPCR);
return 0;
}
-static struct map_desc imx6q_clock_desc[] = {
- imx_map_entry(MX6Q, CCM, MT_DEVICE),
- imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
+struct clk_imx_data {
+ void *ptr;
+ int size;
};
-int __init mx6q_clocks_init(void)
+static struct clk *clk_hw_imx_get(struct of_phandle_args *a, void *data)
+{
+ struct clk_imx_data *d = data;
+ struct clk_hw_imx *p = d->ptr + d->size * a->args[0];
+ return p->hw.clk;
+}
+
+int of_clk_imx6q_register(struct device_node *np)
{
- struct device_node *np;
- void __iomem *base;
- int i, irq;
-
- iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
-
- /* retrieve the freqency of fixed clocks from device tree */
- for_each_compatible_node(np, NULL, "fixed-clock") {
- u32 rate;
- if (of_property_read_u32(np, "clock-frequency", &rate))
- continue;
-
- if (of_device_is_compatible(np, "fsl,imx-ckil"))
- ckil_clk.rate = rate;
- else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
- ckih_clk.rate = rate;
- else if (of_device_is_compatible(np, "fsl,imx-osc"))
- osc_clk.rate = rate;
+ const struct clk_hw_ops *ops = &clk_imx_ops;
+ void __iomem *base = ccm_base;
+ struct clk_imx_data *data;
+ struct clk_hw_imx *p;
+ void *q;
+ const char *name;
+ size_t size = sizeof(struct clk_hw_imx);
+ bool has_gate, has_div, has_mux, has_div_busy, has_mux_busy;
+ int gate_set_bit, powerup_set_bit;
+ u32 num, len;
+ int i, j, num_parents = 1;
+
+ has_gate = has_div = has_mux = has_div_busy = has_mux_busy = false;
+ gate_set_bit = powerup_set_bit = 0;
+
+ if (of_property_read_u32(np, "#clock-cells", &num))
+ return -EINVAL;
+
+ if (of_find_property(np, "imx,clock-gate", &len)) {
+ size += sizeof(struct clk_imx_gate);
+ has_gate = true;
+ }
+
+ if (of_find_property(np, "imx,clock-divider", &len)) {
+ size += sizeof(struct clk_imx_div);
+ has_div = true;
+ if (of_find_property(np, "imx,busy-divider", &len)) {
+ size += sizeof(struct clk_imx_busy);
+ has_div_busy = true;
+ }
+ }
+
+ if (of_find_property(np, "imx,clock-multiplexer", &len)) {
+ struct device_node *inp;
+ i = num_parents = 0;
+ do {
+ inp = of_parse_phandle(np, "clock-input", i);
+ if (!inp)
+ break;
+ of_property_read_u32(inp, "#clock-cells", &j);
+ i += j + 1;
+ num_parents++;
+ } while (1);
+ size += sizeof(struct clk_imx_mux) + num_parents * sizeof(q);
+ has_mux = true;
+ if (of_find_property(np, "imx,busy-multiplexer", &len)) {
+ size += sizeof(struct clk_imx_busy);
+ has_mux_busy = true;
+ }
}
- clk_register(NULL, &clk_dummy_ops, &dummy_clk.hw, "dummy_clk", 0);
- clk_register(NULL, &clk_fixed_ops, &ckil_clk.hw, "ckil_clk", CLK_IS_ROOT);
- clk_register(NULL, &clk_fixed_ops, &ckih_clk.hw, "ckih_clk", CLK_IS_ROOT);
- clk_register(NULL, &clk_fixed_ops, &osc_clk.hw, "osc_clk", CLK_IS_ROOT);
-
- for (i = 0; i < ARRAY_SIZE(imx_clks_1); i++)
- clk_register(NULL, imx_clks_1[i]->ops, &imx_clks_1[i]->hw,
- imx_clks_1[i]->name, 0);
-
- clk_register(NULL, &clk_div_fixed_ops, &pll2_200m.hw, "pll2_200m", 0);
- clk_register(NULL, &clk_div_fixed_ops, &pll3_120m.hw, "pll3_120m", 0);
- clk_register(NULL, &clk_div_fixed_ops, &pll3_80m.hw, "pll3_80m", 0);
- clk_register(NULL, &clk_div_fixed_ops, &pll3_60m.hw, "pll3_60m", 0);
-
- for (i = 0; i < ARRAY_SIZE(imx_clks_2); i++)
- clk_register(NULL, imx_clks_2[i]->ops, &imx_clks_2[i]->hw,
- imx_clks_2[i]->name, 0);
-
- clkdev_add(clkdev_alloc(uart_clk.hw.clk, NULL, "2020000.uart"));
- clkdev_add(clkdev_alloc(uart_clk.hw.clk, NULL, "21e8000.uart"));
- clkdev_add(clkdev_alloc(uart_clk.hw.clk, NULL, "21ec000.uart"));
- clkdev_add(clkdev_alloc(uart_clk.hw.clk, NULL, "21f0000.uart"));
- clkdev_add(clkdev_alloc(uart_clk.hw.clk, NULL, "21f4000.uart"));
- clkdev_add(clkdev_alloc(enet_clk.hw.clk, NULL, "2188000.enet"));
- clkdev_add(clkdev_alloc(usdhc1_clk.hw.clk, NULL, "2190000.usdhc"));
- clkdev_add(clkdev_alloc(usdhc2_clk.hw.clk, NULL, "2194000.usdhc"));
- clkdev_add(clkdev_alloc(usdhc3_clk.hw.clk, NULL, "2198000.usdhc"));
- clkdev_add(clkdev_alloc(usdhc4_clk.hw.clk, NULL, "219c000.usdhc"));
- clkdev_add(clkdev_alloc(i2c1_clk.hw.clk, NULL, "21a0000.i2c"));
- clkdev_add(clkdev_alloc(i2c2_clk.hw.clk, NULL, "21a4000.i2c"));
- clkdev_add(clkdev_alloc(i2c3_clk.hw.clk, NULL, "21a8000.i2c"));
- clkdev_add(clkdev_alloc(ecspi1_clk.hw.clk, NULL, "2008000.ecspi"));
- clkdev_add(clkdev_alloc(ecspi2_clk.hw.clk, NULL, "200c000.ecspi"));
- clkdev_add(clkdev_alloc(ecspi3_clk.hw.clk, NULL, "2010000.ecspi"));
- clkdev_add(clkdev_alloc(ecspi4_clk.hw.clk, NULL, "2014000.ecspi"));
- clkdev_add(clkdev_alloc(ecspi5_clk.hw.clk, NULL, "2018000.ecspi"));
- clkdev_add(clkdev_alloc(sdma_clk.hw.clk, NULL, "20ec000.sdma"));
- clkdev_add(clkdev_alloc(dummy_clk.hw.clk, NULL, "20bc000.wdog"));
- clkdev_add(clkdev_alloc(dummy_clk.hw.clk, NULL, "20c0000.wdog"));
+ q = kzalloc(size * num + sizeof(data), GFP_KERNEL);
+ if (!q)
+ return -ENOMEM;
+ data = q + size * num;
+ data->ptr = p = q;
+ data->size = size;
+
+ if (of_device_is_compatible(np, "fsl,imx6q-pll-sys")) {
+ base = anatop_base;
+ ops = &pll_sys_ops;
+ } else if (of_device_is_compatible(np, "fsl,imx6q-pll-usb")) {
+ base = anatop_base;
+ ops = &pll_ops;
+ powerup_set_bit = true;
+ } else if (of_device_is_compatible(np, "fsl,imx6q-pll-av")) {
+ base = anatop_base;
+ ops = &pll_av_ops;
+ } else if (of_device_is_compatible(np, "fsl,imx6q-pll-enet")) {
+ base = anatop_base;
+ ops = &pll_enet_ops;
+ } else if (of_device_is_compatible(np, "fsl,imx6q-pll")) {
+ base = anatop_base;
+ ops = &pll_ops;
+ } else if (of_device_is_compatible(np, "fsl,imx6q-pfd")) {
+ base = anatop_base;
+ ops = &pfd_ops;
+ gate_set_bit = true;
+ } else if (of_device_is_compatible(np, "fsl,imx6q-ldb-di-clock")) {
+ base = ccm_base;
+ ops = &ldb_di_clk_ops;
+ }
+
+ for (i = 0; i < num; i++) {
+ q = p + 1;
+ if (has_gate) {
+ u32 val[2];
+ of_property_read_u32_array_index(np, "imx,clock-gate",
+ val, i * 2, 2);
+ p->gate = q;
+ p->gate->reg = base + val[0];
+ p->gate->mask = val[1];
+ p->gate->gate_set_bit = gate_set_bit;
+ p->gate->powerup_set_bit = powerup_set_bit;
+ q += sizeof(*p->gate);
+ }
+
+ if (has_div) {
+ u32 val[5];
+ of_property_read_u32_array_index(np,
+ "imx,clock-divider", val, i * 5, 5);
+ p->div = q;
+ p->div->reg = base + val[0];
+ p->div->shift_pred = val[1];
+ p->div->width_pred = val[2];
+ p->div->shift_podf = val[3];
+ p->div->width_podf = val[4];
+ q += sizeof(*p->div);
+
+ if (has_div_busy) {
+ of_property_read_u32_array_index(np,
+ "imx,busy-divider", val, i * 2, 2);
+ p->div->busy = q;
+ p->div->busy->reg = base + val[0];
+ p->div->busy->mask = val[1];
+ q += sizeof(*p->div->busy);
+ }
+ }
+
+ if (has_mux) {
+ u32 val[3];
+ of_property_read_u32_array_index(np,
+ "imx,clock-multiplexer", val, i * 3, 3);
+ p->mux = q;
+ p->mux->reg = base + val[0];
+ p->mux->shift = val[1];
+ p->mux->width = val[2];
+ q += sizeof(*p->mux);
+
+ if (has_mux_busy) {
+ of_property_read_u32_array_index(np,
+ "imx,busy-multiplexer", val, i * 2, 2);
+ p->mux->busy = q;
+ p->mux->busy->reg = base + val[0];
+ p->mux->busy->mask = val[1];
+ q += sizeof(*p->mux->busy);
+ }
+
+ p->mux->parents = q;
+ for (j = 0; j < num_parents; j++)
+ p->mux->parents[j] = of_clk_get(np, j)->hw;
+ p->mux->num_parents = num_parents;
+ } else {
+ p->parent = of_clk_get(np, 0)->hw;
+ }
+
+ of_property_read_string_index(np, "clock-output-name",
+ i, &name);
+ clk_register(NULL, ops, &p->hw, name, 0);
+ p = (void *) p + size;
+ }
+
+ return of_clk_add_provider(np, clk_hw_imx_get, data);
+}
+
+int __init mx6q_clocks_init(void)
+{
+ struct device_node *np, *from;
+ struct clk *clk;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm");
+ ccm_base = of_iomap(np, 0);
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+ anatop_base = of_iomap(np, 0);
+ WARN_ON(!ccm_base || !anatop_base);
+
+ from = of_find_node_by_name(NULL, "clocks");
+ for_each_child_of_node(from, np)
+ if (of_device_is_compatible(np, "dummy-clock"))
+ of_clk_dummy_register(np);
+ else if (of_device_is_compatible(np, "fixed-clock"))
+ of_clk_fixed_register(np);
+ else if (of_device_is_compatible(np, "divider-fixed-clock"))
+ of_clk_divider_fixed_register(np);
+ else
+ of_clk_imx6q_register(np);
/* only keep necessary clocks on */
- writel_relaxed(0x3 << CG0 | 0x3 << CG1 | 0x3 << CG2, CCGR0);
- writel_relaxed(0, CCGR1);
- writel_relaxed(0x3 << CG8 | 0x3 << CG9 | 0x3 << CG10, CCGR2);
- writel_relaxed(0x3 << CG10 | 0x3 << CG12, CCGR3);
- writel_relaxed(0x3 << CG4 | 0x3 << CG6 | 0x3 << CG7, CCGR4);
- writel_relaxed(0x3 << CG0, CCGR5);
- writel_relaxed(0, CCGR6);
- writel_relaxed(0, CCGR7);
-
- clk_prepare(uart_serial_clk.hw.clk);
- clk_enable(uart_serial_clk.hw.clk);
- clk_prepare(uart_clk.hw.clk);
- clk_enable(uart_clk.hw.clk);
- clk_prepare(gpt_serial_clk.hw.clk);
- clk_enable(gpt_serial_clk.hw.clk);
+ writel_relaxed(0x0000003f, ccm_base + CCGR0);
+ writel_relaxed(0x00f00000, ccm_base + CCGR1);
+ writel_relaxed(0x003f0000, ccm_base + CCGR2);
+ writel_relaxed(0x03300000, ccm_base + CCGR3);
+ writel_relaxed(0x0000f300, ccm_base + CCGR4);
+ writel_relaxed(0x0f000003, ccm_base + CCGR5);
+ writel_relaxed(0x0, ccm_base + CCGR6);
+ writel_relaxed(0x0, ccm_base + CCGR7);
/*
* Before pinctrl API is available, we have to rely on the pad
@@ -2031,16 +666,14 @@ int __init mx6q_clocks_init(void)
* At that time, usdhc driver can call pinctrl API to change pad
* configuration dynamically per different usdhc clock settings.
*/
- clk_set_rate(usdhc1_clk.hw.clk, 49500000);
- clk_set_rate(usdhc2_clk.hw.clk, 49500000);
- clk_set_rate(usdhc3_clk.hw.clk, 49500000);
- clk_set_rate(usdhc4_clk.hw.clk, 49500000);
+ for_each_compatible_node(np, NULL, "fsl,imx6q-usdhc") {
+ clk = of_clk_get(np, 0);
+ clk_set_rate(clk, 49500000);
+ }
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
- base = of_iomap(np, 0);
- WARN_ON(!base);
- irq = irq_of_parse_and_map(np, 0);
- mxc_timer_init(gpt_clk.hw.clk, base, irq);
+ mxc_timer_init(of_clk_get(np, 0), of_iomap(np, 0),
+ irq_of_parse_and_map(np, 0));
return 0;
}
diff --git a/arch/arm/mach-imx/clock.c b/arch/arm/mach-imx/clock.c
new file mode 100644
index 0000000..6243622
--- /dev/null
+++ b/arch/arm/mach-imx/clock.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/init.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/processor.h>
+#include "clock.h"
+
+int clk_imx_enable(struct clk_hw *hw)
+{
+ struct clk_imx_gate *g = to_clk_imx(hw)->gate;
+ u32 val;
+
+ if (!g)
+ return 0;
+
+ val = readl_relaxed(g->reg);
+ if (g->gate_set_bit)
+ val &= ~g->mask;
+ else
+ val |= g->mask;
+ writel_relaxed(val, g->reg);
+
+ return 0;
+}
+
+void clk_imx_disable(struct clk_hw *hw)
+{
+ struct clk_imx_gate *g = to_clk_imx(hw)->gate;
+ u32 val;
+
+ if (!g)
+ return;
+
+ val = readl_relaxed(g->reg);
+ if (g->gate_set_bit)
+ val |= g->mask;
+ else
+ val &= ~g->mask;
+ writel_relaxed(val, g->reg);
+}
+
+struct clk *clk_imx_get_parent(struct clk_hw *hw)
+{
+ struct clk_imx_mux *m = to_clk_imx(hw)->mux;
+ u32 i;
+
+ if (!m)
+ return to_clk_imx(hw)->parent->clk;
+
+ i = readl_relaxed(m->reg) >> m->shift;
+ i &= (1 << m->width) - 1;
+
+ if (i >= m->num_parents)
+ return ERR_PTR(-EINVAL);
+
+ return m->parents[i]->clk;
+}
+
+static int clk_imx_busy_wait(struct clk_imx_busy *b)
+{
+ int timeout = 0x100000;
+
+ while ((readl_relaxed(b->reg) & b->mask) && --timeout)
+ cpu_relax();
+
+ if (unlikely(!timeout))
+ return -EBUSY;
+
+ return 0;
+}
+
+static int clk_imx_set_parent(struct clk_hw *hw, struct clk *parent)
+{
+ struct clk_imx_mux *m = to_clk_imx(hw)->mux;
+ int i;
+ u32 val;
+
+ if (!m)
+ return -EINVAL;
+
+ for (i = 0; i < m->num_parents; i++)
+ if (parent == m->parents[i]->clk)
+ break;
+
+ if (i == m->num_parents)
+ return -EINVAL;
+
+ val = readl_relaxed(m->reg);
+ val &= ~(((1 << m->width) - 1) << m->shift);
+ val |= i << m->shift;
+ writel_relaxed(val, m->reg);
+
+ return (m->busy) ? clk_imx_busy_wait(m->busy) : 0;
+}
+
+static unsigned long clk_imx_recalc_rate(struct clk_hw *hw)
+{
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 val, pred, podf;
+
+ if (!d)
+ return clk_get_rate(clk_get_parent(hw->clk));
+
+ val = readl_relaxed(d->reg);
+ pred = (val >> d->shift_pred & ((1 << d->width_pred) - 1)) + 1;
+ podf = (val >> d->shift_podf & ((1 << d->width_podf) - 1)) + 1;
+
+ return clk_get_rate(clk_get_parent(hw->clk)) / (pred * podf);
+}
+
+static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
+{
+ u32 min_pred, temp_pred, old_err, err;
+
+ if (div >= 512) {
+ *pred = 8;
+ *podf = 64;
+ } else if (div >= 8) {
+ min_pred = (div - 1) / 64 + 1;
+ old_err = 8;
+ for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
+ err = div % temp_pred;
+ if (err == 0) {
+ *pred = temp_pred;
+ break;
+ }
+ err = temp_pred - err;
+ if (err < old_err) {
+ old_err = err;
+ *pred = temp_pred;
+ }
+ }
+ *podf = (div + *pred - 1) / *pred;
+ } else if (div < 8) {
+ *pred = div;
+ *podf = 1;
+ }
+}
+
+static long clk_imx_round_rate(struct clk_hw *hw, unsigned long rate)
+{
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 div, div_max, pred = 0, podf;
+ unsigned long parent_rate = clk_get_rate(clk_get_parent(hw->clk));
+
+ if (!d)
+ return -EINVAL;
+
+ div = parent_rate / rate;
+ if (div == 0 || parent_rate % rate)
+ div++;
+
+ if (d->width_pred) {
+ calc_pred_podf_dividers(div, &pred, &podf);
+ div = pred * podf;
+ } else {
+ div_max = 1 << d->width_podf;
+ if (div > div_max)
+ div = div_max;
+ }
+
+ return parent_rate / div;
+}
+
+static int clk_imx_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_imx_div *d = to_clk_imx(hw)->div;
+ u32 val, div, pred = 0, podf;
+
+ if (!d)
+ return -EINVAL;
+
+ *parent_rate = clk_get_rate(clk_get_parent(hw->clk));
+
+ div = *parent_rate / rate;
+ if (div == 0)
+ div++;
+
+ if ((*parent_rate / div != rate) || div >
+ (1 << d->width_pred) * (1 << d->width_podf))
+ return -EINVAL;
+
+ if (d->width_pred) {
+ calc_pred_podf_dividers(div, &pred, &podf);
+ } else {
+ pred = 1;
+ podf = div;
+ }
+
+ val = readl_relaxed(d->reg);
+ val &= ~(((1 << d->width_pred) - 1) << d->shift_pred);
+ val &= ~(((1 << d->width_podf) - 1) << d->shift_podf);
+ val |= (pred - 1) << d->shift_pred;
+ val |= (podf - 1) << d->shift_podf;
+ writel_relaxed(val, d->reg);
+
+ return (d->busy) ? clk_imx_busy_wait(d->busy) : 0;
+}
+
+const struct clk_hw_ops clk_imx_ops = {
+ .enable = clk_imx_enable,
+ .disable = clk_imx_disable,
+ .recalc_rate = clk_imx_recalc_rate,
+ .round_rate = clk_imx_round_rate,
+ .set_rate = clk_imx_set_rate,
+ .get_parent = clk_imx_get_parent,
+ .set_parent = clk_imx_set_parent,
+};
diff --git a/arch/arm/mach-imx/clock.h b/arch/arm/mach-imx/clock.h
new file mode 100644
index 0000000..49e42b9
--- /dev/null
+++ b/arch/arm/mach-imx/clock.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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
+ */
+#ifndef __MACH_IMX_CLK_H
+#define __MACH_IMX_CLK_H
+
+#include <linux/types.h>
+#include <linux/clk.h>
+
+struct clk_imx_busy {
+ void __iomem *reg;
+ u32 mask;
+};
+
+struct clk_imx_gate {
+ void __iomem *reg;
+ u32 mask;
+ int gate_set_bit;
+ int powerup_set_bit;
+};
+
+struct clk_imx_div {
+ void __iomem *reg;
+ u32 shift_pred;
+ u32 width_pred;
+ u32 shift_podf;
+ u32 width_podf;
+ struct clk_imx_busy *busy;
+};
+
+struct clk_imx_mux {
+ void __iomem *reg;
+ u32 shift;
+ u32 width;
+ struct clk_imx_busy *busy;
+ struct clk_hw **parents;
+ int num_parents;
+};
+
+struct clk_hw_imx {
+ struct clk_hw hw;
+ struct clk_imx_gate *gate;
+ struct clk_imx_div *div;
+ struct clk_imx_mux *mux;
+ struct clk_hw *parent;
+};
+
+#define to_clk_imx(c) container_of(c, struct clk_hw_imx, hw)
+
+extern const struct clk_hw_ops clk_imx_ops;
+
+extern int clk_imx_enable(struct clk_hw *hw);
+extern void clk_imx_disable(struct clk_hw *hw);
+extern struct clk *clk_imx_get_parent(struct clk_hw *hw);
+
+#endif /* __MACH_IMX_CLK_H */
--
1.7.4.1
More information about the devicetree-discuss
mailing list