mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
To: Coia Prant <coiaprant@gmail.com>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Heiko Stuebner <heiko@sntech.de>, Vinod Koul <vkoul@kernel.org>,
	Maxime Coquelin <mcoquelin.stm32@gmail.com>,
	Alexandre Torgue <alexandre.torgue@foss.st.com>,
	Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>,
	Romain Gantois <romain.gantois@bootlin.com>,
	Heiner Kallweit <hkallweit1@gmail.com>
Cc: Neil Armstrong <neil.armstrong@linaro.org>,
	Russell King <linux@armlinux.org.uk>,
	Shawn Lin <shawn.lin@rock-chips.com>,
	David Heidelberg <david@ixit.cz>,
	netdev@vger.kernel.org, linux-rockchip@lists.infradead.org,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org,
	linux-stm32@st-md-mailman.stormreply.com,
	linux-renesas-soc@vger.kernel.org
Subject: Re: [PATCH net-next v8 09/11] net: stmmac: dwmac-rk: add SGMII support for RK3568
Date: Sat, 19 Sep 2026 17:27:00 +0200	[thread overview]
Message-ID: <fd6612bc-a7fd-407a-869a-8660f8fcc3a7@bootlin.com> (raw)
In-Reply-To: <20260919125119.2107089-10-coiaprant@gmail.com>

Hi,

On 9/19/26 14:51, Coia Prant wrote:
> The RK3568 SoC integrates a Synopsys DesignWare XPCS that can be
> connected to GMAC0 or GMAC1 in SGMII mode.  Add the necessary glue
> logic to support this configuration.
> 
> The current dwmac-rk driver does not support SGMII mode.  SGMII
> requires a PCS to handle auto-negotiation and link state reporting,
> but the existing driver only supports RGMII and RMII.
> 
> Add a set_to_sgmii() callback to configure the GMAC GRF register for
> SGMII mode (bit 7 set, interface selection bits 4:6 ignored when set).
> Also add a set_to_rmii() callback for rk3568 to explicitly clear bit 7,
> since the new SGMII path leaves it set and the RMII branch previously
> relied on the SoC reset value.
> 
> Provide pcs_init/pcs_exit callbacks to create/destroy the XPCS via
> xpcs_rk_create() from the Rockchip XPCS platform driver, and a
> select_pcs callback to return the XPCS to phylink. SGMII is not added
> to rk_get_interfaces(): it comes from the XPCS's own
> supported_interfaces, merged by stmmac_phylink_setup().
> 
> The SerDes PHY and the PD_PIPE power domain are owned by the XPCS
> driver rather than managed through the stmmac
> serdes_poweron/serdes_poweroff callbacks, which are legacy and meant
> for single-MAC platforms. On RK3568 the XPCS is the natural owner of
> the shared SerDes.
> 
> DWMAC_ROCKCHIP selects PCS_XPCS_ROCKCHIP. PCS_XPCS itself is already
> selected by STMMAC_ETH, and PM is selected by ARCH_ROCKCHIP, so no
> further selects are needed.
> 
> Reorder rk_gmac_powerup() so that gmac_clk_enable() is called before
> the SGMII check.  The SGMII path skips rk_get_phy_intf_sel(), so the
> clock must be enabled earlier to cover all register accesses in that
> path.  While at it, unify the error unwinding into a single
> clk_disable label and add error handling for the default (unhandled
> interface) case.
> 
> SGMII In-band vs Out-of-band
> ============================
> On RK3568, the MAC clock is fixed at 125 MHz and cannot be dynamically
> changed by the stmmac core's set_clk_tx_rate callback.  In-band mode
> works because the PCS handles rate adaptation internally.  Out-of-band
> mode does not work because the MAC would need to change the clock rate
> to 125/12.5/1.25 MHz for 1000/100/10 Mbps respectively, and the clock
> is fixed.
> 
> Enable default_an_inband for SGMII and disable the generic stmmac
> set_clk_tx_rate callback.  This forces phylink to use in-band mode,
> where the PCS is responsible for speed/duplex negotiation.
> 
> Note that default_an_inband can be overridden by a fixed-link node,
> and phylink may also fall back to out-of-band if the PHY does not
> support in-band signalling.  Out-of-band SGMII is not supported by
> this driver: the MAC clock would stay at 125 MHz for 10/100 Mbps,
> giving working TX but failing RX.  Boards must use in-band mode
> (managed = "in-band-status" or an in-band capable PHY).
> 
> Link: https://dl.radxa.com/rock3/docs/hw/datasheet/Rockchip%20RK3568%20TRM%20Part1%20V1.1-20210301.pdf (Page 386)
> Signed-off-by: Coia Prant <coiaprant@gmail.com>

Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com

