* [RFC PATCH] net: stmmac: dwmac-generic: add ACPI support for Phytium FT-2000/4 and D2000
@ 2026-08-11 3:56 yueqiang_fan
0 siblings, 0 replies; 3+ messages in thread
From: yueqiang_fan @ 2026-08-11 3:56 UTC (permalink / raw)
To: netdev; +Cc: Alexandre Torgue, Giuseppe Cavallaro, Jose Abreu,
linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 2515 bytes --]
Hi all,
The Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that
is exposed to ACPI as "FTGM0001" / "PHYT0004". The generic dwmac
platform driver only supports DT and legacy platform data, so on ACPI
(UEFI) firmware the MACs are never probed and there is no network
device. Kylin ships a vendor patch for this; this RFC proposes an
upstream version.
Patch (also available at):
https://github.com/Bitllion/phytium-d2000-netfix/blob/main/upstream/0001-net-stmmac-dwmac-generic-ACPI-support-for-Phytium.patch
Summary of the change to drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c:
- Add an ACPI device ID table (FTGM0001 / PHYT0004).
- Add dwmac_generic_acpi_probe_config(): mirrors the generic
"snps,dwmac" DT defaults, with values from the vendor (Kylin)
firmware DTB:
* phy-mode rgmii-txid. Both SoC MACs share the same two RTL8211F
PHYs on a common MDIO wiring (each bus sees both PHYs at addr 0
and 7), so pin each MAC to its own PHY address (0 for instance
:00, 7 for :01) instead of scanning.
* single DMA channel (dwmac1000-compatible core): use one TX/RX
queue. The netdev is always allocated with MTL_MAX_TX/RX_QUEUES
queues, but the per-queue DMA arrays are only set up for
tx/rx_queues_to_use queues and stmmac_xmit() has no
queue >= tx_queues_to_use guard. With real_num_tx_queues = 1,
stmmac_select_queue() reduces every frame to queue 0, so the
missing guard is never hit.
* has_gmac (dwmac1000 hwif; the dwmac4 hwif fails MDIO on this
core), AXI burst lengths 16/8/4, pbl 16 with fixed burst, FIFO
sizes 0x1000.
- All values can be overridden through ACPI _DSD properties
(phy-mode, phy-addr, tx/rx-queues-to-use, snps,pbl).
Tested on a Phytium D2000 board (JWIPC IF24TH01) with Ubuntu 24.04 /
kernel 6.8.0: both MACs probe (PHYT0004:00/01), interfaces
enaphyt4i0/1 are created, and cable link-up + DHCP work with no
transmit watchdog and no kernel panic.
Two questions for the list:
1. Is an ACPI match table + hardcoded platform defaults acceptable for
dwmac-generic, or would a separate dwmac-phytium.c (like
dwmac-intel.c) be preferred?
2. The missing queue >= tx_queues_to_use guard in stmmac_xmit() looks
like a generic bug (regression since 6.8 removed the guard; any
dwmac platform with tx_queues_to_use < 8 can dereference NULL
tx_skbuff on non-GSO frames hashed to a high queue). Should I
prepare a separate fix for stmmac_main.c?
Signed-off-by: Yueqiang Fan <yueqiang_fan@foxmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-net-stmmac-dwmac-generic-ACPI-support-for-Phytium.patch --]
[-- Type: text/x-patch, Size: 7142 bytes --]
From: Yueqiang Fan <yueqiang_fan@foxmail.com>
Subject: [PATCH] net: stmmac: dwmac-generic: add ACPI support for Phytium
FT-2000/4 and D2000
The Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that
is exposed to ACPI as "FTGM0001" / "PHYT0004". The generic dwmac
platform driver only supports DT and legacy platform data, so on ACPI
(UEFI) firmware the MACs are never probed and there is no network
device.
Add an ACPI device ID table plus a probe configuration path that
mirrors the generic "snps,dwmac" DT defaults, using the values from the
vendor (Kylin) firmware DTB for eth@2820c000 / eth@28210000:
- phy-mode rgmii-txid. Both SoC MACs share the same two RTL8211F PHYs
on a common MDIO wiring (each bus sees both PHYs at addr 0 and 7), so
pin each MAC to its own PHY address instead of scanning: 0 for ACPI
instance :00, 7 for :01.
- single DMA channel (dwmac1000-compatible core): use one TX/RX queue.
The netdev is always allocated with MTL_MAX_TX/RX_QUEUES queues, but
the per-queue DMA arrays are only set up for tx/rx_queues_to_use
queues and stmmac_xmit() does not guard queue >= tx_queues_to_use.
With real_num_tx_queues set to 1, stmmac_select_queue() reduces every
frame to queue 0 so the missing guard is never hit.
- has_gmac (dwmac1000 hwif; the dwmac4 hwif fails MDIO on this core),
AXI burst lengths 16/8/4, pbl 16 with fixed burst, FIFO sizes 0x1000.
All values can be overridden through ACPI _DSD properties
(phy-mode, phy-addr, tx/rx-queues-to-use, snps,pbl).
Tested on a Phytium D2000 board (JWIPC IF24TH01) with Ubuntu 24.04 /
kernel 6.8.0: both MACs probe (PHYT0004:00/01), interfaces enaphyt4i0/1
are created, and cable link-up + DHCP work with no transmit watchdog
and no kernel panic. The default single-queue configuration avoids the
NULL tx_skbuff dereference in stmmac_xmit() that the stock multi-queue
defaults trigger on this hardware.
Signed-off-by: Yueqiang Fan <yueqiang_fan@foxmail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 97 +++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -12,10 +12,107 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/phy.h>
+#include <linux/property.h>
#include "stmmac.h"
#include "stmmac_platform.h"
+/*
+ * Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that is
+ * exposed to ACPI as "FTGM0001" / "PHYT0004". There is no upstream ACPI
+ * support for the generic dwmac platform driver, so provide the
+ * configuration that the generic "snps,dwmac" DT path would produce,
+ * with the values taken from the vendor (Kylin) firmware DTB for the
+ * eth@2820c000 / eth@28210000 nodes.
+ *
+ * Platform facts:
+ * - phy-mode is rgmii-txid; both MACs share the same two RTL8211F PHYs
+ * on a common MDIO wiring (each bus sees both PHYs, at addr 0 and 7),
+ * so pin each MAC to its own PHY address (0 for instance :00, 7 for
+ * :01) instead of scanning.
+ * - the MAC is a dwmac1000-compatible core with a single DMA channel:
+ * use one TX/RX queue. The netdev is always allocated with
+ * MTL_MAX_TX/RX_QUEUES queues but the per-queue DMA arrays are only
+ * set up for tx/rx_queues_to_use queues, and stmmac_xmit() does not
+ * guard queue >= tx_queues_to_use. With real_num_tx_queues set to 1,
+ * stmmac_select_queue() reduces every frame to queue 0, so the
+ * missing guard is never hit.
+ * - do not enable has_gmac4: despite dwmac4-style capability registers
+ * the MDIO registers are dwmac1000-compatible.
+ *
+ * All values may be overridden through ACPI _DSD properties.
+ */
+static int dwmac_generic_acpi_probe_config(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ struct device *dev = &pdev->dev;
+ struct stmmac_dma_cfg *dma_cfg;
+ struct stmmac_axi *axi;
+ const char *phy_mode;
+
+ plat->phy_interface = PHY_INTERFACE_MODE_RGMII_TXID;
+ if (!device_property_read_string(dev, "phy-mode", &phy_mode))
+ phy_interface_mode_from_string(&plat->phy_interface, phy_mode);
+
+ /* bus id from the ACPI instance: PHYT0004:00 -> 0, PHYT0004:01 -> 1 */
+ plat->bus_id = 0;
+ {
+ const char *nm = dev_name(dev);
+ const char *sep = nm ? strrchr(nm, ':') : NULL;
+ int id;
+
+ if (sep && !kstrtoint(sep + 1, 10, &id))
+ plat->bus_id = id;
+ }
+
+ plat->phy_addr = plat->bus_id ? 7 : 0;
+ device_property_read_u32(dev, "phy-addr", &plat->phy_addr);
+
+ plat->clk_csr = -1;
+ plat->maxmtu = JUMBO_LEN;
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+ plat->unicast_filter_entries = 128;
+ plat->has_gmac = 1;
+ plat->pmt = 1;
+
+ plat->tx_queues_to_use = 1;
+ plat->rx_queues_to_use = 1;
+ device_property_read_u32(dev, "tx-queues-to-use",
+ &plat->tx_queues_to_use);
+ device_property_read_u32(dev, "rx-queues-to-use",
+ &plat->rx_queues_to_use);
+
+ plat->force_sf_dma_mode = 1;
+ plat->tx_fifo_size = 0x1000;
+ plat->rx_fifo_size = 0x1000;
+
+ plat->mdio_bus_data = devm_kzalloc(dev, sizeof(*plat->mdio_bus_data),
+ GFP_KERNEL);
+ if (!plat->mdio_bus_data)
+ return -ENOMEM;
+ plat->mdio_bus_data->phy_mask = 0;
+
+ dma_cfg = devm_kzalloc(dev, sizeof(*dma_cfg), GFP_KERNEL);
+ if (!dma_cfg)
+ return -ENOMEM;
+ dma_cfg->pbl = 16;
+ dma_cfg->fixed_burst = 1;
+ device_property_read_u32(dev, "snps,pbl", &dma_cfg->pbl);
+ plat->dma_cfg = dma_cfg;
+
+ axi = devm_kzalloc(dev, sizeof(*axi), GFP_KERNEL);
+ if (!axi)
+ return -ENOMEM;
+ axi->axi_blen[4] = 16;
+ axi->axi_blen[5] = 8;
+ axi->axi_blen[6] = 4;
+ plat->axi = axi;
+
+ return 0;
+}
+
static int dwmac_generic_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
int ret;
@@ -29,6 +126,15 @@ static int dwmac_generic_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
+ } else if (has_acpi_companion(&pdev->dev)) {
+ plat_dat = devm_kzalloc(&pdev->dev, sizeof(*plat_dat),
+ GFP_KERNEL);
+ if (!plat_dat)
+ return -ENOMEM;
+
+ ret = dwmac_generic_acpi_probe_config(pdev, plat_dat);
+ if (ret)
+ return ret;
} else {
plat_dat = dev_get_platdata(&pdev->dev);
if (!plat_dat) {
dev_err(&pdev->dev, "no platform data provided\n");
@@ -52,6 +158,14 @@ static const struct of_device_id dwmac_generic_match[] = {
};
MODULE_DEVICE_TABLE(of, dwmac_generic_match);
+static const struct acpi_device_id dwmac_generic_acpi_match[] = {
+ { "FTGM0001", 0 },
+ { "PHYT0004", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, dwmac_generic_acpi_match);
+
static struct platform_driver dwmac_generic_driver = {
.probe = dwmac_generic_probe,
.driver = {
.name = STMMAC_RESOURCE_NAME,
.pm = &stmmac_pltfr_pm_ops,
.of_match_table = dwmac_generic_match,
+ .acpi_match_table = dwmac_generic_acpi_match,
},
};
module_platform_driver(dwmac_generic_driver);
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH] net: stmmac: dwmac-generic: add ACPI support for Phytium FT-2000/4 and D2000
@ 2026-08-11 3:56 yueqiang_fan
0 siblings, 0 replies; 3+ messages in thread
From: yueqiang_fan @ 2026-08-11 3:56 UTC (permalink / raw)
To: netdev; +Cc: Alexandre Torgue, Giuseppe Cavallaro, Jose Abreu,
linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 2515 bytes --]
Hi all,
The Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that
is exposed to ACPI as "FTGM0001" / "PHYT0004". The generic dwmac
platform driver only supports DT and legacy platform data, so on ACPI
(UEFI) firmware the MACs are never probed and there is no network
device. Kylin ships a vendor patch for this; this RFC proposes an
upstream version.
Patch (also available at):
https://github.com/Bitllion/phytium-d2000-netfix/blob/main/upstream/0001-net-stmmac-dwmac-generic-ACPI-support-for-Phytium.patch
Summary of the change to drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c:
- Add an ACPI device ID table (FTGM0001 / PHYT0004).
- Add dwmac_generic_acpi_probe_config(): mirrors the generic
"snps,dwmac" DT defaults, with values from the vendor (Kylin)
firmware DTB:
* phy-mode rgmii-txid. Both SoC MACs share the same two RTL8211F
PHYs on a common MDIO wiring (each bus sees both PHYs at addr 0
and 7), so pin each MAC to its own PHY address (0 for instance
:00, 7 for :01) instead of scanning.
* single DMA channel (dwmac1000-compatible core): use one TX/RX
queue. The netdev is always allocated with MTL_MAX_TX/RX_QUEUES
queues, but the per-queue DMA arrays are only set up for
tx/rx_queues_to_use queues and stmmac_xmit() has no
queue >= tx_queues_to_use guard. With real_num_tx_queues = 1,
stmmac_select_queue() reduces every frame to queue 0, so the
missing guard is never hit.
* has_gmac (dwmac1000 hwif; the dwmac4 hwif fails MDIO on this
core), AXI burst lengths 16/8/4, pbl 16 with fixed burst, FIFO
sizes 0x1000.
- All values can be overridden through ACPI _DSD properties
(phy-mode, phy-addr, tx/rx-queues-to-use, snps,pbl).
Tested on a Phytium D2000 board (JWIPC IF24TH01) with Ubuntu 24.04 /
kernel 6.8.0: both MACs probe (PHYT0004:00/01), interfaces
enaphyt4i0/1 are created, and cable link-up + DHCP work with no
transmit watchdog and no kernel panic.
Two questions for the list:
1. Is an ACPI match table + hardcoded platform defaults acceptable for
dwmac-generic, or would a separate dwmac-phytium.c (like
dwmac-intel.c) be preferred?
2. The missing queue >= tx_queues_to_use guard in stmmac_xmit() looks
like a generic bug (regression since 6.8 removed the guard; any
dwmac platform with tx_queues_to_use < 8 can dereference NULL
tx_skbuff on non-GSO frames hashed to a high queue). Should I
prepare a separate fix for stmmac_main.c?
Signed-off-by: Yueqiang Fan <yueqiang_fan@foxmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-net-stmmac-dwmac-generic-ACPI-support-for-Phytium.patch --]
[-- Type: text/x-patch, Size: 7142 bytes --]
From: Yueqiang Fan <yueqiang_fan@foxmail.com>
Subject: [PATCH] net: stmmac: dwmac-generic: add ACPI support for Phytium
FT-2000/4 and D2000
The Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that
is exposed to ACPI as "FTGM0001" / "PHYT0004". The generic dwmac
platform driver only supports DT and legacy platform data, so on ACPI
(UEFI) firmware the MACs are never probed and there is no network
device.
Add an ACPI device ID table plus a probe configuration path that
mirrors the generic "snps,dwmac" DT defaults, using the values from the
vendor (Kylin) firmware DTB for eth@2820c000 / eth@28210000:
- phy-mode rgmii-txid. Both SoC MACs share the same two RTL8211F PHYs
on a common MDIO wiring (each bus sees both PHYs at addr 0 and 7), so
pin each MAC to its own PHY address instead of scanning: 0 for ACPI
instance :00, 7 for :01.
- single DMA channel (dwmac1000-compatible core): use one TX/RX queue.
The netdev is always allocated with MTL_MAX_TX/RX_QUEUES queues, but
the per-queue DMA arrays are only set up for tx/rx_queues_to_use
queues and stmmac_xmit() does not guard queue >= tx_queues_to_use.
With real_num_tx_queues set to 1, stmmac_select_queue() reduces every
frame to queue 0 so the missing guard is never hit.
- has_gmac (dwmac1000 hwif; the dwmac4 hwif fails MDIO on this core),
AXI burst lengths 16/8/4, pbl 16 with fixed burst, FIFO sizes 0x1000.
All values can be overridden through ACPI _DSD properties
(phy-mode, phy-addr, tx/rx-queues-to-use, snps,pbl).
Tested on a Phytium D2000 board (JWIPC IF24TH01) with Ubuntu 24.04 /
kernel 6.8.0: both MACs probe (PHYT0004:00/01), interfaces enaphyt4i0/1
are created, and cable link-up + DHCP work with no transmit watchdog
and no kernel panic. The default single-queue configuration avoids the
NULL tx_skbuff dereference in stmmac_xmit() that the stock multi-queue
defaults trigger on this hardware.
Signed-off-by: Yueqiang Fan <yueqiang_fan@foxmail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 97 +++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -12,10 +12,107 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/phy.h>
+#include <linux/property.h>
#include "stmmac.h"
#include "stmmac_platform.h"
+/*
+ * Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that is
+ * exposed to ACPI as "FTGM0001" / "PHYT0004". There is no upstream ACPI
+ * support for the generic dwmac platform driver, so provide the
+ * configuration that the generic "snps,dwmac" DT path would produce,
+ * with the values taken from the vendor (Kylin) firmware DTB for the
+ * eth@2820c000 / eth@28210000 nodes.
+ *
+ * Platform facts:
+ * - phy-mode is rgmii-txid; both MACs share the same two RTL8211F PHYs
+ * on a common MDIO wiring (each bus sees both PHYs, at addr 0 and 7),
+ * so pin each MAC to its own PHY address (0 for instance :00, 7 for
+ * :01) instead of scanning.
+ * - the MAC is a dwmac1000-compatible core with a single DMA channel:
+ * use one TX/RX queue. The netdev is always allocated with
+ * MTL_MAX_TX/RX_QUEUES queues but the per-queue DMA arrays are only
+ * set up for tx/rx_queues_to_use queues, and stmmac_xmit() does not
+ * guard queue >= tx_queues_to_use. With real_num_tx_queues set to 1,
+ * stmmac_select_queue() reduces every frame to queue 0, so the
+ * missing guard is never hit.
+ * - do not enable has_gmac4: despite dwmac4-style capability registers
+ * the MDIO registers are dwmac1000-compatible.
+ *
+ * All values may be overridden through ACPI _DSD properties.
+ */
+static int dwmac_generic_acpi_probe_config(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ struct device *dev = &pdev->dev;
+ struct stmmac_dma_cfg *dma_cfg;
+ struct stmmac_axi *axi;
+ const char *phy_mode;
+
+ plat->phy_interface = PHY_INTERFACE_MODE_RGMII_TXID;
+ if (!device_property_read_string(dev, "phy-mode", &phy_mode))
+ phy_interface_mode_from_string(&plat->phy_interface, phy_mode);
+
+ /* bus id from the ACPI instance: PHYT0004:00 -> 0, PHYT0004:01 -> 1 */
+ plat->bus_id = 0;
+ {
+ const char *nm = dev_name(dev);
+ const char *sep = nm ? strrchr(nm, ':') : NULL;
+ int id;
+
+ if (sep && !kstrtoint(sep + 1, 10, &id))
+ plat->bus_id = id;
+ }
+
+ plat->phy_addr = plat->bus_id ? 7 : 0;
+ device_property_read_u32(dev, "phy-addr", &plat->phy_addr);
+
+ plat->clk_csr = -1;
+ plat->maxmtu = JUMBO_LEN;
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+ plat->unicast_filter_entries = 128;
+ plat->has_gmac = 1;
+ plat->pmt = 1;
+
+ plat->tx_queues_to_use = 1;
+ plat->rx_queues_to_use = 1;
+ device_property_read_u32(dev, "tx-queues-to-use",
+ &plat->tx_queues_to_use);
+ device_property_read_u32(dev, "rx-queues-to-use",
+ &plat->rx_queues_to_use);
+
+ plat->force_sf_dma_mode = 1;
+ plat->tx_fifo_size = 0x1000;
+ plat->rx_fifo_size = 0x1000;
+
+ plat->mdio_bus_data = devm_kzalloc(dev, sizeof(*plat->mdio_bus_data),
+ GFP_KERNEL);
+ if (!plat->mdio_bus_data)
+ return -ENOMEM;
+ plat->mdio_bus_data->phy_mask = 0;
+
+ dma_cfg = devm_kzalloc(dev, sizeof(*dma_cfg), GFP_KERNEL);
+ if (!dma_cfg)
+ return -ENOMEM;
+ dma_cfg->pbl = 16;
+ dma_cfg->fixed_burst = 1;
+ device_property_read_u32(dev, "snps,pbl", &dma_cfg->pbl);
+ plat->dma_cfg = dma_cfg;
+
+ axi = devm_kzalloc(dev, sizeof(*axi), GFP_KERNEL);
+ if (!axi)
+ return -ENOMEM;
+ axi->axi_blen[4] = 16;
+ axi->axi_blen[5] = 8;
+ axi->axi_blen[6] = 4;
+ plat->axi = axi;
+
+ return 0;
+}
+
static int dwmac_generic_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
int ret;
@@ -29,6 +126,15 @@ static int dwmac_generic_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
+ } else if (has_acpi_companion(&pdev->dev)) {
+ plat_dat = devm_kzalloc(&pdev->dev, sizeof(*plat_dat),
+ GFP_KERNEL);
+ if (!plat_dat)
+ return -ENOMEM;
+
+ ret = dwmac_generic_acpi_probe_config(pdev, plat_dat);
+ if (ret)
+ return ret;
} else {
plat_dat = dev_get_platdata(&pdev->dev);
if (!plat_dat) {
dev_err(&pdev->dev, "no platform data provided\n");
@@ -52,6 +158,14 @@ static const struct of_device_id dwmac_generic_match[] = {
};
MODULE_DEVICE_TABLE(of, dwmac_generic_match);
+static const struct acpi_device_id dwmac_generic_acpi_match[] = {
+ { "FTGM0001", 0 },
+ { "PHYT0004", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, dwmac_generic_acpi_match);
+
static struct platform_driver dwmac_generic_driver = {
.probe = dwmac_generic_probe,
.driver = {
.name = STMMAC_RESOURCE_NAME,
.pm = &stmmac_pltfr_pm_ops,
.of_match_table = dwmac_generic_match,
+ .acpi_match_table = dwmac_generic_acpi_match,
},
};
module_platform_driver(dwmac_generic_driver);
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH] net: stmmac: dwmac-generic: add ACPI support for Phytium FT-2000/4 and D2000
@ 2026-08-11 3:58 yueqiang_fan
0 siblings, 0 replies; 3+ messages in thread
From: yueqiang_fan @ 2026-08-11 3:58 UTC (permalink / raw)
To: netdev; +Cc: Alexandre Torgue, Giuseppe Cavallaro, Jose Abreu,
linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 2515 bytes --]
Hi all,
The Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that
is exposed to ACPI as "FTGM0001" / "PHYT0004". The generic dwmac
platform driver only supports DT and legacy platform data, so on ACPI
(UEFI) firmware the MACs are never probed and there is no network
device. Kylin ships a vendor patch for this; this RFC proposes an
upstream version.
Patch (also available at):
https://github.com/Bitllion/phytium-d2000-netfix/blob/main/upstream/0001-net-stmmac-dwmac-generic-ACPI-support-for-Phytium.patch
Summary of the change to drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c:
- Add an ACPI device ID table (FTGM0001 / PHYT0004).
- Add dwmac_generic_acpi_probe_config(): mirrors the generic
"snps,dwmac" DT defaults, with values from the vendor (Kylin)
firmware DTB:
* phy-mode rgmii-txid. Both SoC MACs share the same two RTL8211F
PHYs on a common MDIO wiring (each bus sees both PHYs at addr 0
and 7), so pin each MAC to its own PHY address (0 for instance
:00, 7 for :01) instead of scanning.
* single DMA channel (dwmac1000-compatible core): use one TX/RX
queue. The netdev is always allocated with MTL_MAX_TX/RX_QUEUES
queues, but the per-queue DMA arrays are only set up for
tx/rx_queues_to_use queues and stmmac_xmit() has no
queue >= tx_queues_to_use guard. With real_num_tx_queues = 1,
stmmac_select_queue() reduces every frame to queue 0, so the
missing guard is never hit.
* has_gmac (dwmac1000 hwif; the dwmac4 hwif fails MDIO on this
core), AXI burst lengths 16/8/4, pbl 16 with fixed burst, FIFO
sizes 0x1000.
- All values can be overridden through ACPI _DSD properties
(phy-mode, phy-addr, tx/rx-queues-to-use, snps,pbl).
Tested on a Phytium D2000 board (JWIPC IF24TH01) with Ubuntu 24.04 /
kernel 6.8.0: both MACs probe (PHYT0004:00/01), interfaces
enaphyt4i0/1 are created, and cable link-up + DHCP work with no
transmit watchdog and no kernel panic.
Two questions for the list:
1. Is an ACPI match table + hardcoded platform defaults acceptable for
dwmac-generic, or would a separate dwmac-phytium.c (like
dwmac-intel.c) be preferred?
2. The missing queue >= tx_queues_to_use guard in stmmac_xmit() looks
like a generic bug (regression since 6.8 removed the guard; any
dwmac platform with tx_queues_to_use < 8 can dereference NULL
tx_skbuff on non-GSO frames hashed to a high queue). Should I
prepare a separate fix for stmmac_main.c?
Signed-off-by: Yueqiang Fan <yueqiang_fan@foxmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-net-stmmac-dwmac-generic-ACPI-support-for-Phytium.patch --]
[-- Type: text/x-patch, Size: 7142 bytes --]
From: Yueqiang Fan <yueqiang_fan@foxmail.com>
Subject: [PATCH] net: stmmac: dwmac-generic: add ACPI support for Phytium
FT-2000/4 and D2000
The Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that
is exposed to ACPI as "FTGM0001" / "PHYT0004". The generic dwmac
platform driver only supports DT and legacy platform data, so on ACPI
(UEFI) firmware the MACs are never probed and there is no network
device.
Add an ACPI device ID table plus a probe configuration path that
mirrors the generic "snps,dwmac" DT defaults, using the values from the
vendor (Kylin) firmware DTB for eth@2820c000 / eth@28210000:
- phy-mode rgmii-txid. Both SoC MACs share the same two RTL8211F PHYs
on a common MDIO wiring (each bus sees both PHYs at addr 0 and 7), so
pin each MAC to its own PHY address instead of scanning: 0 for ACPI
instance :00, 7 for :01.
- single DMA channel (dwmac1000-compatible core): use one TX/RX queue.
The netdev is always allocated with MTL_MAX_TX/RX_QUEUES queues, but
the per-queue DMA arrays are only set up for tx/rx_queues_to_use
queues and stmmac_xmit() does not guard queue >= tx_queues_to_use.
With real_num_tx_queues set to 1, stmmac_select_queue() reduces every
frame to queue 0 so the missing guard is never hit.
- has_gmac (dwmac1000 hwif; the dwmac4 hwif fails MDIO on this core),
AXI burst lengths 16/8/4, pbl 16 with fixed burst, FIFO sizes 0x1000.
All values can be overridden through ACPI _DSD properties
(phy-mode, phy-addr, tx/rx-queues-to-use, snps,pbl).
Tested on a Phytium D2000 board (JWIPC IF24TH01) with Ubuntu 24.04 /
kernel 6.8.0: both MACs probe (PHYT0004:00/01), interfaces enaphyt4i0/1
are created, and cable link-up + DHCP work with no transmit watchdog
and no kernel panic. The default single-queue configuration avoids the
NULL tx_skbuff dereference in stmmac_xmit() that the stock multi-queue
defaults trigger on this hardware.
Signed-off-by: Yueqiang Fan <yueqiang_fan@foxmail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 97 +++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -12,10 +12,107 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/phy.h>
+#include <linux/property.h>
#include "stmmac.h"
#include "stmmac_platform.h"
+/*
+ * Phytium FT-2000/4 and D2000 SoCs integrate a DesignWare GMAC that is
+ * exposed to ACPI as "FTGM0001" / "PHYT0004". There is no upstream ACPI
+ * support for the generic dwmac platform driver, so provide the
+ * configuration that the generic "snps,dwmac" DT path would produce,
+ * with the values taken from the vendor (Kylin) firmware DTB for the
+ * eth@2820c000 / eth@28210000 nodes.
+ *
+ * Platform facts:
+ * - phy-mode is rgmii-txid; both MACs share the same two RTL8211F PHYs
+ * on a common MDIO wiring (each bus sees both PHYs, at addr 0 and 7),
+ * so pin each MAC to its own PHY address (0 for instance :00, 7 for
+ * :01) instead of scanning.
+ * - the MAC is a dwmac1000-compatible core with a single DMA channel:
+ * use one TX/RX queue. The netdev is always allocated with
+ * MTL_MAX_TX/RX_QUEUES queues but the per-queue DMA arrays are only
+ * set up for tx/rx_queues_to_use queues, and stmmac_xmit() does not
+ * guard queue >= tx_queues_to_use. With real_num_tx_queues set to 1,
+ * stmmac_select_queue() reduces every frame to queue 0, so the
+ * missing guard is never hit.
+ * - do not enable has_gmac4: despite dwmac4-style capability registers
+ * the MDIO registers are dwmac1000-compatible.
+ *
+ * All values may be overridden through ACPI _DSD properties.
+ */
+static int dwmac_generic_acpi_probe_config(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ struct device *dev = &pdev->dev;
+ struct stmmac_dma_cfg *dma_cfg;
+ struct stmmac_axi *axi;
+ const char *phy_mode;
+
+ plat->phy_interface = PHY_INTERFACE_MODE_RGMII_TXID;
+ if (!device_property_read_string(dev, "phy-mode", &phy_mode))
+ phy_interface_mode_from_string(&plat->phy_interface, phy_mode);
+
+ /* bus id from the ACPI instance: PHYT0004:00 -> 0, PHYT0004:01 -> 1 */
+ plat->bus_id = 0;
+ {
+ const char *nm = dev_name(dev);
+ const char *sep = nm ? strrchr(nm, ':') : NULL;
+ int id;
+
+ if (sep && !kstrtoint(sep + 1, 10, &id))
+ plat->bus_id = id;
+ }
+
+ plat->phy_addr = plat->bus_id ? 7 : 0;
+ device_property_read_u32(dev, "phy-addr", &plat->phy_addr);
+
+ plat->clk_csr = -1;
+ plat->maxmtu = JUMBO_LEN;
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+ plat->unicast_filter_entries = 128;
+ plat->has_gmac = 1;
+ plat->pmt = 1;
+
+ plat->tx_queues_to_use = 1;
+ plat->rx_queues_to_use = 1;
+ device_property_read_u32(dev, "tx-queues-to-use",
+ &plat->tx_queues_to_use);
+ device_property_read_u32(dev, "rx-queues-to-use",
+ &plat->rx_queues_to_use);
+
+ plat->force_sf_dma_mode = 1;
+ plat->tx_fifo_size = 0x1000;
+ plat->rx_fifo_size = 0x1000;
+
+ plat->mdio_bus_data = devm_kzalloc(dev, sizeof(*plat->mdio_bus_data),
+ GFP_KERNEL);
+ if (!plat->mdio_bus_data)
+ return -ENOMEM;
+ plat->mdio_bus_data->phy_mask = 0;
+
+ dma_cfg = devm_kzalloc(dev, sizeof(*dma_cfg), GFP_KERNEL);
+ if (!dma_cfg)
+ return -ENOMEM;
+ dma_cfg->pbl = 16;
+ dma_cfg->fixed_burst = 1;
+ device_property_read_u32(dev, "snps,pbl", &dma_cfg->pbl);
+ plat->dma_cfg = dma_cfg;
+
+ axi = devm_kzalloc(dev, sizeof(*axi), GFP_KERNEL);
+ if (!axi)
+ return -ENOMEM;
+ axi->axi_blen[4] = 16;
+ axi->axi_blen[5] = 8;
+ axi->axi_blen[6] = 4;
+ plat->axi = axi;
+
+ return 0;
+}
+
static int dwmac_generic_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
int ret;
@@ -29,6 +126,15 @@ static int dwmac_generic_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
+ } else if (has_acpi_companion(&pdev->dev)) {
+ plat_dat = devm_kzalloc(&pdev->dev, sizeof(*plat_dat),
+ GFP_KERNEL);
+ if (!plat_dat)
+ return -ENOMEM;
+
+ ret = dwmac_generic_acpi_probe_config(pdev, plat_dat);
+ if (ret)
+ return ret;
} else {
plat_dat = dev_get_platdata(&pdev->dev);
if (!plat_dat) {
dev_err(&pdev->dev, "no platform data provided\n");
@@ -52,6 +158,14 @@ static const struct of_device_id dwmac_generic_match[] = {
};
MODULE_DEVICE_TABLE(of, dwmac_generic_match);
+static const struct acpi_device_id dwmac_generic_acpi_match[] = {
+ { "FTGM0001", 0 },
+ { "PHYT0004", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, dwmac_generic_acpi_match);
+
static struct platform_driver dwmac_generic_driver = {
.probe = dwmac_generic_probe,
.driver = {
.name = STMMAC_RESOURCE_NAME,
.pm = &stmmac_pltfr_pm_ops,
.of_match_table = dwmac_generic_match,
+ .acpi_match_table = dwmac_generic_acpi_match,
},
};
module_platform_driver(dwmac_generic_driver);
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-11 3:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 3:56 [RFC PATCH] net: stmmac: dwmac-generic: add ACPI support for Phytium FT-2000/4 and D2000 yueqiang_fan
-- strict thread matches above, loose matches on Subject: below --
2026-08-11 3:56 yueqiang_fan
2026-08-11 3:58 yueqiang_fan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox