Patchwork ARM: imx6q: support ptp and rmii clock from pad

login
register
mail settings
Submitter Shawn Guo
Date Feb. 6, 2014, 5:53 a.m.
Message ID <1391666018-12825-1-git-send-email-shawn.guo@linaro.org>
Download mbox | patch
Permalink /patch/317353/
State New
Headers show

Comments

Shawn Guo - Feb. 6, 2014, 5:53 a.m.
On imx6qdl, the ENET RMII and PTP clock can come from either internal
ANATOP/CCM or external clock source through pad GPIO_16.  But in case
of the external clock source, bit IOMUXC_GPR1[21] needs to be cleared.

The patch adds the support for systems that use an external clock source
and distinguishes above two cases by checking if the PTP clock specified
in device tree is the one coming from the internal ANATOP/CCM.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/mach-imx/clk-imx6q.c  |    1 +
 arch/arm/mach-imx/mach-imx6q.c |   36 +++++++++++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)
Philippe De Muyter - Feb. 7, 2014, 10:45 a.m.
Thanks, Shawn

your patch works perfectly.  I can now use the same kernel on my sabresd
board (RGMII, enet_ref_clock generated by the imx6q) and my custom board
(RMII, clock generated by the PHY).

some comments. though :

the patch did not apply cleanly in clk-imx6q.c on v3.13

don't forget to complete Documentation/devicetree/bindings/

But, again, many thanks for the support

Philippe


On Thu, Feb 06, 2014 at 01:53:38PM +0800, Shawn Guo wrote:
> On imx6qdl, the ENET RMII and PTP clock can come from either internal
> ANATOP/CCM or external clock source through pad GPIO_16.  But in case
> of the external clock source, bit IOMUXC_GPR1[21] needs to be cleared.
> 
> The patch adds the support for systems that use an external clock source
> and distinguishes above two cases by checking if the PTP clock specified
> in device tree is the one coming from the internal ANATOP/CCM.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  arch/arm/mach-imx/clk-imx6q.c  |    1 +
>  arch/arm/mach-imx/mach-imx6q.c |   36 +++++++++++++++++++++++++++++++++++-
>  2 files changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
> index dd4f1e3..45de2e5 100644
> --- a/arch/arm/mach-imx/clk-imx6q.c
> +++ b/arch/arm/mach-imx/clk-imx6q.c
> @@ -437,6 +437,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
>  
>  	clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
>  	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
> +	clk_register_clkdev(clk[enet_ref], "enet_ref", NULL);
>  
>  	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
>  	    cpu_is_imx6dl()) {
> diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
> index f9cbbf9..d131499b 100644
> --- a/arch/arm/mach-imx/mach-imx6q.c
> +++ b/arch/arm/mach-imx/mach-imx6q.c
> @@ -182,16 +182,50 @@ static void __init imx6q_enet_phy_init(void)
>  
>  static void __init imx6q_1588_init(void)
>  {
> +	struct device_node *np;
> +	struct clk *ptp_clk;
> +	struct clk *enet_ref;
>  	struct regmap *gpr;
> +	u32 clksel;
> +
> +	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
> +	if (!np) {
> +		pr_warn("%s: failed to find fec node\n", __func__);
> +		return;
> +	}
> +
> +	ptp_clk = of_clk_get(np, 2);
> +	if (IS_ERR(ptp_clk)) {
> +		pr_warn("%s: failed to get ptp clock\n", __func__);
> +		goto put_node;
> +	}
> +
> +	enet_ref = clk_get_sys(NULL, "enet_ref");
> +	if (IS_ERR(enet_ref)) {
> +		pr_warn("%s: failed to get enet clock\n", __func__);
> +		goto put_ptp_clk;
> +	}
>  
> +	/*
> +	 * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
> +	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
> +	 * (external OSC), and we need to clear the bit.
> +	 */
> +	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
> +				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>  	if (!IS_ERR(gpr))
>  		regmap_update_bits(gpr, IOMUXC_GPR1,
>  				IMX6Q_GPR1_ENET_CLK_SEL_MASK,
> -				IMX6Q_GPR1_ENET_CLK_SEL_ANATOP);
> +				clksel);
>  	else
>  		pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
>  
> +	clk_put(enet_ref);
> +put_ptp_clk:
> +	clk_put(ptp_clk);
> +put_node:
> +	of_node_put(np);
>  }
>  
>  static void __init imx6q_init_machine(void)
> -- 
> 1.7.9.5
>
Shawn Guo - Feb. 10, 2014, 6:03 a.m.
On Fri, Feb 07, 2014 at 11:45:18AM +0100, Philippe De Muyter wrote:
> Thanks, Shawn
> 
> your patch works perfectly.  I can now use the same kernel on my sabresd
> board (RGMII, enet_ref_clock generated by the imx6q) and my custom board
> (RMII, clock generated by the PHY).

