Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 0/3] Disable CLKOUT on RTL8211F(D)(I)-VD-CG
@ 2025-11-06 11:10 Vladimir Oltean
  2025-11-06 11:10 ` [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable Vladimir Oltean
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Vladimir Oltean @ 2025-11-06 11:10 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Vasut, Wei Fang,
	Clark Wang

The Realtek RTL8211F(D)(I)-VD-CG is similar to other RTL8211F models in
that the CLKOUT signal can be turned off - a feature requested to reduce
EMI, and implemented via "realtek,clkout-disable" as documented in
Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml.

It is also dissimilar to said PHY models because it has no PHYCR2
register, and disabling CLKOUT is done through some other register.

The strategy adopted in this 3-patch series is to make the PHY driver
not think in terms of "priv->has_phycr2" and "priv->phycr2", but of more
high-level features ("priv->disable_clk_out") while maintaining behaviour.
Then, the logic is extended for the new PHY.

Very loosely based on previous work from Clark Wang, who took a
different approach, to pretend that the RTL8211FVD_CLKOUT_REG is
actually this PHY's PHYCR2.

Vladimir Oltean (3):
  net: phy: realtek: eliminate priv->phycr2 variable
  net: phy: realtek: eliminate has_phycr2 variable
  net: phy: realtek: allow CLKOUT to be disabled on RTL8211F(D)(I)-VD-CG

 drivers/net/phy/realtek/realtek_main.c | 60 ++++++++++++++++----------
 1 file changed, 37 insertions(+), 23 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable
  2025-11-06 11:10 [PATCH net-next 0/3] Disable CLKOUT on RTL8211F(D)(I)-VD-CG Vladimir Oltean
@ 2025-11-06 11:10 ` Vladimir Oltean
  2025-11-06 13:51   ` Andrew Lunn
  2025-11-06 11:10 ` [PATCH net-next 2/3] net: phy: realtek: eliminate has_phycr2 variable Vladimir Oltean
  2025-11-06 11:10 ` [PATCH net-next 3/3] net: phy: realtek: allow CLKOUT to be disabled on RTL8211F(D)(I)-VD-CG Vladimir Oltean
  2 siblings, 1 reply; 7+ messages in thread
From: Vladimir Oltean @ 2025-11-06 11:10 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Vasut, Wei Fang,
	Clark Wang

The RTL8211F(D)(I)-VD-CG PHY also has support for disabling the CLKOUT,
and we'd like to introduce the "realtek,clkout-disable" property for
that.

But it isn't done through the PHYCR2 register, and it becomes awkward to
have the driver pretend that it is. So just replace the machine-level
"u16 phycr2" variable with a logical "bool disable_clk_out", which
scales better to the other PHY as well.

The change is a complete functional equivalent. Before, if the device
tree property was absent, priv->phycr2 would contain the RTL8211F_CLKOUT_EN
bit as read from hardware. Now, we don't save priv->phycr2, but we just
don't call phy_modify_paged() on it. Also, we can simply call
phy_modify_paged() with the "set" argument to 0.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/realtek/realtek_main.c | 31 ++++++++++++++------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index 417f9a88aab6..45b53660018a 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -194,8 +194,8 @@ MODULE_LICENSE("GPL");
 
 struct rtl821x_priv {
 	u16 phycr1;
-	u16 phycr2;
 	bool has_phycr2;
+	bool disable_clk_out;
 	struct clk *clk;
 	/* rtl8211f */
 	u16 iner;
@@ -266,15 +266,8 @@ static int rtl821x_probe(struct phy_device *phydev)
 		priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF;
 
 	priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID);
-	if (priv->has_phycr2) {
-		ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2);
-		if (ret < 0)
-			return ret;
-
-		priv->phycr2 = ret & RTL8211F_CLKOUT_EN;
-		if (of_property_read_bool(dev->of_node, "realtek,clkout-disable"))
-			priv->phycr2 &= ~RTL8211F_CLKOUT_EN;
-	}
+	priv->disable_clk_out = of_property_read_bool(dev->of_node,
+						      "realtek,clkout-disable");
 
 	phydev->priv = priv;
 
@@ -587,6 +580,18 @@ static int rtl8211c_config_init(struct phy_device *phydev)
 			    CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER);
 }
 
+static int rtl8211f_disable_clk_out(struct phy_device *phydev)
+{
+	struct rtl821x_priv *priv = phydev->priv;
+
+	/* The value is preserved if the device tree property is absent */
+	if (!priv->disable_clk_out)
+		return 0;
+
+	return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE,
+				RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0);
+}
+
 static int rtl8211f_config_init(struct phy_device *phydev)
 {
 	struct rtl821x_priv *priv = phydev->priv;
@@ -669,10 +674,8 @@ static int rtl8211f_config_init(struct phy_device *phydev)
 	if (ret)
 		return ret;
 
-	ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE,
-			       RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN,
-			       priv->phycr2);
-	if (ret < 0) {
+	ret = rtl8211f_disable_clk_out(phydev);
+	if (ret) {
 		dev_err(dev, "clkout configuration failed: %pe\n",
 			ERR_PTR(ret));
 		return ret;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net-next 2/3] net: phy: realtek: eliminate has_phycr2 variable
  2025-11-06 11:10 [PATCH net-next 0/3] Disable CLKOUT on RTL8211F(D)(I)-VD-CG Vladimir Oltean
  2025-11-06 11:10 ` [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable Vladimir Oltean
@ 2025-11-06 11:10 ` Vladimir Oltean
  2025-11-06 13:52   ` Andrew Lunn
  2025-11-06 11:10 ` [PATCH net-next 3/3] net: phy: realtek: allow CLKOUT to be disabled on RTL8211F(D)(I)-VD-CG Vladimir Oltean
  2 siblings, 1 reply; 7+ messages in thread
From: Vladimir Oltean @ 2025-11-06 11:10 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Vasut, Wei Fang,
	Clark Wang

This variable is assigned in rtl821x_probe() and used in
rtl8211f_config_init(), which is more complex than it needs to be.
Simply testing the same condition from rtl821x_probe() in
rtl8211f_config_init() yields the same result (the PHY driver ID is a
runtime invariant), but with one temporary variable less.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/realtek/realtek_main.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index 45b53660018a..89cc54a7f270 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -194,7 +194,6 @@ MODULE_LICENSE("GPL");
 
 struct rtl821x_priv {
 	u16 phycr1;
-	bool has_phycr2;
 	bool disable_clk_out;
 	struct clk *clk;
 	/* rtl8211f */
@@ -245,7 +244,6 @@ static int rtl821x_probe(struct phy_device *phydev)
 {
 	struct device *dev = &phydev->mdio.dev;
 	struct rtl821x_priv *priv;
-	u32 phy_id = phydev->drv->phy_id;
 	int ret;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -265,7 +263,6 @@ static int rtl821x_probe(struct phy_device *phydev)
 	if (of_property_read_bool(dev->of_node, "realtek,aldps-enable"))
 		priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF;
 
-	priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID);
 	priv->disable_clk_out = of_property_read_bool(dev->of_node,
 						      "realtek,clkout-disable");
 
@@ -665,7 +662,8 @@ static int rtl8211f_config_init(struct phy_device *phydev)
 			str_enabled_disabled(val_rxdly));
 	}
 
-	if (!priv->has_phycr2)
+	/* RTL8211FVD has no PHYCR2 register */
+	if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
 		return 0;
 
 	/* Disable PHY-mode EEE so LPI is passed to the MAC */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net-next 3/3] net: phy: realtek: allow CLKOUT to be disabled on RTL8211F(D)(I)-VD-CG
  2025-11-06 11:10 [PATCH net-next 0/3] Disable CLKOUT on RTL8211F(D)(I)-VD-CG Vladimir Oltean
  2025-11-06 11:10 ` [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable Vladimir Oltean
  2025-11-06 11:10 ` [PATCH net-next 2/3] net: phy: realtek: eliminate has_phycr2 variable Vladimir Oltean
@ 2025-11-06 11:10 ` Vladimir Oltean
  2 siblings, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2025-11-06 11:10 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Vasut, Wei Fang,
	Clark Wang

Add CLKOUT disable support for RTL8211F(D)(I)-VD-CG. Like with other PHY
variants, this feature might be requested by customers when the clock
output is not used, in order to reduce electromagnetic interference (EMI).

In the common driver, the CLKOUT configuration is done through PHYCR2.
The RTL_8211FVD_PHYID is singled out as not having that register, and
execution in rtl8211f_config_init() returns early after commit
2c67301584f2 ("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not
present").

But actually CLKOUT is configured through a different register for this
PHY. Instead of pretending this is PHYCR2 (which it is not), just add
some code for modifying this register inside the rtl8211f_disable_clk_out()
function, and move that outside the code portion that runs only if
PHYCR2 exists.

In practice this reorders the PHYCR2 writes to disable PHY-mode EEE and
to disable the CLKOUT for the normal RTL8211F variants, but this should
be perfectly fine.

It was not noted that RTL8211F(D)(I)-VD-CG would need a genphy_soft_reset()
call after disabling the CLKOUT.

Co-developed-by: Clark Wang <xiaoning.wang@nxp.com>
Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index 89cc54a7f270..c7e54460b58d 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -90,6 +90,14 @@
 #define RTL8211F_LEDCR_MASK			GENMASK(4, 0)
 #define RTL8211F_LEDCR_SHIFT			5
 
+/* RTL8211F(D)(I)-VD-CG CLKOUT configuration is specified via magic values
+ * to undocumented register pages. The names here do not reflect the datasheet.
+ * Unlike other PHY models, CLKOUT configuration does not go through PHYCR2.
+ */
+#define RTL8211FVD_CLKOUT_PAGE			0xd05
+#define RTL8211FVD_CLKOUT_REG			0x11
+#define RTL8211FVD_CLKOUT_EN			BIT(8)
+
 /* RTL8211F RGMII configuration */
 #define RTL8211F_RGMII_PAGE			0xd08
 
@@ -585,6 +593,11 @@ static int rtl8211f_disable_clk_out(struct phy_device *phydev)
 	if (!priv->disable_clk_out)
 		return 0;
 
+	if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
+		return phy_modify_paged(phydev, RTL8211FVD_CLKOUT_PAGE,
+					RTL8211FVD_CLKOUT_REG,
+					RTL8211FVD_CLKOUT_EN, 0);
+
 	return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE,
 				RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0);
 }
@@ -662,6 +675,13 @@ static int rtl8211f_config_init(struct phy_device *phydev)
 			str_enabled_disabled(val_rxdly));
 	}
 
