--- /dev/null
+From 0a4355c2b7f8ecd5e61cc262ecdbd4a2cce1ea7e Mon Sep 17 00:00:00 2001
+From: Joakim Zhang <qiangqing.zhang@nxp.com>
+Date: Tue, 8 Jun 2021 11:15:33 +0800
+Subject: [PATCH] net: phy: realtek: add dt property to disable CLKOUT clock
+
+CLKOUT is enabled by default after PHY hardware reset, this patch adds
+"realtek,clkout-disable" property for user to disable CLKOUT clock
+to save PHY power.
+
+Per RTL8211F guide, a PHY reset should be issued after setting these
+bits in PHYCR2 register. After this patch, CLKOUT clock output to be
+disabled.
+
+Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/realtek.c | 42 ++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 41 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/realtek.c
++++ b/drivers/net/phy/realtek.c
+@@ -8,6 +8,7 @@
+ * Copyright (c) 2004 Freescale Semiconductor, Inc.
+ */
+ #include <linux/bitops.h>
++#include <linux/of.h>
+ #include <linux/phy.h>
+ #include <linux/module.h>
+ #include <linux/delay.h>
+@@ -27,6 +28,7 @@
+ #define RTL821x_PAGE_SELECT 0x1f
+
+ #define RTL8211F_PHYCR1 0x18
++#define RTL8211F_PHYCR2 0x19
+ #define RTL8211F_INSR 0x1d
+
+ #define RTL8211F_TX_DELAY BIT(8)
+@@ -40,6 +42,8 @@
+ #define RTL8211E_TX_DELAY BIT(12)
+ #define RTL8211E_RX_DELAY BIT(11)
+
++#define RTL8211F_CLKOUT_EN BIT(0)
++
+ #define RTL8201F_ISR 0x1e
+ #define RTL8201F_IER 0x13
+
+@@ -62,6 +66,10 @@ MODULE_DESCRIPTION("Realtek PHY driver")
+ MODULE_AUTHOR("Johnson Leung");
+ MODULE_LICENSE("GPL");
+
++struct rtl821x_priv {
++ u16 phycr2;
++};
++
+ static int rtl821x_read_page(struct phy_device *phydev)
+ {
+ return __phy_read(phydev, RTL821x_PAGE_SELECT);
+@@ -72,6 +80,28 @@ static int rtl821x_write_page(struct phy
+ return __phy_write(phydev, RTL821x_PAGE_SELECT, page);
+ }
+
++static int rtl821x_probe(struct phy_device *phydev)
++{
++ struct device *dev = &phydev->mdio.dev;
++ struct rtl821x_priv *priv;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->phycr2 = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2);
++ if (priv->phycr2 < 0)
++ return priv->phycr2;
++
++ priv->phycr2 &= RTL8211F_CLKOUT_EN;
++ if (of_property_read_bool(dev->of_node, "realtek,clkout-disable"))
++ priv->phycr2 &= ~RTL8211F_CLKOUT_EN;
++
++ phydev->priv = priv;
++
++ return 0;
++}
++
+ static int rtl8201_ack_interrupt(struct phy_device *phydev)
+ {
+ int err;
+@@ -180,6 +210,7 @@ static int rtl8211c_config_init(struct p
+
+ static int rtl8211f_config_init(struct phy_device *phydev)
+ {
++ struct rtl821x_priv *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+ u16 val_txdly, val_rxdly;
+ u16 val;
+@@ -243,7 +274,15 @@ static int rtl8211f_config_init(struct p
+ val_rxdly ? "enabled" : "disabled");
+ }
+
+- return 0;
++ ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2,
++ RTL8211F_CLKOUT_EN, priv->phycr2);
++ if (ret < 0) {
++ dev_err(dev, "clkout configuration failed: %pe\n",
++ ERR_PTR(ret));
++ return ret;
++ }
++
++ return genphy_soft_reset(phydev);
+ }
+
+ static int rtl821x_resume(struct phy_device *phydev)
+@@ -633,6 +672,7 @@ static struct phy_driver realtek_drvs[]
+ }, {
+ PHY_ID_MATCH_EXACT(0x001cc916),
+ .name = "RTL8211F Gigabit Ethernet",
++ .probe = rtl821x_probe,
+ .config_init = &rtl8211f_config_init,
+ .ack_interrupt = &rtl8211f_ack_interrupt,
+ .config_intr = &rtl8211f_config_intr,