From 8ff0ff4785acb9e84b6e0172dfeed2526a3c58b2 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Tue, 9 Jun 2020 17:39:24 +0800 Subject: [PATCH] MLK-24295 net: phy: realtek: add dt property to enable clkout Add dt property for user to enable clkout for MAC. Reviewed-by: Richard Zhu Signed-off-by: Fugang Duan --- .../devicetree/bindings/net/realtek.txt | 7 +++ drivers/net/phy/realtek.c | 46 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/realtek.txt diff --git a/Documentation/devicetree/bindings/net/realtek.txt b/Documentation/devicetree/bindings/net/realtek.txt new file mode 100644 index 000000000000..37771fbfffe1 --- /dev/null +++ b/Documentation/devicetree/bindings/net/realtek.txt @@ -0,0 +1,7 @@ +Realtek PHY properties. + +These properties cover the base properties Realtek PHYs. + +Optional properties: + - rtl821x,clkout_en : enable clkout to supply clocks for MAC. + diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 63511b656bba..221d2175c63b 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -9,6 +9,7 @@ * Copyright (c) 2004 Freescale Semiconductor, Inc. */ #include +#include #include #include @@ -50,10 +51,20 @@ #define RTL_GENERIC_PHYID 0x001cc800 +/* page 0xa43, register 0x19 */ +#define RTL8211F_PHYCR2 0x19 +#define RTL8211F_CLKOUT_EN BIT(0) + +#define RTL821X_CLKOUT_EN_FEATURE (1 << 0) + MODULE_DESCRIPTION("Realtek PHY driver"); MODULE_AUTHOR("Johnson Leung"); MODULE_LICENSE("GPL"); +struct rtl821x_priv { + u32 quirks; +}; + static int rtl821x_read_page(struct phy_device *phydev) { return __phy_read(phydev, RTL821x_PAGE_SELECT); @@ -64,6 +75,23 @@ 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; + + if (of_property_read_bool(dev->of_node, "rtl821x,clkout_en")) + priv->quirks |= RTL821X_CLKOUT_EN_FEATURE; + + phydev->priv = priv; + + return 0; +} + static int rtl8201_ack_interrupt(struct phy_device *phydev) { int err; @@ -175,6 +203,7 @@ static int rtl8211f_config_init(struct phy_device *phydev) u16 txdly = 0; u16 rxdly = 0; int ret; + struct rtl821x_priv *priv = phydev->priv; /* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin. @@ -206,6 +235,22 @@ static int rtl8211f_config_init(struct phy_device *phydev) return ret; } + if (priv->quirks & RTL821X_CLKOUT_EN_FEATURE) { + ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, + RTL8211F_CLKOUT_EN, RTL8211F_CLKOUT_EN); + if (ret < 0) { + dev_err(&phydev->mdio.dev, "clkout enable failed\n"); + return ret; + } + } else { + ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, + RTL8211F_CLKOUT_EN, 0); + if (ret < 0) { + dev_err(&phydev->mdio.dev, "clkout disable failed\n"); + return ret; + } + } + return ret; } @@ -505,6 +550,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,