+	ret = rtl8211f_disable_clk_out(phydev);
+	if (ret) {
+		dev_err(dev, "clkout configuration failed: %pe\n",
+			ERR_PTR(ret));
+		return ret;
+	}
+
 	/* RTL8211FVD has no PHYCR2 register */
 	if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
 		return 0;
@@ -672,13 +692,6 @@ static int rtl8211f_config_init(struct phy_device *phydev)
 	if (ret)
 		return ret;
 
-	ret = rtl8211f_disable_clk_out(phydev);
-	if (ret) {
-		dev_err(dev, "clkout configuration failed: %pe\n",
-			ERR_PTR(ret));
-		return ret;
-	}
-
 	return genphy_soft_reset(phydev);
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable
  2025-11-06 11:10 ` [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable Vladimir Oltean
@ 2025-11-06 13:51   ` Andrew Lunn
  2025-11-06 14:47     ` Vladimir Oltean
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Lunn @ 2025-11-06 13:51 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Vasut, Wei Fang,
	Clark Wang

> +static int rtl8211f_disable_clk_out(struct phy_device *phydev)
> +{
> +	struct rtl821x_priv *priv = phydev->priv;
> +
> +	/* The value is preserved if the device tree property is absent */
> +	if (!priv->disable_clk_out)
> +		return 0;

The name rtl8211f_disable_clk_out() suggests that it is going to
disable the clock output. In fact it is conditional, and might not
actually do anything. Maybe move the condition outside? Or maybe
rename it to rtl8211f_config_clk_out()?

	Andrew

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net-next 2/3] net: phy: realtek: eliminate has_phycr2 variable
  2025-11-06 11:10 ` [PATCH net-next 2/3] net: phy: realtek: eliminate has_phycr2 variable Vladimir Oltean
