我是靠谱客的博主 醉熏龙猫,这篇文章主要介绍5-->详解《switch 数据接收驱动框架、mtk7621集成交换芯片mt7530》之一,现在分享给大家,希望可以做个参考。

一、 MTK7621 网络通讯原理简述

本篇博文分析的是mtk7621的芯片所内嵌的交换芯片mt7530的驱动程序,MTK7621采用内部的 MDIO 接口管理MT7530 的 switch 芯片;MT7530包含多个7个 PHY 接口,其中第7个口连接到MTK7621芯片的eth0网口。MTK7621通过MDIO 进行寄存器读写配置使用,逻辑框图如下。

复制代码
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
------------------ | CPU /mtk7621 | | ----------- | | | MAC/ephy | |___|__||_____|__| || RGMII/ || RXP/TXP MII || || ------------------------------------------------||--------- | Switch MT7530 || | | || | | || | | |-----| |-----| |-----| |-----| |-----| | ____|_____|___|_____|___|_____|___|_____|____|_____|______| PHY1 PHY2 PHY3 PHY4 PHY/MAC

二、通过设备树看 MT7530 交换芯片

  • 1.linux 内核源码相对路径:
复制代码
1
2
OpenWrt/mtk7621-19.07/build_dir/target-mipsel_24kc_musl/linux-ramips_mt7621/linux-4.14.200
  • 2.设备树文件相对路径:
复制代码
1
2
3
4
5
6
7
8
9
/OpenWrt/mtk7621-19.07$ ls target/linux/ramips/dts/ |grep 7621 AP-MT7621A-V60.dts MT7621.dts mt7621.dtsi U7621-06-256M-16M.dts U7621-06-256M-64M.dts U7621-06-512M-64M.dts U7621-06.dtsi
  • 3.mt7621.dtsi 文件内容
    文件名称: target/linux/ramips/dts/mt7621.dtsi
