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+
10231108static 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