Skip to content

Commit 08041a9

Browse files
wvoondavem330
authored andcommitted
net: phy: marvell10g: enable WoL for 88X3310 and 88E2110
Implement Wake-on-LAN feature for 88X3310 and 88E2110. This is done by enabling WoL interrupt and WoL detection and configuring MAC address into WoL magic packet registers Signed-off-by: Voon Weifeng <[email protected]> Signed-off-by: Ling Pei Lee <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 86a176f commit 08041a9

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

drivers/net/phy/marvell10g.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/marvell_phy.h>
2929
#include <linux/phy.h>
3030
#include <linux/sfp.h>
31+
#include <linux/netdevice.h>
3132

3233
#define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
3334
#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
@@ -104,6 +105,16 @@ enum {
104105
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5,
105106
MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
106107
MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7,
108+
MV_V2_PORT_INTR_STS = 0xf040,
109+
MV_V2_PORT_INTR_MASK = 0xf043,
110+
MV_V2_PORT_INTR_STS_WOL_EN = BIT(8),
111+
MV_V2_MAGIC_PKT_WORD0 = 0xf06b,
112+
MV_V2_MAGIC_PKT_WORD1 = 0xf06c,
113+
MV_V2_MAGIC_PKT_WORD2 = 0xf06d,
114+
/* Wake on LAN registers */
115+
MV_V2_WOL_CTRL = 0xf06e,
116+
MV_V2_WOL_CTRL_CLEAR_STS = BIT(15),
117+
MV_V2_WOL_CTRL_MAGIC_PKT_EN = BIT(0),
107118
/* Temperature control/read registers (88X3310 only) */
108119
MV_V2_TEMP_CTRL = 0xf08a,
109120
MV_V2_TEMP_CTRL_MASK = 0xc000,
@@ -1020,6 +1031,80 @@ static int mv2111_match_phy_device(struct phy_device *phydev)
10201031
return mv211x_match_phy_device(phydev, false);
10211032
}
10221033

1034+
static void mv3110_get_wol(struct phy_device *phydev,
1035+
struct ethtool_wolinfo *wol)
1036+
{
1037+
int ret;
1038+
1039+
wol->supported = WAKE_MAGIC;
1040+
wol->wolopts = 0;
1041+
1042+
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);
1043+
if (ret < 0)
1044+
return;
1045+
1046+
if (ret & MV_V2_WOL_CTRL_MAGIC_PKT_EN)
1047+
wol->wolopts |= WAKE_MAGIC;
1048+
}
1049+
1050+
static int mv3110_set_wol(struct phy_device *phydev,
1051+
struct ethtool_wolinfo *wol)
1052+
{
1053+
int ret;
1054+
1055+
if (wol->wolopts & WAKE_MAGIC) {
1056+
/* Enable the WOL interrupt */
1057+
ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
1058+
MV_V2_PORT_INTR_MASK,
1059+
MV_V2_PORT_INTR_STS_WOL_EN);
1060+
if (ret < 0)
1061+
return ret;
1062+
1063+
/* Store the device address for the magic packet */
1064+
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
1065+
MV_V2_MAGIC_PKT_WORD2,
1066+
((phydev->attached_dev->dev_addr[5] << 8) |
1067+
phydev->attached_dev->dev_addr[4]));
1068+
if (ret < 0)
1069+
return ret;
1070+
1071+
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
1072+
MV_V2_MAGIC_PKT_WORD1,
1073+
((phydev->attached_dev->dev_addr[3] << 8) |
1074+
phydev->attached_dev->dev_addr[2]));
1075+
if (ret < 0)
1076+
return ret;
1077+
1078+
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
1079+
MV_V2_MAGIC_PKT_WORD0,
1080+
((phydev->attached_dev->dev_addr[1] << 8) |
1081+
phydev->attached_dev->dev_addr[0]));
1082+
if (ret < 0)
1083+
return ret;
1084+
1085+
/* Clear WOL status and enable magic packet matching */
1086+
ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
1087+
MV_V2_WOL_CTRL,
1088+
MV_V2_WOL_CTRL_MAGIC_PKT_EN |
1089+
MV_V2_WOL_CTRL_CLEAR_STS);
1090+
if (ret < 0)
1091+
return ret;
1092+
} else {
1093+
/* Disable magic packet matching & reset WOL status bit */
1094+
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
1095+
MV_V2_WOL_CTRL,
1096+
MV_V2_WOL_CTRL_MAGIC_PKT_EN,
1097+
MV_V2_WOL_CTRL_CLEAR_STS);
1098+
if (ret < 0)
1099+
return ret;
1100+
}
1101+
1102+
/* Reset the clear WOL status bit as it does not self-clear */
1103+
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
1104+
MV_V2_WOL_CTRL,
1105+
MV_V2_WOL_CTRL_CLEAR_STS);
1106+
}
1107+
10231108
static struct phy_driver mv3310_drivers[] = {
10241109
{
10251110
.phy_id = MARVELL_PHY_ID_88X3310,
@@ -1039,6 +1124,8 @@ static struct phy_driver mv3310_drivers[] = {
10391124
.set_tunable = mv3310_set_tunable,
10401125
.remove = mv3310_remove,
10411126
.set_loopback = genphy_c45_loopback,
1127+
.get_wol = mv3110_get_wol,
1128+
.set_wol = mv3110_set_wol,
10421129
},
10431130
{
10441131
.phy_id = MARVELL_PHY_ID_88X3310,
@@ -1076,6 +1163,8 @@ static struct phy_driver mv3310_drivers[] = {
10761163
.set_tunable = mv3310_set_tunable,
10771164
.remove = mv3310_remove,
10781165
.set_loopback = genphy_c45_loopback,
1166+
.get_wol = mv3110_get_wol,
1167+
.set_wol = mv3110_set_wol,
10791168
},
10801169
{
10811170
.phy_id = MARVELL_PHY_ID_88E2110,

0 commit comments

Comments
 (0)