summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2021-06-08 11:41:24 -0700
committerDavid S. Miller <davem@davemloft.net>2021-06-08 11:41:24 -0700
commit5552571c657d57e532b321c902bddc73c7807f07 (patch)
tree1c2c1b0943586e65847584348ff36080c61648d6
parentd6dd33ffa33b7a6a05e98f8f0cb2f256640fa5d5 (diff)
parent6813cc8cfdaf401476e1a007cec8ae338cefa573 (diff)
Merge branch 'realtek-dt'
Joakim Zhang says: ==================== net: phy: add dt property for realtek phy Add dt property for realtek phy. --- ChangeLogs: V1->V2: * store the desired PHYCR1/2 register value in "priv" rather than using "quirks", per Russell King suggestion, as well as can cover the bootloader setting. * change the behavior of ALDPS mode, default is disabled, add dt property for users to enable it. * fix dt binding yaml build issues. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml45
-rw-r--r--drivers/net/phy/realtek.c75
2 files changed, 116 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
new file mode 100644
index 0000000000000..bb94a2388520b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/realtek,rtl82xx.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0+
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/realtek,rtl82xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek RTL82xx PHY
+
+maintainers:
+ - Andrew Lunn <andrew@lunn.ch>
+ - Florian Fainelli <f.fainelli@gmail.com>
+ - Heiner Kallweit <hkallweit1@gmail.com>
+
+description:
+ Bindings for Realtek RTL82xx PHYs
+
+allOf:
+ - $ref: ethernet-phy.yaml#
+
+properties:
+ realtek,clkout-disable:
+ type: boolean
+ description:
+ Disable CLKOUT clock, CLKOUT clock default is enabled after hardware reset.
+
+
+ realtek,aldps-enable:
+ type: boolean
+ description:
+ Enable ALDPS mode, ALDPS mode default is disabled after hardware reset.
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ realtek,clkout-disable;
+ realtek,aldps-enable;
+ };
+ };
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 821e85a973679..1b844a06fe72a 100644
--- 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_ISR_ANERR BIT(15)
#define RTL8201F_ISR_DUPLEX BIT(13)
@@ -71,6 +75,11 @@ MODULE_DESCRIPTION("Realtek PHY driver");
MODULE_AUTHOR("Johnson Leung");
MODULE_LICENSE("GPL");
+struct rtl821x_priv {
+ u16 phycr1;
+ u16 phycr2;
+};
+
static int rtl821x_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, RTL821x_PAGE_SELECT);
@@ -81,6 +90,36 @@ static int rtl821x_write_page(struct phy_device *phydev, int page)
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->phycr1 = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1);
+ if (priv->phycr1 < 0)
+ return priv->phycr1;
+
+ priv->phycr1 &= (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF);
+ 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->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;
@@ -291,13 +330,19 @@ static int rtl8211c_config_init(struct phy_device *phydev)
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;
int ret;
- val = RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_XTAL_OFF;
- phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, val, val);
+ ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1,
+ RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF,
+ priv->phycr1);
+ if (ret < 0) {
+ dev_err(dev, "aldps mode configuration failed: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
@@ -354,6 +399,27 @@ static int rtl8211f_config_init(struct phy_device *phydev)
val_rxdly ? "enabled" : "disabled");
}
+ 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)
+{
+ int ret;
+
+ ret = genphy_resume(phydev);
+ if (ret < 0)
+ return ret;
+
+ msleep(20);
+
return 0;
}
@@ -847,12 +913,13 @@ static struct phy_driver realtek_drvs[] = {
}, {
PHY_ID_MATCH_EXACT(0x001cc916),
.name = "RTL8211F Gigabit Ethernet",
+ .probe = rtl821x_probe,
.config_init = &rtl8211f_config_init,
.read_status = rtlgen_read_status,
.config_intr = &rtl8211f_config_intr,
.handle_interrupt = rtl8211f_handle_interrupt,
.suspend = genphy_suspend,
- .resume = genphy_resume,
+ .resume = rtl821x_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {