Linux内核移植之网络驱动更改说明二

一.  简介

本文继续学习 NXP官方Linux内核移植网络驱动的更改。

在学习 uboot 移植的时候就已经说过了,正点原子开发板的网络和 NXP 官方的网络硬件上不同,网络 PHY 芯片由 KSZ8081 换为了 LAN8720A,两个网络 PHY 芯片的复位 IO 也不同。 所以,Linux 内核自带的网络驱动是驱动不起来 I.MX6U-ALPHA 开发板上的网络的,需要做修改。

本文继上一篇文章的学习,文章地址如下:

Linux内核移植之网络驱动更改说明一-CSDN博客

二.   Linux内核移植之网络驱动更改

之前网络驱动更改中,修改网络复位IO和PHY 地址以后,Linux 内核内部通用 PHY驱动已经正常工作。上一篇文章已经可以 ping通 ubuntu系统了。

但是,正点原子视频学习中,左神说网络可能还会存在问题,还需要做网络其他方面的更改。

这里在之前更改的基础上,再进行网络驱动其他方面的更改。具体如下:

4. 修改 fec_main.c 文件

要 在 I.MX6ULL 上 使 用 LAN8720A , 需 要 修 改 一 下 Linux 内 核 源 码 , 打 开
drivers/net/ethernet/freescale/fec_main.c,找到 fec_probe() 函数,在 fec_probe() 函数 中加入如下代码:
static int fec_probe(struct platform_device *pdev)
{
	struct fec_enet_private *fep;
	struct fec_platform_data *pdata;
	struct net_device *ndev;
	int i, irq, ret = 0;
	struct resource *r;
	const struct of_device_id *of_id;
	static int dev_id;
	struct device_node *np = pdev->dev.of_node, *phy_node;
	int num_tx_qs;
	int num_rx_qs;

    /* zuozhongkai 2019/2/20 设置MX6UL_PAD_ENET1_TX_CLK和
     * MX6UL_PAD_ENET2_TX_CLK这两个IO的复用寄存器的SION位
     * 为1。
     */
    void __iomem *IMX6U_ENET1_TX_CLK;
    void __iomem *IMX6U_ENET2_TX_CLK;

    IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
    writel(0X14, IMX6U_ENET1_TX_CLK);
 
    IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
    writel(0X14, IMX6U_ENET2_TX_CLK);

...........................................
    return 0;
}

第18行 ~ 第 25行,是新添加的代码,如果要在 I.MX6ULL 上使用 LAN8720A 就需要设置 ENET1 ENET2 TX_CLK 引脚复位寄存器的 SION 位为 1

参考 IMX6ULL参考手册,TX_CLK寄存器的  SION位如下:

5. 修改 smsc.c 文件

正点原子文档中,左神的说明:

在修改 smsc.c 文件之前先说点题外话,那就是我是怎么确定要修改 smsc.c 这个文件的?
写本书之前我并没有修改过 smsc.c 这个文件,都是使能 LAN8720A 驱动以后就直接使用。但是 , 我在测试 NFS 挂载文件系统的时候发现文件系统挂载成功率很低!老是提示 NFS 服务器找不 到,三四次就有一次挂载失败!很折磨人。 NFS 挂载就是通过网络来挂载文件系统,这样做的
好处就是方便我们后续调试 Linux 驱动。既然老是挂载失败那么可以肯定的是网络驱动有问题。
网络驱动分两部分:内部 MAC+外部 PHY,内部 MAC 驱动是由 NXP 提供的,一般不会出问
题,否则的话用户早就给 NXP 反馈了。
而且我用 NXP 官方的开发板测试网络是一直正常的, 但是 NXP 官方的开发板所使用的 PHY 芯片为 KSZ8081 。所以只有可能是外部 PHY芯片的驱动 ,也就是 ALPHA开发板上的PHY芯片 LAN8720A 的驱动可能出问题了。鉴于 LAN8720A 有“前车之鉴”,那就是在 uboot 中需要对 LAN8720A 进行一次软复位(要设置 LAN8720A BMCR( 寄存器地址为 0) 寄存器 bit15 1) 所以我猜测,在 Linux 内核源码 中可能也需要对PHA芯片 LAN8720A 进行一次软复位。

