【uboot】imx6ull uboot移植LAN8720A网卡驱动

【uboot】imx6ull uboot移植LAN8720A网卡驱动文章目录相关文章1.前言2.IMX6ULLEthernetLAN8720A硬件连接3.支持LAN8720A修改步骤4.验证测试问题1:如何确定LAN8720A网卡PHYAD地址?问题2:如何确定devicetree中对resetgpio的定义?问题3:LAN8720A网卡nINTSEL是如何配置?问题4:IMX6ULLETH是如何被初始化的?相关文章1.《【uboot】imx6ulluboot2020.04源码下载和编译环境配置》2.《【Ethernet】以太网卡LAN8720

大家好,又见面了,我是你们的朋友全栈君。

相关文章

1.《【uboot】imx6ull uboot 2020.04源码下载和编译环境配置》
2.《【Ethernet】以太网卡LAN8720A分析和使用》

1. 前言

本篇文章主要是介绍,基于IMX6ULL平台uboot来移植LAN8720A网卡驱动,代码是基于《【uboot】imx6ull uboot 2020.04源码下载和编译环境配置》这篇文章下载后的修改。

2. IMX6ULL Ethernet LAN8720A硬件连接

IMX6ULL 平台支持2个以太网口,在uboot中我们基本上使用一个uboot就足够,所以后面主要是介绍imx6ull Ethernet2如何支持LAN8720A网卡。下面是IMX6ULL 连接LAN8720A的原理图:

在这里插入图片描述

3. 支持LAN8720A修改步骤

