转载请注明原帖链接和作者!
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. 编译测试
略
手头有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里应该怎么配置?
拆机的主要芯片图片在数码之家有
谢谢大神
BreedEnter目前已经没法在https://breed.hackpascal.net/ 下载到了,烦请补链一下~谢谢