Skip to content

Commit 83a5c9e

Browse files
committed
Supported Wake On LAN
Change-Id: I06d26ab4dc6c639e438bdc9c9469420359a99d6f Reviewed-on: https://tp-biosrd-v02/gerrit/82841 Reviewed-by: Alex Cheng(鄭富元) <Alex_Cheng@asus.com> Tested-by: Alex Cheng(鄭富元) <Alex_Cheng@asus.com>
1 parent 976b702 commit 83a5c9e

5 files changed

Lines changed: 173 additions & 1 deletion

File tree

arch/arm/boot/dts/rk3288-miniarm.dts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@
292292
snps,reset-delays-us = <0 10000 1000000>;
293293
assigned-clocks = <&cru SCLK_MAC>;
294294
assigned-clock-parents = <&ext_gmac>;
295+
wolirq-gpio = <&gpio0 8 GPIO_ACTIVE_LOW>;
295296
pinctrl-names = "default";
296297
pinctrl-0 = <&rgmii_pins>;
297298
tx_delay = <0x30>;

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
#include "stmmac.h"
5454
#include <linux/reset.h>
5555
#include <linux/of_mdio.h>
56+
#include <linux/interrupt.h>
57+
#include <linux/gpio.h>
5658
#include "eth_mac_tinker.h"
5759

5860
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
@@ -1819,6 +1821,15 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
18191821
return 0;
18201822
}
18211823

1824+
static irqreturn_t wol_io_isr(int irq, void *dev_id)
1825+
{
1826+
struct net_device *dev = (struct net_device *)dev_id;
1827+
struct stmmac_priv *priv = netdev_priv(dev);
1828+
1829+
wake_lock_timeout(&priv->plat->wol_wake_lock, msecs_to_jiffies(8000));
1830+
return IRQ_HANDLED;
1831+
}
1832+
18221833
/**
18231834
* stmmac_open - open entry point of the driver
18241835
* @dev : pointer to the device structure.
@@ -1908,6 +1919,26 @@ static int stmmac_open(struct net_device *dev)
19081919
}
19091920
}
19101921

1922+
if (priv->plat->wolirq_io > 0) {
1923+
ret = devm_gpio_request(priv->device, priv->plat->wolirq_io, "gmac_wol_io");
1924+
if (ret) {
1925+
pr_err("%s: ERROR: failed to request WOL GPIO %d, err: %d\n",
1926+
__func__, priv->plat->wolirq_io, ret);
1927+
goto lpiirq_error;
1928+
}
1929+
1930+
priv->plat->wol_irq = gpio_to_irq(priv->plat->wolirq_io);
1931+
ret = devm_request_irq(priv->device, priv->plat->wol_irq, wol_io_isr,
1932+
IRQF_TRIGGER_FALLING, "gmac_wol_io_irq", dev);
1933+
if (ret) {
1934+
pr_err("%s: ERROR: request wol io irq fail: %d", __func__, ret);
1935+
devm_gpio_free(priv->device, priv->plat->wolirq_io);
1936+
goto lpiirq_error;
1937+
}
1938+
disable_irq(priv->plat->wol_irq);
1939+
enable_irq_wake(priv->plat->wol_irq);
1940+
}
1941+
19111942
napi_enable(&priv->napi);
19121943
netif_start_queue(dev);
19131944

@@ -1961,6 +1992,12 @@ static int stmmac_release(struct net_device *dev)
19611992
if (priv->lpi_irq > 0)
19621993
free_irq(priv->lpi_irq, dev);
19631994

1995+
if (priv->plat->wol_irq > 0)
1996+
devm_free_irq(priv->device, priv->plat->wol_irq, dev);
1997+
1998+
if (priv->plat->wolirq_io > 0)
1999+
devm_gpio_free(priv->device, priv->plat->wolirq_io);
2000+
19642001
/* Stop TX/RX DMA and clear the descriptors */
19652002
priv->hw->dma->stop_tx(priv->ioaddr);
19662003
priv->hw->dma->stop_rx(priv->ioaddr);
@@ -3017,6 +3054,8 @@ int stmmac_dvr_probe(struct device *device,
30173054
goto error_netdev_register;
30183055
}
30193056

3057+
wake_lock_init(&priv->plat->wol_wake_lock, WAKE_LOCK_SUSPEND, "wol_wake_lock");
3058+
30203059
return ret;
30213060

30223061
error_netdev_register:
@@ -3082,6 +3121,8 @@ int stmmac_suspend(struct device *dev)
30823121
struct stmmac_priv *priv = netdev_priv(ndev);
30833122
unsigned long flags;
30843123

