AnsweredAssumed Answered

How to output 50MHz on a pin of imx7d constantly

Question asked by Cheng Shi on Jun 5, 2018
Latest reply on Jun 21, 2018 by Cheng Shi

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

Outcomes