build/patch/kernel/archive/odroidxu4-5.15/0064-ODROID-COMMON-phy-realtek-add-Wake-on-Lan-to-Realtek.patch

114 lines
3.3 KiB
Diff
Raw Normal View History

From 0595f01e280d1f0943ab1dc88e5d16f2ba435426 Mon Sep 17 00:00:00 2001
From: Dongjin Kim <tobetter@gmail.com>
Date: Thu, 15 Jul 2021 19:32:42 +0900
Subject: [PATCH 64/75] ODROID-COMMON: phy/realtek: add Wake-on-Lan to Realtek
PHY
Wake-On-Lan can set with 'ethtool'
$ sudo ethtool -s eth0 wol g
Check if 'Wake-on' is set with 'g'
$ sudo ethtool eth0 | grep Wake
Supports Wake-on: ug
Wake-on: g
In order to wake from remote, run 'wakeonlan' with IP address:
$ wakeonlan 00:1e:06:42:45:32
Change-Id: Ida2e9ac5ce623fceecc7d00c712f173bca16e322
Signed-off-by: Dongjin Kim <tobetter@gmail.com>
---
.../ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 +
drivers/net/phy/realtek.c | 48 +++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index d89455803bed..439be5b6590d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -749,6 +749,8 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
disable_irq_wake(priv->wol_irq);
}
+ phylink_ethtool_set_wol(priv->phylink, wol);
+
mutex_lock(&priv->lock);
priv->wolopts = wol->wolopts;
mutex_unlock(&priv->lock);
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 11be60333fa8..dd82045b5ef3 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -12,6 +12,8 @@
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX BIT(13)
@@ -300,6 +302,51 @@ static irqreturn_t rtl8211f_handle_interrupt(struct phy_device *phydev)
return IRQ_HANDLED;
}
+static int rtl8211f_set_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ struct net_device *ndev = phydev->attached_dev;
+ const u8 *mac;
+ int val;
+
+ if (wol->wolopts & WAKE_MAGIC) {
+ mac = (const u8 *)ndev->dev_addr;
+
+ if (!is_valid_ether_addr(mac))
+ return -EINVAL;
+
+ /* Set MAC address */
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd8c);
+ phy_write(phydev, 0x10, (mac[1] << 8) | mac[0]);
+ phy_write(phydev, 0x11, (mac[3] << 8) | mac[2]);
+ phy_write(phydev, 0x12, (mac[5] << 8) | mac[4]);
+
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd8a);
+
+ /* Set magic packet for WOL */
+ phy_write(phydev, 0x10, 0x1000);
+ phy_write(phydev, 0x11, 0x9fff);
+
+ /* PIN31 - pull high */
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd40);
+ val = phy_read(phydev, 0x16);
+ phy_write(phydev, 0x16, val | BIT(5));
+
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0);
+ } else {
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd8a);
+
+ /* Reset magic packet for WOL */
+ phy_write(phydev, 0x10, 0x0);
+ val = phy_read(phydev, 0x11);
+ phy_write(phydev, 0x11, val & ~BIT(15));
+
+ phy_write(phydev, RTL821x_PAGE_SELECT, 0);
+ }
+
+ return 0;
+}
+
static int rtl8211_config_aneg(struct phy_device *phydev)
{
int ret;
@@ -909,6 +956,7 @@ static struct phy_driver realtek_drvs[] = {
.handle_interrupt = rtl821x_handle_interrupt,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .set_wol = rtl8211f_set_wol,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
}, {
--
2.25.1