3124+
enable_irq(priv->plat->wol_irq);
3125+
30853126
if (!ndev || !netif_running(ndev))
30863127
return 0;
30873128

@@ -3115,6 +3156,7 @@ int stmmac_suspend(struct device *dev)
31153156
priv->oldlink = 0;
31163157
priv->speed = 0;
31173158
priv->oldduplex = -1;
3159+
31183160
return 0;
31193161
}
31203162
EXPORT_SYMBOL_GPL(stmmac_suspend);
@@ -3131,6 +3173,8 @@ int stmmac_resume(struct device *dev)
31313173
struct stmmac_priv *priv = netdev_priv(ndev);
31323174
unsigned long flags;
31333175

3176+
disable_irq(priv->plat->wol_irq);
3177+
31343178
if (!netif_running(ndev))
31353179
return 0;
31363180

drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/of_net.h>
3030
#include <linux/of_device.h>
3131
#include <linux/of_mdio.h>
32+
#include <linux/of_gpio.h>
3233

3334
#include "stmmac.h"
3435
#include "stmmac_platform.h"
@@ -110,6 +111,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
110111
struct device_node *np = pdev->dev.of_node;
111112
struct plat_stmmacenet_data *plat;
112113
struct stmmac_dma_cfg *dma_cfg;
114+
enum of_gpio_flags flags;
113115

114116
plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
115117
if (!plat)
@@ -118,6 +120,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
118120
*mac = of_get_mac_address(np);
119121
plat->interface = of_get_phy_mode(np);
120122

123+
plat->wolirq_io = of_get_named_gpio_flags(np, "wolirq-gpio", 0, &flags);
124+
121125
/* Get max speed of operation from device tree */
122126
if (of_property_read_u32(np, "max-speed", &plat->max_speed))
123127
plat->max_speed = -1;

drivers/net/phy/phy_device.c

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,8 +735,8 @@ void phy_detach(struct phy_device *phydev)
735735
int i;
736736

737737
phydev->attached_dev->phydev = NULL;
738-
phydev->attached_dev = NULL;
739738
phy_suspend(phydev);
739+
phydev->attached_dev = NULL;
740740

741741
/* If the device had no specific driver before (i.e. - it
742742
* was using the generic driver), we unbind the device
@@ -1226,7 +1226,70 @@ static int gen10g_config_init(struct phy_device *phydev)
12261226
int genphy_suspend(struct phy_device *phydev)
12271227
{
12281228
int value;
1229+
struct net_device * ndev = phydev->attached_dev;
1230+
1231+
mutex_lock(&phydev->lock);
1232+
1233+
//#if RTL8211E
1234+
#if 1
1235+
phy_write(phydev, 31, 0x07);
1236+
phy_write(phydev, 30, 0x6e);
1237+
1238+
phy_write(phydev, 21, ((u16)ndev->dev_addr[1] << 8) + ndev->dev_addr[0]);
1239+
phy_write(phydev, 22, ((u16)ndev->dev_addr[3] << 8) + ndev->dev_addr[2]);
1240+
phy_write(phydev, 23, ((u16)ndev->dev_addr[5] << 8) + ndev->dev_addr[4]);
1241+
1242+
phy_write(phydev, 31, 0x07);
1243+
phy_write(phydev, 30, 0x6d);
1244+
phy_write(phydev, 22, 0x1fff);
1245+
value = phy_read(phydev, 22);
1246+
1247+
phy_write(phydev, 31, 0x07);
1248+
phy_write(phydev, 30, 0x6d);
1249+
phy_write(phydev, 21, 0x1000);
1250+
value = phy_read(phydev, 21);
1251+
1252+
phy_write(phydev, 31, 0x07);
1253+
phy_write(phydev, 30, 0x6d);
1254+
value = phy_read(phydev, 25);
1255+
phy_write(phydev, 25, value | 0x1);
1256+
1257+
phy_write(phydev, 31, 0x0);
1258+
value = phy_read(phydev, 31);
1259+
#endif
1260+
1261+
//#if RTL8211F
1262+
#if 0
1263+
//set INTB pin
1264+
phy_write(priv->phydev, 31, 0x0d40);
1265+
value = phy_read(priv->phydev, 22);
1266+
phy_write(priv->phydev, 22, value | BIT(5));
1267+
1268+
//set MAC address
1269+
phy_write(priv->phydev, 31, 0x0d8c);
1270+
phy_write(priv->phydev, 16, ((u16)ndev->dev_addr[1] << 8) + ndev->dev_addr[0]);
1271+
phy_write(priv->phydev, 17, ((u16)ndev->dev_addr[3] << 8) + ndev->dev_addr[2]);
1272+
phy_write(priv->phydev, 18, ((u16)ndev->dev_addr[5] << 8) + ndev->dev_addr[4]);
1273+
1274+
//set max packet length
1275+
phy_write(priv->phydev, 31, 0x0d8a);
1276+
phy_write(priv->phydev, 17, 0x9fff);
1277+
1278+
//enable wol event
1279+
phy_write(priv->phydev, 31, 0x0d8a);
1280+
phy_write(priv->phydev, 16, 0x1000);
1281+
1282+
//disable rgmii pad
1283+
phy_write(priv->phydev, 31, 0x0d8a);
1284+
value = phy_read(priv->phydev, 19);
1285+
phy_write(priv->phydev, 19, value | BIT(15));
1286+
1287+
phy_write(priv->phydev, 31, 0xa42);
1288+
#endif
1289+
mutex_unlock(&phydev->lock);
12291290

1291+
return 0;
1292+
/*
12301293
mutex_lock(&phydev->lock);
12311294
12321295
value = phy_read(phydev, MII_BMCR);
@@ -1235,6 +1298,7 @@ int genphy_suspend(struct phy_device *phydev)
12351298
mutex_unlock(&phydev->lock);
12361299
12371300
return 0;
1301+
*/
12381302
}
12391303
EXPORT_SYMBOL(genphy_suspend);
12401304

