Merge branch 'net-stmmac-eic7700-add-eth1-variant-support-and-update-delay-bindings'

Zhi Li says:

====================
net: stmmac: eic7700: add eth1 variant support and update delay bindings

This series updates Ethernet support for the ESWIN EIC7700 SoC,
including support for the eth1 MAC variant.

The series includes DT binding updates and stmmac glue driver updates
for the EIC7700 Ethernet controller.

The changes include:
  - Update the tx-internal-delay-ps binding property from a fixed enum
    list to a range-based definition, and make it optional with the
    corresponding driver update.

  - Add support for the EIC7700 eth1 MAC variant, which has
    silicon-specific RX sampling behavior and TX timing characteristics.
    A dedicated compatible string is introduced for this hardware variant,
    and the driver applies the required RX clock inversion handling and
    timing adjustments.

Due to silicon characteristics, the eth1 interface has a fixed TX
internal delay of approximately 2 ns and an RX sampling skew of 4-5 ns
that cannot be compensated solely by standard RGMII delay settings.
The binding models the effective TX delay range of this variant, while
the driver handles the required hardware-specific timing configuration.

Only the DT bindings and driver patches are included in this series. The
DTS changes are intentionally omitted for the following reasons:
  - The HSP bus infrastructure is being introduced by Pinkesh Vaghela's
    DT series [0], currently under review.
  - The HSPCRG clock/reset series [1] provides additional infrastructure
    for the HSP subsystem.

Once these dependencies are merged, a follow-up DT series will enable
Ethernet, USB, eMMC, and SD across the HSP bus.

Reference:
  [0] https://lore.kernel.org/lkml/20260706081055.1126275-1-pinkesh.vaghela@einfochips.com/
  [1] https://lore.kernel.org/all/20260605060730.1605-1-dongxuyang@eswincomputing.com/
====================

Link: https://patch.msgid.link/20260707064033.1265-1-lizhi2@eswincomputing.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni
2026-07-21 09:06:04 +02:00
2 changed files with 164 additions and 27 deletions

View File

@@ -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:
@@ -63,10 +84,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: 4540
multipleOf: 20
eswin,hsp-sp-csr:
description:
@@ -105,8 +130,6 @@ required:
- phy-mode
- resets
- reset-names
- rx-internal-delay-ps
- tx-internal-delay-ps
- eswin,hsp-sp-csr
unevaluatedProperties: false
@@ -116,26 +139,51 @@ 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>;
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>;
};
};

View File

@@ -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)) {
@@ -165,12 +228,15 @@ 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 */
/* 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)
@@ -178,18 +244,22 @@ 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;
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 =
@@ -260,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);