Bjørn Mork <bj...@mork.no> writes: > The WiFi extender I am having trouble with (ZyXEL WAP6805 - similar to > the WAP6806) has an RGMII connected Quantenna 5Ghz module. My > assumption is that this module is connected to the RGMII pads on the > MT7621 and that I need support for the second GMAC to get it running. > The Quantenna module loads its firmware using TFTP in the OEM firmware. > > I note that forum user Thirsty has had some success using the mainline > MT7623 driver to enable both GMACs: > https://forum.lede-project.org/t/er-x-sfp-sfp-eth5-port-has-link-state-led-lit-but-swconfig-says-link-port-5-link-down/4608/70 > > but this currently implies DSA, so it's not exactly plug-and-play with > OpenWrt. I haven't tried it myself yet.
My progress is slow... Just keeping this thread alive ;-) Encouraged by the possible switch (pun intended) to DSA for the next release, I decided to try out Thirsty's solution. And it worked fine, with a slight device-specific tweak (details below). So I thought I could go a little further and try to reduce the diff as much as possible. The attached patch is what I ended up with. Like John said: pretty easy. Almost no diff at all. How to use: Remove the conflicting out-of-tree mtk_eth_soc driver from the ramips target, copy all mtk_eth_soc patches from the mediatek target to the ramips target, and then apply the attached patch. And use the following kernel config changes (are all these necessary? not verified): KCONFIG:= \ CONFIG_NET_MEDIATEK_GSW_MT7621=n \ CONFIG_NET_MEDIATEK_MDIO=n \ CONFIG_NET_MEDIATEK_MDIO_MT7620=n \ CONFIG_NET_MEDIATEK_MT7621=n \ CONFIG_NET_DSA=y \ CONFIG_NET_DSA_MT7530=y \ CONFIG_NET_DSA_TAG_MTK=y \ CONFIG_MDIO_BUS=y \ CONFIG_MDIO_DEVICE=y \ CONFIG_MDIO_I2C=y \ CONFIG_MFD_SYSCON=y \ CONFIG_REGMAP_MMIO=y With a minor diff to the mt7621.dtsi for the syscon support. note that the ethernet reg size adjustment is somewhat optional. You'll only get access warnings from the mt7623_trgmii_* functions in the mt7530 driver without it. That code should probably be disabled instead: diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi index 31d930d2251b..389c7064cc9a 100644 --- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -60,7 +60,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "mtk,mt7621-sysc"; + compatible = "mtk,mt7621-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -384,11 +384,11 @@ }; ethernet: ethernet@1e100000 { - compatible = "mediatek,mt7621-eth"; - reg = <0x1e100000 0x10000>; + compatible = "mediatek,mt7621-eth", "syscon"; + reg = <0x1e100000 0x20000>; #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; resets = <&rstctrl 6 &rstctrl 23>; reset-names = "fe", "eth"; @@ -397,6 +397,7 @@ interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>; mediatek,switch = <&gsw>; + mediatek,ethsys = <&sysc>; mdio-bus { #address-cells = <1>; In my target device DTS I've used this ðernet { gmac0: mac@0 { compatible = "mediatek,eth-mac"; reg = <0>; phy-mode = "rgmii"; mtd-mac-address = <&factory 0xe000>; fixed-link { speed = <1000>; full-duplex; pause; }; }; gmac1: mac@1 { compatible = "mediatek,eth-mac"; reg = <1>; phy-mode = "rgmii"; mtd-mac-address = <&factory 0xe000>; mtd-mac-address-increment = <1>; fixed-link { speed = <1000>; full-duplex; pause; }; }; }; &phy1f { compatible = "mediatek,mt7530"; #address-cells = <1>; #size-cells = <0>; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; label = "lan0"; }; port@1 { reg = <1>; label = "lan1"; }; port@2 { reg = <2>; label = "lan2"; }; port@3 { reg = <3>; label = "lan3"; }; cpu_port0: port@6 { reg = <6>; label = "cpu"; ethernet = <&gmac0>; }; }; }; That's everything necessary for the mainline mtk_etc_soc and mt7530 drivers with MT7621, with both GMACs enabled! There are still a couple of rough corners though: - I've completely ignored clocks. Thirsty created a clock driver, but looking at mtk_eth_soc, this seemed optional to me. So I dropped it for simplicity and simply did '#define MT7621_CLKS_BITMAP (0)' - I've also ignored regulators. The mt7530 drivers needs a couple, but the automatic dummy does the job. - Not too sure about the shared interrupt thingy. I tried reusing the interrupt handlers, and it ends up in a tight ksoftirq loop (aka lockup) if there is simultaneous traffic over the two gmacs. This "fixes" the problem, but something doesn't seem quite right: --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1775,8 +1775,8 @@ static irqreturn_t mtk_handle_irq_rx(int if (likely(napi_schedule_prep(ð->rx_napi))) { __napi_schedule(ð->rx_napi); - mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); } + mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); return IRQ_HANDLED; } @@ -1787,8 +1787,8 @@ static irqreturn_t mtk_handle_irq_tx(int if (likely(napi_schedule_prep(ð->tx_napi))) { __napi_schedule(ð->tx_napi); - mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); } + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); return IRQ_HANDLED; } It does halfway make sense, given that returning IRQ_HANDLED without actually doing anything seems like a bad idea. But that code is there in the mainline driver. Why doesn't it lock up from time to time? Or does it? The required device specific tweak mentioned above is related to an undocumented(?) FE or switch register at 0x1e110008. By default this register reads root@OpenWrt:/# io -4 0x1e110008 1e110008: 000c000c and nothing is received on the eth1 interface. But the FCS error counter increases. Writing another magic value makes the FCS errors go away and packets are received normally: root@OpenWrt:/# io -4 -w 0x1e110008 0x9000c I've experimented somewhat with different values and found that 0x8000c also works. So it seems clearing bit 18 is the important part. For those who wonder where I got this magic: It comes almost directly from an OEM firmware script (/sbin/internet.sh), having: # Support QTN 5G if [ "$CONFIG_QTN_5G" = "y" ]; then reg s 0xbe110000 reg w 8 0x9000c mii_mgr -s -p 0 -r 0 -v 0x3900 mii_mgr -s -p 1 -r 0 -v 0x3900 mii_mgr -s -p 2 -r 0 -v 0x3900 mii_mgr -s -p 3 -r 0 -v 0x3900 #switch reg w 2004 20ff0400 #switch reg w 2104 20ff0400 #switch reg w 2204 20ff0400 #switch reg w 2304 20ff0400 ifconfig eth3 up brctl addif br0 eth3 ifconfig br0:9 1.1.1.1 netmask 255.255.255.0 broadcast 1.1.1.255 cp /usr/etc/protocols /etc/ cp /usr/etc/rmt_ip.conf /etc/ rmt_qcsmngr -m 0 & fi My best guess is that this is somehow related to RMGII delays, based on the FCS effect. In which case it should probably be related to rgmii-id, rgmii-txid, or rgmii-rxid somewhere. But guessing where is difficult not knowing the exact meaning of those bits. So I've not implemented anything here yet, except a local device fix to ease my own testing. Still have a long way to go before I have the Quantenna module up and running without a kick in the butt. But the good news is that the Quantenna PCIe work done by ILOVEPIE at https://github.com/ILOVEPIE/qts1kpcie_wifi_driver.git seems to apply to RMGII connected Quantenna modules too. Even the module firmware! So there is a good chance we can reuse tools, plugins and firmware packages for all Quantenna modules regardless of connection, if we ever finish the support. But there is quite a lot of polishing left... Anyway, the main point here was the mtk_eth_soc and mt7530 mainline driver part. Hope this info is useful to someone. root@OpenWrt:/# ifconfig -a br-lan Link encap:Ethernet HWaddr 60:31:97:66:16:10 inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::6231:97ff:fe66:1610/64 Scope:Link inet6 addr: fd5f:9350:2bf2::1/60 Scope:Global UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:47 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:2414 (2.3 KiB) TX bytes:8170 (7.9 KiB) eth0 Link encap:Ethernet HWaddr 60:31:97:66:16:10 inet6 addr: fe80::6231:97ff:fe66:1610/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:405 errors:0 dropped:0 overruns:0 frame:0 TX packets:61 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:96287 (94.0 KiB) TX bytes:11043 (10.7 KiB) Interrupt:15 eth1 Link encap:Ethernet HWaddr 60:31:97:66:16:11 inet addr:1.1.1.1 Bcast:255.255.255.248 Mask:255.255.255.248 inet6 addr: fe80::6231:97ff:fe66:1611/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6457 errors:0 dropped:0 overruns:0 frame:0 TX packets:6544 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:396616 (387.3 KiB) TX bytes:9515000 (9.0 MiB) Interrupt:15 lan0 Link encap:Ethernet HWaddr 60:31:97:66:16:10 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:405 errors:0 dropped:399 overruns:0 frame:0 TX packets:47 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:88997 (86.9 KiB) TX bytes:8170 (7.9 KiB) lan1 Link encap:Ethernet HWaddr 60:31:97:66:16:10 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lan2 Link encap:Ethernet HWaddr 60:31:97:66:16:10 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lan3 Link encap:Ethernet HWaddr 60:31:97:66:16:10 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:2073 errors:0 dropped:0 overruns:0 frame:0 TX packets:2073 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:134060 (130.9 KiB) TX bytes:134060 (130.9 KiB) wlan0 Link encap:Ethernet HWaddr 02:10:18:FF:5B:F8 BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) root@OpenWrt:/# ls -la /sys/class/net/*/device/driver lrwxrwxrwx 1 root root 0 Aug 17 11:24 /sys/class/net/eth0/device/driver -> ../../../bus/platform/drivers/mtk_soc_eth lrwxrwxrwx 1 root root 0 Aug 17 11:24 /sys/class/net/eth1/device/driver -> ../../../bus/platform/drivers/mtk_soc_eth lrwxrwxrwx 1 root root 0 Aug 17 11:25 /sys/class/net/lan0/device/driver -> ../../../../../../bus/mdio_bus/drivers/mt7530 lrwxrwxrwx 1 root root 0 Aug 17 11:25 /sys/class/net/lan1/device/driver -> ../../../../../../bus/mdio_bus/drivers/mt7530 lrwxrwxrwx 1 root root 0 Aug 17 11:25 /sys/class/net/lan2/device/driver -> ../../../../../../bus/mdio_bus/drivers/mt7530 lrwxrwxrwx 1 root root 0 Aug 17 11:25 /sys/class/net/lan3/device/driver -> ../../../../../../bus/mdio_bus/drivers/mt7530 lrwxrwxrwx 1 root root 0 Aug 17 11:25 /sys/class/net/wlan0/device/driver -> ../../../../bus/pci/drivers/mt7603e root@OpenWrt:/# brctl show bridge name bridge id STP enabled interfaces br-lan 7fff.603197661610 no lan0 lan1 lan2 lan3 root@OpenWrt:/# ip route get 192.168.1.33 192.168.1.33 dev br-lan src 192.168.1.1 root@OpenWrt:/# ping 192.168.1.33 PING 192.168.1.33 (192.168.1.33): 56 data bytes 64 bytes from 192.168.1.33: seq=0 ttl=64 time=1.010 ms ^C --- 192.168.1.33 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 1.010/1.010/1.010 ms root@OpenWrt:/# qcsapi_sockrpc --host 1.1.1.2 get_info eth1 Build name: v37.3.1.25 Build revision: 30503 Build type: GPL Build timestamp: 1429609059 Platform ID: 450 Hardware ID: QV840 Hardware revision: bbic4_rev_a2 Band: 5GHz Kernel version: 2.6.35 Calibration version: disabled DC/IQ cal version: V8.1 Power cal version: V8.1 MuC firmware: qtn_driver.qtn_ruby.0.bin DSP firmware: rdsp_driver.0.bin AuC firmware: auc_driver.0.bin MAC address 0: 00:26:86:32:b9:03 MAC address 1: 00:00:00:00:00:00 U-Boot version: v37.3.0.22 Bjørn
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1792,6 +1792,19 @@ static irqreturn_t mtk_handle_irq_tx(int return IRQ_HANDLED; } +static irqreturn_t mtk_handle_irq(int irq, void *_eth) +{ + struct mtk_eth *eth = _eth; + + if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT) + mtk_handle_irq_rx(irq, _eth); + + if (mtk_r32(eth, MTK_QMTK_INT_STATUS) & MTK_TX_DONE_INT) + mtk_handle_irq_tx(irq, _eth); + + return IRQ_HANDLED; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void mtk_poll_controller(struct net_device *dev) { @@ -2184,11 +2197,13 @@ static int mtk_free_dev(struct mtk_eth * static int mtk_unreg_dev(struct mtk_eth *eth) { + struct mtk_mac *mac; int i; for (i = 0; i < MTK_MAC_COUNT; i++) { if (!eth->netdev[i]) continue; + mac = netdev_priv(eth->netdev[i]); unregister_netdev(eth->netdev[i]); } @@ -2579,8 +2594,12 @@ static int mtk_probe(struct platform_dev } } - for (i = 0; i < 3; i++) { - eth->irq[i] = platform_get_irq(pdev, i); + for (i = 0; i < 3; i++) + { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) + eth->irq[i] = eth->irq[0]; + else + eth->irq[i] = platform_get_irq(pdev, i); if (eth->irq[i] < 0) { dev_err(&pdev->dev, "no IRQ%d resource found\n", i); return -ENXIO; @@ -2627,13 +2646,18 @@ 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 (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { + err = devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq, 0, + dev_name(eth->dev), eth); + } else { + 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); + 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; @@ -2706,6 +2730,12 @@ static const struct mtk_soc_data mt2701_ .required_pctl = true, }; +static const struct mtk_soc_data mt7621_data = { + .caps = MTK_SHARED_INT, + .required_clks = MT7621_CLKS_BITMAP, + .required_pctl = false, +}; + static const struct mtk_soc_data mt7622_data = { .caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW, .required_clks = MT7622_CLKS_BITMAP, @@ -2720,6 +2750,7 @@ static const struct mtk_soc_data mt7623_ const struct of_device_id of_mtk_match[] = { { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data}, + { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data}, { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, {}, --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -364,6 +364,7 @@ #define ETHSYS_CHIPID4_7 0x4 #define MT7623_ETH 7623 #define MT7622_ETH 7622 +#define MT7621_ETH 7621 /* ethernet subsystem config register */ #define ETHSYS_SYSCFG0 0x14 @@ -489,6 +490,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 @@ -567,6 +570,8 @@ struct mtk_rx_ring { #define MTK_GMAC2_SGMII (BIT(10) | MTK_SGMII) #define MTK_DUAL_GMAC_SHARED_SGMII (BIT(11) | MTK_GMAC1_SGMII | \ MTK_GMAC2_SGMII) +#define MTK_SHARED_INT BIT(12) + #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) /* struct mtk_eth_data - This is the structure holding all differences --- 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.
_______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel