From 7c27c1b7b32b9a7e8c2b07354f8d8f1ae7953ef6 Mon Sep 17 00:00:00 2001 From: Zhi Li Date: Tue, 7 Jul 2026 14:41:30 +0800 Subject: [PATCH 1/4] dt-bindings: ethernet: eswin: relax internal delay model to range-based constraints Relax internal delay constraints for EIC7700 Ethernet binding. Replace fixed enumeration of rx-internal-delay-ps and tx-internal-delay-ps with a range-based definition (0-2540 ps, 20 ps steps) to reflect actual hardware capability. Mark rx/tx internal delay properties as optional, as they are board- specific tuning parameters rather than mandatory configuration. Update the device tree example to align with the relaxed constraint model and remove delay properties from the example to avoid implying they are required. No functional change to existing DT users. Reviewed-by: Rob Herring (Arm) Signed-off-by: Zhi Li Link: https://patch.msgid.link/20260707064131.1282-1-lizhi2@eswincomputing.com Signed-off-by: Paolo Abeni --- .../bindings/net/eswin,eic7700-eth.yaml | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml index 65882ff79d8d..4e02fedae5c6 100644 --- a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml +++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml @@ -63,10 +63,14 @@ properties: - const: stmmaceth rx-internal-delay-ps: - enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400] + minimum: 0 + maximum: 2540 + multipleOf: 20 tx-internal-delay-ps: - enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400] + minimum: 0 + maximum: 2540 + multipleOf: 20 eswin,hsp-sp-csr: description: @@ -105,8 +109,6 @@ required: - phy-mode - resets - reset-names - - rx-internal-delay-ps - - tx-internal-delay-ps - eswin,hsp-sp-csr unevaluatedProperties: false @@ -116,23 +118,22 @@ examples: ethernet@50400000 { compatible = "eswin,eic7700-qos-eth", "snps,dwmac-5.20"; reg = <0x50400000 0x10000>; - clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>, - <&d0_clock 193>; - clock-names = "axi", "cfg", "stmmaceth", "tx"; interrupt-parent = <&plic>; interrupts = <61>; interrupt-names = "macirq"; - phy-mode = "rgmii-id"; - phy-handle = <&phy0>; + clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>, + <&d0_clock 193>; + clock-names = "axi", "cfg", "stmmaceth", "tx"; resets = <&reset 95>; reset-names = "stmmaceth"; - rx-internal-delay-ps = <200>; - tx-internal-delay-ps = <200>; eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118 0x114 0x11c>; - snps,axi-config = <&stmmac_axi_setup>; + phy-handle = <&phy0>; + phy-mode = "rgmii-id"; snps,aal; snps,fixed-burst; snps,tso; + snps,axi-config = <&stmmac_axi_setup>; + stmmac_axi_setup: stmmac-axi-config { snps,blen = <0 0 0 0 16 8 4>; snps,rd_osr_lmt = <2>; From 3c6dfb86db07534ee34fa834c51d3608df4af197 Mon Sep 17 00:00:00 2001 From: Zhi Li Date: Tue, 7 Jul 2026 14:41:59 +0800 Subject: [PATCH 2/4] dt-bindings: ethernet: eswin: add EIC7700 eth1 RX clock inversion variant The EIC7700 SoC integrates two GMAC instances. The eth1 MAC exhibits different RX clock sampling characteristics due to silicon-inherent timing behavior. The eth1 MAC has a fixed, non-configurable RX clock-to-data skew at the MAC input in the order of 4-5 ns. This cannot be compensated solely by the standard MAC internal delay configuration and PHY delay, and RX clock inversion is required at 1000Mbps for correct sampling. The eth1 TX path also includes a fixed silicon-inherent delay of approximately 2 ns. This delay is always present and cannot be disabled. It is therefore part of the effective transmit timing observed on the wire. For the eth1 variant, the valid tx-internal-delay-ps values include this fixed delay component. Consequently, the effective range becomes 2000-4540 ps (approximately 2000 ps fixed delay plus 0-2540 ps programmable delay). Introduce a dedicated compatible string "eswin,eic7700-qos-eth-clk-inversion" to represent the eth1 variant, allowing the driver to apply RX clock inversion only when required by hardware variant selection. This keeps SoC-level differentiation without exposing silicon-fixed skew as configurable device tree parameters. To reflect this, model the TX internal delay as a base 0-4540 ps range, and constrain valid values per compatible using conditional schema rules. Update the binding schema as follows: - Define tx-internal-delay-ps as a base range: 0-4540 ps - Add compatible-specific constraints using if/then rules: * eswin,eic7700-qos-eth: max 2540 ps * eswin,eic7700-qos-eth-clk-inversion: minimum 2000 ps (effective range 2000-4540 ps) No functional change for existing "eswin,eic7700-qos-eth" users. Acked-by: Conor Dooley Signed-off-by: Zhi Li Link: https://patch.msgid.link/20260707064159.1299-1-lizhi2@eswincomputing.com Signed-off-by: Paolo Abeni --- .../bindings/net/eswin,eic7700-eth.yaml | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml index 4e02fedae5c6..ba49fd6a086c 100644 --- a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml +++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml @@ -20,16 +20,37 @@ select: contains: enum: - eswin,eic7700-qos-eth + - eswin,eic7700-qos-eth-clk-inversion required: - compatible allOf: - $ref: snps,dwmac.yaml# + - if: + properties: + compatible: + contains: + const: eswin,eic7700-qos-eth + then: + properties: + tx-internal-delay-ps: + maximum: 2540 + - if: + properties: + compatible: + contains: + const: eswin,eic7700-qos-eth-clk-inversion + then: + properties: + tx-internal-delay-ps: + minimum: 2000 properties: compatible: items: - - const: eswin,eic7700-qos-eth + - enum: + - eswin,eic7700-qos-eth + - eswin,eic7700-qos-eth-clk-inversion - const: snps,dwmac-5.20 reg: @@ -69,7 +90,7 @@ properties: tx-internal-delay-ps: minimum: 0 - maximum: 2540 + maximum: 4540 multipleOf: 20 eswin,hsp-sp-csr: @@ -140,3 +161,29 @@ examples: snps,wr_osr_lmt = <2>; }; }; + + ethernet@50410000 { + compatible = "eswin,eic7700-qos-eth-clk-inversion", "snps,dwmac-5.20"; + reg = <0x50410000 0x10000>; + interrupt-parent = <&plic>; + interrupts = <70>; + interrupt-names = "macirq"; + clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>, + <&d0_clock 194>; + clock-names = "axi", "cfg", "stmmaceth", "tx"; + resets = <&reset 94>; + reset-names = "stmmaceth"; + eswin,hsp-sp-csr = <&hsp_sp_csr 0x200 0x208 0x218 0x214 0x21c>; + phy-handle = <&gmac1_phy0>; + phy-mode = "rgmii-id"; + snps,aal; + snps,fixed-burst; + snps,tso; + snps,axi-config = <&stmmac_axi_setup_gmac1>; + + stmmac_axi_setup_gmac1: stmmac-axi-config { + snps,blen = <0 0 0 0 16 8 4>; + snps,rd_osr_lmt = <2>; + snps,wr_osr_lmt = <2>; + }; + }; From 186f38935e28ae700b0fe062dcc6ab345211dcee Mon Sep 17 00:00:00 2001 From: Zhi Li Date: Tue, 7 Jul 2026 14:42:17 +0800 Subject: [PATCH 3/4] net: stmmac: eic7700: make RGMII delay properties optional Make rx-internal-delay-ps and tx-internal-delay-ps optional in the EIC7700 DWMAC driver. The driver previously required both properties to be present and would fail probe when they were missing. This restricts valid hardware configurations where RGMII timing is instead provided by the PHY or board design. Update the driver to treat missing delay properties as zero delay, allowing systems without explicit MAC-side delay tuning to operate correctly. This aligns the driver behavior with the updated device tree binding and provides a safe default configuration when MAC-side delay programming is not required. Signed-off-by: Zhi Li Link: https://patch.msgid.link/20260707064218.1316-1-lizhi2@eswincomputing.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c index 4ac979d874d6..ec99b597aeaf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c @@ -165,9 +165,6 @@ static int eic7700_dwmac_probe(struct platform_device *pdev) dwc_priv->eth_clk_dly_param &= ~EIC7700_ETH_RX_ADJ_DELAY; dwc_priv->eth_clk_dly_param |= FIELD_PREP(EIC7700_ETH_RX_ADJ_DELAY, val); - } else { - return dev_err_probe(&pdev->dev, -EINVAL, - "missing required property rx-internal-delay-ps\n"); } /* Read tx-internal-delay-ps and update tx_clk delay */ @@ -187,9 +184,6 @@ static int eic7700_dwmac_probe(struct platform_device *pdev) dwc_priv->eth_clk_dly_param &= ~EIC7700_ETH_TX_ADJ_DELAY; dwc_priv->eth_clk_dly_param |= FIELD_PREP(EIC7700_ETH_TX_ADJ_DELAY, val); - } else { - return dev_err_probe(&pdev->dev, -EINVAL, - "missing required property tx-internal-delay-ps\n"); } dwc_priv->eic7700_hsp_regmap = From 0cb57bdebd101da07587e7f43d9473af826dd527 Mon Sep 17 00:00:00 2001 From: Zhi Li Date: Tue, 7 Jul 2026 14:42:32 +0800 Subject: [PATCH 4/4] net: stmmac: eic7700: add support for eth1 clock inversion variant The eth1 MAC exhibits silicon-inherent RX and TX timing behavior that differs from the eth0 implementation. At 1000Mbps, RX sampling requires clock inversion due to a fixed MAC input skew that cannot be compensated by standard RGMII delay settings. The TX path includes a fixed ~2ns internal delay introduced by the MAC silicon. This delay is always present and is already accounted for in the device tree tx-internal-delay-ps property as part of the effective output timing. The tx-internal-delay-ps property describes the effective delay seen at the MAC output. Since the hardware register controls only the programmable portion of the delay, the driver subtracts the fixed silicon-inherent component before programming the delay register. Use compatible-specific match data to identify the eth1 variant and apply RX clock inversion only at 1000Mbps. The PHY interface mode is adjusted via phy_fix_phy_mode_for_mac_delays() to avoid double-application of RGMII delays when MAC-side delays are already present. Link speed dependency means RX sampling configuration is applied in the fix_mac_speed callback after negotiation. No behavior changes for the existing eth0 controller. Signed-off-by: Zhi Li Link: https://patch.msgid.link/20260707064234.1333-1-lizhi2@eswincomputing.com Signed-off-by: Paolo Abeni --- .../ethernet/stmicro/stmmac/dwmac-eic7700.c | 111 ++++++++++++++++-- 1 file changed, 103 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c index ec99b597aeaf..eab8c13fbdcc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c @@ -28,11 +28,15 @@ /* * TX/RX Clock Delay Bit Masks: - * - TX Delay: bits [14:8] — TX_CLK delay (unit: 0.02ns per bit) - * - RX Delay: bits [30:24] — RX_CLK delay (unit: 0.02ns per bit) + * - TX Delay: bits [14:8] - TX_CLK delay (unit: 0.02ns per bit) + * - TX Invert : bit [15] + * - RX Delay: bits [30:24] - RX_CLK delay (unit: 0.02ns per bit) + * - RX Invert : bit [31] */ #define EIC7700_ETH_TX_ADJ_DELAY GENMASK(14, 8) #define EIC7700_ETH_RX_ADJ_DELAY GENMASK(30, 24) +#define EIC7700_ETH_TX_INV_DELAY BIT(15) +#define EIC7700_ETH_RX_INV_DELAY BIT(31) #define EIC7700_MAX_DELAY_STEPS 0x7F #define EIC7700_DELAY_STEP_PS 20 @@ -43,7 +47,14 @@ static const char * const eic7700_clk_names[] = { "tx", "axi", "cfg", }; +struct eic7700_dwmac_data { + bool rgmii_rx_clk_invert; + bool has_internal_tx_delay; + u32 tx_clk_inherent_skew_ps; +}; + struct eic7700_qos_priv { + struct device *dev; struct plat_stmmacenet_data *plat_dat; struct regmap *eic7700_hsp_regmap; u32 eth_axi_lp_ctrl_offset; @@ -54,6 +65,7 @@ struct eic7700_qos_priv { u32 eth_clk_dly_param; bool has_txd_offset; bool has_rxd_offset; + bool eth_rx_clk_inv; }; static int eic7700_clks_config(void *priv, bool enabled) @@ -97,9 +109,6 @@ static int eic7700_dwmac_init(struct device *dev, void *priv) if (dwc->has_rxd_offset) regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_rxd_offset, 0); - regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_clk_offset, - dwc->eth_clk_dly_param); - return 0; } @@ -126,8 +135,38 @@ static int eic7700_dwmac_resume(struct device *dev, void *priv) return ret; } +/* + * eth1 requires RX clock inversion at 1000Mbps due to silicon-inherent + * RX sampling skew at MAC input. + * + * The configuration is updated in fix_mac_speed() because the required + * sampling behavior depends on the negotiated link speed. + */ +static void eic7700_dwmac_fix_speed(void *priv, phy_interface_t interface, + int speed, unsigned int mode) +{ + struct eic7700_qos_priv *dwc = (struct eic7700_qos_priv *)priv; + u32 dly_param = dwc->eth_clk_dly_param; + + switch (speed) { + case SPEED_1000: + if (dwc->eth_rx_clk_inv) + dly_param |= EIC7700_ETH_RX_INV_DELAY; + break; + case SPEED_100: + case SPEED_10: + break; + default: + dev_warn(dwc->dev, "unsupported speed %u\n", speed); + return; + } + + regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_clk_offset, dly_param); +} + static int eic7700_dwmac_probe(struct platform_device *pdev) { + const struct eic7700_dwmac_data *data; struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct eic7700_qos_priv *dwc_priv; @@ -148,6 +187,30 @@ static int eic7700_dwmac_probe(struct platform_device *pdev) if (!dwc_priv) return -ENOMEM; + dwc_priv->dev = &pdev->dev; + + data = device_get_match_data(&pdev->dev); + if (!data) + return dev_err_probe(&pdev->dev, + -EINVAL, "no match data found\n"); + + dwc_priv->eth_rx_clk_inv = data->rgmii_rx_clk_invert; + /* + * The MAC silicon unconditionally adds ~2 ns TX delay; prevent + * the PHY from also adding TX delay to avoid doubling it. + * + * DT specifies rgmii-id (TX from MAC silicon, RX from PHY); + * override to rgmii-rxid so the PHY only adds its RX delay. + */ + if (data->has_internal_tx_delay) { + plat_dat->phy_interface = + phy_fix_phy_mode_for_mac_delays(plat_dat->phy_interface, + true, false); + if (plat_dat->phy_interface == PHY_INTERFACE_MODE_NA) + return dev_err_probe(&pdev->dev, -EINVAL, + "phy interface mode is NA\n"); + } + /* Read rx-internal-delay-ps and update rx_clk delay */ if (!of_property_read_u32(pdev->dev.of_node, "rx-internal-delay-ps", &delay_ps)) { @@ -167,7 +230,13 @@ static int eic7700_dwmac_probe(struct platform_device *pdev) FIELD_PREP(EIC7700_ETH_RX_ADJ_DELAY, val); } - /* Read tx-internal-delay-ps and update tx_clk delay */ + /* Read tx-internal-delay-ps and update tx_clk delay. + * + * For eswin,eic7700-qos-eth-clk-inversion, the DT property describes + * the effective TX delay at the MAC output, including the inherent + * silicon delay. Subtract the fixed component to obtain the + * programmable delay value. + */ if (!of_property_read_u32(pdev->dev.of_node, "tx-internal-delay-ps", &delay_ps)) { if (delay_ps % EIC7700_DELAY_STEP_PS) @@ -175,9 +244,16 @@ static int eic7700_dwmac_probe(struct platform_device *pdev) "tx delay must be multiple of %dps\n", EIC7700_DELAY_STEP_PS); + if (delay_ps < data->tx_clk_inherent_skew_ps) + return dev_err_probe(&pdev->dev, -EINVAL, + "tx delay %ups below inherent skew %ups\n", + delay_ps, data->tx_clk_inherent_skew_ps); + + delay_ps -= data->tx_clk_inherent_skew_ps; + if (delay_ps > EIC7700_MAX_DELAY_PS) return dev_err_probe(&pdev->dev, -EINVAL, - "tx delay out of range\n"); + "tx delay out of programmable range\n"); val = delay_ps / EIC7700_DELAY_STEP_PS; @@ -254,12 +330,31 @@ static int eic7700_dwmac_probe(struct platform_device *pdev) plat_dat->exit = eic7700_dwmac_exit; plat_dat->suspend = eic7700_dwmac_suspend; plat_dat->resume = eic7700_dwmac_resume; + plat_dat->fix_mac_speed = eic7700_dwmac_fix_speed; return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); } +static const struct eic7700_dwmac_data eic7700_dwmac_data = { + .rgmii_rx_clk_invert = false, + .has_internal_tx_delay = false, + .tx_clk_inherent_skew_ps = 0, +}; + +static const struct eic7700_dwmac_data eic7700_dwmac_data_clk_inversion = { + .rgmii_rx_clk_invert = true, + .has_internal_tx_delay = true, + .tx_clk_inherent_skew_ps = 2000, +}; + static const struct of_device_id eic7700_dwmac_match[] = { - { .compatible = "eswin,eic7700-qos-eth" }, + { .compatible = "eswin,eic7700-qos-eth", + .data = &eic7700_dwmac_data, + }, + { + .compatible = "eswin,eic7700-qos-eth-clk-inversion", + .data = &eic7700_dwmac_data_clk_inversion, + }, { } }; MODULE_DEVICE_TABLE(of, eic7700_dwmac_match);