How to output 50MHz on a pin of imx7d constantly

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to output 50MHz on a pin of imx7d constantly

Jump to solution
3,145 Views
x10
Contributor V

Hi, 

iMX7D enet2 is configured as rmii to lan8720a(phy) in my customer board. With following dts and code change, I can see the 50Mhz on the pin only for very short time, and then disabled when kernel booting finished.

DTS:

pinctrl_enet2: enet2grp {
fsl,pins = <
MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x73
MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x73
MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x73 /* TX_EN */
MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x73
MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x73
MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x73 /* CRS_DV */
MX7D_PAD_EPDC_BDR0__CCM_ENET_REF_CLK2 0x73 /* output REF_CLK (50MHz) */
/* not used in LAN8720A */
/*MX7D_PAD_EPDC_SDCE1__ENET2_RX_ER 0x73*/ /* RX_ER */
>;

&fec2 {
compatible = "fsl,imx7d-fec", "fsl,imx6sx-fec";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
clocks = <&clks IMX7D_ENET2_IPG_ROOT_CLK>,
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_50M_CLK>,
<&clks IMX7D_ENET2_REF_ROOT_CLK>;
clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out";
assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>;
mac-address = [ d0 9b 05 00 10 20 ]; /* temp mac id */
phy-mode = "rmii";
phy-handle = <&ethphy1>;
fsl,magic-packet;
status = "okay";
};

clk-imx7d.c code changed as follows:

/*
* init enet clock source:
* AXI clock source is 250Mhz
* Phy refrence clock is 25Mhz
* 1588 time clock source is 100Mhz
*/
imx_clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]);
imx_clk_set_rate(clks[IMX7D_ENET_AXI_ROOT_CLK], 267000000);
imx_clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_25M_CLK]);

+ /* clock mux has to be put to the 50Mhz */
+ imx_clk_set_parent(clks[IMX7D_ENET2_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_50M_CLK]);

+

/* set pcie root's parent clk source */
imx_clk_set_parent(clks[IMX7D_PCIE_CTRL_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]);

 

changes in mach-imx7d.c are referenced that of toradex:

static void __init imx7d_enet_clk_sel(void)
{
 struct device_node *np;
 struct clk *enet_out_clk;
 struct regmap *gpr;

 np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-fec");
 if (!np) {
 pr_warn("%s: failed to find fec node\n", __func__);
 return;
 }

 enet_out_clk = of_clk_get_by_name(np, "enet_out");

 gpr = syscon_regmap_lookup_by_compatible("fsl,imx7d-iomuxc-gpr");

 if (!IS_ERR(gpr)) {
 if (IS_ERR(enet_out_clk)) {
 pr_info("%s: failed to get enet_out clock, assuming ext. clock source\n", __func__);
 /* use external clock for PHY */
 regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK);
 regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_CLK_DIR_MASK, 0);
 } else {
 pr_info("%s: found enet_out clock, assuming internal clock source\n", __func__);
 /* use internal clock generation and output it to PHY */
 regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK, 0);
 regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_CLK_DIR_MASK, IMX7D_GPR1_ENET_CLK_DIR_MASK);
 clk_put(enet_out_clk);

 }
 } else {
 pr_err("failed to find fsl,imx7d-iomux-gpr regmap\n");
 }
 of_node_put(np);
}

The kernel is from yocto, it's 4.9.11. 

The changes should be OK as 50Mhz can be seen during booting, but I can not figure out the cause which stops outputing the clock. Thanks for all helps in adavnce.

BR

Cheng Shi

Labels (1)
1 Solution
2,200 Views
x10
Contributor V

Hi, Igor

The fec2 in my board is got work with following config:

&fec2 {
compatible = "fsl,imx7d-fec", "fsl,imx6sx-fec";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
clocks = <&clks IMX7D_ENET2_IPG_ROOT_CLK>,
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_50M_CLK>,
<&clks IMX7D_ENET2_REF_ROOT_CLK>;
clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "no_enet_out";
assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>;
local-mac-address = [ d0 9b 05 00 10 20 ]; /* temp mac id */
phy-mode = "rmii";
phy-handle = <&ethphy1>;
fsl,magic-packet;
status = "okay";
};

pinctrl_enet2: enet2grp {
fsl,pins = <
MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x73
MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x73
MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x73 /* TX_EN */
MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x73
MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x73
MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x73 /* CRS_DV */
MX7D_PAD_EPDC_SDCE1__ENET2_RX_ER 0x73 /* RX_ER */
MX7D_PAD_EPDC_BDR0__CCM_ENET_REF_CLK2 0x40000073 /* PAD_EPDC_BDR0_ALT3 => CCM_ENET_REF_CLK2: 50MHz input */
>;
};

ENET_PHY_REF_CLK is used as 50MHz clock source with update in clk-imx7d.c as follows:

