转载请注明原帖链接和作者!
OpenWrt 自带的 swconfig 功能对于 Debian 来说,就不是那么好用了。除此之外,Linux 对交换机的支持就只剩 DSA 了。幸好 MT7530 有 DSA 驱动。
但是 MT7530 的 DSA 驱动是给 MT7623 用的,里面硬编码了很多 MT7623 的设置,还用到了很多 MT7621 中不存在的东西,例如 Power domain。
这些都需要全部去掉,并为 MT7621 添加所需的代码。
此外,用于 MT7621 的以太网驱动 mtk_soc_eth 也一团糟,里面杂揉了各个芯片的代码,不纯粹,不适合拿给 DSA 用。因此也需要进行修改。
1. 修改 mtk_soc_eth
我选择对 ARM 版的 mtk_soc_eth 下手。
1.1 加入 MT7621 支持
--- a/drivers/net/ethernet/mediatek/Kconfig +++ b/drivers/net/ethernet/mediatek/Kconfig @@ -1,6 +1,6 @@ config NET_VENDOR_MEDIATEK bool "MediaTek ethernet driver" - depends on ARCH_MEDIATEK + depends on ARCH_MEDIATEK || SOC_MT7621 ---help--- If you have a Mediatek SoC with ethernet, say Y. --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -76,7 +76,6 @@ static int mtk_mdio_busy_wait(struct mtk return 0; if (time_after(jiffies, t_start + PHY_IAC_TIMEOUT)) break; - usleep_range(10, 20); } dev_err(eth->dev, "mdio: MDIO timeout\n"); @@ -1748,6 +1747,34 @@ static void mtk_tx_timeout(struct net_de schedule_work(ð->pending_work); } +static irqreturn_t mtk_handle_irq_tx_rx(int irq, void *_eth) +{ + struct mtk_eth *eth = _eth; + u32 tx_status, rx_status; + + tx_status = mtk_r32(eth, MTK_QMTK_INT_STATUS); + + if (tx_status & MTK_TX_DONE_INT) { + if (likely(napi_schedule_prep(ð->tx_napi))) { + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); + __napi_schedule(ð->tx_napi); + } + mtk_w32(eth, tx_status, MTK_QMTK_INT_STATUS); + } + + rx_status = mtk_r32(eth, MTK_PDMA_INT_STATUS); + + if (rx_status & MTK_RX_DONE_INT) { + if (likely(napi_schedule_prep(ð->rx_napi))) { + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); + __napi_schedule(ð->rx_napi); + } + mtk_w32(eth, rx_status, MTK_PDMA_INT_STATUS); + } + + return IRQ_HANDLED; +} + static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) { struct mtk_eth *eth = _eth; @@ -1950,14 +1977,16 @@ static int mtk_hw_init(struct mtk_eth *e } regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val); - /* Set GE2 driving and slew rate */ - regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00); + if (eth->pctl) { + /* Set GE2 driving and slew rate */ + regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00); - /* set GE2 TDSEL */ - regmap_write(eth->pctl, GPIO_OD33_CTRL8, 0x5); + /* set GE2 TDSEL */ + regmap_write(eth->pctl, GPIO_OD33_CTRL8, 0x5); - /* set GE2 TUNE */ - regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0); + /* set GE2 TUNE */ + regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0); + } /* Set linkdown as the default for each GMAC. Its own MCR would be set * up with the more appropriate value when mtk_phy_link_adjust call is @@ -2536,14 +2565,16 @@ static int mtk_probe(struct platform_dev } } - eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "mediatek,pctl"); - if (IS_ERR(eth->pctl)) { - dev_err(&pdev->dev, "no pctl regmap found\n"); - return PTR_ERR(eth->pctl); + if (eth->soc->require_pctl) { + eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "mediatek,pctl"); + if (IS_ERR(eth->pctl)) { + dev_info(&pdev->dev, "no pctl regmap found\n"); + return PTR_ERR(eth->pctl); + } } - for (i = 0; i < 3; i++) { + for (i = 0; i < eth->soc->irq_num; i++) { eth->irq[i] = platform_get_irq(pdev, i); if (eth->irq[i] < 0) { dev_err(&pdev->dev, "no IRQ%d resource found\n", i); @@ -2591,15 +2622,22 @@ static int mtk_probe(struct platform_dev goto err_deinit_hw; } - err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0, - dev_name(eth->dev), eth); - if (err) - goto err_free_dev; + if (eth->soc->irq_num > 1) { + err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0, + dev_name(eth->dev), eth); + if (err) + goto err_free_dev; - err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0, - dev_name(eth->dev), eth); - if (err) - goto err_free_dev; + err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0, + dev_name(eth->dev), eth); + if (err) + goto err_free_dev; + } else { + err = devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq_tx_rx, 0, + dev_name(eth->dev), eth); + if (err) + goto err_free_dev; + } err = mtk_mdio_init(eth); if (err) @@ -2666,23 +2704,37 @@ static int mtk_remove(struct platform_de static const struct mtk_soc_data mt2701_data = { .caps = MTK_GMAC1_TRGMII, - .required_clks = MT7623_CLKS_BITMAP + .required_clks = MT7623_CLKS_BITMAP, + .require_pctl = true, + .irq_num = 3, }; static const struct mtk_soc_data mt7622_data = { .caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW, - .required_clks = MT7622_CLKS_BITMAP + .required_clks = MT7622_CLKS_BITMAP, + .require_pctl = false, + .irq_num = 3, }; static const struct mtk_soc_data mt7623_data = { .caps = MTK_GMAC1_TRGMII, - .required_clks = MT7623_CLKS_BITMAP + .required_clks = MT7623_CLKS_BITMAP, + .require_pctl = true, + .irq_num = 3, +}; + +static const struct mtk_soc_data mt7621_data = { + .caps = MTK_GMAC1_TRGMII, + .required_clks = MT7621_CLKS_BITMAP, + .require_pctl = false, + .irq_num = 1, }; const struct of_device_id of_mtk_match[] = { { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data}, { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, + { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data}, {}, }; MODULE_DEVICE_TABLE(of, of_mtk_match); --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -486,6 +486,8 @@ enum mtk_clks_map { BIT(MTK_CLK_SGMII_CDR_FB) | \ BIT(MTK_CLK_SGMII_CK) | \ BIT(MTK_CLK_ETH2PLL)) +#define MT7621_CLKS_BITMAP 0 + enum mtk_dev_state { MTK_HW_INIT, MTK_RESETTING @@ -575,6 +577,8 @@ struct mtk_rx_ring { struct mtk_soc_data { u32 caps; u32 required_clks; + bool require_pctl; + u32 irq_num; }; /* currently no SoC has more than 2 macs */ }; /* currently no SoC has more than 2 macs */
1.2 从 mediatek 这个 target 中提取 mtk_soc_eth 相关的改动
0027-net-next-mediatek-fix-DQL-support.patch
0035-net-mediatek-disable-RX-VLan-offloading.patch
0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch
0043-net-next-mediatek-enable-special-tag-indication-for-.patch
0051-net-mediatek-increase-tx_timeout.patch
0063-atomic-sleep.patch
2. 修改 DSA 驱动
2.1 从 mediatek 这个 target 中提取 DSA 相关的改动
0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch
0033-dsa-multi-cpu.patch
0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch
0045-net-dsa-mediatek-turn-into-platform-driver.patch
2.2 针对 MT7621 进行修改
2.2.1 去除 MT7623 TRGMII 相关的设置
--- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -76,58 +76,6 @@ static const struct mt7530_mib_desc mt75 }; static int -mt7623_trgmii_write(struct mt7530_priv *priv, u32 reg, u32 val) -{ - int ret; - - ret = regmap_write(priv->ethernet, TRGMII_BASE(reg), val); - if (ret < 0) - dev_err(priv->dev, - "failed to priv write register\n"); - return ret; -} - -static u32 -mt7623_trgmii_read(struct mt7530_priv *priv, u32 reg) -{ - int ret; - u32 val; - - ret = regmap_read(priv->ethernet, TRGMII_BASE(reg), &val); - if (ret < 0) { - dev_err(priv->dev, - "failed to priv read register\n"); - return ret; - } - - return val; -} - -static void -mt7623_trgmii_rmw(struct mt7530_priv *priv, u32 reg, - u32 mask, u32 set) -{ - u32 val; - - val = mt7623_trgmii_read(priv, reg); - val &= ~mask; - val |= set; - mt7623_trgmii_write(priv, reg, val); -} - -static void -mt7623_trgmii_set(struct mt7530_priv *priv, u32 reg, u32 val) -{ - mt7623_trgmii_rmw(priv, reg, 0, val); -} - -static void -mt7623_trgmii_clear(struct mt7530_priv *priv, u32 reg, u32 val) -{ - mt7623_trgmii_rmw(priv, reg, val, 0); -} - -static int core_read_mmd_indirect(struct mt7530_priv *priv, int prtad, int devad) { struct mii_bus *bus = priv->bus; @@ -515,24 +463,6 @@ mt7530_pad_clk_setup(struct dsa_switch * for (i = 0 ; i < NUM_TRGMII_CTRL; i++) mt7530_rmw(priv, MT7530_TRGMII_RD(i), RD_TAP_MASK, RD_TAP(16)); - else - mt7623_trgmii_set(priv, GSW_INTF_MODE, INTF_MODE_TRGMII); - - return 0; -} - -static int -mt7623_pad_clk_setup(struct dsa_switch *ds) -{ - struct mt7530_priv *priv = ds->priv; - int i; - - for (i = 0 ; i < NUM_TRGMII_CTRL; i++) - mt7623_trgmii_write(priv, GSW_TRGMII_TD_ODT(i), - TD_DM_DRVP(8) | TD_DM_DRVN(8)); - - mt7623_trgmii_set(priv, GSW_TRGMII_RCK_CTRL, RX_RST | RXC_DQSISEL); - mt7623_trgmii_clear(priv, GSW_TRGMII_RCK_CTRL, RX_RST); return 0; } @@ -619,12 +549,6 @@ static void mt7530_adjust_link(struct ds /* Setup TX circuit incluing relevant PAD and driving */ mt7530_pad_clk_setup(ds, phydev->interface); - - /* Setup RX circuit, relevant PAD and driving on the host - * which must be placed after the setup on the device side is - * all finished. - */ - mt7623_pad_clk_setup(ds); } else { u16 lcl_adv = 0, rmt_adv = 0; u8 flowctrl;
2.2.2 添加 MT7621 TRGMII 相关的设置
目前 Upstream 并没有完善的 TRGMII 支持,因此暂时先用 RGMII。毕竟 MT7621 的 TRGMII 只有 1.2Gbps,只比 RGMII 的 1Gbps 快了一点,影响不大。
这个先留着,等以后再补充。
3. 修改 DTS 文件
3.1 修改 mt7621.dtsi
--- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -406,22 +406,38 @@ 0x1e003800 0x800>; }; + ethsys: ethsys@1e000000 { + compatible = "mediatek,mt7621-ethsys", "syscon"; + reg = <0x1e000000 0x8000>; + }; + ethernet: ethernet@1e100000 { - compatible = "mediatek,mt7621-eth"; + compatible = "mediatek,mt7621-eth", "syscon"; reg = <0x1e100000 0x10000>; #address-cells = <1>; #size-cells = <1>; + mediatek,ethsys = <ðsys>; + resets = <&rstctrl 6 &rstctrl 23>; reset-names = "fe", "eth"; interrupt-parent = <&gic>; interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>; - mediatek,switch = <&gsw>; + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "rgmii"; + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; + }; - mdio-bus { + mdio: mdio-bus { #address-cells = <1>; #size-cells = <0>; @@ -430,16 +446,6 @@ 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 {
3.2 修改对应板子的 dts
这里用的是 CreativeBox 这个板子。
--- a/target/linux/ramips/dts/CreativeBox-v1.dts +++ b/target/linux/ramips/dts/CreativeBox-v1.dts @@ -86,6 +86,10 @@ gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; }; }; + + mt7530: switch@0 { + compatible = "mediatek,mt7530"; + }; }; &sdhci { @@ -115,6 +119,67 @@ mtd-mac-address = <&factory 0xe000>; }; +&mt7530 { + compatible = "mediatek,mt7530"; + + #address-cells = <1>; + #size-cells = <0>; + + mediatek,mcm; + resets = <&rstctrl 2>; + reset-names = "mcm"; + + dsa,mii-bus = <&mdio>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + port@0 { + reg = <0>; + label = "lan0"; + cpu = <&cpu_port0>; + }; + + port@1 { + reg = <1>; + label = "lan1"; + cpu = <&cpu_port0>; + }; + + port@2 { + reg = <2>; + label = "lan2"; + cpu = <&cpu_port0>; + }; + + port@3 { + reg = <3>; + label = "lan3"; + cpu = <&cpu_port0>; + }; + + port@4 { + reg = <4>; + label = "wan"; + cpu = <&cpu_port0>; + }; + + cpu_port0: port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; + &pinctrl { state_default: pinctrl0 { gpio {
4. 修改 OpenWrt 中的网络配置
这里仅仅是为了在 OpenWrt 中测试 DSA 是否正常工作
修改 target/linux/ramips/base-files/etc/board.d/02_network,将对应板子的脚本语句修改为:
ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" "wan"
5. 开启 kernel 网络子系统的 DSA 功能
Networking support —> Networking options —> Distributed Switch Architecture
Device Drivers —> Network device support —> Distributed Switch Architecture drivers —> Mediatek MT7530 Ethernet switch support
6. 编译测试
略
BreedEnter目前已经没法在https://breed.hackpascal.net/ 下载到了,烦请补链一下~谢谢
手头有1台 水星的MER2600G, 用的MT7621芯片
RAM 128M
ROM 16M
有5G和2.4G, 带PA和LNA
原厂系统有一个BUG
运行一段时间后,就会卡住,不回复ISP OLT发出的PPP echo 导致被服务器判断为掉线。
改为光猫直接拨号,路由的WAN是 静态IP,也一样无法上网。
官方自己写了一个判断是否掉线的小程序,也会导致无法上网。
要冷却一段时间后才能再次PPPoe上网,联系了官方技术,换了3次新机,都没有解决。
想自己编译一下 最新版本的 openwrt
已用breed 测试出 几个 GPIO 的情况
reset按钮 GPIO 8
turbo按钮 GPIO 12
sys LED GPIO 3
turbo LED GPIO 4
USB LED GPIO 15
想请教一下 在DTS里应该怎么配置?
拆机的主要芯片图片在数码之家有
谢谢大神