I’m trying to bring up a board with a second Ethernet interface on a Colibri i.mx7D. We’re using RMII to connect a KSZ8041 PHY. In our design, the 50MHz reference clock is to be generated internal to the i.mx SoC and driven out the CCM_ENET2_REF_CLK path. Things are mostly working, but there’s no data going through the MAC. Some sleuthing suggests that the MAC is missing its reference clock, although that clock is enabled (see clk summary below) and is driving the PHY correctly.
Here’s how we have the fec configured:
&fec2 {
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_DIV>;
clock-names = "ipg", "ahb", "ptp", "enet_clk_ref", "enet_out";
assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>,
<&clks IMX7D_ENET_PHY_REF_ROOT_DIV>;
assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
assigned-clock-rates = <0>, <100000000>, <50000000>;
phy-mode = "rmii";
fsl,mii-exclusive;
status = "okay";
};
The pin group is defined as follows:
pinctrl_enet2: enet2grp {
fsl,pins = <
MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x73
MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x73
MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x73
MX7D_PAD_EPDC_SDCE1__ENET2_RX_ER 0x73
MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x73
MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x73
MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x73
MX7D_PAD_EPDC_BDR0__CCM_ENET_REF_CLK2 0x73
MX7D_PAD_GPIO1_IO14__ENET2_MDIO 0x3
MX7D_PAD_GPIO1_IO15__ENET2_MDC 0x3
>;
};
As already mentioned, the 50 MHz clock is appearing on the EPDC_BDR0 ball and the PHY is properly negotiating the link. Data is received by the PHY, and there is clearly data queued for transmission in the kernel. An ethtool dump of the MAC registers shows that the receiver is enabled, and the TDAR bit is set. Yet, nothing is received through the MAC and nothing is ever transmitted. There’s no action on the TX_EN or the TD RMII signals. The TDAR bit never clears, and eventually the driver times out and dumps the ring buffer to the console. So it looks to me like the MAC isn’t getting the reference clock.
We’re using the latest supported Linux kernel (4.9.84). Here’s a dump of the Ethernet clock tree (edited to remove what I think are the irrelevant parts):
pll_enet_main 1
pll_enet_main_bypass 1
pll_enet_main_clk 3
pll_enet_25m 0
pll_enet_25m_clk 0
enet_phy_ref_src 0
enet_phy_ref_cg 0
enet_phy_ref_pre_div 0
enet_phy_ref_post_div 0
pll_enet_50m 1
pll_enet_50m_clk 3
enet2_ref_src 1
enet2_ref_cg 1
enet2_ref_pre_div 1
enet2_ref_post_div 1
pll_enet_100m 1
pll_enet_100m_clk 2
pcie_phy_src 0
pcie_phy_cg 0
pcie_phy_pre_div 0
pcie_phy_post_div 0
pcie_phy_root_clk 0
enet2_time_src 1
enet2_time_cg 1
enet2_time_pre_div 1
enet2_time_post_div 1
enet2_time_root_clk 1
enet1_time_src 1
enet1_time_cg 1
enet1_time_pre_div 1
enet1_time_post_div 1
enet1_time_root_clk 1
pll_enet_250m 1
pll_enet_250m_clk 1
enet_axi_src 1
enet_axi_cg 1
enet_axi_pre_div 1
enet_axi_post_div 3
enet2_ipg_root_clk 1
enet1_ipg_root_clk 1
enet_axi_root_clk 2
Where does the MAC get its reference clock from when the ENET2_TX_CLK_SEL bit is set to use an internal reference clock? (I.e., which CCM output) The documentation from NXP seems a big vague on this subject.
What is the meaning of ALT1 vis a vis the ENET2_CLK_DIR bit in GPR1? The ball that outputs the ENET_REF_CLK2 has no ALT1 function defined. Is that a documentation error, or am I missing something?