Maxime

> ---
>  drivers/net/ethernet/stmicro/stmmac/Kconfig   |   1 +
>  .../net/ethernet/stmicro/stmmac/dwmac-rk.c    | 130 +++++++++++++++---
>  2 files changed, 111 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index e3dd5adda5aca..5088acc06982e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -170,6 +170,7 @@ config DWMAC_ROCKCHIP
>  	default ARCH_ROCKCHIP
>  	depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
>  	select MFD_SYSCON
> +	select PCS_XPCS_ROCKCHIP
>  	help
>  	  Support for Ethernet controller on Rockchip RK3288 SoC.
>  
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> index 8d7042e689261..88f09014e3a69 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> @@ -20,6 +20,7 @@
>  #include <linux/delay.h>
>  #include <linux/mfd/syscon.h>
>  #include <linux/regmap.h>
> +#include <linux/pcs/pcs-xpcs-rk.h>
>  #include <linux/pm_runtime.h>
>  
>  #include "stmmac_platform.h"
> @@ -47,6 +48,7 @@ struct rk_gmac_ops {
>  	void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
>  			     int tx_delay, int rx_delay);
>  	void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
> +	void (*set_to_sgmii)(struct rk_priv_data *bsp_priv);
>  	int (*set_speed)(struct rk_priv_data *bsp_priv,
>  			 phy_interface_t interface, int speed);
>  	void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
> @@ -63,6 +65,7 @@ struct rk_gmac_ops {
>  	bool clock_grf_reg_in_php;
>  	bool supports_rgmii;
>  	bool supports_rmii;
> +	bool supports_sgmii;
>  	bool php_grf_required;
>  	bool regs_valid;
>  	u32 regs[];
> @@ -98,6 +101,7 @@ struct rk_priv_data {
>  	bool integrated_phy;
>  	bool supports_rgmii;
>  	bool supports_rmii;
> +	bool supports_sgmii;
>  
>  	struct clk_bulk_data *clks;
>  	int num_clks;
> @@ -809,6 +813,8 @@ static const struct rk_gmac_ops rk3528_ops = {
>  #define RK3568_GRF_GMAC1_CON1		0x038c
>  
>  /* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
> +#define RK3568_GMAC_MODE_RMII_RGMII		GRF_CLR_BIT(7)
> +#define RK3568_GMAC_MODE_SGMII_QSGMII		GRF_BIT(7)
>  #define RK3568_GMAC_FLOW_CTRL			GRF_BIT(3)
>  #define RK3568_GMAC_FLOW_CTRL_CLR		GRF_CLR_BIT(3)
>  #define RK3568_GMAC_RXCLK_DLY_ENABLE		GRF_BIT(1)
> @@ -836,6 +842,16 @@ static int rk3568_init(struct rk_priv_data *bsp_priv)
>  	}
>  }
>  
> +static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv)
> +{
> +	u32 con1;
> +
> +	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				     RK3568_GRF_GMAC0_CON1;
> +
> +	regmap_write(bsp_priv->grf, con1, RK3568_GMAC_MODE_RMII_RGMII);
> +}
> +
>  static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
>  				int tx_delay, int rx_delay)
>  {
> @@ -851,19 +867,31 @@ static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
>  		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
>  
>  	regmap_write(bsp_priv->grf, con1,
> +		     RK3568_GMAC_MODE_RMII_RGMII |
>  		     RK3568_GMAC_RXCLK_DLY_ENABLE |
>  		     RK3568_GMAC_TXCLK_DLY_ENABLE);
>  }
>  
> +static void rk3568_set_to_sgmii(struct rk_priv_data *bsp_priv)
> +{
> +	u32 con1;
> +
> +	con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				     RK3568_GRF_GMAC0_CON1;
> +
> +	regmap_write(bsp_priv->grf, con1, RK3568_GMAC_MODE_SGMII_QSGMII);
> +}
> +
>  static const struct rk_gmac_ops rk3568_ops = {
>  	.init = rk3568_init,
> +	.set_to_rmii = rk3568_set_to_rmii,
>  	.set_to_rgmii = rk3568_set_to_rgmii,
> +	.set_to_sgmii = rk3568_set_to_sgmii,
> +
>  	.set_speed = rk_set_clk_mac_speed,
>  
>  	.gmac_phy_intf_sel_mask = GENMASK_U16(6, 4),
>  
> -	.supports_rmii = true,
> -
>  	.regs_valid = true,
>  	.regs = {
>  		0xfe2a0000, /* gmac0 */
> @@ -1208,6 +1236,43 @@ static void rk_phy_powerdown(struct rk_priv_data *bsp_priv)
>  		dev_err(bsp_priv->dev, "fail to disable phy-supply\n");
>  }
>  
> +static int rk_pcs_init(struct stmmac_priv *priv)
> +{
> +	struct device_node *np = priv->device->of_node;
> +	struct device_node *pcs_node;
> +	struct dw_xpcs *xpcs;
> +
> +	pcs_node = of_parse_phandle(np, "pcs-handle", 0);
> +	if (!pcs_node)
> +		return -ENODEV;
> +
> +	xpcs = xpcs_rk_create(priv->device, pcs_node);
> +	of_node_put(pcs_node);
> +	if (IS_ERR(xpcs))
> +		return PTR_ERR(xpcs);
> +
> +	priv->hw->xpcs = xpcs;
> +	return 0;
> +}
> +
> +static void rk_pcs_exit(struct stmmac_priv *priv)
> +{
> +	if (!priv->hw->xpcs)
> +		return;
> +
> +	xpcs_destroy(priv->hw->xpcs);
> +	priv->hw->xpcs = NULL;
> +}
> +
> +static struct phylink_pcs *rk_select_pcs(struct stmmac_priv *priv,
> +					 phy_interface_t interface)
> +{
> +	if (!priv->hw->xpcs)
> +		return NULL;
> +
> +	return xpcs_to_phylink_pcs(priv->hw->xpcs);
> +}
> +
>  static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
>  					  struct plat_stmmacenet_data *plat,
>  					  const struct rk_gmac_ops *ops)
> @@ -1330,6 +1395,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
>  
>  	bsp_priv->supports_rgmii = ops->supports_rgmii || !!ops->set_to_rgmii;
>  	bsp_priv->supports_rmii = ops->supports_rmii || !!ops->set_to_rmii;
> +	bsp_priv->supports_sgmii = ops->supports_sgmii || !!ops->set_to_sgmii;
>  
>  	if (ops->init) {
>  		ret = ops->init(bsp_priv);
> @@ -1361,6 +1427,10 @@ static int rk_gmac_check_ops(struct rk_priv_data *bsp_priv)
>  		if (!bsp_priv->supports_rmii)
>  			return -EINVAL;
>  		break;
> +	case PHY_INTERFACE_MODE_SGMII:
> +		if (!bsp_priv->supports_sgmii)
> +			return -EINVAL;
> +		break;
>  	default:
>  		dev_err(bsp_priv->dev,
>  			"unsupported interface %d", bsp_priv->phy_iface);
> @@ -1379,16 +1449,19 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
>  	if (ret)
>  		return ret;
>  
> +	ret = gmac_clk_enable(bsp_priv, true);
> +	if (ret)
> +		return ret;
> +
> +	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_SGMII)
> +		goto set_mode;
> +
>  	ret = rk_get_phy_intf_sel(bsp_priv->phy_iface);
>  	if (ret < 0)
> -		return ret;
> +		goto clk_disable;
>  
>  	intf = ret;
>  
> -	ret = gmac_clk_enable(bsp_priv, true);
> -	if (ret)
> -		return ret;
> -
>  	if (bsp_priv->gmac_phy_intf_sel_mask ||
>  	    bsp_priv->gmac_rmii_mode_mask) {
>  		/* If defined, encode the phy_intf_sel value */
> @@ -1399,10 +1472,8 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
>  				      bsp_priv->gmac_rmii_mode_mask);
>  
>  		ret = rk_write_gmac_grf_reg(bsp_priv, val);
> -		if (ret < 0) {
> -			gmac_clk_enable(bsp_priv, false);
> -			return ret;
> -		}
> +		if (ret < 0)
> +			goto clk_disable;
>  	}
>  
>  	if (bsp_priv->clock.rmii_mode_mask) {
> @@ -1410,13 +1481,12 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
>  				     bsp_priv->clock.rmii_mode_mask);
>  
>  		ret = rk_write_clock_grf_reg(bsp_priv, val);
> -		if (ret < 0) {
> -			gmac_clk_enable(bsp_priv, false);
> -			return ret;
> -		}
> +		if (ret < 0)
> +			goto clk_disable;
>  	}
>  
> -	/*rmii or rgmii*/
> +set_mode:
> +	/* rmii, rgmii, sgmii */
>  	switch (bsp_priv->phy_iface) {
>  	case PHY_INTERFACE_MODE_RGMII:
>  		dev_info(dev, "init for RGMII\n");
> @@ -1447,15 +1517,20 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
>  		if (bsp_priv->ops->set_to_rmii)
>  			bsp_priv->ops->set_to_rmii(bsp_priv);
>  		break;
> +	case PHY_INTERFACE_MODE_SGMII:
> +		dev_info(dev, "init for SGMII\n");
> +		if (bsp_priv->ops->set_to_sgmii)
> +			bsp_priv->ops->set_to_sgmii(bsp_priv);
> +		break;
>  	default:
>  		dev_err(dev, "NO interface defined!\n");
> +		ret = -EINVAL;
> +		goto clk_disable;
>  	}
>  
>  	ret = rk_phy_powerup(bsp_priv);
> -	if (ret) {
> -		gmac_clk_enable(bsp_priv, false);
> -		return ret;
> -	}
> +	if (ret)
> +		goto clk_disable;
>  
>  	pm_runtime_get_sync(dev);
>  
> @@ -1463,6 +1538,10 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
>  		bsp_priv->ops->integrated_phy_powerup(bsp_priv);
>  
>  	return 0;
> +
> +clk_disable:
> +	gmac_clk_enable(bsp_priv, false);
> +	return ret;
>  }
>  
>  static void rk_gmac_powerdown(struct rk_priv_data *gmac)
> @@ -1602,6 +1681,17 @@ static int rk_gmac_probe(struct platform_device *pdev)
>  	plat_dat->suspend = rk_gmac_suspend;
>  	plat_dat->resume = rk_gmac_resume;
>  
> +	if (plat_dat->phy_interface == PHY_INTERFACE_MODE_SGMII) {
> +		/* SGMII clock always runs at 125 MHz */
> +		plat_dat->set_clk_tx_rate = NULL;
> +
> +		/* SGMII requires a PCS */
> +		plat_dat->default_an_inband = true;
> +		plat_dat->pcs_init = rk_pcs_init;
> +		plat_dat->pcs_exit = rk_pcs_exit;
> +		plat_dat->select_pcs = rk_select_pcs;
> +	}
> +
>  	plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data);
>  	if (IS_ERR(plat_dat->bsp_priv))
>  		return PTR_ERR(plat_dat->bsp_priv);


  reply	other threads:[~2026-09-19 15:27 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19 12:51 [PATCH net-next v8 00/11] net: pcs: add basic support for RK3568 XPCS Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 01/11] net: stmmac: move XPCS lifetime management to platform drivers Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 02/11] dt-bindings: phy: rockchip: naneng-combphy: add rockchip,sgmii-mac-sel property Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 03/11] phy: rockchip: naneng-combphy: add SGMII MAC selection for RK3568 Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 04/11] dt-bindings: net: pcs: add rockchip,rk3568-xpcs support Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 05/11] arm64: dts: rockchip: rk3568: add XPCS and fixed-clock nodes Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 06/11] net: pcs: xpcs: add ANRESTART support for SGMII link recovery Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 07/11] net: pcs: xpcs: add Rockchip RK3568 platform glue driver Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 08/11] dt-bindings: net: rockchip-dwmac: document pcs-handle Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 09/11] net: stmmac: dwmac-rk: add SGMII support for RK3568 Coia Prant
2026-09-19 15:27   ` Maxime Chevallier [this message]
2026-09-19 12:51 ` [PATCH net-next v8 10/11] arm64: dts: rockchip: rk3568-photonicat: enable SGMII LAN port Coia Prant
2026-09-19 12:51 ` [PATCH net-next v8 11/11] MAINTAINERS: add entry for Rockchip XPCS driver Coia Prant

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fd6612bc-a7fd-407a-869a-8660f8fcc3a7@bootlin.com \
    --to=maxime.chevallier@bootlin.com \
    --cc=alexandre.torgue@foss.st.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=coiaprant@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=davem@davemloft.net \
    --cc=david@ixit.cz \
    --cc=devicetree@vger.kernel.org \
    --cc=edumazet@google.com \
    --cc=heiko@sntech.de \
    --cc=hkallweit1@gmail.com \
    --cc=krzk+dt@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=linux-stm32@st-md-mailman.stormreply.com \
    --cc=linux@armlinux.org.uk \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=neil.armstrong@linaro.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
    --cc=robh@kernel.org \
    --cc=romain.gantois@bootlin.com \
    --cc=shawn.lin@rock-chips.com \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®