That's great.

> 
> some comments. though :
> 
> the patch did not apply cleanly in clk-imx6q.c on v3.13

The patch targets v3.14-rc1, and if you need it for v3.13 you will need
to back port it.

> 
> don't forget to complete Documentation/devicetree/bindings/

It requires change on device tree sources but not bindings.  Which part
of Documentation/devicetree/bindings/ do you think we need to update?

Shawn

> 
> But, again, many thanks for the support
> 
> Philippe
> 
> 
> On Thu, Feb 06, 2014 at 01:53:38PM +0800, Shawn Guo wrote:
> > On imx6qdl, the ENET RMII and PTP clock can come from either internal
> > ANATOP/CCM or external clock source through pad GPIO_16.  But in case
> > of the external clock source, bit IOMUXC_GPR1[21] needs to be cleared.
> > 
> > The patch adds the support for systems that use an external clock source
> > and distinguishes above two cases by checking if the PTP clock specified
> > in device tree is the one coming from the internal ANATOP/CCM.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > ---
> >  arch/arm/mach-imx/clk-imx6q.c  |    1 +
> >  arch/arm/mach-imx/mach-imx6q.c |   36 +++++++++++++++++++++++++++++++++++-
> >  2 files changed, 36 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
> > index dd4f1e3..45de2e5 100644
> > --- a/arch/arm/mach-imx/clk-imx6q.c
> > +++ b/arch/arm/mach-imx/clk-imx6q.c
> > @@ -437,6 +437,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
> >  
> >  	clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
> >  	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
> > +	clk_register_clkdev(clk[enet_ref], "enet_ref", NULL);
> >  
> >  	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
> >  	    cpu_is_imx6dl()) {
> > diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
> > index f9cbbf9..d131499b 100644
> > --- a/arch/arm/mach-imx/mach-imx6q.c
> > +++ b/arch/arm/mach-imx/mach-imx6q.c
> > @@ -182,16 +182,50 @@ static void __init imx6q_enet_phy_init(void)
> >  
> >  static void __init imx6q_1588_init(void)
> >  {
> > +	struct device_node *np;
> > +	struct clk *ptp_clk;
> > +	struct clk *enet_ref;
> >  	struct regmap *gpr;
> > +	u32 clksel;
> > +
> > +	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
> > +	if (!np) {
> > +		pr_warn("%s: failed to find fec node\n", __func__);
> > +		return;
> > +	}
> > +
> > +	ptp_clk = of_clk_get(np, 2);
> > +	if (IS_ERR(ptp_clk)) {
> > +		pr_warn("%s: failed to get ptp clock\n", __func__);
> > +		goto put_node;
> > +	}
> > +
> > +	enet_ref = clk_get_sys(NULL, "enet_ref");
> > +	if (IS_ERR(enet_ref)) {
> > +		pr_warn("%s: failed to get enet clock\n", __func__);
> > +		goto put_ptp_clk;
> > +	}
> >  
> > +	/*
> > +	 * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
> > +	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
> > +	 * (external OSC), and we need to clear the bit.
> > +	 */
> > +	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
> > +				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
> >  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
> >  	if (!IS_ERR(gpr))
> >  		regmap_update_bits(gpr, IOMUXC_GPR1,
> >  				IMX6Q_GPR1_ENET_CLK_SEL_MASK,
> > -				IMX6Q_GPR1_ENET_CLK_SEL_ANATOP);
> > +				clksel);
> >  	else
> >  		pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
> >  
> > +	clk_put(enet_ref);
> > +put_ptp_clk:
> > +	clk_put(ptp_clk);
> > +put_node:
> > +	of_node_put(np);
> >  }
> >  
> >  static void __init imx6q_init_machine(void)
> > -- 
> > 1.7.9.5
> > 
> 
> -- 
> Philippe De Muyter +32 2 6101532 Macq SA rue de l'Aeronef 2 B-1140 Bruxelles
Philippe De Muyter - Feb. 10, 2014, 8:26 a.m.
On Mon, Feb 10, 2014 at 02:03:23PM +0800, Shawn Guo wrote:
> On Fri, Feb 07, 2014 at 11:45:18AM +0100, Philippe De Muyter wrote:
> > Thanks, Shawn
> > 
> > your patch works perfectly.  I can now use the same kernel on my sabresd
> > board (RGMII, enet_ref_clock generated by the imx6q) and my custom board
> > (RMII, clock generated by the PHY).
> 
> That's great.
> 
> > 
> > some comments. though :
> > 
> > the patch did not apply cleanly in clk-imx6q.c on v3.13
> 
> The patch targets v3.14-rc1, and if you need it for v3.13 you will need
> to back port it.
> 
> > 
> > don't forget to complete Documentation/devicetree/bindings/
> 
> It requires change on device tree sources but not bindings.  Which part
> of Documentation/devicetree/bindings/ do you think we need to update?

