概述

以 JL2101B 千兆网口 phy 为例,默认驱动无法正常点亮网口灯,需要移植驱动

1. 硬件原理图


2. 驱动添加

// drivers/net/phy/jl2101b.c
// 添加到内核源码

#include <linux/phy.h>
#include <linux/module.h>

#define JL2101B_PHY_ID          0x937c4032
#define JL2101B_LED_PAGE        0xD04
#define JL2101B_LED_REG         0x10
#define JL2101B_LED_VAL         0x3388  // 黄灯, 链路+活动

static int jl2101b_config_init(struct phy_device *phydev)
{
    int ret;

    // 切换到 LED 控制页
    ret = phy_write(phydev, 31, JL2101B_LED_PAGE);
    if (ret < 0)
        return ret;

    // 写入 LED 配置
    ret = phy_write(phydev, JL2101B_LED_REG, JL2101B_LED_VAL);
    if (ret < 0)
        return ret;

    // 切回默认页
    ret = phy_write(phydev, 31, 0x0000);
    if (ret < 0)
        return ret;

    phydev_info(phydev, "JL2101B LED configured: 0x%04x\n", JL2101B_LED_VAL);

    return 0;
}

static struct phy_driver jl2101b_driver[] = {
    {
        .phy_id         = JL2101B_PHY_ID,
        .phy_id_mask    = 0xfffffff0,
        .name           = "JL2101B Gigabit Ethernet",
        .features       = PHY_GBIT_FEATURES,
        .config_init    = jl2101b_config_init,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
    },
};

module_phy_driver(jl2101b_driver);

static struct mdio_device_id __maybe_unused jl2101b_tbl[] = {
    { JL2101B_PHY_ID, 0xfffffff0 },
    { }
};

MODULE_DEVICE_TABLE(mdio, jl2101b_tbl);
MODULE_DESCRIPTION("JL2101B PHY driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chen");

驱动添加加到:kernel/linux-5.10-origin/drivers/net/phy/jl2101b.c

修改 kernel/linux-5.10-origin/drivers/net/phy/Makefile

修改 kernel/linux-5.10-origin/drivers/net/phy/Kconfig

然后在内核 menuconfig 勾选驱动

./build.sh menuconfig

3. 修改设备树

/delete-node/ &gmac0_phy0;
&mdio0{
    status = "okay";    
    gmac0_phy0: ethernet-phy@0 {
        compatible = "ethernet-phy-ieee802.3-c22", "jl2101b";
        reg = <0x0>;
        max-speed = <1000>;  /* Max speed capability */
        /* PHY datasheet rst time */
        reset-gpios = <&pio PG 5 GPIO_ACTIVE_LOW>;
        reset-assert-us = <10000>;
        reset-deassert-us = <150000>;
    };
};


&gmac0 {
    phy-mode = "rgmii";
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&gmac0_pins_default>;
    pinctrl-1 = <&gmac0_pins_sleep>;
    phy-handle = <&gmac0_phy0>;
    tx-delay = <5>;
    rx-delay = <5>;
    aw,soc-phy-clk-en;
    /delete-property/ aw,rgmii-clk-ext;
    status = "okay";    
};

参数解释:

/delete-node/ &gmac0_phy0;

删除由bsp/configs/linux-5.10-origin/sun8iw22p1.dtsi文件中配置的影响

compatible = “ethernet-phy-ieee802.3-c22”, “jl2101b”;

ethernet-phy-ieee802.3-c22:PHY遵循标准的IEEE 802.3 Clause 22管理接口
jl2101b :新增的 jl2101b 网口灯驱动。

reg = <0x0>;

phy物理地址,如果硬件没有配置,默认为0。

max-speed = <1000>;

配置协商速度,这里最大是1000M。

reset-gpios = <&pio PG 5 GPIO_ACTIVE_LOW>;

配置复位引脚,建议配置上,在网卡up、down时会使用到此引脚。

phy-mode = “rgmii”;

配置phy的工作模式,常用的有rgmii,rmii等。

tx-delay = <5>;
rx-delay = <5>;

配置TX或者RX数据线延时,总共有0-31档,一档约536ps(皮秒)。

aw,soc-phy-clk-en;
/delete-property/ aw,rgmii-clk-ext;

删除外部时钟,使用内部时钟

4. 网络测速

重新编译烧录后使用 iperf3 测试:
Ubuntu 虚拟机和开发板处在同一网段,虚拟机开启 iperf3 服务器

iperf3 -s


开发板测试网速

iperf3 -c 192.168.0.31 # 虚拟机的 ip

作者:陈柏林  创建时间:2026-09-16 10:19
最后编辑:陈柏林  更新时间:2026-10-12 11:13