【Linux】LAN8720 phy网络驱动调试配置记录

发布于 2020-09-01  148 次阅读


背景描述

前段时间在弄嵌入式的Linux系统,其实我主要负责的工作是QT应用层的维护开发,但是突然更换硬件平台,人手不够也就顺便搞了下驱动的移植。
对于Linux嵌入式设备而言,其主要构成也就是核心电路、flash、lcd、网口、串口、I2C、其他外设。
而驱动大都由芯片厂商提供了,从0开始写驱动基本上是不太现实的,基本步骤都是从已有的平台移植驱动,或者修改相似驱动。
最多的还是对驱动进行配置,也就是配置启用即可。

基本流程

  1. 复制驱动代码到相应的驱动目录,并修改KconfigMakefile文件。Kconfig是用于图形化菜单配置(make menuconfig)的配置文件,用于控制配置项以及在菜单中显示相关描述信息。配置项就是一个宏,保存后会生成一个.config文件,会根据配置项在Makefile中编译对应的.c程序文件。
  2. menu config中打开驱动的选项。Enter进入次级目录,Y是选中编译(*),N是取消选中(空),M是编译为模块(M)。[ ] 方括号的选项是 * 和空 (一般选中后还有二级选项),< >尖括号的选项可以是 * /空/M,( )圆括号的选项是多个选项中选择一项。
  3. 修改DTS设备树,添加配置节点。

如果无法使用make menuconfig命令,提示未安装ncurses libraries,那么安装一个便是。Ubuntu可以使用sudo apt-get install libncurses5-dev直接安装;使用yum安装可以先用yum search ncurses搜索一下,找到一个对应的进行安装即可。

硬件平台

我这边使用的是周立功的 A3352-WB128Li 核心板 + 公司的拓展底板。系统是从以前公司基于 Ti AM3352 自己做的核心板进行移植,芯片是同款芯片,移植起来稍微轻松些。
Linux 系统版本为 4.9.26。
周立功使用的phy芯片是Ti公司自家的 DP8384,而我们使用的是Microchip的SMSC LAN8720,两者的成本差距在几十块左右,所以还是有必要更换的。
本来是在周立功的平台上找他们专业工程师进行技术支持的,但是那边回复太慢了,寄过去也要一段时间,而且自己对BSP部分的了解还比较薄弱,因此还是决定自己搞。

移植记录

首先查看周立功提供的内核源码是否有LAN87xx相关的驱动。
可以直接进入make menuconfig里面进行搜索查找,也可以使用查找文件字符串的方式直接搜索。
进入到驱动文件夹drivers,使用命令grep -rn "LAN87",其中r表示递归,n表示
搜索结果中看到了相关输出,还是比较幸运,周立功内核中带的有这个驱动,可以省去很多步骤了。

net/phy/smsc.c:215: .name       = "SMSC LAN8700",
net/phy/smsc.c:260: .name       = "SMSC LAN8710/LAN8720",
net/phy/smsc.c:283: .name       = "SMSC LAN8740",

可以看到是smsc.c的文件中有相关信息。
于是使用make menuconfig在4.9的内核中打开SMSC网卡的驱动进行编译(同时也开启了PHY中的SMSC选项)。
在周立功提供的内核源码中,只需要去掉./build脚本中的对应注释即可直接打开配置菜单。
该脚本在linux-4.9.28/board/am335x-T目录下,这个目录也存放了am335x-T.dts 设备树源码。

想要知道通过菜单配置的驱动是否已经编译进了内核,可以在驱动文件的probe相关函数中,添加kprintf,即可以在驱动挂载时从内核输出信息了。

驱动代码已经编译通过了,并且有我们自己添加的输出,说明驱动本身没有任何问题。
查看内核启动日志,始终是两个网口,地址分别为:4a1000004a101000
正常的只有4a101000这个地址才对,打算找一下地址的配置,也就是pinmux引脚里面,可以看到cpsw_default配置了两个slave。将Slave 2 注释掉。

