* [RFC PATCH 0/3] Convert imx6 clock to device tree
@ 2011-11-22 1:48 Shawn Guo
[not found] ` <1321926536-671-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-11-22 1:48 ` [RFC PATCH 3/3] arm/imx6: convert " Shawn Guo
0 siblings, 2 replies; 11+ messages in thread
From: Shawn Guo @ 2011-11-22 1:48 UTC (permalink / raw)
To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: Sascha Hauer, Rob Herring, Richard Zhao
As I promised to Arnd, I will convert imx6 clock code to common clock
framework and in turn device tree at the earliest time. 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@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@02198000 { /* uSDHC3 */
compatible = "fsl,imx6q-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 0x04>;
clock-input = <&usdhc_clk 2>; <--
clock-input-name = "usdhc3";
};
Regards,
Shawn
Shawn Guo (3):
arm/imx6: describe clocks in device tree source
arm/imx: add a generic clock implementation for imx
arm/imx6: convert clock to device tree
.../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(-)
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 1/3] arm/imx6: describe clocks in device tree source
[not found] ` <1321926536-671-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-11-22 1:48 ` Shawn Guo
[not found] ` <1321926536-671-2-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-11-22 1:48 ` [RFC PATCH 2/3] arm/imx: add a generic clock implementation for imx Shawn Guo
2011-11-22 8:23 ` [RFC PATCH 0/3] Convert imx6 clock to device tree Sascha Hauer
2 siblings, 1 reply; 11+ messages in thread
From: Shawn Guo @ 2011-11-22 1:48 UTC (permalink / raw)
To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: Sascha Hauer, Rob Herring, Richard Zhao
It adds document for imx clock device tree bindings and then describes
imx6 clocks in dts.
Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
.../devicetree/bindings/clock/clock-imx.txt | 124 +++
arch/arm/boot/dts/imx6q.dtsi | 943 +++++++++++++++++++-
2 files changed, 1058 insertions(+), 9 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/clock-imx.txt
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@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@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@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@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@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";
};
};
--
1.7.4.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH 2/3] arm/imx: add a generic clock implementation for imx
[not found] ` <1321926536-671-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-11-22 1:48 ` [RFC PATCH 1/3] arm/imx6: describe clocks in device tree source Shawn Guo
@ 2011-11-22 1:48 ` Shawn Guo
2011-11-22 8:23 ` [RFC PATCH 0/3] Convert imx6 clock to device tree Sascha Hauer
2 siblings, 0 replies; 11+ messages in thread
From: Shawn Guo @ 2011-11-22 1:48 UTC (permalink / raw)
To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: Sascha Hauer, Rob Herring, Richard Zhao
It adds a generic clock implementation which applies on several
modern imx generations.
Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
arch/arm/mach-imx/clock.c | 222 +++++++++++++++++++++++++++++++++++++++++++++
arch/arm/mach-imx/clock.h | 64 +++++++++++++
2 files changed, 286 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-imx/clock.c
create mode 100644 arch/arm/mach-imx/clock.h
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
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH 3/3] arm/imx6: convert clock to device tree
2011-11-22 1:48 [RFC PATCH 0/3] Convert imx6 clock to device tree Shawn Guo
[not found] ` <1321926536-671-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-11-22 1:48 ` Shawn Guo
1 sibling, 0 replies; 11+ messages in thread
From: Shawn Guo @ 2011-11-22 1:48 UTC (permalink / raw)
To: linux-arm-kernel, devicetree-discuss
Cc: Arnd Bergmann, Sascha Hauer, Rob Herring, Grant Likely, Shawn Guo,
Richard Zhao
It converts imx6 clock code to common clock frame and device tree.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/Kconfig | 5 +
arch/arm/mach-imx/Makefile | 1 +
arch/arm/mach-imx/clock-imx6q.c | 2135 +++++++--------------------------------
3 files changed, 390 insertions(+), 1751 deletions(-)
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;
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 0/3] Convert imx6 clock to device tree
[not found] ` <1321926536-671-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-11-22 1:48 ` [RFC PATCH 1/3] arm/imx6: describe clocks in device tree source Shawn Guo
2011-11-22 1:48 ` [RFC PATCH 2/3] arm/imx: add a generic clock implementation for imx Shawn Guo
@ 2011-11-22 8:23 ` Sascha Hauer
[not found] ` <20111122082314.GB27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2 siblings, 1 reply; 11+ messages in thread
From: Sascha Hauer @ 2011-11-22 8:23 UTC (permalink / raw)
To: Shawn Guo
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Richard Zhao, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
On Tue, Nov 22, 2011 at 09:48:53AM +0800, Shawn Guo wrote:
> As I promised to Arnd, I will convert imx6 clock code to common clock
> framework and in turn device tree at the earliest time. Here it is.
Very nice ;) I like the patches.
Is there a way to improve the way how the entities find their base
addresses? Currently the C code figures out the base addresses based
on compatible. Maybe we could put the crm clocks and anatop clocks into
two different nodes instead of putting them all directly under clocks{}.
Could you split the last patch into two, one adding new device tree
clock support in a new file and another removing the old clock support?
This would help reviewing.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 1/3] arm/imx6: describe clocks in device tree source
[not found] ` <1321926536-671-2-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-11-22 8:56 ` Sascha Hauer
[not found] ` <20111122085649.GC27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: Sascha Hauer @ 2011-11-22 8:56 UTC (permalink / raw)
To: Shawn Guo
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring,
Richard Zhao, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
On Tue, Nov 22, 2011 at 09:48:54AM +0800, Shawn Guo wrote:
> It adds document for imx clock device tree bindings and then describes
> imx6 clocks in dts.
>
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> .../devicetree/bindings/clock/clock-imx.txt | 124 +++
> arch/arm/boot/dts/imx6q.dtsi | 943 +++++++++++++++++++-
> 2 files changed, 1058 insertions(+), 9 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/clock/clock-imx.txt
>
> 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.
On i.MX53 we have two bit gates:
00b disable
01b disable in stop mode, enable in run mode
10b reserved
11b enable
I can't find this description in my i.MX6RM, but I suppose it's the same
here. Do you have plans for these? Currently only disable and enable
seem to be handled.
> +
> + 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";
> + };
Does this pll simultaneously have three different output frequencies?
I'm not familiar with the i.MX6 yet.
> +
> + 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";
> + };
I'm not sure you do yourself a favour if you skip all the muxes and
assume reset default for them. The ecspi-root parent is a mux The mux
seems to be missing in the can clock, uart and probably others.
> +
> + 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";
> + };
> +
[...]
> +
> + 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";
> + };
This seems wrong. The UARTs have two clocks, the register clock and the
baud clock. parent of the baud clock is uart-root (the mux is missing
here) and parent of the register clock is the ipg clock. This node only
has one parent.
> +
> + 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";
> + };
> +
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 0/3] Convert imx6 clock to device tree
[not found] ` <20111122082314.GB27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2011-11-24 2:59 ` Shawn Guo
[not found] ` <20111124025902.GB17979-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: Shawn Guo @ 2011-11-24 2:59 UTC (permalink / raw)
To: Sascha Hauer
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Richard Zhao,
Rob Herring
On Tue, Nov 22, 2011 at 09:23:14AM +0100, Sascha Hauer wrote:
> On Tue, Nov 22, 2011 at 09:48:53AM +0800, Shawn Guo wrote:
> > As I promised to Arnd, I will convert imx6 clock code to common clock
> > framework and in turn device tree at the earliest time. Here it is.
>
> Very nice ;) I like the patches.
>
> Is there a way to improve the way how the entities find their base
> addresses? Currently the C code figures out the base addresses based
> on compatible.
May I understand the problem with doing that?
> Maybe we could put the crm clocks and anatop clocks into
> two different nodes instead of putting them all directly under clocks{}.
>
I do not quite understand this. Are you suggesting we keep using the
static base address definition in C code for ccm and anatop rather than
retrieving them from device tree? No, we do not want to do this. So
if we need to get the addresses from device tree anyhow, using
compatible to find the correct node is the best way to me.
> Could you split the last patch into two, one adding new device tree
> clock support in a new file and another removing the old clock support?
> This would help reviewing.
>
Yes, will do. I would also rename the new file back to clock-imx6q.c
in the last patch, because I want to keep using that file name.
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 1/3] arm/imx6: describe clocks in device tree source
[not found] ` <20111122085649.GC27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2011-11-24 4:01 ` Shawn Guo
[not found] ` <20111124040128.GC17979-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: Shawn Guo @ 2011-11-24 4:01 UTC (permalink / raw)
To: Sascha Hauer
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Richard Zhao,
Rob Herring
On Tue, Nov 22, 2011 at 09:56:49AM +0100, Sascha Hauer wrote:
> On Tue, Nov 22, 2011 at 09:48:54AM +0800, Shawn Guo wrote:
> > It adds document for imx clock device tree bindings and then describes
> > imx6 clocks in dts.
> >
> > Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > ---
> > .../devicetree/bindings/clock/clock-imx.txt | 124 +++
> > arch/arm/boot/dts/imx6q.dtsi | 943 +++++++++++++++++++-
> > 2 files changed, 1058 insertions(+), 9 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/clock/clock-imx.txt
> >
> > 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.
>
> On i.MX53 we have two bit gates:
>
> 00b disable
> 01b disable in stop mode, enable in run mode
> 10b reserved
> 11b enable
>
> I can't find this description in my i.MX6RM, but I suppose it's the same
> here. Do you have plans for these? Currently only disable and enable
> seem to be handled.
>
Yes, imx6 is same as imx5 on this. It's something missing from clock
driver rather than binding. The binding only describes the shift and
mask of the gate bits, and the encoding of the bits is left to clock
driver. And I plan to add support for cases 01b and 10b when the need
occurs.
>
> > +
> > + 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";
> > + };
>
> Does this pll simultaneously have three different output frequencies?
> I'm not familiar with the i.MX6 yet.
>
This is not a PLL. Instead, they are 3 PFDs having the PLL2 as the
parent clock.
> > +
> > + 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";
> > + };
>
> I'm not sure you do yourself a favour if you skip all the muxes and
> assume reset default for them. The ecspi-root parent is a mux The mux
> seems to be missing in the can clock, uart and probably others.
>
I'm looking at IMX6DQRM.pdf 'Rev. B, 07/2011'. I do not see mux for
ECSPI_CLK_ROOT as well as other clocks you mentioned. Instead, I can
only see divider for these clocks. Can you point out the registers
and bits of these muxes you are seeing with these clocks?
> > +
> > + 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";
> > + };
> > +
>
> [...]
>
> > +
> > + 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";
> > + };
>
> This seems wrong. The UARTs have two clocks, the register clock and the
> baud clock. parent of the baud clock is uart-root (the mux is missing
> here) and parent of the register clock is the ipg clock. This node only
> has one parent.
>
Yes, this is wrong. Thanks for catching. But still I do not see mux
for uart-root but only divider.
Regards,
Shawn
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 1/3] arm/imx6: describe clocks in device tree source
[not found] ` <20111124040128.GC17979-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
@ 2011-11-24 8:17 ` Sascha Hauer
0 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2011-11-24 8:17 UTC (permalink / raw)
To: Shawn Guo
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Richard Zhao,
Rob Herring
On Thu, Nov 24, 2011 at 12:01:29PM +0800, Shawn Guo wrote:
> On Tue, Nov 22, 2011 at 09:56:49AM +0100, Sascha Hauer wrote:
> > On Tue, Nov 22, 2011 at 09:48:54AM +0800, Shawn Guo wrote:
> > > It adds document for imx clock device tree bindings and then describes
> > > imx6 clocks in dts.
> > >
> > > +
> > > + 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";
> > > + };
> >
> > I'm not sure you do yourself a favour if you skip all the muxes and
> > assume reset default for them. The ecspi-root parent is a mux The mux
> > seems to be missing in the can clock, uart and probably others.
> >
> I'm looking at IMX6DQRM.pdf 'Rev. B, 07/2011'. I do not see mux for
> ECSPI_CLK_ROOT as well as other clocks you mentioned. Instead, I can
> only see divider for these clocks. Can you point out the registers
> and bits of these muxes you are seeing with these clocks?
No, I can't find them either ;) I must have looked into the wrong manual
at that moment. Sorry for the noise.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 0/3] Convert imx6 clock to device tree
[not found] ` <20111124025902.GB17979-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
@ 2011-11-24 8:49 ` Sascha Hauer
[not found] ` <20111124084923.GW27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: Sascha Hauer @ 2011-11-24 8:49 UTC (permalink / raw)
To: Shawn Guo
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Richard Zhao,
Rob Herring
On Thu, Nov 24, 2011 at 10:59:03AM +0800, Shawn Guo wrote:
> On Tue, Nov 22, 2011 at 09:23:14AM +0100, Sascha Hauer wrote:
> > On Tue, Nov 22, 2011 at 09:48:53AM +0800, Shawn Guo wrote:
> > > As I promised to Arnd, I will convert imx6 clock code to common clock
> > > framework and in turn device tree at the earliest time. Here it is.
> >
> > Very nice ;) I like the patches.
> >
> > Is there a way to improve the way how the entities find their base
> > addresses? Currently the C code figures out the base addresses based
> > on compatible.
>
> May I understand the problem with doing that?
>
> > Maybe we could put the crm clocks and anatop clocks into
> > two different nodes instead of putting them all directly under clocks{}.
> >
> I do not quite understand this. Are you suggesting we keep using the
> static base address definition in C code for ccm and anatop rather than
> retrieving them from device tree? No, we do not want to do this. So
> if we need to get the addresses from device tree anyhow, using
> compatible to find the correct node is the best way to me.
What I meant is that currently there are many clock nodes which do have
a register offset associated with them, but the base address has to be
guessed in C code, like this:
> 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;
> }
Wouldn't it be possible to arrange the devicetree like this:
ccm@020c4000 {
compatible = "fsl,imx6q-ccm";
reg = <0x020c4000 0x4000>;
interrupts = <0 87 0x04 0 88 0x04>;
clocks {
/* put ccm clocks here */
}
}
anatop@020c8000 {
compatible = "fsl,imx6q-anatop";
reg = <0x020c8000 0x1000>;
interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
clocks {
/* put anatop clocks here */
}
}
Of course this has a high cost on indention levels.
On i.MX6 we only seem to have two base addresses relevant for clocks,
but on i.MX5 there are multiple identical PLLs with different base
addresses, so guessing the base address would not be possible based
on of_device_is_compatible(), we would also have to match the name or
some other identification property:
if (is_compatible(np, "fsl,imx5-pll") && np->name == "pll1")
base = pll1_base;
else if ...
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 0/3] Convert imx6 clock to device tree
[not found] ` <20111124084923.GW27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2011-11-24 12:21 ` Shawn Guo
0 siblings, 0 replies; 11+ messages in thread
From: Shawn Guo @ 2011-11-24 12:21 UTC (permalink / raw)
To: Sascha Hauer
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Richard Zhao,
Rob Herring
On Thu, Nov 24, 2011 at 09:49:23AM +0100, Sascha Hauer wrote:
> On Thu, Nov 24, 2011 at 10:59:03AM +0800, Shawn Guo wrote:
> > On Tue, Nov 22, 2011 at 09:23:14AM +0100, Sascha Hauer wrote:
> > > On Tue, Nov 22, 2011 at 09:48:53AM +0800, Shawn Guo wrote:
> > > > As I promised to Arnd, I will convert imx6 clock code to common clock
> > > > framework and in turn device tree at the earliest time. Here it is.
> > >
> > > Very nice ;) I like the patches.
> > >
> > > Is there a way to improve the way how the entities find their base
> > > addresses? Currently the C code figures out the base addresses based
> > > on compatible.
> >
> > May I understand the problem with doing that?
> >
> > > Maybe we could put the crm clocks and anatop clocks into
> > > two different nodes instead of putting them all directly under clocks{}.
> > >
> > I do not quite understand this. Are you suggesting we keep using the
> > static base address definition in C code for ccm and anatop rather than
> > retrieving them from device tree? No, we do not want to do this. So
> > if we need to get the addresses from device tree anyhow, using
> > compatible to find the correct node is the best way to me.
>
> What I meant is that currently there are many clock nodes which do have
> a register offset associated with them, but the base address has to be
> guessed in C code, like this:
>
> > 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;
> > }
>
> Wouldn't it be possible to arrange the devicetree like this:
Yes, it is possible and actually better. Thanks for the suggestion.
>
> ccm@020c4000 {
> compatible = "fsl,imx6q-ccm";
> reg = <0x020c4000 0x4000>;
> interrupts = <0 87 0x04 0 88 0x04>;
> clocks {
> /* put ccm clocks here */
> }
> }
>
> anatop@020c8000 {
> compatible = "fsl,imx6q-anatop";
> reg = <0x020c8000 0x1000>;
> interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
> clocks {
> /* put anatop clocks here */
> }
> }
>
> Of course this has a high cost on indention levels.
>
I think I will drop node 'clocks' and list those clock nodes directly
under ccm and anatop nodes to save one level indention.
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2011-11-24 12:21 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-22 1:48 [RFC PATCH 0/3] Convert imx6 clock to device tree Shawn Guo
[not found] ` <1321926536-671-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-11-22 1:48 ` [RFC PATCH 1/3] arm/imx6: describe clocks in device tree source Shawn Guo
[not found] ` <1321926536-671-2-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-11-22 8:56 ` Sascha Hauer
[not found] ` <20111122085649.GC27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2011-11-24 4:01 ` Shawn Guo
[not found] ` <20111124040128.GC17979-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-11-24 8:17 ` Sascha Hauer
2011-11-22 1:48 ` [RFC PATCH 2/3] arm/imx: add a generic clock implementation for imx Shawn Guo
2011-11-22 8:23 ` [RFC PATCH 0/3] Convert imx6 clock to device tree Sascha Hauer
[not found] ` <20111122082314.GB27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2011-11-24 2:59 ` Shawn Guo
[not found] ` <20111124025902.GB17979-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-11-24 8:49 ` Sascha Hauer
[not found] ` <20111124084923.GW27267-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2011-11-24 12:21 ` Shawn Guo
2011-11-22 1:48 ` [RFC PATCH 3/3] arm/imx6: convert " Shawn Guo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).