Re: [PATCH v2 2/2] net: stmmac: eic7700: enable clocks before syscon access and correct RX sampling timing
From: Andrew Lunn <andrew@lunn.ch>
Date: 2026-02-09 13:34:42
Also in:
linux-arm-kernel, linux-devicetree, lkml
static int eic7700_dwmac_init(struct device *dev, void *priv)
{
struct eic7700_qos_priv *dwc = priv;
+ u32 eth_phy_ctrl_regset;
+ int ret = 0;
+
+ ret = eic7700_clks_config(dwc, true);No point initialising ret if the first thing you do is assign to it.
+ if (ret) + return ret; + + regmap_read(dwc->eic7700_hsp_regmap, dwc->eth_phy_ctrl_offset, + ð_phy_ctrl_regset); + eth_phy_ctrl_regset |= + (EIC7700_ETH_TX_CLK_SEL | EIC7700_ETH_PHY_INTF_SELI); + regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_phy_ctrl_offset, + eth_phy_ctrl_regset);
regmap_set_bits(dwc->eic7700_hsp_regmap, dwc->eth_phy_ctrl_offset, EIC7700_ETH_TX_CLK_SEL | EIC7700_ETH_PHY_INTF_SELI);
+ regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_axi_lp_ctrl_offset, + EIC7700_ETH_CSYSREQ_VAL); + + regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_txd_offset, 0); + regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_rxd_offset, 0); - return eic7700_clks_config(dwc, true); + return ret;
returning ret here seems pointless. You already know it is 0.
quoted hunk ↗ jump to hunk
} static void eic7700_dwmac_exit(struct device *dev, void *priv)@@ -88,17 +124,33 @@ static int eic7700_dwmac_resume(struct device *dev, void *priv) return ret; } +static void eic7700_dwmac_fix_speed(void *priv, 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_err(dwc->dev, "invalid speed %u\n", speed); + break; + } + + 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; - struct regmap *eic7700_hsp_regmap; - u32 eth_axi_lp_ctrl_offset; - u32 eth_phy_ctrl_offset; - u32 eth_phy_ctrl_regset; - u32 eth_rxd_dly_offset; - u32 eth_dly_param = 0; u32 delay_ps; int i, ret;@@ -116,13 +168,23 @@ 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; + /* 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)) { - u32 val = min(delay_ps / 100, EIC7700_MAX_DELAY_UNIT); + u32 val = min(delay_ps / 20, EIC7700_MAX_DELAY_STEPS);
If the value it too big, please return -EINVAL. You have listed in the DT binding what the valid range is, not that you clamp to the maximum value.
- eth_dly_param &= ~EIC7700_ETH_RX_ADJ_DELAY;
- eth_dly_param |= FIELD_PREP(EIC7700_ETH_RX_ADJ_DELAY, val);
+ 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");
RX and TX internal delays are generally optional, because most boards
don't require them. Default to 0 if not supplied.
Andrew
---
pw-bot: cr