// 屏蔽Slave 2
cpsw_default: cpsw_default {
    pinctrl-single,pins = <
        /* Slave 1 */
        AM33XX_IOPAD(MII1_CRS,    PIN_INPUT_PULLDOWN  | MUX_MODE1)   /* mii1_crs.rmii1_crs_dv  */
        AM33XX_IOPAD(MII1_RXERR,  PIN_INPUT_PULLDOWN  | MUX_MODE1)   /* mii1_rxerr.rmii1_rxerr */
        AM33XX_IOPAD(MII1_TXEN,   PIN_OUTPUT | MUX_MODE1)           /* mii1_txen.rmii1_txen   */
        AM33XX_IOPAD(MII1_TXD1,   PIN_OUTPUT | MUX_MODE1)           /* mii1_txd1.rmii1_txd1   */
        AM33XX_IOPAD(MII1_TXD0,   PIN_OUTPUT | MUX_MODE1)           /* mii1_txd0.rmii1_txd0   */
        AM33XX_IOPAD(MII1_RXD1,   PIN_INPUT_PULLDOWN  | MUX_MODE1)   /* mii1_rxd1.rmii1_rxd1   */
        AM33XX_IOPAD(MII1_RXD0,   PIN_INPUT_PULLDOWN  | MUX_MODE1)   /* mii1_rxd0.rmii1_rxd0   */
        AM33XX_IOPAD(MII1_REFCLK, PIN_INPUT_PULLDOWN  | MUX_MODE0)   /* rmii1_refclk           */

        /* Slave 2 */
        /*AM33XX_IOPAD(GPMC_A0, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a0.rgmii2_tctl */
        /*AM33XX_IOPAD(GPMC_A1, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a1.rgmii2_rctl */
        /*AM33XX_IOPAD(GPMC_A2, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a2.rgmii2_td3  */
        /*AM33XX_IOPAD(GPMC_A3, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a3.rgmii2_td2  */
        /*AM33XX_IOPAD(GPMC_A4, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a4.rgmii2_td1  */
        /*AM33XX_IOPAD(GPMC_A5, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a5.rgmii2_td0  */
        /*AM33XX_IOPAD(GPMC_A6, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a6.rgmii2_tclk */
        /*AM33XX_IOPAD(GPMC_A7, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a7.rgmii2_rclk */
        /*AM33XX_IOPAD(GPMC_A8, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a8.rgmii2_rd3  */
        /*AM33XX_IOPAD(GPMC_A9, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a9.rgmii2_rd2  */
        /*AM33XX_IOPAD(GPMC_A10, PIN_INPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a10.rgmii2_rd1 */
        /*AM33XX_IOPAD(GPMC_A11, PIN_INPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a11.rgmii2_rd0 */
    >;
};

屏蔽后启动输出稍微有些不一样,但还是无法使用网络,并且仍然提示

[    1.598551] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
[    1.604958] libphy: 4a101000.mdio: probed
[    1.611981] smsc phy probe !![    1.614942] davinci_mdio 4a101000.mdio: phy[0]: device 4a101000.mdio:00, driver SMSC LAN8710/LAN8720
[    1.627433] cpsw 4a100000.ethernet: No slave[1] phy_id, phy-handle, or fixed-link property
[    1.636109] cpsw 4a100000.ethernet: Detected MACID = 44:ea:d8:ad:a8:1a
[    1.645316] cpsw 4a100000.ethernet: cpts: overflow check period 500 (jiffies)
..........
[    4.789015] SMSC LAN8710/LAN8720 4a101000.mdio:00: attached PHY driver [SMSC LAN8710/LAN8720] (mii_bus:phy_addr=4a101000.mdio:00, irq=-1)
[    4.804095] libphy: PHY  not found
[    4.809679] net eth0: phy "" not found on slave 1, err -19
[    4.822573] 8021q: adding VLAN 0 to HW filter on device eth0

后面终于找到这个配置的地方,在cpsw_emac0节点里面,给phy_id指定了1
我猜可能就是这里导致明明有mdio:00 内核却依然选择mdio:01 的原因,修改了先试一下。

&cpsw_emac0 {
     /* phy_id = <&davinci_mdio>, <1>; */
     phy_id = <&davinci_mdio>, <0>;
     phy-mode = "rmii";
};

这里提一下phy-mode的几种方式。详细介绍可以参考 这篇博客

  • MII(Media Independent Interface)即媒体独立接口,以4位半字节方式传送数据双向传输,时钟速率25MHz。其工作速率可达100Mb/s。

  • RMII(Reduced Media Independent Interface)是简化媒体独立接口,是标准的以太网接口之一,比MII有更少的I/O传输。RMII收发使用2位数据进行传输,收发时钟均采用50MHz时钟源。

  • SMII(Serial Media Independant Interface),串行MII接口。它包括TXD,RXD,SYNC三个信号线,共用一个时钟信号,此时钟信号是125MHz,信号线与此时钟同步。

  • GMII(Gigabit Media Independent Interface),千兆MII接口。GMII采用8位接口数据,工作时钟125MHz,因此传输速率可达1000Mbps。同时兼容MII所规定的10/100Mbps工作方式。

编译后重新烧录一遍设备树,发现启动日志终于有输出正常挂载PHY地址的信息了,虽然还是有错误的地方,但是不影响。

尝试连接上网线,终于输出了期待已久的 Link upSSH也可以正常登录了。

cpsw 4a100000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx

Comments


来自像素世界的代码家,创造第九艺术!