imx_clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_50M_CLK]);

The ENET_PHY_REF_CLK is connected to both CCM_ENET_REF_CLK2 and external phy's CLKIN.

Thanks for all your help.

BR

Cheng Shi

View solution in original post

0 Kudos
8 Replies
2,200 Views
emintolgasivri
Contributor II

Did you try to change "no_enet_out" with "enet_out"

0 Kudos
2,201 Views
x10
Contributor V

Hi, Igor

The fec2 in my board is got work with following config:

&fec2 {
compatible = "fsl,imx7d-fec", "fsl,imx6sx-fec";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2>;
clocks = <&clks IMX7D_ENET2_IPG_ROOT_CLK>,
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_50M_CLK>,
<&clks IMX7D_ENET2_REF_ROOT_CLK>;
clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "no_enet_out";
assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>;
local-mac-address = [ d0 9b 05 00 10 20 ]; /* temp mac id */
phy-mode = "rmii";
phy-handle = <&ethphy1>;
fsl,magic-packet;
status = "okay";
};

pinctrl_enet2: enet2grp {
fsl,pins = <
MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x73
MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x73
MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x73 /* TX_EN */
MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x73
MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x73
MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x73 /* CRS_DV */
MX7D_PAD_EPDC_SDCE1__ENET2_RX_ER 0x73 /* RX_ER */
MX7D_PAD_EPDC_BDR0__CCM_ENET_REF_CLK2 0x40000073 /* PAD_EPDC_BDR0_ALT3 => CCM_ENET_REF_CLK2: 50MHz input */
>;
};

ENET_PHY_REF_CLK is used as 50MHz clock source with update in clk-imx7d.c as follows:

imx_clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_50M_CLK]);

The ENET_PHY_REF_CLK is connected to both CCM_ENET_REF_CLK2 and external phy's CLKIN.

Thanks for all your help.

BR

Cheng Shi

0 Kudos
2,200 Views
x10
Contributor V

Hi, Igor

Thanks for reply. The ENET2_TX_CLK_SEL set to 0, and ENET2_CLK_DIR set to 1 with following code:

 regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK, 0);
 regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_CLK_DIR_MASK, IMX7D_GPR1_ENET_CLK_DIR_MASK);

in mach-imx7d.c. On pin MX7D_PAD_EPDC_BDR0, a 50MHz clock can be seen on oscilloscope. 
With further tesing, I'm sure the problem is that fec2 can not send out tx data, as TX_EN is always low. The phy lan8720a
can be set in normal link state, and rx data is on chip's pins. As result eth1 is invalid, and be shutdown by system, which cause 
the 50Mhz clock is disabled as well. I have double checked 3.3V power supply to NVCC_EPDC1 and NVCC_EPDC2 is okay,
and some gpio pins from the same group are work fine.
In my design, fec1 is in rgmii, which works fine, and fec2 is in rmii.

BR
Cheng Shi
0 Kudos
2,200 Views
igorpadykov
NXP Employee
NXP Employee

Hi Cheng

one can check assigned clocks, below example

RMII interface on the IMX7 

Best regards
igor

0 Kudos
2,200 Views
x10
Contributor V

Hi, Igor

I have changed assigned-clocks to IMX7D_PLL_ENET_MAIN_50M_CLK, no luck. 

I just wonder how to know that the ENET2_REF_CLK is applied to fec2 controller, as ENET2_REF_CLK is not listed in Table11-2 in RM, which is a table of enet clocks. The ENET2_REF_CLK may not be applied to fec2 properly, so that TX_EN can not been clocked out on its pin?

BR

Cheng Shi

0 Kudos
2,200 Views
igorpadykov
NXP Employee
NXP Employee

Hi Cheng

one can try to rebuild all sources anew from scratch, also

what bsp used in the case, one can try nxp release

linux-imx - i.MX Linux kernel 

also one can try to test in L4.1.15 kernel

Best regards
igor

0 Kudos
2,200 Views
x10
Contributor V

Hi, Igor

The kernel I'm using is 4.9.11_1.0.0 already. I will try imx_4.9.11_2.0.0_ga later.

I haven't found the IMX7D_ENET2_REF_ROOT_CLK clk instance in clk-imx7d.c, but the clock is used in fec driver code. confused.

Thanks for help.

BR

Cheng Shi

0 Kudos
2,200 Views
igorpadykov
NXP Employee
NXP Employee

Hi Cheng

one can set  IMX7D_GPR1_ENET_CLK_DIR to 1, as described in

sect.8.2.4.2 GPR1 General Purpose Register (IOMUXC_GPR_GPR1)

i.MX7D Reference Manual:

1 ENET_TX_CLK output driver is enabled when configured for ALT1

http://cache.nxp.com/files/32bit/doc/ref_manual/IMX7DRM.pdf

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------