mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 06:57:57 +00:00
120 lines
3.3 KiB
Diff
120 lines
3.3 KiB
Diff
|
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,
|