ARM: imx6q: clean up board specific CLKO setup
Subsystems (6)
cover ARM: imx6q: clean up board specific CLKO setup
The CLKO is widely used by imx6q board designs to clock audio codec. Currently, imx6q-sabrelite and imx6qdl-sabresd set up CLKO in board specific hooks, while imx6qdl-wandboard handles that in U-Boot. Since most audio codecs accept 24 MHz frequency, the series adds missing CLKO pieces into clock driver, and initially sets up CLKO with OSC24M (cko <-- cko2 <-- osc). Then those board specific CLKO setup for audio codec can be removed, while it improves the power efficiency@the same time by saving the use of PLL.
Shawn
Shawn Guo (4):
ARM: imx6q: add spdif gate clock
ARM: imx6q: add cko2 clocks
ARM: imx6q: add the missing cko output selection
ARM: imx6q: remove board specific CLKO setup
.../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ arch/arm/boot/dts/imx6q-sabrelite.dts | 2 +- arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-wandboard.dtsi | 2 +- arch/arm/mach-imx/clk-imx6q.c | 30 ++++++++- arch/arm/mach-imx/mach-imx6q.c | 69 -------------------- 6 files changed, 37 insertions(+), 73 deletions(-)
Signature · 1 line
1.7.9.5
PATCH 1/4 ARM: imx6q: add spdif gate clock
It adds the missing spdif gate clock into imx6q clock driver.
--- .../devicetree/bindings/clock/imx6q-clock.txt | 1 + arch/arm/mach-imx/clk-imx6q.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/clock/imx6q-clock.txt +1 -0
@@ -209,6 +209,7 @@ clocks and IDs. pll5_post_div 194 pll5_video_div 195 eim_slow 196 + spdif 197 Examples:
arch/arm/mach-imx/clk-imx6q.c +3 -1
@@ -239,7 +239,8 @@ enum mx6q_clks { pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg, ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, - usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, clk_max + usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, + spdif, clk_max };static struct clk *clk[clk_max];
@@ -521,6 +522,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[sata] =imx_clk_gate2 ("sata" ,"ipg" , base +0x7c ,4 ); clk[sdma] =imx_clk_gate2 ("sdma" ,"ahb" , base +0x7c ,6 ); clk[spba] =imx_clk_gate2 ("spba" ,"ipg" , base +0x7c ,12 ); + clk[spdif] =imx_clk_gate2 ("spdif" ,"spdif_podf" , base +0x7c ,14 ); clk[ssi1_ipg] =imx_clk_gate2 ("ssi1_ipg" ,"ipg" , base +0x7c ,18 ); clk[ssi2_ipg] =imx_clk_gate2 ("ssi2_ipg" ,"ipg" , base +0x7c ,20 ); clk[ssi3_ipg] =imx_clk_gate2 ("ssi3_ipg" ,"ipg" , base +0x7c ,22 );
Signature · 1 line
1.7.9.5
PATCH 2/4 ARM: imx6q: add cko2 clocks
In reply to Shawn GuoIt adds the missing cko2 clocks, including multiplexer, divider and gate.
--- .../devicetree/bindings/clock/imx6q-clock.txt | 3 +++ arch/arm/mach-imx/clk-imx6q.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/clock/imx6q-clock.txt +3 -0
@@ -210,6 +210,9 @@ clocks and IDs. pll5_video_div 195 eim_slow 196 spdif 197 + cko2_sel 198 + cko2_podf 199 + cko2 200 Examples:
arch/arm/mach-imx/clk-imx6q.c +14 -1
@@ -206,6 +206,16 @@ static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m",static const char *cko1_sels[] = {"pll3_usb_otg" ,"pll2_bus" ,"pll1_sys" ,"pll5_video_div" ,"dummy" ,"axi" ,"enfc" ,"ipu1_di0" ,"ipu1_di1" ,"ipu2_di0" ,"ipu2_di1" ,"ahb" ,"ipg" ,"ipg_per" ,"ckil" ,"pll4_post_div" , }; +static const char *cko2_sels[] = { +"mmdc_ch0_axi" ,"mmdc_ch1_axi" ,"usdhc4" ,"usdhc1" , +"gpu2d_axi" ,"dummy" ,"ecspi_root" ,"gpu3d_axi" , +"usdhc3" ,"dummy" ,"arm" ,"ipu1" , +"ipu2" ,"vdo_axi" ,"osc" ,"gpu2d_core" , +"gpu3d_core" ,"usdhc2" ,"ssi1" ,"ssi2" , +"ssi3" ,"gpu3d_shader" ,"vpu_axi" ,"can_root" , +"ldb_di0" ,"ldb_di1" ,"esai" ,"eim_slow" , +"uart_serial" ,"spdif" ,"asrc" ,"hsi_tx" , +};enum mx6q_clks { dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
@@ -240,7 +250,7 @@ enum mx6q_clks { ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, - spdif, clk_max + spdif, cko2_sel, cko2_podf, cko2, clk_max };static struct clk *clk[clk_max];
@@ -398,6 +408,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[vdo_axi_sel] =imx_clk_mux ("vdo_axi_sel" , base +0x18 ,11 ,1 , vdo_axi_sels,ARRAY_SIZE (vdo_axi_sels)); clk[vpu_axi_sel] =imx_clk_mux ("vpu_axi_sel" , base +0x18 ,14 ,2 , vpu_axi_sels,ARRAY_SIZE (vpu_axi_sels)); clk[cko1_sel] =imx_clk_mux ("cko1_sel" , base +0x60 ,0 ,4 , cko1_sels,ARRAY_SIZE (cko1_sels)); + clk[cko2_sel] =imx_clk_mux ("cko2_sel" , base +0x60 ,16 ,5 , cko2_sels,ARRAY_SIZE (cko2_sels));/* name reg shift width busy: reg, shift parent_names num_parents */ clk[periph] =imx_clk_busy_mux ("periph" , base +0x14 ,25 ,1 , base +0x48 ,5 , periph_sels,ARRAY_SIZE (periph_sels));
@@ -447,6 +458,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[emi_slow_podf] =imx_clk_fixup_divider ("emi_slow_podf" ,"emi_slow_sel" , base +0x1c ,23 ,3 , imx_cscmr1_fixup); clk[vpu_axi_podf] =imx_clk_divider ("vpu_axi_podf" ,"vpu_axi_sel" , base +0x24 ,25 ,3 ); clk[cko1_podf] =imx_clk_divider ("cko1_podf" ,"cko1_sel" , base +0x60 ,4 ,3 ); + clk[cko2_podf] =imx_clk_divider ("cko2_podf" ,"cko2_sel" , base +0x60 ,21 ,3 );/* name parent_name reg shift width busy: reg, shift */ clk[axi] =imx_clk_busy_divider ("axi" ,"axi_sel" , base +0x14 ,16 ,3 , base +0x48 ,0 );
@@ -537,6 +549,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[vdo_axi] =imx_clk_gate2 ("vdo_axi" ,"vdo_axi_sel" , base +0x80 ,12 ); clk[vpu_axi] =imx_clk_gate2 ("vpu_axi" ,"vpu_axi_podf" , base +0x80 ,14 ); clk[cko1] =imx_clk_gate ("cko1" ,"cko1_podf" , base +0x60 ,7 ); + clk[cko2] =imx_clk_gate ("cko2" ,"cko2_podf" , base +0x60 ,24 );for (i =0 ; i <ARRAY_SIZE (clk); i++)if (IS_ERR (clk[i]))
Signature · 1 line
1.7.9.5
PATCH 3/4 ARM: imx6q: add the missing cko output selection
In reply to Shawn GuoThe clock output on imx6q CCM_CLKO1 pad is not always cko1 clock, and there is a multiplexer to select between cko1 and cko2. Add this missing selection as the clock cko.
--- .../devicetree/bindings/clock/imx6q-clock.txt | 1 + arch/arm/mach-imx/clk-imx6q.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/clock/imx6q-clock.txt +1 -0
@@ -213,6 +213,7 @@ clocks and IDs. cko2_sel 198 cko2_podf 199 cko2 200 + cko 201 Examples:
arch/arm/mach-imx/clk-imx6q.c +3 -1
@@ -216,6 +216,7 @@ static const char *cko2_sels[] = {"ldb_di0" ,"ldb_di1" ,"esai" ,"eim_slow" , "uart_serial", "spdif", "asrc", "hsi_tx", }; +static const char *cko_sels[] = {"cko1" ,"cko2" , };enum mx6q_clks { dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
@@ -250,7 +251,7 @@ enum mx6q_clks { ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, - spdif, cko2_sel, cko2_podf, cko2, clk_max + spdif, cko2_sel, cko2_podf, cko2, cko, clk_max };static struct clk *clk[clk_max];
@@ -409,6 +410,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[vpu_axi_sel] =imx_clk_mux ("vpu_axi_sel" , base +0x18 ,14 ,2 , vpu_axi_sels,ARRAY_SIZE (vpu_axi_sels)); clk[cko1_sel] =imx_clk_mux ("cko1_sel" , base +0x60 ,0 ,4 , cko1_sels,ARRAY_SIZE (cko1_sels)); clk[cko2_sel] =imx_clk_mux ("cko2_sel" , base +0x60 ,16 ,5 , cko2_sels,ARRAY_SIZE (cko2_sels)); + clk[cko] =imx_clk_mux ("cko" , base +0x60 ,8 ,1 , cko_sels,ARRAY_SIZE (cko_sels));/* name reg shift width busy: reg, shift parent_names num_parents */ clk[periph] =imx_clk_busy_mux ("periph" , base +0x14 ,25 ,1 , base +0x48 ,5 , periph_sels,ARRAY_SIZE (periph_sels));
Signature · 1 line
1.7.9.5
PATCH 4/4 ARM: imx6q: remove board specific CLKO setup
In reply to Shawn GuoThe CLKO is widely used by imx6q board designs to clock audio codec. Since most codecs accept 24 MHz frequency, let's initially set up CLKO with OSC24M (cko <-- cko2 <-- osc). Then those board specific CLKO setup for audio codec can be removed.
The board dts files also need an update on cko reference in codec node.
--- arch/arm/boot/dts/imx6q-sabrelite.dts | 2 +- arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 2 +- arch/arm/boot/dts/imx6qdl-wandboard.dtsi | 2 +- arch/arm/mach-imx/clk-imx6q.c | 11 +++++ arch/arm/mach-imx/mach-imx6q.c | 69 ------------------------------ 5 files changed, 14 insertions(+), 72 deletions(-)
arch/arm/boot/dts/imx6q-sabrelite.dts +1 -1
@@ -167,7 +167,7 @@ codec: sgtl5000 at 0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 169>; + clocks = <&clks 201>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; };
arch/arm/boot/dts/imx6qdl-sabresd.dtsi +1 -1
@@ -109,7 +109,7 @@ codec: wm8962 at 1a { compatible = "wlf,wm8962"; reg = <0x1a>; - clocks = <&clks 169>; + clocks = <&clks 201>; DCVDD-supply = <®_audio>; DBVDD-supply = <®_audio>; AVDD-supply = <®_audio>;
arch/arm/boot/dts/imx6qdl-wandboard.dtsi +1 -1
@@ -60,7 +60,7 @@ codec: sgtl5000 at 0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 169>; + clocks = <&clks 201>; VDDA-supply = <®_2p5v>; VDDIO-supply = <®_3p3v>; };
arch/arm/mach-imx/clk-imx6q.c +11 -0
@@ -288,6 +288,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)struct device_node *np;void __iomem *base;int i, irq; +int ret; clk[dummy] =imx_clk_fixed ("dummy" ,0 ); clk[ckil] =imx_obtain_fixed_clock ("ckil" ,0 );
@@ -591,6 +592,16 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)clk_prepare_enable (clk[usbphy2_gate]); } +/* +* Let's initially set up CLKO with OSC24M, since this configuration +* is widely used by imx6q board designs to clock audio codec. +*/ + ret =clk_set_parent (clk[cko2_sel], clk[osc]); +if (!ret) + ret =clk_set_parent (clk[cko], clk[cko2]); +if (ret) +pr_warn ("failed to set up CLKO: %d\n" , ret); +/* Set initial power mode */ imx6q_set_lpm (WAIT_CLOCKED );
arch/arm/mach-imx/mach-imx6q.c +0 -69
87 lines not on this page · raw message
Signature · 1 line
1.7.9.5
Sascha Hauer
maintainerPATCH 4/4 ARM: imx6q: remove board specific CLKO setup
Quoted 7 lines · Shawn Guo
The CLKO is widely used by imx6q board designs to clock audio codec. Since most codecs accept 24 MHz frequency, let's initially set up CLKO with OSC24M (cko <-- cko2 <-- osc). Then those board specific CLKO setup for audio codec can be removed.
The board dts files also need an update on cko reference in codec node.
arch/arm/mach-imx/clk-imx6q.c static void __init imx6q_clocks_init(struct device_node *ccm_node) · line 603
Quoted 9 lines
arch/arm/mach-imx/clk-imx6q.c +9
-0+/* +* Let's initially set up CLKO with OSC24M, since this configuration +* is widely used by imx6q board designs to clock audio codec. +*/ + ret =clk_set_parent (clk[cko2_sel], clk[osc]); +if (!ret) + ret =clk_set_parent (clk[cko], clk[cko2]); +if (ret) +pr_warn ("failed to set up CLKO: %d\n" , ret);
I don't really like that the clock setup code fiddles with clocks it has no knowledge about just because it happens to be correct for several boards.
I currently have no example where this bites me, so I think I can live with it for now. I just wonder what I should do when this clock is used for something vital to the system (clocking an FPGA for example?).
Sascha
Signature · 4 lines
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 |
PATCH 4/4 ARM: imx6q: remove board specific CLKO setup
Quoted 8 lines · Sascha Hauer
Quoted 7 lines · Shawn Guo
The CLKO is widely used by imx6q board designs to clock audio codec. Since most codecs accept 24 MHz frequency, let's initially set up CLKO with OSC24M (cko <-- cko2 <-- osc). Then those board specific CLKO setup for audio codec can be removed.
The board dts files also need an update on cko reference in codec node.
Quoted 14 lines
arch/arm/mach-imx/clk-imx6q.c static void __init imx6q_clocks_init(struct device_node *ccm_node) · line 603
Quoted 9 lines
arch/arm/mach-imx/clk-imx6q.c +9
-0+/* +* Let's initially set up CLKO with OSC24M, since this configuration +* is widely used by imx6q board designs to clock audio codec. +*/ + ret =clk_set_parent (clk[cko2_sel], clk[osc]); +if (!ret) + ret =clk_set_parent (clk[cko], clk[cko2]); +if (ret) +pr_warn ("failed to set up CLKO: %d\n" , ret);I don't really like that the clock setup code fiddles with clocks it has no knowledge about just because it happens to be correct for several boards.
I have to admit it's not the best way to handle it, and I can understand your concern. What I like about it is we can remove those board specific hooks from mach-imx6q.c at least for now.
Quoted 4 lines
I currently have no example where this bites me, so I think I can live with it for now. I just wonder what I should do when this clock is used for something vital to the system (clocking an FPGA for example?).
Go back to set up CLKO in mach-imx6q.c with board specific hook for the system?
I think I chose to change the default CLKO setup for audio use case, as all the users we've seen so far is audio codec. I can still have this setup done in mach-imx6q.c with of_machine_is_compatible() check on all those board. But that also means we need to register lookups for those CLKO clocks and call clk_get_sys() to get them.
Shawn