pmaports/device/testing/linux-postmarketos-exynos5/0007-ODROID-COMMON-phy-realtek-add-Wake-on-Lan-to-Realtek.patch

107 lines
3.3 KiB
Diff

From eec2539ec9efc8a4f50c68204c01c113c39f2976 Mon Sep 17 00:00:00 2001
From: Dongjin Kim <tobetter@gmail.com>
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 <tobetter@gmail.com>
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 <linux/phy.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/etherdevice.h>
#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