复制代码
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
ethernet: ethernet@1e100000 { compatible = "mediatek,mt7621-eth"; # 对应的驱动程序 soc_mt7621.c 文件中 reg = <0x1e100000 0x10000>; #address-cells = <1>; #size-cells = <1>; resets = <&rstctrl 6 &rstctrl 23>; reset-names = "fe", "eth"; interrupt-parent = <&gic>; interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>; mediatek,switch = <&gsw>; #交换芯片 mt7530 mdio-bus { #address-cells = <1>; #size-cells = <0>; phy1f: ethernet-phy@1f { # 内部 MDIO 总线描述 reg = <0x1f>; phy-mode = "rgmii"; }; }; hnat: hnat@0 { compatible = "mediatek,mt7623-hnat"; reg = <0 0x10000>; mtketh-ppd = "eth0"; mtketh-lan = "eth0"; mtketh-wan = "eth0"; resets = <&rstctrl 0>; reset-names = "mtketh"; }; }; gsw: gsw@1e110000 { compatible = "mediatek,mt7621-gsw"; # 对应驱动程序 gsw_mt7621.c 文件中。 reg = <0x1e110000 0x8000>; interrupt-parent = <&gic>; interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>; };
  • 4.驱动文件位置
    检索驱动文件: $ ls drivers/net/ethernet/mediatek/
复制代码
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
built-in.o gsw_mt7620.c mdio.c mdio_rt2880.h mtk_debugfs.o mtk_offload.h soc_rt3050.c esw_rt3050.c gsw_mt7620.h mdio.h modules.builtin mtk_eth_soc.c mtk_offload.o soc_rt3883.c esw_rt3050.h gsw_mt7621.c mdio_mt7620.c mt7530.c mtk_eth_soc.h soc_mt7620.c ethtool.c gsw_mt7621.o mdio_mt7620.o mt7530.h mtk_eth_soc.o soc_mt7621.c ethtool.h Kconfig mdio.o mt7530.o mtk-eth-soc.o soc_mt7621.o ethtool.o Makefile mdio_rt2880.c mtk_debugfs.c mtk_offload.c soc_rt2880.c

三、网口与交换芯片如何关联起来? 网口驱动加载。

MT7621 的片上网口驱动 soc_mt7621.c 文件中,eth 驱动方法结构体定义如下:

复制代码
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
static struct fe_soc_data mt7621_data = { .init_data = mt7621_init_data, /* 芯片初始化 */ .reset_fe = mt7621_fe_reset, .set_mac = mt7621_set_mac, .fwd_config = mt7621_fwd_config, /* Vlan 转发配置 */ .tx_dma = mt7621_tx_dma, .switch_init = mtk_gsw_init, /* 关联 MT7530 交换芯片,初始化配置 */ .switch_config = mt7621_gsw_config, /* 配置 MT7530 芯片、并 probe MT7530 驱动 */ .reg_table = mt7621_reg_table, .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, .rx_int = RT5350_RX_DONE_INT, .tx_int = RT5350_TX_DONE_INT, .status_int = (MT7621_FE_GDM1_AF | MT7621_FE_GDM2_AF), .checksum_bit = MT7621_L4_VALID, .has_carrier = mt7620_has_carrier, /* mdio_mt7621.c 状态检测 */ .mdio_read = mt7620_mdio_read, /* mdio 总线读取操作 */ .mdio_write = mt7620_mdio_write, /* mdio 总线写操作 */ .mdio_adjust_link = mt7620_mdio_link_adjust, /* mdio_mt7621.c 连接检测 */ }; /* mtk7621-eth 驱动程序入口处 */ const struct of_device_id of_fe_match[] = { { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data }, {}, }; MODULE_DEVICE_TABLE(of, of_fe_match);

mtk7621 片上的eth驱动就包含这 switch 芯片的驱动内容, mt7530 的驱动挂载是由 mt7621_gsw_config 函数触发。
在这里插入图片描述
由源码调用关系,mt7530操作函数主要是 vlan 和 port 的操作,如:mt7530_get_vlan_ports 函数,最终调用 mdiobus_read/mdio_write 函数实现操作内部芯片mt7530 的目的。

switch 交换芯片驱动加载

mtk7621 片上交换芯片设备名称mt7621-gsw ,驱动程序 gsw_mt7621.c 文件中。

复制代码
1
2
3
4
5
6
7
8
9
gsw: gsw@1e110000 { compatible = "mediatek,mt7621-gsw"; # 对应驱动程序 gsw_mt7621.c 文件中。 reg = <0x1e110000 0x8000>; interrupt-parent = <&gic>; interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>; };

在这里插入图片描述
mtk7621_gsw 驱动实现的是 gsw 设备实例 与 网口设备的绑定,卸载 mt7621-gsw 驱动,实际上是移除 gsw 与 网口间关系。

mt7621-eth 初始化分析

  • mt7621 驱动支持的芯片操作函数集合
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static struct fe_soc_data mt7621_data = { .init_data = mt7621_init_data, .reset_fe = mt7621_fe_reset, .set_mac = mt7621_set_mac, .fwd_config = mt7621_fwd_config, .tx_dma = mt7621_tx_dma, .switch_init = mtk_gsw_init, /* switch 芯片初始化 */ .switch_config = mt7621_gsw_config, .reg_table = mt7621_reg_table, .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, .rx_int = RT5350_RX_DONE_INT, .tx_int = RT5350_TX_DONE_INT, .status_int = (MT7621_FE_GDM1_AF | MT7621_FE_GDM2_AF), .checksum_bit = MT7621_L4_VALID, .has_carrier = mt7620_has_carrier, .mdio_read = mt7620_mdio_read, .mdio_write = mt7620_mdio_write, .mdio_adjust_link = mt7620_mdio_link_adjust, };
  • mtk_gsw_init 初始化
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int mtk_gsw_init(struct fe_priv *priv) { struct device_node *np = priv->switch_np; struct platform_device *pdev = of_find_device_by_node(np); struct mt7620_gsw *gsw; if (!pdev) return -ENODEV; if (!of_device_is_compatible(np, mediatek_gsw_match->compatible)) return -EINVAL; gsw = platform_get_drvdata(pdev); /* 申请中断 */ priv->soc->swpriv = gsw; if (gsw->irq) { request_irq(gsw->irq, gsw_interrupt_mt7621, 0, "gsw", priv); disable_irq(gsw->irq); } /* mt7621-hw 硬件初始化 */ mt7621_hw_init(gsw, np); if (gsw->irq) enable_irq(gsw->irq); return 0; }
  • 初始内容如下
复制代码
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
static void mt7621_hw_init(struct mt7620_gsw *gsw, struct device_node *np) { u32 i; u32 val; /* wardware reset the switch */ fe_reset(RST_CTRL_MCM); mdelay(10); /* reduce RGMII2 PAD driving strength */ rt_sysc_m32(3 << 4, 0, SYSC_PAD_RGMII2_MDIO); /* gpio mux - RGMII1=Normal mode */ rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE); /* set GMAC1 RGMII mode */ rt_sysc_m32(3 << 12, 0, SYSC_REG_CFG1); /* enable MDIO to control MT7530 ,设置 MDIO 控制 MT7530 */ rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE); /* turn off all PHYs */ for (i = 0; i <= 4; i++) { val = _mt7620_mii_read(gsw, i, 0x0); val |= BIT(11); _mt7620_mii_write(gsw, i, 0x0, val); } /* reset the switch */ mt7530_mdio_w32(gsw, 0x7000, 0x3); usleep_range(10, 20); /* (GE1, Force 1000M/FD, FC OFF, MAX_RX_LENGTH 1536) */ mtk_switch_w32(gsw, 0x2305e30b, GSW_REG_MAC_P0_MCR); mt7530_mdio_w32(gsw, 0x3600, 0x5e30b); /* (GE2, Link down) , 关闭 GE2 口,此接口暂时未使用 */ mtk_switch_w32(gsw, 0x8000, GSW_REG_MAC_P1_MCR); /* Set switch max RX frame length to 2k */ mt7530_mdio_w32(gsw, GSW_REG_GMACCR, 0x3F0B); /* Enable Port 6, P5 as GMAC5, P5 disable */ val = mt7530_mdio_r32(gsw, 0x7804); val &= ~BIT(8); val |= BIT(6) | BIT(13) | BIT(16); mt7530_mdio_w32(gsw, 0x7804, val); val = rt_sysc_r32(0x10); val = (val >> 6) & 0x7; if (val >= 6) { /* 25Mhz Xtal - do nothing */ } else if (val >= 3) { /* 40Mhz */ /* disable MT7530 core clock */ _mt7620_mii_write(gsw, 0, 13, 0x1f); _mt7620_mii_write(gsw, 0, 14, 0x410); _mt7620_mii_write(gsw, 0, 13, 0x401f); _mt7620_mii_write(gsw, 0, 14, 0x0); /* 省略部分代码 */ } else { /* 20Mhz Xtal - TODO */ } /* RGMII */ _mt7620_mii_write(gsw, 0, 14, 0x1); /* set MT7530 central align */ /* 省略部分代码 */ /* delay setting for 10/1000M */ /* 省略部分代码 */ /* lower Tx Driving*/ /* 省略部分代码 */ /* turn on all PHYs */ for (i = 0; i <= 4; i++) { val = _mt7620_mii_read(gsw, i, 0); val &= ~BIT(11); _mt7620_mii_write(gsw, i, 0, val); } /* enable irq ,打开中断接收允许 */ mt7530_mdio_w32(gsw, 0x7008, 0x1f); val = mt7530_mdio_r32(gsw, 0x7808); val |= 3 << 16; mt7530_mdio_w32(gsw, 0x7808, val); }

本篇描述 mtk7621 芯片 eth 网口、switch交换芯片之间关系,驱动加载关系;在此 mtk7621 具备数据接收与发送功能,下一篇分享网络协议栈数据接收过程。

当开启 switch 交换口时(例如,通过 ifconfig eth0.2 up),mtk7621_ops 中的 mt7530_set_port 方法会被调用;设置端口、配置vlan 的 vid 号等操作,与mtk7621_ops各方法对应。

最后

以上就是醉熏龙猫最近收集整理的关于5-->详解《switch 数据接收驱动框架、mtk7621集成交换芯片mt7530》之一的全部内容,更多相关5-->详解《switch内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部