@ 2025-11-06 13:52   ` Andrew Lunn
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Lunn @ 2025-11-06 13:52 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: netdev, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Vasut, Wei Fang,
	Clark Wang

On Thu, Nov 06, 2025 at 01:10:02PM +0200, Vladimir Oltean wrote:
> This variable is assigned in rtl821x_probe() and used in
> rtl8211f_config_init(), which is more complex than it needs to be.
> Simply testing the same condition from rtl821x_probe() in
> rtl8211f_config_init() yields the same result (the PHY driver ID is a
> runtime invariant), but with one temporary variable less.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable
  2025-11-06 13:51   ` Andrew Lunn
@ 2025-11-06 14:47     ` Vladimir Oltean
  0 siblings, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2025-11-06 14:47 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: netdev, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Marek Vasut, Wei Fang,
	Clark Wang

On Thu, Nov 06, 2025 at 02:51:12PM +0100, Andrew Lunn wrote:
> > +static int rtl8211f_disable_clk_out(struct phy_device *phydev)
> > +{
> > +	struct rtl821x_priv *priv = phydev->priv;
> > +
> > +	/* The value is preserved if the device tree property is absent */
> > +	if (!priv->disable_clk_out)
> > +		return 0;
> 
> The name rtl8211f_disable_clk_out() suggests that it is going to
> disable the clock output. In fact it is conditional, and might not
> actually do anything. Maybe move the condition outside? Or maybe
> rename it to rtl8211f_config_clk_out()?
> 
> 	Andrew

It was born out of a desire to keep the main control flow simpler.
Among the two alternatives, I would prefer to rename this function to
rtl8211f_config_clk_out().

Thanks for the review.

pw-bot: cr

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-11-06 14:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-06 11:10 [PATCH net-next 0/3] Disable CLKOUT on RTL8211F(D)(I)-VD-CG Vladimir Oltean
2025-11-06 11:10 ` [PATCH net-next 1/3] net: phy: realtek: eliminate priv->phycr2 variable Vladimir Oltean
2025-11-06 13:51   ` Andrew Lunn
2025-11-06 14:47     ` Vladimir Oltean
2025-11-06 11:10 ` [PATCH net-next 2/3] net: phy: realtek: eliminate has_phycr2 variable Vladimir Oltean
2025-11-06 13:52   ` Andrew Lunn
2025-11-06 11:10 ` [PATCH net-next 3/3] net: phy: realtek: allow CLKOUT to be disabled on RTL8211F(D)(I)-VD-CG Vladimir Oltean

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox