i.MX6 clock
Subsystems (6)
Sascha Hauer
maintainerPATCH 1/1 i.MX6 clock
The following contains fixes/cleanups for the i.MX6 clock support, mostly driven by the missing SATA clock support.
----------------------------------------------------------------
Sascha Hauer (3):
ARM i.MX6: rename PLLs according to datasheet ARM i.MX6: Fix ethernet PLL clocks ARM i.MX6: remove gate_mask from pllv3
.../devicetree/bindings/clock/imx6q-clock.txt | 9 ++- arch/arm/mach-imx/clk-imx6q.c | 39 ++++++++--- arch/arm/mach-imx/clk-pllv3.c | 72 ++------------------ arch/arm/mach-imx/clk.h | 3 +- 4 files changed, 40 insertions(+), 83 deletions(-)
Sascha Hauer
maintainerPATCH 1/3 ARM i.MX6: rename PLLs according to datasheet
In recent reference manuals the PLLs were renumbered. PLL8 now is PLL6 and vice versa. Change the code according to the reference manual to avoid confusion.
--- Documentation/devicetree/bindings/clock/imx6q-clock.txt | 4 ++-- arch/arm/mach-imx/clk-imx6q.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
Documentation/devicetree/bindings/clock/imx6q-clock.txt +2 -2
@@ -187,9 +187,9 @@ clocks and IDs. pll3_usb_otg 172 pll4_audio 173 pll5_video 174 - pll6_mlb 175 + pll8_mlb 175 pll7_usb_host 176 - pll8_enet 177 + pll6_enet 177 ssi1_ipg 178 ssi2_ipg 179 ssi3_ipg 180
arch/arm/mach-imx/clk-imx6q.c +4 -4
@@ -151,7 +151,7 @@ enum mx6q_clks { gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1, ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3, usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, - pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg, + 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, clk_max };
@@ -195,9 +195,9 @@ int __init mx6q_clocks_init(void) clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 ); clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll6_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); - clk[pll8_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll8_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); + clk[pll8_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll8_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 ); clk[usbphy1] =imx_clk_gate ("usbphy1" ,"pll3_usb_otg" , base +0x10 ,6 ); clk[usbphy2] =imx_clk_gate ("usbphy2" ,"pll7_usb_host" , base +0x20 ,6 );
@@ -357,7 +357,7 @@ int __init mx6q_clocks_init(void) clk[ldb_di1] =imx_clk_gate2 ("ldb_di1" ,"ldb_di1_podf" , base +0x74 ,14 ); clk[ipu2_di1] =imx_clk_gate2 ("ipu2_di1" ,"ipu2_di1_sel" , base +0x74 ,10 ); clk[hsi_tx] =imx_clk_gate2 ("hsi_tx" ,"hsi_tx_podf" , base +0x74 ,16 ); - clk[mlb] =imx_clk_gate2 ("mlb" ,"pll6_mlb" , base +0x74 ,18 ); + clk[mlb] =imx_clk_gate2 ("mlb" ,"pll8_mlb" , base +0x74 ,18 ); clk[mmdc_ch0_axi] =imx_clk_gate2 ("mmdc_ch0_axi" ,"mmdc_ch0_axi_podf" , base +0x74 ,20 ); clk[mmdc_ch1_axi] =imx_clk_gate2 ("mmdc_ch1_axi" ,"mmdc_ch1_axi_podf" , base +0x74 ,22 ); clk[ocram] =imx_clk_gate2 ("ocram" ,"ahb" , base +0x74 ,28 );
Signature · 1 line
1.7.10.4
Sascha Hauer
maintainerPATCH 2/3 ARM i.MX6: Fix ethernet PLL clocks
In reply to Sascha HauerIn current code the ethernet PLL is not handled correctly. The PLL runs at 500MHz and has different outputs. Only the enet reference clock is implemented. This patch changes the PLL so that it outputs 500MHz and adds the additional outputs as dividers. This now matches the datasheet which says:
Quoted 5 lines
This PLL synthesizes a low jitter clock from 24 MHz reference clock. The PLL outputs a 500 MHz clock. The reference clocks generated by this PLL are:
?Ref_PCIe= 125 MHz
?Ref_SATA= 100 MHz
?Ref_ethernet, which is configurable based on the PLL_ENET[1:0] register field.
--- .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ arch/arm/mach-imx/clk-imx6q.c | 21 ++++++- arch/arm/mach-imx/clk-pllv3.c | 63 +------------------- 3 files changed, 25 insertions(+), 64 deletions(-)
Documentation/devicetree/bindings/clock/imx6q-clock.txt +5 -0
@@ -198,6 +198,11 @@ clocks and IDs. usbphy2 183 ldb_di0_div_3_5 184 ldb_di1_div_3_5 185 + sata_ref 186 + sata_ref_100m 187 + pcie_ref 188 + pcie_ref_125m 189 + enet_ref 190 Examples:
arch/arm/mach-imx/clk-imx6q.c +19 -2
@@ -153,6 +153,7 @@ enum mx6q_clks { usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, 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, clk_max };
@@ -163,6 +164,13 @@ static enum mx6q_clks const clks_init_on[] __initconst = { mmdc_ch0_axi, rom, }; +static struct clk_div_table clk_enet_ref_table[] = { + { .val =0 , .div =20 , }, + { .val =1 , .div =10 , }, + { .val =2 , .div =5 , }, + { .val =3 , .div =4 , }, +}; +int __init mx6q_clocks_init (void ) {struct device_node *np;
@@ -195,13 +203,22 @@ int __init mx6q_clocks_init(void) clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 ); clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x2000 ,0x3 ); clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); - clk[pll8_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll8_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 ); clk[usbphy1] =imx_clk_gate ("usbphy1" ,"pll3_usb_otg" , base +0x10 ,6 ); clk[usbphy2] =imx_clk_gate ("usbphy2" ,"pll7_usb_host" , base +0x20 ,6 ); + clk[sata_ref] =imx_clk_fixed_factor ("sata_ref" ,"pll6_enet" ,1 ,5 ); + clk[pcie_ref] =imx_clk_fixed_factor ("pcie_ref" ,"pll6_enet" ,1 ,4 ); + + clk[sata_ref_100m] =imx_clk_gate ("sata_ref_100m" ,"sata_ref" , base +0xe0 ,20 ); + clk[pcie_ref_125m] =imx_clk_gate ("pcie_ref_125m" ,"pcie_ref" , base +0xe0 ,19 ); + + clk[enet_ref] =clk_register_divider_table (NULL ,"enet_ref" ,"pll6_enet" ,0 , + base +0xe0 ,0 ,2 ,0 , clk_enet_ref_table, + &imx_ccm_lock); +/* name parent_name reg idx */ clk[pll2_pfd0_352m] =imx_clk_pfd ("pll2_pfd0_352m" ,"pll2_bus" , base +0x100 ,0 ); clk[pll2_pfd1_594m] =imx_clk_pfd ("pll2_pfd1_594m" ,"pll2_bus" , base +0x100 ,1 );
arch/arm/mach-imx/clk-pllv3.c +1 -62
75 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH 2/3 ARM i.MX6: Fix ethernet PLL clocks
Quoted 61 lines · Sascha Hauer
In current code the ethernet PLL is not handled correctly. The PLL runs at 500MHz and has different outputs. Only the enet reference clock is implemented. This patch changes the PLL so that it outputs 500MHz and adds the additional outputs as dividers. This now matches the datasheet which says:
Quoted 5 lines
This PLL synthesizes a low jitter clock from 24 MHz reference clock. The PLL outputs a 500 MHz clock. The reference clocks generated by this PLL are:
?Ref_PCIe= 125 MHz
?Ref_SATA= 100 MHz
?Ref_ethernet, which is configurable based on the PLL_ENET[1:0] register field.Signed-off-by Sascha Hauer <[email protected]>--- .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ arch/arm/mach-imx/clk-imx6q.c | 21 ++++++- arch/arm/mach-imx/clk-pllv3.c | 63 +------------------- 3 files changed, 25 insertions(+), 64 deletions(-)Documentation/devicetree/bindings/clock/imx6q-clock.txt +5
-0@@ -198,6 +198,11 @@ clocks and IDs. usbphy2 183 ldb_di0_div_3_5 184 ldb_di1_div_3_5 185 + sata_ref 186 + sata_ref_100m 187 + pcie_ref 188 + pcie_ref_125m 189 + enet_ref 190 Examples:arch/arm/mach-imx/clk-imx6q.c +8
-0@@ -153,6 +153,7 @@ enum mx6q_clks { usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, 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, clk_max };@@ -163,6 +164,13 @@ static enum mx6q_clks const clks_init_on[] __initconst = { mmdc_ch0_axi, rom, }; +static struct clk_div_table clk_enet_ref_table[] = { + { .val =0 , .div =20 , }, + { .val =1 , .div =10 , }, + { .val =2 , .div =5 , }, + { .val =3 , .div =4 , }, +}; +int __init mx6q_clocks_init (void ) {struct device_node *np;
arch/arm/mach-imx/clk-imx6q.c int __init mx6q_clocks_init(void) · line 200
Quoted 7 lines
arch/arm/mach-imx/clk-imx6q.c +1
-2@@ -195,13 +203,22 @@ int __init mx6q_clocks_init(void) clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 ); clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x2000 ,0x3 ); clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); - clk[pll8_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll8_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 );
It gets removed by accident?
Otherwise, for the series:
Quoted 101 lines
arch/arm/mach-imx/clk-imx6q.c +10
-0clk[usbphy1] =imx_clk_gate ("usbphy1" ,"pll3_usb_otg" , base +0x10 ,6 ); clk[usbphy2] =imx_clk_gate ("usbphy2" ,"pll7_usb_host" , base +0x20 ,6 ); + clk[sata_ref] =imx_clk_fixed_factor ("sata_ref" ,"pll6_enet" ,1 ,5 ); + clk[pcie_ref] =imx_clk_fixed_factor ("pcie_ref" ,"pll6_enet" ,1 ,4 ); + + clk[sata_ref_100m] =imx_clk_gate ("sata_ref_100m" ,"sata_ref" , base +0xe0 ,20 ); + clk[pcie_ref_125m] =imx_clk_gate ("pcie_ref_125m" ,"pcie_ref" , base +0xe0 ,19 ); + + clk[enet_ref] =clk_register_divider_table (NULL ,"enet_ref" ,"pll6_enet" ,0 , + base +0xe0 ,0 ,2 ,0 , clk_enet_ref_table, + &imx_ccm_lock); +/* name parent_name reg idx */ clk[pll2_pfd0_352m] =imx_clk_pfd ("pll2_pfd0_352m" ,"pll2_bus" , base +0x100 ,0 ); clk[pll2_pfd1_594m] =imx_clk_pfd ("pll2_pfd1_594m" ,"pll2_bus" , base +0x100 ,1 );arch/arm/mach-imx/clk-pllv3.c +1
-62@@ -287,66 +287,7 @@ static const struct clk_ops clk_pllv3_av_ops = {static unsigned long clk_pllv3_enet_recalc_rate (struct clk_hw *hw,unsigned long parent_rate) { -struct clk_pllv3 *pll =to_clk_pllv3 (hw); -u32 div =readl_relaxed (pll->base) & pll->div_mask; - -switch (div) { -case 0 : -return 25000000 ; -case 1 : -return 50000000 ; -case 2 : -return 100000000 ; -case 3 : -return 125000000 ; - } - -return 0 ; -} - -static long clk_pllv3_enet_round_rate (struct clk_hw *hw,unsigned long rate, -unsigned long *prate) -{ -if (rate >=125000000 ) - rate =125000000 ; -else if (rate >=100000000 ) - rate =100000000 ; -else if (rate >=50000000 ) - rate =50000000 ; -else - rate =25000000 ; -return rate; -} - -static int clk_pllv3_enet_set_rate (struct clk_hw *hw,unsigned long rate, -unsigned long parent_rate) -{ -struct clk_pllv3 *pll =to_clk_pllv3 (hw); -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 : -return -EINVAL ; - } - - val =readl_relaxed (pll->base); - val &= ~pll->div_mask; - val |= div; -writel_relaxed (val, pll->base); - -return 0 ; +return 500000000 ; }static const struct clk_ops clk_pllv3_enet_ops = {@@ -355,8 +296,6 @@ static const struct clk_ops clk_pllv3_enet_ops = { .enable = clk_pllv3_enable, .disable = clk_pllv3_disable, .recalc_rate = clk_pllv3_enet_recalc_rate, - .round_rate = clk_pllv3_enet_round_rate, - .set_rate = clk_pllv3_enet_set_rate, };static const struct clk_ops clk_pllv3_mlb_ops = {Signature · 1 line
1.7.10.4
Sascha Hauer
maintainerPATCH 2/3 ARM i.MX6: Fix ethernet PLL clocks
Quoted 63 lines · Shawn Guo
Quoted 62 lines · Sascha Hauer
In current code the ethernet PLL is not handled correctly. The PLL runs at 500MHz and has different outputs. Only the enet reference clock is implemented. This patch changes the PLL so that it outputs 500MHz and adds the additional outputs as dividers. This now matches the datasheet which says:
Quoted 5 lines
This PLL synthesizes a low jitter clock from 24 MHz reference clock. The PLL outputs a 500 MHz clock. The reference clocks generated by this PLL are:
?Ref_PCIe= 125 MHz
?Ref_SATA= 100 MHz
?Ref_ethernet, which is configurable based on the PLL_ENET[1:0] register field.Signed-off-by Sascha Hauer <[email protected]>--- .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ arch/arm/mach-imx/clk-imx6q.c | 21 ++++++- arch/arm/mach-imx/clk-pllv3.c | 63 +------------------- 3 files changed, 25 insertions(+), 64 deletions(-)Documentation/devicetree/bindings/clock/imx6q-clock.txt +5
-0@@ -198,6 +198,11 @@ clocks and IDs. usbphy2 183 ldb_di0_div_3_5 184 ldb_di1_div_3_5 185 + sata_ref 186 + sata_ref_100m 187 + pcie_ref 188 + pcie_ref_125m 189 + enet_ref 190 Examples:arch/arm/mach-imx/clk-imx6q.c +8
-0@@ -153,6 +153,7 @@ enum mx6q_clks { usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, 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, clk_max };@@ -163,6 +164,13 @@ static enum mx6q_clks const clks_init_on[] __initconst = { mmdc_ch0_axi, rom, }; +static struct clk_div_table clk_enet_ref_table[] = { + { .val =0 , .div =20 , }, + { .val =1 , .div =10 , }, + { .val =2 , .div =5 , }, + { .val =3 , .div =4 , }, +}; +int __init mx6q_clocks_init (void ) {struct device_node *np;@@ -195,13 +203,22 @@ int __init mx6q_clocks_init(void) clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 );
Quoted 8 lines
arch/arm/mach-imx/clk-imx6q.c int __init mx6q_clocks_init(void) · line 200
Quoted 6 lines
arch/arm/mach-imx/clk-imx6q.c +1
-2clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x2000 ,0x3 ); clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); - clk[pll8_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll8_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 );It gets removed by accident?
Yes, I screwed it up while rebasing. Find an updated version attached.
Quoted 4 lines
Otherwise, for the series:
Acked-by Shawn Guo <[email protected]>
Thanks.
Sascha
8<----------------------------------------------------
Quoted 1 line
From
4de7de851c6666c4dca4f36acbc7f9b802ea7d7fMon Sep 17 00:00:00 2001
From: Sascha Hauer <[email protected]>
Date: Wed, 21 Nov 2012 14:42:31 +0100
Subject: [PATCH 2/3] ARM i.MX6: Fix ethernet PLL clocks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In current code the ethernet PLL is not handled correctly. The PLL runs at 500MHz and has different outputs. Only the enet reference clock is implemented. This patch changes the PLL so that it outputs 500MHz and adds the additional outputs as dividers. This now matches the datasheet which says:
Quoted 5 lines
This PLL synthesizes a low jitter clock from 24 MHz reference clock. The PLL outputs a 500 MHz clock. The reference clocks generated by this PLL are:
?Ref_PCIe= 125 MHz
?Ref_SATA= 100 MHz
?Ref_ethernet, which is configurable based on the PLL_ENET[1:0] register field.
--- .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ arch/arm/mach-imx/clk-imx6q.c | 20 ++++++- arch/arm/mach-imx/clk-pllv3.c | 63 +------------------- 3 files changed, 25 insertions(+), 63 deletions(-)
Documentation/devicetree/bindings/clock/imx6q-clock.txt +5 -0
@@ -198,6 +198,11 @@ clocks and IDs. usbphy2 183 ldb_di0_div_3_5 184 ldb_di1_div_3_5 185 + sata_ref 186 + sata_ref_100m 187 + pcie_ref 188 + pcie_ref_125m 189 + enet_ref 190 Examples:
arch/arm/mach-imx/clk-imx6q.c +19 -1
@@ -153,6 +153,7 @@ enum mx6q_clks { usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, 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, clk_max };
@@ -163,6 +164,13 @@ static enum mx6q_clks const clks_init_on[] __initconst = { mmdc_ch0_axi, rom, }; +static struct clk_div_table clk_enet_ref_table[] = { + { .val =0 , .div =20 , }, + { .val =1 , .div =10 , }, + { .val =2 , .div =5 , }, + { .val =3 , .div =4 , }, +}; +int __init mx6q_clocks_init (void ) {struct device_node *np;
@@ -195,13 +203,23 @@ int __init mx6q_clocks_init(void) clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 ); clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x2000 ,0x3 ); clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); clk[pll8_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll8_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 ); clk[usbphy1] =imx_clk_gate ("usbphy1" ,"pll3_usb_otg" , base +0x10 ,6 ); clk[usbphy2] =imx_clk_gate ("usbphy2" ,"pll7_usb_host" , base +0x20 ,6 ); + clk[sata_ref] =imx_clk_fixed_factor ("sata_ref" ,"pll6_enet" ,1 ,5 ); + clk[pcie_ref] =imx_clk_fixed_factor ("pcie_ref" ,"pll6_enet" ,1 ,4 ); + + clk[sata_ref_100m] =imx_clk_gate ("sata_ref_100m" ,"sata_ref" , base +0xe0 ,20 ); + clk[pcie_ref_125m] =imx_clk_gate ("pcie_ref_125m" ,"pcie_ref" , base +0xe0 ,19 ); + + clk[enet_ref] =clk_register_divider_table (NULL ,"enet_ref" ,"pll6_enet" ,0 , + base +0xe0 ,0 ,2 ,0 , clk_enet_ref_table, + &imx_ccm_lock); +/* name parent_name reg idx */ clk[pll2_pfd0_352m] =imx_clk_pfd ("pll2_pfd0_352m" ,"pll2_bus" , base +0x100 ,0 ); clk[pll2_pfd1_594m] =imx_clk_pfd ("pll2_pfd1_594m" ,"pll2_bus" , base +0x100 ,1 );
arch/arm/mach-imx/clk-pllv3.c +1 -62
75 lines not on this page · raw message
Signature · 7 lines
1.7.10.4 -- 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 2/3 ARM i.MX6: Fix ethernet PLL clocks
Hi Sascha and Shawn,
Quoted 237 lines · Sascha Hauer
Quoted 63 lines · Shawn Guo
Quoted 62 lines · Sascha Hauer
In current code the ethernet PLL is not handled correctly. The PLL runs at 500MHz and has different outputs. Only the enet reference clock is implemented. This patch changes the PLL so that it outputs 500MHz and adds the additional outputs as dividers. This now matches the datasheet which says:
Quoted 5 lines
This PLL synthesizes a low jitter clock from 24 MHz reference clock. The PLL outputs a 500 MHz clock. The reference clocks generated by this PLL are:
?Ref_PCIe= 125 MHz
?Ref_SATA= 100 MHz
?Ref_ethernet, which is configurable based on the PLL_ENET[1:0] register field.Signed-off-by Sascha Hauer <[email protected]>--- .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ arch/arm/mach-imx/clk-imx6q.c | 21 ++++++- arch/arm/mach-imx/clk-pllv3.c | 63 +------------------- 3 files changed, 25 insertions(+), 64 deletions(-)Documentation/devicetree/bindings/clock/imx6q-clock.txt +5
-0@@ -198,6 +198,11 @@ clocks and IDs. usbphy2 183 ldb_di0_div_3_5 184 ldb_di1_div_3_5 185 + sata_ref 186 + sata_ref_100m 187 + pcie_ref 188 + pcie_ref_125m 189 + enet_ref 190 Examples:arch/arm/mach-imx/clk-imx6q.c +8
-0@@ -153,6 +153,7 @@ enum mx6q_clks { usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, 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, clk_max };@@ -163,6 +164,13 @@ static enum mx6q_clks const clks_init_on[] __initconst = { mmdc_ch0_axi, rom, }; +static struct clk_div_table clk_enet_ref_table[] = { + { .val =0 , .div =20 , }, + { .val =1 , .div =10 , }, + { .val =2 , .div =5 , }, + { .val =3 , .div =4 , }, +}; +int __init mx6q_clocks_init (void ) {struct device_node *np;@@ -195,13 +203,22 @@ int __init mx6q_clocks_init(void) clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 );Quoted 8 lines
arch/arm/mach-imx/clk-imx6q.c int __init mx6q_clocks_init(void)
Quoted 6 lines
arch/arm/mach-imx/clk-imx6q.c +1
-2clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x2000 ,0x3 ); clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); - clk[pll8_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll8_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 );It gets removed by accident?
Yes, I screwed it up while rebasing. Find an updated version attached.
Quoted 4 lines
Otherwise, for the series:
Acked-by Shawn Guo <[email protected]>Thanks.
Sascha
8<----------------------------------------------------
From
4de7de851c6666c4dca4f36acbc7f9b802ea7d7fMon Sep 17 00:00:00 2001
From: Sascha Hauer <[email protected]>
Date: Wed, 21 Nov 2012 14:42:31 +0100
Subject: [PATCH 2/3] ARM i.MX6: Fix ethernet PLL clocks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bitIn current code the ethernet PLL is not handled correctly. The PLL runs at 500MHz and has different outputs. Only the enet reference clock is implemented. This patch changes the PLL so that it outputs 500MHz and adds the additional outputs as dividers. This now matches the datasheet which says:
Quoted 5 lines
This PLL synthesizes a low jitter clock from 24 MHz reference clock. The PLL outputs a 500 MHz clock. The reference clocks generated by this PLL are:
?Ref_PCIe= 125 MHz
?Ref_SATA= 100 MHz
?Ref_ethernet, which is configurable based on the PLL_ENET[1:0] register field.Signed-off-by Sascha Hauer <[email protected]>--- .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ arch/arm/mach-imx/clk-imx6q.c | 20 ++++++- arch/arm/mach-imx/clk-pllv3.c | 63 +------------------- 3 files changed, 25 insertions(+), 63 deletions(-)Documentation/devicetree/bindings/clock/imx6q-clock.txt +5
-0@@ -198,6 +198,11 @@ clocks and IDs. usbphy2 183 ldb_di0_div_3_5 184 ldb_di1_div_3_5 185 + sata_ref 186 + sata_ref_100m 187 + pcie_ref 188 + pcie_ref_125m 189 + enet_ref 190 Examples:arch/arm/mach-imx/clk-imx6q.c +19
-1@@ -153,6 +153,7 @@ enum mx6q_clks { usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, 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, clk_max };@@ -163,6 +164,13 @@ static enum mx6q_clks const clks_init_on[] __initconst = { mmdc_ch0_axi, rom, }; +static struct clk_div_table clk_enet_ref_table[] = { + { .val =0 , .div =20 , }, + { .val =1 , .div =10 , }, + { .val =2 , .div =5 , }, + { .val =3 , .div =4 , }, +}; +int __init mx6q_clocks_init (void ) {struct device_node *np;@@ -195,13 +203,23 @@ int __init mx6q_clocks_init(void) clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 ); clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x182000 ,0x3 ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x2000 ,0x3 ); clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); clk[pll8_mlb] =imx_clk_pllv3 (IMX_PLLV3_MLB ,"pll8_mlb" ,"osc" , base +0xd0 ,0x2000 ,0x0 ); clk[usbphy1] =imx_clk_gate ("usbphy1" ,"pll3_usb_otg" , base +0x10 ,6 ); clk[usbphy2] =imx_clk_gate ("usbphy2" ,"pll7_usb_host" , base +0x20 ,6 ); + clk[sata_ref] =imx_clk_fixed_factor ("sata_ref" ,"pll6_enet" ,1 ,5 ); + clk[pcie_ref] =imx_clk_fixed_factor ("pcie_ref" ,"pll6_enet" ,1 ,4 ); + + clk[sata_ref_100m] =imx_clk_gate ("sata_ref_100m" ,"sata_ref" , base +0xe0 ,20 ); + clk[pcie_ref_125m] =imx_clk_gate ("pcie_ref_125m" ,"pcie_ref" , base +0xe0 ,19 ); + + clk[enet_ref] =clk_register_divider_table (NULL ,"enet_ref" ,"pll6_enet" ,0 , + base +0xe0 ,0 ,2 ,0 , clk_enet_ref_table, + &imx_ccm_lock); +/* name parent_name reg idx */ clk[pll2_pfd0_352m] =imx_clk_pfd ("pll2_pfd0_352m" ,"pll2_bus" , base +0x100 ,0 ); clk[pll2_pfd1_594m] =imx_clk_pfd ("pll2_pfd1_594m" ,"pll2_bus" , base +0x100 ,1 );arch/arm/mach-imx/clk-pllv3.c +0
-50@@ -287,66 +287,7 @@ static const struct clk_ops clk_pllv3_av_ops = {static unsigned long clk_pllv3_enet_recalc_rate (struct clk_hw *hw,unsigned long parent_rate) { -struct clk_pllv3 *pll =to_clk_pllv3 (hw); -u32 div =readl_relaxed (pll->base) & pll->div_mask; - -switch (div) { -case 0 : -return 25000000 ; -case 1 : -return 50000000 ; -case 2 : -return 100000000 ; -case 3 : -return 125000000 ; - } - -return 0 ; -} - -static long clk_pllv3_enet_round_rate (struct clk_hw *hw,unsigned long rate, -unsigned long *prate) -{ -if (rate >=125000000 ) - rate =125000000 ; -else if (rate >=100000000 ) - rate =100000000 ; -else if (rate >=50000000 ) - rate =50000000 ; -else - rate =25000000 ; -return rate; -} - -static int clk_pllv3_enet_set_rate (struct clk_hw *hw,unsigned long rate, -unsigned long parent_rate) -{ -struct clk_pllv3 *pll =to_clk_pllv3 (hw); -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 ;
arch/arm/mach-imx/clk-pllv3.c static const struct clk_ops clk_pllv3_av_ops = { · line 349
Quoted 10 lines
arch/arm/mach-imx/clk-pllv3.c +0
-10-default : -return -EINVAL ; - } - - val =readl_relaxed (pll->base); - val &= ~pll->div_mask; - val |= div; -writel_relaxed (val, pll->base); - -return 0 ;
I'm no expert on this, but it seems to be able to use 100MHz or 125Mhz enet clock, you additionally have to set the ENABLE_100M (CCM_ANALOG_PLL_ENET[20]) or ENABLE_125M (CCM_ANALOG_PLL_ENET[19]) bits. Which isn't done by above change, and even worse, it's not possible with switching from dedicated clk_pllv3_enet_set_rate() to the generic ones using the clk_enet_ref_table.
Therefore, I've seen people doing
static int clk_pllv3_enet_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val, div, phase_shift_flag = 0;
switch (rate) {
case 25000000:
div = 0;
break;
case 50000000:
div = 1;
break;
case 100000000:
div = 2;
phase_shift_flag = 0x1 << 20;
break;
case 125000000:
div = 3;
phase_shift_flag = 0x1 << 19;
break;
default:
return -EINVAL;
}
val = readl_relaxed(pll->base);
val &= ~pll->div_mask;
val |= div;
val |= phase_shift_flag;
writel_relaxed(val, pll->base);
return 0;
}again (note the additional phase_shift_flag).
What do you think?
Best regards
Dirk
PATCH 2/3 ARM i.MX6: Fix ethernet PLL clocks
Quoted 4 lines · Dirk Behme
I'm no expert on this, but it seems to be able to use 100MHz or 125Mhz enet clock, you additionally have to set the
ENABLE_100M(CCM_ANALOG_PLL_ENET[20]) orENABLE_125M(CCM_ANALOG_PLL_ENET[19]) bits. Which isn't done by above change,
The following two lines added by the patch should just do.
clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);Quoted 3 lines
and even worse, it's not
possible with switching from dedicatedclk_pllv3_enet_set_rate()to the generic ones using theclk_enet_ref_table.
Hmm, I'm not sure I understand it. But why not possible?
Shawn
PATCH 2/3 ARM i.MX6: Fix ethernet PLL clocks
Quoted 10 lines · Shawn Guo
Quoted 4 lines · Dirk Behme
I'm no expert on this, but it seems to be able to use 100MHz or 125Mhz enet clock, you additionally have to set the
ENABLE_100M(CCM_ANALOG_PLL_ENET[20]) orENABLE_125M(CCM_ANALOG_PLL_ENET[19]) bits. Which isn't done by above change,The following two lines added by the patch should just do.
clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20); clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
Many thanks, we'll test that :)
It seems that it's unsure at the moment if ENABLE_100M (CCM_ANALOG_PLL_ENET[20]) or ENABLE_125M (CCM_ANALOG_PLL_ENET[19]) are really needed, though ...
Many thanks and best regards
Dirk
Sascha Hauer
maintainerPATCH 3/3 ARM i.MX6: remove gate_mask from pllv3
In reply to Sascha HauerNow that the additional enable bits in the enet PLL are handled as gates, the gate_mask is identical for all plls. Remove the gate_mask from the code and use the BM_PLL_ENABLE bit for enabling/disabling the PLL.
--- arch/arm/mach-imx/clk-imx6q.c | 16 ++++++++-------- arch/arm/mach-imx/clk-pllv3.c | 9 +++------ arch/arm/mach-imx/clk.h | 3 +-- 3 files changed, 12 insertions(+), 16 deletions(-)
arch/arm/mach-imx/clk-imx6q.c +8 -8
@@ -197,14 +197,14 @@ int __init mx6q_clocks_init(void) base =of_iomap (np,0 );WARN_ON (!base); -/* type name parent_name base gate_mask div_mask */ - clk[pll1_sys] =imx_clk_pllv3 (IMX_PLLV3_SYS ,"pll1_sys" ,"osc" , base,0x2000 ,0x7f ); - clk[pll2_bus] =imx_clk_pllv3 (IMX_PLLV3_GENERIC ,"pll2_bus" ,"osc" , base +0x30 ,0x2000 ,0x1 ); - clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x2000 ,0x3 ); - clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x2000 ,0x7f ); - clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x2000 ,0x7f ); - clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x2000 ,0x3 ); - clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x2000 ,0x3 ); +/* type name parent_name base div_mask */ + clk[pll1_sys] =imx_clk_pllv3 (IMX_PLLV3_SYS ,"pll1_sys" ,"osc" , base,0x7f ); + clk[pll2_bus] =imx_clk_pllv3 (IMX_PLLV3_GENERIC ,"pll2_bus" ,"osc" , base +0x30 ,0x1 ); + clk[pll3_usb_otg] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll3_usb_otg" ,"osc" , base +0x10 ,0x3 ); + clk[pll4_audio] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll4_audio" ,"osc" , base +0x70 ,0x7f ); + clk[pll5_video] =imx_clk_pllv3 (IMX_PLLV3_AV ,"pll5_video" ,"osc" , base +0xa0 ,0x7f ); + clk[pll6_enet] =imx_clk_pllv3 (IMX_PLLV3_ENET ,"pll6_enet" ,"osc" , base +0xe0 ,0x3 ); + clk[pll7_usb_host] =imx_clk_pllv3 (IMX_PLLV3_USB ,"pll7_usb_host" ,"osc" , base +0x20 ,0x3 ); clk[usbphy1] =imx_clk_gate ("usbphy1" ,"pll3_usb_otg" , base +0x10 ,6 ); clk[usbphy2] =imx_clk_gate ("usbphy2" ,"pll7_usb_host" , base +0x20 ,6 );
arch/arm/mach-imx/clk-pllv3.c +3 -6
@@ -31,7 +31,6 @@* @clk_hw: clock source * @base: base address of PLL registers * @powerup_set: set POWER bit to power up the PLL -* @gate_mask: mask of gate bits * @div_mask: mask of divider bits * * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3
@@ -41,7 +40,6 @@ struct clk_pllv3 {struct clk_hw hw;void __iomem *base;bool powerup_set; -u32 gate_mask;u32 div_mask; };
@@ -89,7 +87,7 @@ static int clk_pllv3_enable(struct clk_hw *hw)u32 val; val =readl_relaxed (pll->base); - val |= pll->gate_mask; + val |=BM_PLL_ENABLE ;writel_relaxed (val, pll->base);return 0 ;
@@ -101,7 +99,7 @@ static void clk_pllv3_disable(struct clk_hw *hw)u32 val; val =readl_relaxed (pll->base); - val &= ~pll->gate_mask; + val &= ~BM_PLL_ENABLE ;writel_relaxed (val, pll->base); }
@@ -307,7 +305,7 @@ static const struct clk_ops clk_pllv3_mlb_ops = {struct clk *imx_clk_pllv3 (enum imx_pllv3_type type,const char *name,const char *parent_name,void __iomem *base, -u32 gate_mask,u32 div_mask) +u32 div_mask) {struct clk_pllv3 *pll;const struct clk_ops *ops;
@@ -339,7 +337,6 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, ops = &clk_pllv3_ops; } pll->base = base; - pll->gate_mask = gate_mask; pll->div_mask = div_mask; init.name = name;
arch/arm/mach-imx/clk.h +1 -2
@@ -22,8 +22,7 @@ enum imx_pllv3_type { };struct clk *imx_clk_pllv3 (enum imx_pllv3_type type,const char *name, -const char *parent_name,void __iomem *base,u32 gate_mask, -u32 div_mask); +const char *parent_name,void __iomem *base,u32 div_mask); struct clk *clk_register_gate2(struct device *dev, const char *name, const char *parent_name, unsigned long flags,
Signature · 1 line
1.7.10.4