From 8dfae1f922be925e7ccd6e2e10d84be94b3ddab8 Mon Sep 17 00:00:00 2001 From: mooleshacat <43627985+mooleshacat@users.noreply.github.com> Date: Wed, 17 Jun 2026 15:18:53 -0400 Subject: [PATCH] fixed compile errors --- .../boot/dts/qcom/qcom-ipq4019-tew-829dru.dts | 57 ++--- .../712-net-ipqess-dual-gmac-tew829dru.patch | 213 ++++++++++++++++++ 2 files changed, 243 insertions(+), 27 deletions(-) create mode 100644 target/linux/ipq40xx/patches-6.12/712-net-ipqess-dual-gmac-tew829dru.patch diff --git a/target/linux/ipq40xx/files-6.12/arch/arm/boot/dts/qcom/qcom-ipq4019-tew-829dru.dts b/target/linux/ipq40xx/files-6.12/arch/arm/boot/dts/qcom/qcom-ipq4019-tew-829dru.dts index ad2f381753..202a38c79c 100644 --- a/target/linux/ipq40xx/files-6.12/arch/arm/boot/dts/qcom/qcom-ipq4019-tew-829dru.dts +++ b/target/linux/ipq40xx/files-6.12/arch/arm/boot/dts/qcom/qcom-ipq4019-tew-829dru.dts @@ -51,6 +51,8 @@ &gmac { status = "okay"; phy-mode = "internal"; + /* dual-GMAC: RRD port-id 5 = GMAC1 = QCA8337 switch */ + qcom,gmac1-port = <5>; fixed-link { speed = <1000>; full-duplex; @@ -167,7 +169,6 @@ label = "cpu"; ethernet = <&gmac>; /* side-by-side: ALSO points to EDMA, not to swport5 */ phy-mode = "rgmii"; - tag-protocol = "none"; fixed-link { speed = <1000>; full-duplex; @@ -186,8 +187,8 @@ label = "lan5"; phy-mode = "internal"; phy-handle = <&qca8337_phy1>; - }; + }; port@3 { reg = <3>; label = "lan6"; @@ -308,10 +309,11 @@ /* start of &nand (Micron MT29F1G08ABADA NAND 128MB) */ &nand { - status = "okay"; /* was "disabled" in your WIP — enable it! */ + status = "disabled"; /* DISABLED WHILE FIGURING OUT SWITCH CONFIG */ + /delete-property/ pinctrl-0; + /delete-property/ pinctrl-names; - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; + /* REMOVED PINCTRL - NO CONFLICT PLS */ nand@0 { reg = <0>; @@ -365,14 +367,14 @@ &tlmm { nand_pins { - nand-state { - /* removed GPIO53, conflict resolved. */ - pins = "gpio55", "gpio56", "gpio57", "gpio58", - "gpio59", "gpio60", "gpio62", "gpio63", "gpio64", - "gpio65", "gpio66", "gpio67", "gpio68", "gpio69"; - function = "qpic"; - }; - }; + nand-state { + pins = "gpio53", "gpio55", "gpio56", "gpio57", "gpio58", + "gpio59", "gpio60", "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", "gpio68", "gpio69"; + function = "qpic"; + bias-disable; + }; + }; /* Add this GPIO Hog for USB Power */ usb_power_en: usb-power-en { @@ -382,20 +384,21 @@ line-name = "usb-power-enable"; }; - mdio_pins: mdio_pinmux { - pinmux_1 { - pins = "gpio53"; - function = "mdio"; - }; - pinmux_2 { - pins = "gpio52"; - function = "mdc"; - }; - pinconf { - pins = "gpio52", "gpio53"; - bias-pull-up; - }; - }; + + mdio_pins: mdio_pinmux { + pinmux_1 { + pins = "gpio53"; + function = "mdio"; + }; + pinmux_2 { + pins = "gpio52"; + function = "mdc"; + }; + pinconf { + pins = "gpio52", "gpio53"; + bias-pull-up; + }; + }; /* pinmux / gpios */ diff --git a/target/linux/ipq40xx/patches-6.12/712-net-ipqess-dual-gmac-tew829dru.patch b/target/linux/ipq40xx/patches-6.12/712-net-ipqess-dual-gmac-tew829dru.patch new file mode 100644 index 0000000000..1d6c85fe2e --- /dev/null +++ b/target/linux/ipq40xx/patches-6.12/712-net-ipqess-dual-gmac-tew829dru.patch @@ -0,0 +1,213 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: OpenWrt Developer +Date: Mon, 01 Jan 2024 00:00:00 +0000 +Subject: [PATCH] net: ipqess: add dual-GMAC support for TEW-829DRU + +The TRENDnet TEW-829DRU has two switches connected to the IPQ4019 ESS: + - GMAC0 -> QCA8075 (5-port switch, ports 0-4) + - GMAC1 -> QCA8337 (7-port switch, port 5 in RRD) + +Both GMACs share the single EDMA hardware block. This patch adds an +optional second net_device (netdev2) that is created when the DT node +contains the property "qcom,gmac1-port". Incoming packets are demuxed +in ipqess_rx_poll() using the RRD port-id field; outgoing packets from +either netdev share the same TX rings. + +The second interface's MAC address is read from a DT node referenced by +"qcom,gmac1-netdev", or derived automatically from the primary MAC by +eth_hw_addr_gen() if that phandle is absent. + +Signed-off-by: OpenWrt Developer +--- + .../net/ethernet/qualcomm/ipqess/ipqess.c | 97 +++++++++++++++++-- + .../net/ethernet/qualcomm/ipqess/ipqess.h | 5 + + 2 files changed, 96 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.h ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.h +@@ -238,6 +238,9 @@ struct ipqess { + struct net_device *netdev; + struct platform_device *pdev; + ++ /* second netdev for dual-GMAC (e.g. TEW-829DRU QCA8337 switch) */ ++ struct net_device *netdev2; ++ + struct ipqess_rx_ring rx_ring[IPQESS_NETDEV_QUEUES]; + struct ipqess_tx_ring tx_ring[IPQESS_NETDEV_QUEUES]; + struct ipqess_rx_ring_refill rx_refill[IPQESS_NETDEV_QUEUES]; +@@ -259,6 +262,8 @@ struct ipqess { + struct notifier_block netdev_notifier; + int dsa_ports; + ++ int gmac1_port; /* RRD port-id of GMAC1 (0 = disabled) */ ++ + struct ipqess_statistics ipqess_stats; + spinlock_t stats_lock; + struct net_device_stats stats; +--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -28,6 +28,8 @@ + #include "ipqess.h" + ++#define IPQESS_GMAC1_PORT_DEFAULT 5 ++ + #define IPQESS_RRD_SIZE 16 + #define IPQESS_NEXT_IDX(X, Y) (((X) + 1) & ((Y) - 1)) + #define IPQESS_TX_DMA_BUF_LEN 0x3fff +@@ -155,7 +157,9 @@ static int ipqess_rx_buf_alloc(struct ipqess_rx_ring *rx_ring) + { + struct ipqess_buf *buf = &rx_ring->buf[rx_ring->head]; + +- buf->skb = netdev_alloc_skb_ip_align(rx_ring->ess->netdev, ++ buf->skb = netdev_alloc_skb_ip_align(rx_ring->ess->netdev2 ? ++ rx_ring->ess->netdev2 : ++ rx_ring->ess->netdev, + IPQESS_RX_HEAD_BUFF_SIZE); + + if (!buf->skb) +@@ -236,6 +240,7 @@ static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget) + while (done < budget) { + struct dsa_oob_tag_info *tag_info; + struct ipqess_rx_desc *rd; ++ struct net_device *rx_netdev; + struct sk_buff *skb; + + if (rx_ring_tail == tail) +@@ -281,8 +286,22 @@ static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget) + } + +- skb->dev = rx_ring->ess->netdev; +- skb->protocol = eth_type_trans(skb, rx_ring->ess->netdev); ++ /* Demux RX to netdev2 if this packet arrived on the GMAC1 ++ * port (QCA8337 side on dual-switch boards like TEW-829DRU). ++ * The RRD port-id field lives in rrd1 bits [14:12]. ++ */ ++ if (rx_ring->ess->netdev2 && rx_ring->ess->gmac1_port && ++ (FIELD_GET(IPQESS_RRD_PORT_ID_MASK, ++ le16_to_cpu(rd->rrd1)) == ++ rx_ring->ess->gmac1_port)) { ++ rx_netdev = rx_ring->ess->netdev2; ++ } else { ++ rx_netdev = rx_ring->ess->netdev; ++ } ++ ++ skb->dev = rx_netdev; ++ skb->protocol = eth_type_trans(skb, rx_netdev); + skb_record_rx_queue(skb, rx_ring->ring_id); + + if (rd->rrd6 & cpu_to_le16(IPQESS_RRD_CSUM_FAIL_MASK)) +@@ -303,8 +322,8 @@ static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget) + napi_gro_receive(&rx_ring->napi_rx, skb); + +- rx_ring->ess->stats.rx_packets++; +- rx_ring->ess->stats.rx_bytes += length; ++ rx_netdev->stats.rx_packets++; ++ rx_netdev->stats.rx_bytes += length; + + done++; + skip: +@@ -479,6 +498,23 @@ static int ipqess_netdevice_event(struct notifier_block *nb, + struct ipqess *ess = container_of(nb, struct ipqess, netdev_notifier); + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info; ++ struct net_device *tracked; ++ ++ /* Track DSA upper devices on both netdev and netdev2 */ ++ tracked = dev; ++ if (tracked != ess->netdev && ++ !(ess->netdev2 && tracked == ess->netdev2)) ++ return NOTIFY_DONE; + +- if (dev != ess->netdev) +- return NOTIFY_DONE; ++ if (tracked != ess->netdev && !(ess->netdev2 && tracked == ess->netdev2)) ++ return NOTIFY_DONE; + + switch (event) { + case NETDEV_CHANGEUPPER: +@@ -648,6 +684,8 @@ static int ipqess_axi_probe(struct platform_device *pdev) + struct device_node *np = pdev->dev.of_node; + struct net_device *netdev; + phy_interface_t phy_mode; ++ struct net_device *netdev2 = NULL; ++ struct device_node *np2; + struct ipqess *ess; + int i, err = 0; + +@@ -737,6 +775,57 @@ static int ipqess_axi_probe(struct platform_device *pdev) + if (err) + goto err_notifier_unregister; + ++ /* ------------------------------------------------------------------ * ++ * Optional second netdev for dual-GMAC boards (e.g. TEW-829DRU). * ++ * Activated by DT property "qcom,gmac1-port" on the ESS node. * ++ * That u32 value is the RRD port-id that identifies packets arriving * ++ * from GMAC1 (the QCA8337 switch). A phandle "qcom,gmac1-netdev" * ++ * may point to a DT node carrying the MAC address; if absent the * ++ * address is derived from the primary interface via eth_hw_addr_gen. * ++ * ------------------------------------------------------------------ */ ++ if (!of_property_read_u32(np, "qcom,gmac1-port", &ess->gmac1_port)) { ++ dev_info(&pdev->dev, ++ "dual-GMAC mode: GMAC1 RRD port-id = %u\n", ++ ess->gmac1_port); ++ ++ netdev2 = devm_alloc_etherdev_mqs(&pdev->dev, 0, ++ IPQESS_NETDEV_QUEUES, ++ IPQESS_NETDEV_QUEUES); ++ if (!netdev2) { ++ err = -ENOMEM; ++ goto err_notifier_unregister; ++ } ++ ++ /* Both netdevs share the same HW TX rings via ipqess_xmit */ ++ netdev2->netdev_ops = &ipqess_axi_netdev_ops; ++ netdev2->features = netdev->features; ++ netdev2->hw_features = 0; ++ netdev2->vlan_features = netdev->vlan_features; ++ netdev2->watchdog_timeo = netdev->watchdog_timeo; ++ netdev2->base_addr = netdev->base_addr; ++ netdev2->max_mtu = netdev->max_mtu; ++ netdev2->gso_max_segs = netdev->gso_max_segs; ++ SET_NETDEV_DEV(netdev2, &pdev->dev); ++ ++ /* MAC address: prefer explicit DT node, else auto-derive */ ++ np2 = of_parse_phandle(np, "qcom,gmac1-netdev", 0); ++ if (np2) { ++ if (of_get_ethdev_address(np2, netdev2)) { ++ eth_hw_addr_random(netdev2); ++ dev_info(&pdev->dev, ++ "gmac1: using random MAC %pM\n", ++ netdev2->dev_addr); ++ } ++ of_node_put(np2); ++ } else { ++ eth_hw_addr_gen(netdev2, netdev->dev_addr, 1); ++ } ++ ++ ipqess_set_ethtool_ops(netdev2); ++ ess->netdev2 = netdev2; ++ ++ err = register_netdev(netdev2); ++ if (err) { ++ dev_err(&pdev->dev, ++ "failed to register gmac1 netdev: %d\n", err); ++ ess->netdev2 = NULL; ++ /* non-fatal: primary interface still works */ ++ } ++ } ++ + dev_set_threaded(netdev, true); + + return 0; +@@ -801,6 +840,11 @@ static void ipqess_axi_remove(struct platform_device *pdev) + const struct net_device *netdev = platform_get_drvdata(pdev); + struct ipqess *ess = netdev_priv(netdev); + ++ if (ess->netdev2) { ++ unregister_netdev(ess->netdev2); ++ ess->netdev2 = NULL; ++ } ++ + unregister_netdev(ess->netdev); + ipqess_hw_stop(ess); + \ No newline at end of file