From eec2539ec9efc8a4f50c68204c01c113c39f2976 Mon Sep 17 00:00:00 2001 From: Dongjin Kim Date: Wed, 17 Nov 2021 13:17:51 +0900 Subject: [PATCH 07/16] ODROID-COMMON: phy/realtek: add Wake-on-Lan to Realtek PHY Wake-On-Lan can set with 'ethtool' $ sudo ethtool -s eth0 wol u Check if 'Wake-on' is set with 'u' $ sudo ethtool eth0 | grep Wake Supports Wake-on: ug Wake-on: u In order to wake from remote, run 'wakeonlan' with IP address: $ wakeonlan 00:1e:06:42:45:32 Signed-off-by: Dongjin Kim Change-Id: I8ade81ab50d8d886e2908b9cec543e3bf8cc7abd --- .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 ++ drivers/net/phy/realtek.c | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index d89455803bed..98f3913b7ae5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -753,6 +753,8 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) priv->wolopts = wol->wolopts; mutex_unlock(&priv->lock); + phy_ethtool_set_wol(dev->phydev, wol); + return 0; } diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index a5671ab896b3..f832992d80fd 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -12,6 +12,7 @@ #include #include #include +#include #define RTL821x_PHYSR 0x11 #define RTL821x_PHYSR_DUPLEX BIT(13) @@ -228,7 +229,11 @@ static int rtl8211f_config_intr(struct phy_device *phydev) val = RTL8211F_INER_LINK_STATUS; err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); + + phy_modify_paged(phydev, 0xd40, 0x16, BIT(5), 0); } else { + phy_modify_paged(phydev, 0xd40, 0x16, 0, BIT(5)); + val = 0; err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); if (err) @@ -329,6 +334,34 @@ static int rtl8211c_config_init(struct phy_device *phydev) CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); } +static int rtl8211f_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + struct net_device *netdev = phydev->attached_dev; + const u8 *mac = (const u8 *)netdev->dev_addr; + + if ((wol->wolopts & (WAKE_MAGIC | WAKE_UCAST)) == 0) { + disable_irq_wake(phydev->irq); + return 0; + } + + if ((wol->wolopts & WAKE_UCAST) + && is_valid_ether_addr(mac)) { + phy_write_paged(phydev, 0xd8c, 0x10, (mac[1] << 8) | mac[0]); + phy_write_paged(phydev, 0xd8c, 0x11, (mac[3] << 8) | mac[2]); + phy_write_paged(phydev, 0xd8c, 0x12, (mac[5] << 8) | mac[4]); + } + + if (wol->wolopts & WAKE_MAGIC) { + phy_write_paged(phydev, 0xd8a, 0x10, 0x1000); + phy_write_paged(phydev, 0xd8a, 0x11, 0x9fff); + } + + enable_irq_wake(phydev->irq); + + return 0; +} + static int rtl8211f_config_init(struct phy_device *phydev) { struct rtl821x_priv *priv = phydev->priv; @@ -921,6 +954,7 @@ static struct phy_driver realtek_drvs[] = { .handle_interrupt = rtl8211f_handle_interrupt, .suspend = genphy_suspend, .resume = rtl821x_resume, + .set_wol = rtl8211f_set_wol, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, }, { -- 2.34.1