基于IMX6ULL平台uboot中,修改支持LAN8720A网卡。

  • 修改config配置文件对LAN8720A网卡的支持,并且关闭对其它网卡的支持。
    在这里插入图片描述

    --- a/configs/mx6ull_14x14_evk_emmc_zc_defconfig
    +++ b/configs/mx6ull_14x14_evk_emmc_zc_defconfig
    @@ -1025,13 +1025,11 @@ CONFIG_PHYLIB=y
     # CONFIG_PHY_LXT is not set
     # CONFIG_PHY_MARVELL is not set
     # CONFIG_PHY_MESON_GXL is not set
    -CONFIG_PHY_MICREL=y
    -# CONFIG_PHY_MICREL_KSZ90X1 is not set
    -CONFIG_PHY_MICREL_KSZ8XXX=y
    +# CONFIG_PHY_MICREL is not set
     # CONFIG_PHY_MSCC is not set
     # CONFIG_PHY_NATSEMI is not set
     # CONFIG_PHY_REALTEK is not set
    -# CONFIG_PHY_SMSC is not set
    +CONFIG_PHY_SMSC=y
     # CONFIG_PHY_TERANETICS is not set
     # CONFIG_PHY_TI is not set
     # CONFIG_PHY_VITESSE is not set
    
  • 修改device tree文件,禁用ETH1并且修改ETH2增加对RESET GPIO的支持。
    在这里插入图片描述

    --- a/arch/arm/dts/imx6ul-14x14-evk.dtsi
    +++ b/arch/arm/dts/imx6ul-14x14-evk.dtsi
    @@ -83,7 +83,7 @@
     	pinctrl-0 = <&pinctrl_enet1>;
     	phy-mode = "rmii";
     	phy-handle = <&ethphy0>;
    -	status = "okay";
    +	status = "disabled";
     };
     
     &fec2 { 
         
    @@ -91,14 +91,17 @@
     	pinctrl-0 = <&pinctrl_enet2>;
     	phy-mode = "rmii";
     	phy-handle = <&ethphy1>;
    +	phy-reset-gpios = <&gpio5 6 GPIO_ACTIVE_LOW>;
    +	phy-reset-duration = <15>;
    +	phy-reset-post-delay = <15>;
     	status = "okay";
    
  • 修改phy.c文件,在启用了自动协商之前,再次进行网卡的软件reset。(NOTE:至于为什么需要再次reset还不太清楚,有了解的话欢迎在下面留言。)
    在这里插入图片描述

    --- a/drivers/net/phy/phy.c
    +++ b/drivers/net/phy/phy.c
    @@ -177,6 +177,9 @@ int genphy_config_aneg(struct phy_device *phydev)
     { 
         
     	int result;
     
    +	/* Soft Reset the PHY */
    +	phy_reset(phydev); // add by cai.zhong 2021-06-20
    +
     	if (phydev->autoneg != AUTONEG_ENABLE)
     		return genphy_setup_forced(phydev);
    

4. 验证测试

编译烧录后,通过使用ping命令ping通局域网的其它设备,说明网卡已经调试成功。打印log如下:

U-Boot 2020.04-g7a4fc484-dirty (Jun 27 2021 - 20:46:38 +0800)

CPU:   i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 51C
Reset cause: POR
Model: i.MX6 ULL 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... OK
[*]-Video Link 0 (480 x 272)
[0] lcdif@21c8000, video
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc1(part 0) is current device
flash target is MMC:1
Net:   eth1: ethernet@20b4000 [PRIME]
Fastboot: Normal
Normal Boot
Hit any key to stop autoboot:  3  0 
=> 
=> dhcp
BOOTP broadcast 1
DHCP client bound to address 192.168.1.105 (4 ms)
*** ERROR: `serverip' not set
Cannot autoload with TFTPGET
=> ping 192.168.10 .10
Using ethernet@20b4000 device
host 192.168.1.10 is alive
=> 

问题1:如何确定LAN8720A网卡PHYAD地址?

PHYAD[0]引脚用于配置 SMI通信的 LAN8720A 地址,在芯片内部该引脚已经自带下拉电阻,默认认为 0(即使外部悬空不接),在系统上电时会检测该引脚获取得到 LAN8720A的地址为 0 或者 1,并保存在特殊模式寄存器(R18)的 PHYAD位中,该寄存器的 PHYAD5个位,在需要超过 2个 LAN8720A 时可以通过软件设置不同 SMI通信地址
在这里插入图片描述
根据上面的硬件连接Ethernet2使用的PHYAD = 1,所以在device tree可以再次确认mdioreg是否等于1
在这里插入图片描述

问题2:如何确定device tree中对reset gpio的定义?

一般都是driver驱动确定了device tree的编写格式,对于imx6ull uboot的ETHdriver路径如下:
PATH:imx-uboot/drivers/net/fec_mxc.c
在这里插入图片描述

在驱动绑定成功后,都会从设备树中进行平台数据的加载,调用函数fecmxc_ofdata_to_platdata()。通过它我们就知道,需要在device tree中定义phy-reset-gpiosphy-reset-durationphy-reset-post-delay这3个属性。

static int fecmxc_ofdata_to_platdata(struct udevice *dev)
{ 
   
	int ret = 0;
	struct eth_pdata *pdata = dev_get_platdata(dev);
	struct fec_priv *priv = dev_get_priv(dev);
	const char *phy_mode;

	...

#if CONFIG_IS_ENABLED(DM_GPIO)
	ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
				   &priv->phy_reset_gpio, GPIOD_IS_OUT);
	if (ret < 0)
		return 0; /* property is optional, don't return error! */

	priv->reset_delay = dev_read_u32_default(dev, "phy-reset-duration", 1);
	if (priv->reset_delay > 1000) { 
   
		printf("FEC MXC: phy reset duration should be <= 1000ms\n");
		/* property value wrong, use default value */
		priv->reset_delay = 1;
	}

	priv->reset_post_delay = dev_read_u32_default(dev,
						      "phy-reset-post-delay",
						      0);
	if (priv->reset_post_delay > 1000) { 
   
		printf("FEC MXC: phy reset post delay should be <= 1000ms\n");
		/* property value wrong, use default value */
		priv->reset_post_delay = 0;
	}
#endif

	return 0;
}

???那么这3个属性是怎么使用的呢???
imx-uboot/drivers/net/fec_mxc.c文件中,我们发现是通过这个GPIO硬件reset网卡,可以通过原理图查看得知网卡的reset是连接的在imx6ull GPIO5_6上,所以phy-reset-gpios就是GPIO5_6。

static void fec_gpio_reset(struct fec_priv *priv)
{ 
   
	debug("fec_gpio_reset: fec_gpio_reset(dev)\n");
	if (dm_gpio_is_valid(&priv->phy_reset_gpio)) { 
   
		dm_gpio_set_value(&priv->phy_reset_gpio, 1);
		mdelay(priv->reset_delay);
		dm_gpio_set_value(&priv->phy_reset_gpio, 0);
		if (priv->reset_post_delay)
			mdelay(priv->reset_post_delay);
	}
}

phy-reset-durationphy-reset-post-delay就是用来延时维持io的状态,它需要延时多久我们可以通过查看LAN8720A datasheet知道,具体如下:
在这里插入图片描述

问题3:LAN8720A网卡nINTSEL是如何配置?

通过nINTSEL来配置两个模式:REF_CLK输入模式(nINT)和REF_CLK输出模式。通过该引脚的高低电平决定了nINT / REFCLKO引脚的功能。

STRAP VALUE MODE REF_CLK DESCRIPTION
nINTSEL = 0 REF_CLK Out Mode nINT/REFCLKO is the source of REF_CLK.
nINTSEL = 1 REF_CLK In Mode nINT/REFCLKO is the source of REF_CLK.

根据如下硬件连接,那么nINTSEL = 1,所以选择的是REF_CLK输入模式。即外部时钟源直接提供 50MHz时钟接入 主机MAC接口REF_CLK引脚和 LAN8720A 的 XTAL1/CLKIN 引脚,此时 nINT/REFCLKO 可用于中断功能。IMX6ULL中内部分频给MAC模块,并且输出到ENET2_TX_CLK给外部的PHY LAN8720A 使用。
在这里插入图片描述

问题4:IMX6ULL ETH是如何被初始化的?

下面是IMX6ULL ETH的初始化流程,后面有时间再详细的分析。

[board_r.c]initr_net();
[eth-uclass.c]eth_initialize();
[eth-uclass.c]eth_common_init();
[miiphyutil.c]miiphy_init();
[phy.c]phy_init();
[smsc.c]phy_smsc_init();
[phy.c]phy_register(&lan8710_driver); // 将lan8720a phy_driver添加到LIST_HEAD(phy_drivers)队列中
[phy.c]genphy_init();
[phy.c]phy_register(&genphy_driver);
[uclass.c]uclass_first_device_check(UCLASS_ETH, &dev); // dev = ethernet@20b4000
[device.c]device_probe(*devp); // 探测udevice ethernet@20b4000
[device.c]device_ofdata_to_platdata(dev); // 给dev配置需要的空间,并从Devcie Tree中获取dev ethernet@20b4000的平台数据。
[fec_mxc.c]fecmxc_ofdata_to_platdata(dev); // 1:获取eth iobase地址;2:获取phy-mode值"rmii";3:通过phy-reset-gpios值申请GPIO资源;4:通过phy-reset-duration值设置reset delay的时间;
[pinctrl-uclass.c]pinctrl_select_state(dev, "default"); // 设置eth IO为default状态,default为eth功能pinctrl_enet1、pinctrl_enet2;
[uclass.c]uclass_pre_probe_device(dev); // 
[fec_mxc.c]fecmxc_probe(dev); //
[fec_mxc.c]fec_gpio_reset(priv); // 根据device tree里面定义的reset pin,操作它让eth reset并延时。
[fec_mxc.c]fec_get_miibus((ulong)priv->eth, dev->seq); // 获取mii总线,包括mdio。
[fec_mxc.c]fec_phy_init(priv, dev); //
[fec_mxc.c]device_get_phy_addr(dev); // 从device tree中获取phy reg地址,reg = <1>;
[phy.c]phy_connect(priv->bus, addr, dev, priv->interface); // 
[phy.c]phy_find_by_mask(bus, mask, interface);
[phy.c]get_phy_device_by_mask(bus, phy_mask, interface); 
[phy.c]create_phy_by_mask(bus, phy_mask, i ? i : MDIO_DEVAD_NONE, interface);
[phy.c]get_phy_id(bus, addr, devad, &phy_id); // 读取PHY Identifier 1 Register和PHY Identifier 2 Register的值;
[phy.c]phy_device_create(bus, addr, phy_id, is_c45, interface);// 创建一个phy_device设备
[phy.c]get_phy_driver(dev, interface); // 遍历phy_drivers链表,通过driver定义的uid和读取的实际phy_id匹配,找到合适的driver。
[phy.c]phy_probe(dev); // 设置phydev->advertising和phydev->supported为PHY_BASIC_FEATURES
[phy.c]phy_connect_dev(phydev, dev); // 将给定的PHY和以太网设备绑定起来
[phy.c]phy_reset(phydev); // 软件复位PHY
[phy.c]phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); // 发送reset命令给网卡lan8720a
[phy.c]phy_read(phydev, devad, MII_BMCR); //读取网卡lan8720a Basic mode control register的reset是否完成
[log.h]debug("%s connected to %s\n", dev->name, phydev->drv->name); // ethernet@20b4000 connected to SMSC LAN8710/LAN8720
[phy.c]phy_config(phydev); // 
[phy.c]board_phy_config(phydev);
[phy.c]genphy_config_aneg(phydev); // 重启自协商或写入BMCR
[phy.c]genphy_config_advert(phydev); // 清除和发布自动协商参数
[uclass.c]uclass_post_probe_device(dev); // 处理一个刚刚被probed过的设备
[eth-uclass.c]eth_post_probe(dev); // 获取mac地址
[eth-uclass.c]eth_dev_get_mac_address(dev, pdata->enetaddr); // 从设备树中获取mac-address
[fec_mxc.c]fecmxc_read_rom_hwaddr(dev); // 从ROM中获取mac地址
[mac.c]imx_get_mac_from_fuse(dev_id, mac); // 从ROM中获取mac地址
[eth-uclass.c]eth_write_hwaddr(dev); // 将mac地址写入到eth寄存器
[fec_mxc.c]fecmxc_set_hwaddr(dev); // 将mac地址写入到eth寄存器
[eth-uclass.c]eth_get_dev_by_name(ethprime);  // ethprime = eth1; 
[eth-uclass.c]eth_set_dev(prime_dev); 
[eth_common.c]eth_current_changed();
[eth_common.c]eth_write_hwaddr(dev);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/147907.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • ffplay播放器移植VC的工程:ffplay for MFC

    ffplay播放器移植VC的工程:ffplay for MFCffplay播放器移植VC的工程:ffplayforMFC本文介绍一个自己做的FFPLAY移植到VC下的开源工程:ffplayforMFC。本工程将ffmpeg项目中的ffplay播放器(ffplay.c)移植到了VC的环境下。并且使用MFC做了一套简单的界面。它可以完成一个播放器播放视频的基本流程:解协议,解封装,视频/音频解码,视音频同步,视音频输出。此外还包含一些控制功能:播放,暂停/继

  • Canalyzer使用介绍

    Canalyzer使用介绍Canalyzer使用介绍什么是canalyzer?简单来说就是解析汽车can报文,可收可发,可记录可回播报文。汽车行业开发,测试,路试使用居多。下面主要分界面介绍,canalyzer设置,离线回放,在线回放等四大主要且常用功能去说明。一.Canlayzer界面介绍打开canalyzer工程左上方闪电标志是启动和暂停作用。panel是可用于添加panel界面,有助于调试。analysis&stimulation主菜单下有以下子菜单1.measurementset

  • Lucene.net(4.8.0) 学习问题记录二: 分词器Analyzer中的TokenStream和AttributeSource[通俗易懂]

    Lucene.net(4.8.0) 学习问题记录二: 分词器Analyzer中的TokenStream和AttributeSource[通俗易懂]前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移。因为项目整体要迁移到ASP.NETCore2.0版本,而Lucene使用的版本是3.6.0,PanGu分词也是对应Lucene3.6.0版本的。不过好在Lucene.net已经有了Core2.0版本,4.8.0bate版,而PanGu分词,目前有人正在做,貌似已经做完,只是…

  • mtk手机维修_mtk平台手机

    mtk手机维修_mtk平台手机默认分类2009-10-1902:21:04阅读1252评论7字号:大中小  MTK用电池不开机,用外用电源能开机的维修方法:MTK用电池不开机,用外用电源能开机的维修方法,我们可以找到VBAT也就是电触B+通电源的sas31233l213321+987+9877777777777777777777777777777777777777777777777777

    2022年10月28日
  • Android四大组件Broadcast中注册广播registerReceiver流程源代码详解

    Android四大组件Broadcast中注册广播registerReceiver流程源代码详解在Android系统中,为什么需要广播机制呢?广播机制,本质上它就是一种组件间的通信方式,如果是两个组件位于不同的进程当中,那么可以用Binder机制来实现,如果两个组件是在同一个进程中,那么它们之间可以用来通信的方式就更多了,这样看来,广播机制似乎是多余的。然而,广播机制却是不可替代的,它和Binder机制不一样的地方在于,广播的发送者和接收者事先是不需要知道对方的存在的,这样带来的好处便是,系统的各个组件可以松耦合地组织在一起,这样系统就具有高度的可扩展性,容易与其它系统进行集成。在软件工程中,是非常强

  • 电网101、104规约解析(Java)「建议收藏」

    电网101、104规约解析(Java)「建议收藏」国家电网101规约解析(Java)最近在研究国家电网的101与104规约,也就是DL/T634.5101-2002和DL/T634.5104-2009。因为要做一个规约解析的软件(基于Android平台的),刚开始接触的也是一头雾水,因为没有接触过这方面的知识,所以就在网上搜索各种技术帖,大神经验什么的。后来在网上找到了一个软件–IEC8705(报文翻译工具).exe,这个##可以解析一…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号