Linux系统下的phy驱动调试记录

        在Linux下添加一块新的网卡驱动(以下简称phy芯片)时,需要实现mac驱动和phy驱动。通常,mac驱动已由CPU厂家实现。作为驱动工程师,我们仅需匹配phy驱动即可。以下的phy驱动调试均在Linux5.10的源码下进行。

一、CPU与网络芯片的连接情况

1.CPU与phy芯片连接分为两种:

网络数据连接:CPU <---->rmii/rgmii <------> phy <------> RJ45网口
            连接方式包括:rmii/rgmii/mii等。
控制数据连接:CPU <---->MDIO <------> phy寄存器  (主要配置一些寄存器内容,明确phy地址)
            连接方式包括:SMI/SPI/IIC等

2.注意事项      

            某些芯片可通过外部io(拉高或拉低电平)来配置寄存器内容(硬件strap)
            phy芯片的前16个寄存器为标准寄存器,遵循IEEE802.3标准
            CPU的mac层驱动,由CPU芯片厂家提供,在使用是,注意在dts中配置引脚复用方式。
            在使用网口的其他未使用,需要在uboot中将这些资源关闭。
            对于单口phy,配置一些基本的寄存器即可,对于多口phy(例如switch),可以使用通用驱动,配置成单口phy,以验证连接的准确性,检查上电是否有交换功能,以验证硬件的正确性。
            如要使用switch功能,还需要根据芯片手册配置vlan。
            phyID在寄存器的第一页第2字节和第3字节。

             查看时钟提供的方式以及时钟频率。

3.SMI接口

SMI是MAC内核访问PHY寄存器接口,它由两根线组成,双工,MDC为时钟,MDIO为双向数据通信,原理上跟I2C总线很类似,也可以通过总线访问多个不同的phy。
 MDC/MDIO基本特性:
            两线制:MDC(时钟线)和MDIO(数据线)。
            时钟频率:2.5MHz
            通信方式:总线制,可同时接入的PHY数量为32个
            通过SMI接口,MAC芯片主动的轮询PHY层芯片,获得状态信息,并发出命令信息。时序可分为两类:cluase22和cluase45.,详见下图

        

class22格式

class45格式

二、设备树示例

gmac0: ethernet@40120000 {
		compatible = "xxxxxxxxx-gmac";		//mac层驱动,有MCU厂家提供
		reg = <0x0 0x40120000 0x0 0x10000>;		
		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;	
		interrupt-names = "macirq";
		phy-mode = "rgmii-id";	//phy模式,包含rmii,rgmii等
		nuvoton,ma35d1-sys = <&sys>;
		clocks = <&clk EMAC0_GATE>, <&clk EPLL_DIV8>;
		clock-names = "stmmaceth", "ptp_ref";
		resets = <&reset XXXXXX_GMAC0>;
		reset-names = "stmmaceth";
		mac-id = <0>;	//mac的序号
		clk_csr = <4>;	//时钟
		status = "disable";
		phy-handle = <&eth_phy0>;	//phy节点引用
		mdio0 {
			compatible = "snps,dwmac-mdio";	//mdio驱动
			#address-cells = <1>;
			#size-cells = <0>;

			eth_phy0: ethernet-phy@1 {	//phy节点实例,可在该节点下实现自己的phy驱动,实现自己的一些配置,1表示phy地址,与reg一致
				reg = <1>;//
				fixed-link{    //此为固定连接
					speed=<100>;//速度100M
					full-duplex;//
				}
			};
		};

	};

三、驱动注册流程

        1.如何找到驱动

驱动使用结构体struct phy_driver进行注册,驱动加载时,会根据phy_id进行匹配驱动,找到驱动后,即可对phy寄存器进行相应的配置,并设置驱动名字。

因此结构体中以下两个参数phyid和name所有的phy驱动不要设置一致。

        2.注册驱动demo

#define JLSEMI_PHY_ID_MASK  0xfffffff0

static struct phy_driver jlsemi_drivers[] = {

    

    {

                .phy_id         = 0x937c4101,        //phyID,可从芯片中读取到

                .phy_id_mask    = JLSEMI_PHY_ID_MASK,        //掩码

                .name           = DRIVER_NAME_100M,        //驱动名字

                /* PHY_BASIC_FEATURES */

                .features       = PHY_BASIC_FEATURES,

                .probe          = jl51xx_probe,                //驱动探测

                .config_intr    = jl51xx_config_intr,        //配置

                .read_status    = jl51xx_read_status,        //读状态

                .config_init    = jl51xx_config_init,        //初始化

                .remove         = jl51xx_remove,//删除

#if (JLSEMI_PHY_WOL)

                .get_wol        = jl51xx_get_wol,

                .set_wol        = jl51xx_set_wol,

#endif

        }

};

module_phy_driver(jlsemi_drivers);//注册phy驱动
    
    注意:对于某些phy,可能存在link state需要cpu进行设置,在初始化时设置或者在.suspend函数中进行设置即可

四、遇到的问题

    1)     no phy at addr -1;stmmac_open: cannot attach to phy (error -19)
        未识别到phy,可能是phy addr不正确,需要修改设备树中phyaddr (eth_phy0: ethernet-phy@1)
        phy地址需要查看硬件手册及原理图
    2)    linkup,但是网络不通
        可能是晶振导致时钟不对,另外检查芯片上的strap引脚是否配置正确
    3) 使用 "virtual,mdio-gpio" 驱动,出现问题1中的记录,应检查gpio配置和phyaddr配置,且在设备树中将phy节点放置在根目录下
        简单配置如下
        {
            mdio1 {
                compatible = "virtual,mdio-gpio";
                #address-cells = <1>;
                #size-cells = <0>;
                gpios =<&gpiof 0 0         #用于模拟sdio数据的两个gpio
                        &gpiof 1 0 >;                #
                eth_phy1: ethernet-phy@1 {#phy芯片的地址为1
                    reg = <1>;
                };
            };
            gmac1: ethernet@40130000 {
                compatible = "xxxxxxxx-gmac";
                status = "disable";
                phy-handle = <&eth_phy1>;#引用phy节点
            };
        }
    4) mii_bus无法读写内部寄存器:
        可能是phy的时序要求不一样,对标准phy寄存器,使用Clause22时序即可
        对于某些内部寄存器,可使用扩展的Clause45时序进行读写
        对于一些特殊的phy芯片,读写内部寄存器的C45时序要求不同,例如:其startFrame为01,OpCode为00,
            此时可根据芯片手册的时序要求,使用virtual,mdio-gpio驱动来实现特殊的时序
            备注:因芯片的smi接口为寄存器操作,是标准的smi接口,不方便修改。改为gpio模拟时序后更方便修改时序
        在Linux源码中有virtual,mdio-gpio驱动。在Linux源码中有很多类似的驱动支持,遇见新的硬件,可先在Linux源码中寻找驱动支持,
            找到类似的解决方案。若Linux源码中没有相关内容,可找芯片厂家进行支持。
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值