首先需要找到 LAN8720A 的驱动文件, LAN8720A 的驱动文件是 drivers/net/phy/smsc.c
在此文件中有个叫做 smsc_phy_reset () 的函数,这是 SMSC PHY 的复位函数,因 此, LAN8720A 肯定也会使用到这个复位函数,修改此函数的内容,修改以后的 smsc_phy_reset () 函数内容如下所示:
static int smsc_phy_reset(struct phy_device *phydev)
{
    int err, phy_reset;
    int msec = 1;
    struct device_node *np;
    int timeout = 50000;

    if(phydev->addr == 0)  /* FEC1 */
    {
        np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
        if(np == NULL) {
          return -EINVAL;
        }
    }
    if(phydev->addr == 1) /* FEC2 */ 
    {
        np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
        if(np == NULL) {
            return -EINVAL;
        }
    }

    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 (!gpio_is_valid(phy_reset))
//        return;
        gpio_free(phy_reset);

    gpio_direction_output(phy_reset, 0);
    gpio_set_value(phy_reset, 0);
    msleep(msec);
    gpio_set_value(phy_reset, 1);

	int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
	if (rc < 0)
		return rc;

	/* If the SMSC PHY is in power down mode, then set it
	 * in all capable mode before using it.
	 */
	if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
		/* set "all capable" mode and reset the phy */
		rc |= MII_LAN83C185_MODE_ALL;
		phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
	}

    phy_write(phydev, MII_BMCR, BMCR_RESET);

	/* wait end of reset (max 500 ms) */
	do {
		    udelay(10);
			if (timeout-- == 0)
				return -1;
			rc = phy_read(phydev, MII_BMCR);
	} while (rc & BMCR_RESET);

	return 0;
}

6. 配置 Linux 内核,使能 LAN8720 驱动

进入 NXP 官方提供的 Kernel源码的根目录下,输入 “make menuconfig”命令,打开图形化配置界面,选择使能 LAN8720A 的驱动,路径 如下:
-> Device Drivers
    -> Network device support
          -> PHY Device support and infrastructure
                  -> Drivers for SMSC PHYs

选中 "Driver for SMSC PHYs" 选项,如下:

选择 "Driver for SMSC PHYs" 选项后,进行保存。

三.  网络驱动测试

修改好设备树和 Linux 内核以后重新编译一下,得到新的 zImage 镜像文件和 imx6ull-alientek-nand.dtb 设备树文件,将 zImage与 imx6ull-alientek-nand.dtb 拷贝到 tftp服务所设置的 目录下。
使用网线将 I.MX6U-ALPHA 开发板的 网口2(即ENET2) 与电脑连接起来。

开发板重新上电后,就会重新下载上面新编译的 zImage与 imx6ull-alientek-nand.dtb设备树文件。

注意:确认 zImage的编译时间是否是最新的!!!

开发板正常启动到根文件系统项,进入根文件系统的根目录下。如下:

Running local boot scripts (/etc/rc.local).

root@ATK-IMX6U:~# icm20608: version magic '4.1.15-g19f085b-dirty SMP preempt mod_unload modversions ARMv7 p2v8 ' should be '4.1.15 SMP preempt mod_unload modversions ARMv6 p2v8 '

root@ATK-IMX6U:~# 

1.  查看开发板上的所有网卡,输入 "ifconfig"  命令查看:

root@ATK-IMX6U:~# ifconfig 
eth0      Link encap:Ethernet  HWaddr 88:9f:ed:ad:10:d1  
          inet addr:169.254.200.201  Bcast:169.254.255.255  Mask:255.255.0.0
          inet6 addr: fe80::8a9f:edff:fead:10d1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:75 errors:0 dropped:0 overruns:0 frame:0
          TX packets:48 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:5817 (5.6 KiB)  TX bytes:10902 (10.6 KiB)

eth1      Link encap:Ethernet  HWaddr 88:e5:e1:37:af:b5  
          UP BROADCAST MULTICAST DYNAMIC  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:22 errors:0 dropped:0 overruns:0 frame:0
          TX packets:22 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1340 (1.3 KiB)  TX bytes:1340 (1.3 KiB)

2.  eth0 eth1 是网络接口的网卡,其中 eth0 对应于 ENET2 eth1 对应于 ENET1
设置 eth0 的 ip地址,这里我设置为 192.168.1.50。设置后可查看是否成功,操作如下:
root@ATK-IMX6U:~# ifconfig eth0 192.168.1.50
root@ATK-IMX6U:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 88:9f:ed:ad:10:d1  
          inet addr:192.168.1.50  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::8a9f:edff:fead:10d1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:228 errors:0 dropped:0 overruns:0 frame:0
          TX packets:224 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:19328 (18.8 KiB)  TX bytes:106747 (104.2 KiB)
.................................

3. 使用 “ping” 命令来 ping 一下自己的主机,如果能 ping 通那说明网络驱动修改成功!我的 Ubuntu 主机 IP 地址为 192.168.1.66,操作如下:

root@ATK-IMX6U:~# ping 192.168.1.66
PING 192.168.1.66 (192.168.1.66) 56(84) bytes of data.
64 bytes from 192.168.1.66: icmp_seq=1 ttl=64 time=0.977 ms
64 bytes from 192.168.1.66: icmp_seq=2 ttl=64 time=1.35 ms
64 bytes from 192.168.1.66: icmp_seq=3 ttl=64 time=0.990 ms
64 bytes from 192.168.1.66: icmp_seq=4 ttl=64 time=1.03 ms

可以看出, ping 成功,说明网络驱动修改成功!我们在后面的构建根文件系统和 Linux 驱动开发中就可以使用网络调试代码啦。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值