IMX6ULL+LAN8720*2移植

内核版本:kernel5.10.35
1、硬件连接
两路网口都采用的RMII方式连接。fec1连接的PHY地址"0",fec2连接的PHY地址"1"。PHY地址由LAN8720第10引脚"REER/PHYAD0"的电平决定,高电平是1,低电平是0。时钟由imx6ull的ref_clk(50MHz)提供,所以LAN8720第14引脚需要上拉。
2、dts配置。
参考imx6ll的evb板修改dts如下:

&fec1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet1>;
        phy-mode = "rmii";
        phy-handle = <&ethphy0>;
        phy-reset-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* GPIO4_15 */
        phy-reset-duration = <50>;
        status = "okay";
};
&fec2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet2>;
        phy-mode = "rmii";
        phy-handle = <&ethphy1>;
        phy-reset-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>; /* GPIO4_12 */
        phy-reset-duration = <50>;
        status = "okay";

        mdio {
                #address-cells = <1>;
                #size-cells = <0>;
                clock-frequency = <1000000>;

                ethphy0: ethernet-phy@0 {
                        compatible = "ethernet-phy-ieee802.3-c22";
                        reg = <0>;
                        smsc,disable-energy-detect;
                        clocks = <&clks IMX6UL_CLK_ENET_REF>;
                        clock-names = "rmii-ref";
                };

                ethphy1: ethernet-phy@1 {
                        compatible = "ethernet-phy-ieee802.3-c22";
                        reg = <1>;
                        smsc,disable-energy-detect;
                        clocks = <&clks IMX6UL_CLK_ENET2_REF>;
                        clock-names = "rmii-ref";
                };
        };
};

&iomuxc {
        pinctrl-names = "default";

        pinctrl_enet1: enet1grp {
                fsl,pins = <
                        MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN      0x1b0b0
                        MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER      0x1b0b0
                        MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
                        MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
                        MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN      0x1b0b0
                        MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
                        MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
                        MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1  0x4001b031
                        MX6UL_PAD_NAND_CLE__GPIO4_IO15          0x800050b0
                >;
        };
        pinctrl_enet2: enet2grp {
                fsl,pins = <
                        MX6UL_PAD_GPIO1_IO07__ENET2_MDC         0x1b0b0
                        MX6UL_PAD_GPIO1_IO06__ENET2_MDIO        0x1b0b0
                        MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN      0x1b0b0
                        MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER      0x1b0b0
                        MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
                        MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
                        MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN      0x1b0b0
                        MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
                        MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
                        MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2  0x4001b031
                        MX6UL_PAD_NAND_READY_B__GPIO4_IO12      0x800050b0
                >;
        };

};

对于复位操作,有一下属性可配置:

phy-reset-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;   //定义复位用的的gpio
phy-reset-duration = <50>;						//复位保持时间
phy-reset-active-high;							//定义高电平复位,未定义低电平复位
phy-reset-post-delay = <50>;					//复位后需要延时的时间。

驱动中对上面属性的使用参见"drivers/net/ethernet/freescale/fec_main.c"中fec_reset_phy函数。

static int fec_reset_phy(struct platform_device *pdev)
{
        int err, phy_reset;
        bool active_high = false;
        int msec = 1, phy_post_delay = 0;
        struct device_node *np = pdev->dev.of_node;

        if (!np)
                return 0;

        err = of_property_read_u32(np, "phy-reset-duration", &msec);
        /* A sane reset duration should not be longer than 1s */
        if (!err && msec > 1000)
                msec = 1;

        phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
        if (phy_reset == -EPROBE_DEFER)
                return phy_reset;
        else if (!gpio_is_valid(phy_reset))
                return 0;

        err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay);
        /* valid reset duration should be less than 1s */
        if (!err && phy_post_delay > 1000)
                return -EINVAL;

        active_high = of_property_read_bool(np, "phy-reset-active-high");

        err = devm_gpio_request_one(&pdev->dev, phy_reset,
                        active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
                        "phy-reset");
        if (err) {
                dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err);
                return err;
        }

        if (msec > 20)
                msleep(msec);
        else
                usleep_range(msec * 1000, msec * 1000 + 1000);

        gpio_set_value_cansleep(phy_reset, !active_high);

        if (!phy_post_delay)
                return 0;

        if (phy_post_delay > 20)
                msleep(phy_post_delay);
        else
                usleep_range(phy_post_delay * 1000,
                             phy_post_delay * 1000 + 1000);

        return 0;
}

3、遇到的问题。
(1).fec1无法连接到PHY,但是reboot重启后是正常,错误log提示如下:

mdio_bus 20b4000.ethernet-1: MDIO device at address 0 is missing.
fec 2188000.ethernet eth1: Unable to connect to phy

结果办法:将ref_clk 50MHZ时钟让提前产生。
修改如下:

@@ -357,6 +357,7 @@

 &iomuxc {
        pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_eth_ref_clk>;
+
+        pinctrl_eth_ref_clk: ethfredclkgrp {
+                fsl,pins = <
+                        MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1  0x4001b031
+                        MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2  0x4001b031
+                >;
+        };
+
        pinctrl_enet1: enet1grp {
                fsl,pins = <
                        MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN      0x1b0b0
@@ -384,7 +392,7 @@
                        MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN      0x1b0b0
                        MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
                        MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
-                       MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1  0x4001b031
+//                     MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1  0x4001b031
                        MX6UL_PAD_NAND_CLE__GPIO4_IO15          0x800050b0
                >;
        };
@@ -400,7 +408,7 @@
                        MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN      0x1b0b0
                        MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
                        MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
-                       MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2  0x4001b031
+//                     MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2  0x4001b031
                        MX6UL_PAD_NAND_READY_B__GPIO4_IO12      0x800050b0
                >;
        };

总结:
MDIO注册后,imx6ull和PHY通信的第一件事就是获取phy_id。所以可以在"drivers/net/phy/phy_device.c"的get_phy_device函数中可以添加log将phy_id打印出来,可以看到当故障时读取的phy_id一直是0xffff。从这里可以判断出通过MDIO读取PHY时出现了错误。又因为MDIO读取另一路上的PHY是正常的,所以排除imx6ull端MDIO出问题,所以问题就集中在PHY上面,又因为reboot是正常的,所以排除硬件固件。接下来就是排查时钟和上电时序。通过对时钟的调整,phy可以被正常识别。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飘忽不定的bug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值