Message ID | 1353505652-28200-1-git-send-email-s.hauer@pengutronix.de |
---|---|
State | New |
Headers | show |
On Wed, Nov 21, 2012 at 02:47:32PM +0100, Sascha Hauer wrote: > In current code the ethernet PLL (according to code pll8, according to datasheet > pll6) 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: > > > 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 <s.hauer@pengutronix.de> > --- > .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ > arch/arm/mach-imx/clk-imx6q.c | 18 +++++- > arch/arm/mach-imx/clk-pllv3.c | 59 +------------------- > 3 files changed, 24 insertions(+), 58 deletions(-) > > diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt > index 492bd99..94311e2 100644 > --- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt > +++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt > @@ -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: > > diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c > index 3ec242f..95f8ea5 100644 > --- a/arch/arm/mach-imx/clk-imx6q.c > +++ b/arch/arm/mach-imx/clk-imx6q.c > @@ -153,7 +153,7 @@ enum mx6q_clks { > 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, > ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, > - clk_max > + sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, clk_max > }; > > static struct clk *clk[clk_max]; > @@ -163,6 +163,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; > @@ -202,6 +209,15 @@ int __init mx6q_clocks_init(void) > 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_gate("sata_ref", "pll8_enet", base + 0x20, 20); > + clk[pcie_ref] = imx_clk_gate("pcie_ref", "pll8_enet", base + 0x20, 19); > + clk[sata_ref_100m] = imx_clk_fixed_factor("sata_ref_100m", "sata_ref", 1, 5); > + clk[pcie_ref_125m] = imx_clk_fixed_factor("pcie_ref_100m", "pcie_ref", 1, 4); > + > + clk[enet_ref] = clk_register_divider_table(NULL, "enet_ref", "pll8_enet", 0, > + base + 0x20, 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); > diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c > index 36aac94..f5e210a 100644 > --- a/arch/arm/mach-imx/clk-pllv3.c > +++ b/arch/arm/mach-imx/clk-pllv3.c > @@ -287,66 +287,13 @@ 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; > + return 500000000; > } > > static long clk_pllv3_enet_round_rate(struct clk_hw *hw, unsigned long rate, > unsigned long *prate) > { This function should be removed completely. Will fix. Sascha
On Wed, Nov 21, 2012 at 02:47:32PM +0100, Sascha Hauer wrote: > In current code the ethernet PLL (according to code pll8, according to datasheet > pll6) Yes, just checked the latest RM, it gets renumbered so. > 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: > > > 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 <s.hauer@pengutronix.de> > --- > .../devicetree/bindings/clock/imx6q-clock.txt | 5 ++ > arch/arm/mach-imx/clk-imx6q.c | 18 +++++- > arch/arm/mach-imx/clk-pllv3.c | 59 +------------------- > 3 files changed, 24 insertions(+), 58 deletions(-) > > diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt > index 492bd99..94311e2 100644 > --- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt > +++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt > @@ -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: > > diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c > index 3ec242f..95f8ea5 100644 > --- a/arch/arm/mach-imx/clk-imx6q.c > +++ b/arch/arm/mach-imx/clk-imx6q.c > @@ -153,7 +153,7 @@ enum mx6q_clks { > 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, > ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, > - clk_max > + sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, clk_max The clk_max was put on a separate line on purpose, so that you can add new ones with + lines only. > }; > > static struct clk *clk[clk_max]; > @@ -163,6 +163,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; > @@ -202,6 +209,15 @@ int __init mx6q_clocks_init(void) > 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_gate("sata_ref", "pll8_enet", base + 0x20, 20); > + clk[pcie_ref] = imx_clk_gate("pcie_ref", "pll8_enet", base + 0x20, 19); Offset 0x20 for PLL_ENET? > + clk[sata_ref_100m] = imx_clk_fixed_factor("sata_ref_100m", "sata_ref", 1, 5); > + clk[pcie_ref_125m] = imx_clk_fixed_factor("pcie_ref_100m", "pcie_ref", 1, 4); s/pcie_ref_100m/pcie_ref_125m Also, don't we generally have divider/factor be parent of gate, do we? > + > + clk[enet_ref] = clk_register_divider_table(NULL, "enet_ref", "pll8_enet", 0, > + base + 0x20, 0, 2, 0, clk_enet_ref_table, Ditto on offset? Shawn > + &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); > diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c > index 36aac94..f5e210a 100644 > --- a/arch/arm/mach-imx/clk-pllv3.c > +++ b/arch/arm/mach-imx/clk-pllv3.c > @@ -287,66 +287,13 @@ 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; > + return 500000000; > } > > 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 +302,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 = { > -- > 1.7.10.4 >
On Thu, Nov 22, 2012 at 04:42:31PM +0800, Shawn Guo wrote: > On Wed, Nov 21, 2012 at 02:47:32PM +0100, Sascha Hauer wrote: > > In current code the ethernet PLL (according to code pll8, according to datasheet > > pll6) > > Yes, just checked the latest RM, it gets renumbered so. So do we want to keep current code or change it according to the datasheet? > > diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c > > index 3ec242f..95f8ea5 100644 > > --- a/arch/arm/mach-imx/clk-imx6q.c > > +++ b/arch/arm/mach-imx/clk-imx6q.c > > @@ -153,7 +153,7 @@ enum mx6q_clks { > > 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, > > ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, > > - clk_max > > + sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, clk_max > > The clk_max was put on a separate line on purpose, so that you can add > new ones with + lines only. Ok, will fix. > > > }; > > > > static struct clk *clk[clk_max]; > > @@ -163,6 +163,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; > > @@ -202,6 +209,15 @@ int __init mx6q_clocks_init(void) > > 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_gate("sata_ref", "pll8_enet", base + 0x20, 20); > > + clk[pcie_ref] = imx_clk_gate("pcie_ref", "pll8_enet", base + 0x20, 19); > > Offset 0x20 for PLL_ENET? Indeed, that's wrong. It turned out that my sata disk only worked because the enet pll had the enable bits for the sata clock in the gate mask. Will fix that. > > > + clk[sata_ref_100m] = imx_clk_fixed_factor("sata_ref_100m", "sata_ref", 1, 5); > > + clk[pcie_ref_125m] = imx_clk_fixed_factor("pcie_ref_100m", "pcie_ref", 1, 4); > > s/pcie_ref_100m/pcie_ref_125m ok. > > Also, don't we generally have divider/factor be parent of gate, do we? Will change. Sascha
On Thu, Nov 22, 2012 at 05:16:21PM +0800, Shawn Guo wrote: > On Thu, Nov 22, 2012 at 09:47:07AM +0100, Sascha Hauer wrote: > > On Thu, Nov 22, 2012 at 04:42:31PM +0800, Shawn Guo wrote: > > > On Wed, Nov 21, 2012 at 02:47:32PM +0100, Sascha Hauer wrote: > > > > In current code the ethernet PLL (according to code pll8, according to datasheet > > > > pll6) > > > > > > Yes, just checked the latest RM, it gets renumbered so. > > > > So do we want to keep current code or change it according to the > > datasheet? > > > While you are there, yeah, let's make it match doc :) Will do. Sascha
On Thu, Nov 22, 2012 at 09:47:07AM +0100, Sascha Hauer wrote: > On Thu, Nov 22, 2012 at 04:42:31PM +0800, Shawn Guo wrote: > > On Wed, Nov 21, 2012 at 02:47:32PM +0100, Sascha Hauer wrote: > > > In current code the ethernet PLL (according to code pll8, according to datasheet > > > pll6) > > > > Yes, just checked the latest RM, it gets renumbered so. > > So do we want to keep current code or change it according to the > datasheet? > While you are there, yeah, let's make it match doc :) Shawn
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt index 492bd99..94311e2 100644 --- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt +++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt @@ -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: diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 3ec242f..95f8ea5 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -153,7 +153,7 @@ enum mx6q_clks { 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, ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, - clk_max + sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, clk_max }; static struct clk *clk[clk_max]; @@ -163,6 +163,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; @@ -202,6 +209,15 @@ int __init mx6q_clocks_init(void) 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_gate("sata_ref", "pll8_enet", base + 0x20, 20); + clk[pcie_ref] = imx_clk_gate("pcie_ref", "pll8_enet", base + 0x20, 19); + clk[sata_ref_100m] = imx_clk_fixed_factor("sata_ref_100m", "sata_ref", 1, 5); + clk[pcie_ref_125m] = imx_clk_fixed_factor("pcie_ref_100m", "pcie_ref", 1, 4); + + clk[enet_ref] = clk_register_divider_table(NULL, "enet_ref", "pll8_enet", 0, + base + 0x20, 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); diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index 36aac94..f5e210a 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -287,66 +287,13 @@ 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; + return 500000000; } 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 +302,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 = {