November 17, 2024

DWMAC-RK驱动解析

PHY

PHY芯片通常都符合IEEE标准。IEEE 802.3标准定义了一组标准的MII管理寄存器(如控制寄存器和状态寄存器)。这些标准寄存器通常编号为0到15。

标准寄存器列表 (Registers 0–15)

寄存器 0: 基本控制寄存器(Basic Control Register, BMCR)

寄存器 1: 基本状态寄存器(Basic Status Register, BMSR)

寄存器 2: PHY标识1(PHY Identifier 1, PHYIDR1)

寄存器 3: PHY标识2(PHY Identifier 2, PHYIDR2)

寄存器 4: 自动协商广告寄存器(Auto-Negotiation Advertisement, ANAR)

寄存器 5: 链路伙伴能力寄存器(Link Partner Ability, ANLPAR)

寄存器 6: 自动协商扩展寄存器(Auto-Negotiation Expansion, ANER)

寄存器 7: 下一个页面传输寄存器(Next Page Transmit, ANNPTR)

寄存器 8: 链路伙伴下一页寄存器(Link Partner Next Page, ANLPNPR)

寄存器 9: 1000BASE-T能力寄存器(1000BASE-T Control, MSEADR)

寄存器 10: 1000BASE-T状态寄存器(1000BASE-T Status, MSEADR)

- 显示千兆以太网的状态信息。

寄存器 11–15: 保留(Reserved)

- 通常为厂商定义的扩展寄存器。

寄存器地址为0x00xF,通过MII(Management Data Input/Output)总线访问。

DWMAC简介

DWMAC(DesignWare MAC,简称DWMAC)是由Synopsys公司设计的一种网络控制器IP核心,属于DesignWare系列的以太网媒体访问控制器(Ethernet Media Access Controller,MAC)。DWMAC主要应用于嵌入式设备、片上系统(SoC)以及支持以太网通信的设备中。

DWMAC-RK驱动解析

RK3568的GMAC设备描述在rk3568.dtsi文件中可以找到。根据设备树描述可知,RK3568的GMAC控制器使用的是新思科技提供的IP核,型号是dwmac-4.20a

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
gmac0: ethernet@fe2a0000 {
compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a";
reg = <0x0 0xfe2a0000 0x0 0x10000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq", "eth_wake_irq";
rockchip,grf = <&grf>;
clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>,
<&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>,
<&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>,
<&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>,
<&cru PCLK_XPCS>;
clock-names = "stmmaceth", "mac_clk_rx",
"mac_clk_tx", "clk_mac_refout",
"aclk_mac", "pclk_mac",
"clk_mac_speed", "ptp_ref",
"pclk_xpcs";
resets = <&cru SRST_A_GMAC0>;
reset-names = "stmmaceth";

snps,mixed-burst;
snps,tso;

snps,axi-config = <&gmac0_stmmac_axi_setup>;
snps,mtl-rx-config = <&gmac0_mtl_rx_setup>;
snps,mtl-tx-config = <&gmac0_mtl_tx_setup>;
status = "disabled";

mdio0: mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <0x1>;
#size-cells = <0x0>;
};

gmac0_stmmac_axi_setup: stmmac-axi-config {
snps,wr_osr_lmt = <4>;
snps,rd_osr_lmt = <8>;
snps,blen = <0 0 0 0 16 8 4>;
};

gmac0_mtl_rx_setup: rx-queues-config {
snps,rx-queues-to-use = <1>;
queue0 {};
};

gmac0_mtl_tx_setup: tx-queues-config {
snps,tx-queues-to-use = <1>;
queue0 {};
};
};

驱动代码位于**/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c**。

1
2
3
4
5
6
7
8
9
10
static struct platform_driver rk_gmac_dwmac_driver = {
.probe = rk_gmac_probe,
.remove = rk_gmac_remove,
.driver = {
.name = "rk_gmac-dwmac",
.pm = &rk_gmac_pm_ops,
.of_match_table = rk_gmac_dwmac_match,
},
};
module_platform_driver(rk_gmac_dwmac_driver);

rk_gmac_probe函数负责在设备和驱动匹配后初始化 Rockchip 的 GMAC 控制器驱动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
static int rk_gmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
const struct rk_gmac_ops *data;
int ret;

data = of_device_get_match_data(&pdev->dev);
if (!data) {
dev_err(&pdev->dev, "no of match data provided\n");
return -EINVAL;
}

ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
return ret;

plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
if (IS_ERR(plat_dat))
return PTR_ERR(plat_dat);

if (!of_device_is_compatible(pdev->dev.of_node, "snps,dwmac-4.20a"))
plat_dat->has_gmac = true;

plat_dat->fix_mac_speed = rk_fix_speed;
plat_dat->get_eth_addr = rk_get_eth_addr;

plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data);
if (IS_ERR(plat_dat->bsp_priv)) {
ret = PTR_ERR(plat_dat->bsp_priv);
goto err_remove_config_dt;
}

ret = rk_gmac_clk_init(plat_dat);
if (ret)
goto err_remove_config_dt;

ret = rk_gmac_powerup(plat_dat->bsp_priv);
if (ret)
goto err_remove_config_dt;

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
goto err_gmac_powerdown;

ret = dwmac_rk_create_loopback_sysfs(&pdev->dev);
if (ret)
goto err_gmac_powerdown;

return 0;

err_gmac_powerdown:
rk_gmac_powerdown(plat_dat->bsp_priv);
err_remove_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);

return ret;
}

首先使用```of_device_get_match_data``函数用来匹配设备树中启用的GMAC驱动版本,如图:

image-20250110164114172

stmmac_get_platform_resources函数用于从设备树中获取GMAC的中断号、唤醒终端号以及低功耗空闲模式中断号。并使用platform_get_resource```接口获取GMAC控制器的物理内存地址,使用devm_ioremap_resource``接口映射这段内存地址,以方便接下来的操作。

image-20250110170234258

stmmac_probe_config_dt函数有一点复杂。

关于本文

由 Shane 撰写, 采用 CC BY-NC 4.0 许可协议.

#DWMAC#RK3568