Would Documentation/devicetree/bindings/net/fsl-fec.txt (perhaps also
Documentation/devicetree/bindings/clock/imx6q-clock.txt) not be a good place
for that ?

Philippe

> 
> Shawn
> 
> > 
> > But, again, many thanks for the support
> > 
> > Philippe
> > 
> > 
> > On Thu, Feb 06, 2014 at 01:53:38PM +0800, Shawn Guo wrote:
> > > On imx6qdl, the ENET RMII and PTP clock can come from either internal
> > > ANATOP/CCM or external clock source through pad GPIO_16.  But in case
> > > of the external clock source, bit IOMUXC_GPR1[21] needs to be cleared.
> > > 
> > > The patch adds the support for systems that use an external clock source
> > > and distinguishes above two cases by checking if the PTP clock specified
> > > in device tree is the one coming from the internal ANATOP/CCM.
> > > 
> > > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>

Patch

diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index dd4f1e3..45de2e5 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -437,6 +437,7 @@  static void __init imx6q_clocks_init(struct device_node *ccm_node)
 
 	clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
 	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
+	clk_register_clkdev(clk[enet_ref], "enet_ref", NULL);
 
 	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
 	    cpu_is_imx6dl()) {
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index f9cbbf9..d131499b 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -182,16 +182,50 @@  static void __init imx6q_enet_phy_init(void)
 
 static void __init imx6q_1588_init(void)
 {
+	struct device_node *np;
+	struct clk *ptp_clk;
+	struct clk *enet_ref;
 	struct regmap *gpr;
+	u32 clksel;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
+	if (!np) {
+		pr_warn("%s: failed to find fec node\n", __func__);
+		return;
+	}
+
+	ptp_clk = of_clk_get(np, 2);
+	if (IS_ERR(ptp_clk)) {
+		pr_warn("%s: failed to get ptp clock\n", __func__);
+		goto put_node;
+	}
+
+	enet_ref = clk_get_sys(NULL, "enet_ref");
+	if (IS_ERR(enet_ref)) {
+		pr_warn("%s: failed to get enet clock\n", __func__);
+		goto put_ptp_clk;
+	}
 
+	/*
+	 * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
+	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
+	 * (external OSC), and we need to clear the bit.
+	 */
+	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
+				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
 	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (!IS_ERR(gpr))
 		regmap_update_bits(gpr, IOMUXC_GPR1,
 				IMX6Q_GPR1_ENET_CLK_SEL_MASK,
-				IMX6Q_GPR1_ENET_CLK_SEL_ANATOP);
+				clksel);
 	else
 		pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
 
+	clk_put(enet_ref);
+put_ptp_clk:
+	clk_put(ptp_clk);
+put_node:
+	of_node_put(np);
 }
 
 static void __init imx6q_init_machine(void)