@@ -1247,6 +1311,60 @@ int genphy_resume(struct phy_device *phydev)
12471311
{
12481312
int value;
12491313

1314+
if (phydev->suspended) {
1315+
mutex_lock(&phydev->lock);
1316+
//#if RTL8211E
1317+
#if 1
1318+
phy_write(phydev, 31, 0x07);
1319+
phy_write(phydev, 30, 0x6d);
1320+
phy_write(phydev, 21, 0x0);
1321+
value = phy_read(phydev, 21);
1322+
1323+
phy_write(phydev, 31, 0x07);
1324+
phy_write(phydev, 30, 0x6d);
1325+
value = phy_read(phydev, 22);
1326+
phy_write(phydev, 22, value | BIT(15));
1327+
value = phy_read(phydev, 22);
1328+
1329+
phy_write(phydev, 31, 0x07);
1330+
phy_write(phydev, 30, 0x6d);
1331+
value = phy_read(phydev, 25);
1332+
phy_write(phydev, 25, value & (~(0x1)));
1333+
1334+
phy_write(phydev, 31, 0x0);
1335+
value = phy_read(phydev, 31);
1336+
#endif
1337+
1338+
//#if RTL8211F
1339+
#if 0
1340+
//disable wol event
1341+
phy_write(priv->phydev, 31, 0x0d8a);
1342+
phy_write(priv->phydev, 16, 0x0);
1343+
1344+
//reset wol
1345+
phy_write(priv->phydev, 31, 0x0d8a);
1346+
value = phy_read(priv->phydev, 17);
1347+
phy_write(priv->phydev, 17, value & (~BIT(15)));
1348+
1349+
//enable rgmii pad
1350+
phy_write(priv->phydev, 31, 0x0d8a);
1351+
value = phy_read(priv->phydev, 19);
1352+
phy_write(priv->phydev, 19, value & (~BIT(15)));
1353+
1354+
//set INTB pin
1355+
phy_write(priv->phydev, 31, 0x0d40);
1356+
value = phy_read(priv->phydev, 22);
1357+
phy_write(priv->phydev, 22, value & (~BIT(5)));
1358+
1359+
phy_write(priv->phydev, 31, 0xa42);
1360+
#endif
1361+
mutex_unlock(&phydev->lock);
1362+
1363+
msleep(100);
1364+
1365+
return 0;
1366+
}
1367+
12501368
mutex_lock(&phydev->lock);
12511369

12521370
value = phy_read(phydev, MII_BMCR);

include/linux/stmmac.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define __STMMAC_PLATFORM_DATA
2828

2929
#include <linux/platform_device.h>
30+
#include <linux/wakelock.h>
3031

3132
#define STMMAC_RX_COE_NONE 0
3233
#define STMMAC_RX_COE_TYPE1 1
@@ -123,5 +124,9 @@ struct plat_stmmacenet_data {
123124
void (*exit)(struct platform_device *pdev, void *priv);
124125
void (*get_eth_addr)(void *priv, unsigned char *addr);
125126
void *bsp_priv;
127+
int wolirq_io;
128+
int wolirq_io_level;
129+
int wol_irq;
130+
struct wake_lock wol_wake_lock;
126131
};
127132
#endif

0 commit comments

Comments
 (0)