以太网驱动
概述
以太网(Ethernet)是一种广泛应用于局域网的计算机网络技术,用于实现设备间的高效数据通信。 以太网基于有线介质的网络通信标准,定义了数据帧格式、传输协议及物理层规范。以太网拥有以下优势:
- 高可靠性
- 低延迟
- 强兼容性
- 成本可控
功能描述
- 支持两路以太网控制器
- 支持十兆、百兆和千兆模式
- 支持 RGMII 和 RMII PHY 接口
- RGMII 使用 1.8V 电压
- RMII 使用 3.3V 电压
- 支持全双工和半双工模式
- 支持 MAC 自环回调试
- 支持 Receive Checksum Offload
- 支持 TCP Segmentation Offload(
TSO) - 支持 UDP Fragmentation Offload(
UFO)
配置流程
步骤 1:配置 U-Boot 设备树
U-Boot 中目前仅支持以太网控制器 eth0。
MTT E300 的设备树文件路径为:arch/arm/dts/。以下以现有的 aimodule 配置作为板级设备树文件示例。
打开 mthreads-m1000-aimodule.dts,找到 gem0 节点,并根据接口类型修改节点内容:
-
若为 RGMII 接口:
- 配置:
phy-mode = "rgmii-id"; - 设置:
v1_8 = <0>;代表以太网使用 1.8V 电压
- 配置:
-
若为 RMII 接口:
- 配置:
phy-mode = "rmii"; - 屏蔽
v1_8 = <0>;,使用默认的 3.3V 电压
- 配置:
-
网速配置:
- 若为千兆网络:
max-speed-mhz = <1000>; - 若为百兆网络:
max-speed-mhz = <100>;
- 若为千兆网络:
步骤 2:配置 ACPI table
以太网的 ACPI table 配置文件位于 uboot 源码中的 board/mthreads/common/AcpiTables/Common/Ethernet.asl。该文件支持 2 路以太网:ETH0 和 ETH1。
Name (_HID, "CSET0001")
Name: 声明一个名字对象(ACPI 语法)。_HID: 是 ACPI 的 标准设备标识符(Hardware
ID)。"CSET0001": 是这个设备的 硬件 ID 字符串。
Name (_UID, Zero)
_UID 是 ACPI 中的 唯一标识符(Unique
ID)。它和 _HID(硬件 ID)一起用于唯一标识设备,尤其是当有多个设备具有相同 _HID 时。Zero 是 ACPI 定义的一个常量,代表数值。
Method (_STA)
{
Return (0xf)
}
_STA 是一个标准的 ACPI 方法,表示设备的状态(_STA)。全称为 Status,用于告知操作系统当前设备是否存在、是否已启用、是否可用于子设备枚举。_STA 方法应返回一个位掩码(bitmask),每一位表示设备的某种状态。bit0:设备存在;bit1:设备已启用;bit2:设备可用于 I/O;bit3:子设备应被枚举。此处返回 0xF 表示上述各 bit 均为 1。
Name (_CCA, 0x0) 这是用于 ACPI 设备描述中的一条标准属性,表示该设备的 Cache Coherency
Attribute,也就是缓存一致性属性。这里的值是 0 表示该设备不具备缓存一致性,即 non-coherent。
Name (_DEP, Package () // _DEP: Dependencies
{
_SB.CRG
})
是对 _DEP 这一标准 ACPI 对象的定义,它表示该设备对系统中其它设备或对象的依赖关系(Dependencies)。它是一个 Package 类型的对象,列出当前设备在初始化之前所依赖的其它对象(通常是设备)。通常用于告诉操作系统:我需要先有某个设备或对象准备好,我才能正常工作。_SB.CRG 是当前设备所依赖的对象,全路径是 _SB.CRG。_SB:系统总线(System
Bus)节点。CRG:时钟控制器。
Method (_INI) {
SSID(0x73d500, ETH0_STREAM_ID)
IOSW(GID_ETH0, POWERSTAT_NORMAL)
}
是 ACPI 中设备的 _INI 方法,表示 设备初始化逻辑,但里面调用了两个 非标准的、平台自定义方法:SSID 和 IOSW。_INI 是 ACPI 中每个 Device 或 Scope 对象都可以定义的 初始化方法。操作系统会在设备 被枚举之后、设备驱动绑定之前 调用 _INI,用于初始化该设备的 ACPI 逻辑状态。SSID(0x73d500,
ETH0_STREAM_ID):将 0x73d500 寄存器的值写为 42(这里 ETH0_STREAM_ID 的值是 42)。IOSW(GID_ETH0,
POWERSTAT_NORMAL):切换以太网 0 的 gpio 状态为 normal。
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite,
0x734000,
0x2000,
)
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
{
99,
98,
97,
96,
}
})
是定义该设备的 _CRS 方法(Current Resource
Settings),其作用是告诉操作系统这个设备所使用的硬件资源(内存、IO、IRQ 等)。Memory32Fixed (ReadWrite, 0x734000, 0x2000) 表示该设备的 MMIO(寄存器映射)地址,驱动会 ioremap() 后访问。Interrupt (...) { 99, 98, 97, 96 } 表示该设备使用了中断资源。ResourceConsumer 表示这是一个使用(而非提供)中断的设备。Level 表示电平触发。ActiveHigh 表示高电平有效。Exclusive 表示中断不可共享。{ 99, 98, 97, 96 } 表示用到的中断号。
Name (_DSD, Package () { [...] }) 是 ACPI 中的 Device Specific Data
(_DSD) 描述,用于向操作系统传递设备特定的属性。ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"):这是 Device Properties
UUID,这是 ACPI 官方为 _DSD 定义的标准 UUID,用来标识属性是键值对形式。Package () { ... } 包含多个键值对,这些是具体的属性定义,以 "key", value 的形式存在,每个用 Package (0x02) 包裹。
Package () {
"clock-names",
Package () { "pclk", "hclk", "tx_clk", "tsu_clk" }
}
定义设备所需时钟的逻辑名称。和 "clocks" 一一对应。驱动中通常会通过 clk_get(dev,
"pclk") 获取对应时钟。
Package () {
"clocks",
Package () {
[...]
}
}
给出实际的时钟控制器引用以及对应的时钟编号。^CRG 表示当前作用域(当前 device)中的父级 CRG 设备(时钟控制器)。后面是该控制器下的具体时钟编号或 ID(PERI_GMAC0_PCLK 等。这些信息通常对应到 Linux 的 clk_get() 框架。
Package () {
"phy-mode",
Package () { "rgmii-id" }
}
指定该以太网设备使用的 PHY 接口类型。"rgmii-id" 表示 RGMII 接口,并开启了 内部延迟(Internal
Delay)。如果使用 rmii,可以写为 Package () rgmii-id。