All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] net: phy: dp83867: support Wake on LAN
@ 2019-10-22 11:11 Thomas Hämmerle
  2019-10-22 12:34 ` Andrew Lunn
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Thomas Hämmerle @ 2019-10-22 11:11 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, hkallweit1, davem, m.tretter, Thomas Hämmerle

From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>

This adds WoL support on TI DP83867 for magic, magic secure, unicast and
broadcast.

Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
---
 drivers/net/phy/dp83867.c | 131 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 130 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 37fceaf..a3b7ff7 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -12,6 +12,8 @@
 #include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 
 #include <dt-bindings/net/ti-dp83867.h>
 
@@ -21,8 +23,9 @@
 #define MII_DP83867_PHYCTRL	0x10
 #define MII_DP83867_MICR	0x12
 #define MII_DP83867_ISR		0x13
-#define DP83867_CTRL		0x1f
+#define DP83867_CFG2		0x14
 #define DP83867_CFG3		0x1e
+#define DP83867_CTRL		0x1f
 
 /* Extended Registers */
 #define DP83867_CFG4            0x0031
@@ -36,6 +39,13 @@
 #define DP83867_STRAP_STS1	0x006E
 #define DP83867_STRAP_STS2	0x006f
 #define DP83867_RGMIIDCTL	0x0086
+#define DP83867_RXFCFG		0x0134
+#define DP83867_RXFPMD1	0x0136
+#define DP83867_RXFPMD2	0x0137
+#define DP83867_RXFPMD3	0x0138
+#define DP83867_RXFSOP1	0x0139
+#define DP83867_RXFSOP2	0x013A
+#define DP83867_RXFSOP3	0x013B
 #define DP83867_IO_MUX_CFG	0x0170
 #define DP83867_SGMIICTL	0x00D3
 #define DP83867_10M_SGMII_CFG   0x016F
@@ -65,6 +75,13 @@
 /* SGMIICTL bits */
 #define DP83867_SGMII_TYPE		BIT(14)
 
+/* RXFCFG bits*/
+#define DP83867_WOL_MAGIC_EN		BIT(0)
+#define DP83867_WOL_BCAST_EN		BIT(2)
+#define DP83867_WOL_UCAST_EN		BIT(4)
+#define DP83867_WOL_SEC_EN		BIT(5)
+#define DP83867_WOL_ENH_MAC		BIT(7)
+
 /* STRAP_STS1 bits */
 #define DP83867_STRAP_STS1_RESERVED		BIT(11)
 
@@ -126,6 +143,115 @@ static int dp83867_ack_interrupt(struct phy_device *phydev)
 	return 0;
 }
 
+static int dp83867_set_wol(struct phy_device *phydev,
+			   struct ethtool_wolinfo *wol)
+{
+	struct net_device *ndev = phydev->attached_dev;
+	u16 val_rxcfg, val_micr;
+	const u8 *mac;
+
+	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
+	val_micr = phy_read(phydev, MII_DP83867_MICR);
+
+	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
+			    WAKE_BCAST)) {
+		val_rxcfg |= DP83867_WOL_ENH_MAC;
+		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
+
+		if (wol->wolopts & WAKE_MAGIC) {
+			mac = (const u8 *)ndev->dev_addr;
+
+			if (!is_valid_ether_addr(mac))
+				return -EINVAL;
+
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD1,
+				      (mac[1] << 8 | mac[0]));
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD2,
+				      (mac[3] << 8 | mac[2]));
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD3,
+				      (mac[5] << 8 | mac[4]));
+
+			val_rxcfg |= DP83867_WOL_MAGIC_EN;
+		} else {
+			val_rxcfg &= ~DP83867_WOL_MAGIC_EN;
+		}
+
+		if (wol->wolopts & WAKE_MAGICSECURE) {
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[1] << 8) | wol->sopass[0]);
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[3] << 8) | wol->sopass[2]);
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[5] << 8) | wol->sopass[3]);
+
+			val_rxcfg |= DP83867_WOL_SEC_EN;
+		} else {
+			val_rxcfg &= ~DP83867_WOL_SEC_EN;
+		}
+
+		if (wol->wolopts & WAKE_UCAST)
+			val_rxcfg |= DP83867_WOL_UCAST_EN;
+		else
+			val_rxcfg &= ~DP83867_WOL_UCAST_EN;
+
+		if (wol->wolopts & WAKE_BCAST)
+			val_rxcfg |= DP83867_WOL_BCAST_EN;
+		else
+			val_rxcfg &= ~DP83867_WOL_BCAST_EN;
+	} else {
+		val_rxcfg &= ~DP83867_WOL_ENH_MAC;
+		val_micr &= ~MII_DP83867_MICR_WOL_INT_EN;
+	}
+
+	phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG, val_rxcfg);
+	phy_write(phydev, MII_DP83867_MICR, val_micr);
+
+	return 0;
+}
+
+static void dp83867_get_wol(struct phy_device *phydev,
+			    struct ethtool_wolinfo *wol)
+{
+	u16 value, sopass_val;
+
+	wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |
+			WAKE_MAGICSECURE);
+	wol->wolopts = 0;
+
+	value = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
+
+	if (value & DP83867_WOL_UCAST_EN)
+		wol->wolopts |= WAKE_UCAST;
+
+	if (value & DP83867_WOL_BCAST_EN)
+		wol->wolopts |= WAKE_BCAST;
+
+	if (value & DP83867_WOL_MAGIC_EN)
+		wol->wolopts |= WAKE_MAGIC;
+
+	if (value & DP83867_WOL_SEC_EN) {
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP1);
+		wol->sopass[0] = (sopass_val & 0xff);
+		wol->sopass[1] = (sopass_val >> 8);
+
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP2);
+		wol->sopass[2] = (sopass_val & 0xff);
+		wol->sopass[3] = (sopass_val >> 8);
+
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP3);
+		wol->sopass[4] = (sopass_val & 0xff);
+		wol->sopass[5] = (sopass_val >> 8);
+
+		wol->wolopts |= WAKE_MAGICSECURE;
+	}
+
+	if (!(value & DP83867_WOL_ENH_MAC))
+		wol->wolopts = 0;
+}
+
 static int dp83867_config_intr(struct phy_device *phydev)
 {
 	int micr_status;
@@ -463,6 +589,9 @@ static struct phy_driver dp83867_driver[] = {
 		.config_init	= dp83867_config_init,
 		.soft_reset	= dp83867_phy_reset,
 
+		.get_wol	= dp83867_get_wol,
+		.set_wol	= dp83867_set_wol,
+
 		/* IRQ related */
 		.ack_interrupt	= dp83867_ack_interrupt,
 		.config_intr	= dp83867_config_intr,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] net: phy: dp83867: support Wake on LAN
  2019-10-22 11:11 [PATCH] net: phy: dp83867: support Wake on LAN Thomas Hämmerle
@ 2019-10-22 12:34 ` Andrew Lunn
  2019-10-22 13:06 ` [PATCH v2] " Thomas Hämmerle
  2019-10-28  8:08 ` [PATCH v3] " Thomas Hämmerle
  2 siblings, 0 replies; 11+ messages in thread
From: Andrew Lunn @ 2019-10-22 12:34 UTC (permalink / raw)
  To: Thomas Hämmerle; +Cc: netdev, f.fainelli, hkallweit1, davem, m.tretter

On Tue, Oct 22, 2019 at 11:11:07AM +0000, Thomas Hämmerle wrote:
> +		if (wol->wolopts & WAKE_MAGICSECURE) {
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[1] << 8) | wol->sopass[0]);
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[3] << 8) | wol->sopass[2]);
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[5] << 8) | wol->sopass[3]);

Hi Thomas

I see sopass[3] twice here. Is that a typo?

  Andrew

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2] net: phy: dp83867: support Wake on LAN
  2019-10-22 11:11 [PATCH] net: phy: dp83867: support Wake on LAN Thomas Hämmerle
  2019-10-22 12:34 ` Andrew Lunn
@ 2019-10-22 13:06 ` Thomas Hämmerle
  2019-10-22 13:30   ` Michael Tretter
                     ` (3 more replies)
  2019-10-28  8:08 ` [PATCH v3] " Thomas Hämmerle
  2 siblings, 4 replies; 11+ messages in thread
From: Thomas Hämmerle @ 2019-10-22 13:06 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, hkallweit1, davem, m.tretter, Thomas Hämmerle

From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>

This adds WoL support on TI DP83867 for magic, magic secure, unicast and
broadcast.

Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
---
 drivers/net/phy/dp83867.c | 131 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 130 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 37fceaf..1a3f8f1 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -12,6 +12,8 @@
 #include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 
 #include <dt-bindings/net/ti-dp83867.h>
 
@@ -21,8 +23,9 @@
 #define MII_DP83867_PHYCTRL	0x10
 #define MII_DP83867_MICR	0x12
 #define MII_DP83867_ISR		0x13
-#define DP83867_CTRL		0x1f
+#define DP83867_CFG2		0x14
 #define DP83867_CFG3		0x1e
+#define DP83867_CTRL		0x1f
 
 /* Extended Registers */
 #define DP83867_CFG4            0x0031
@@ -36,6 +39,13 @@
 #define DP83867_STRAP_STS1	0x006E
 #define DP83867_STRAP_STS2	0x006f
 #define DP83867_RGMIIDCTL	0x0086
+#define DP83867_RXFCFG		0x0134
+#define DP83867_RXFPMD1	0x0136
+#define DP83867_RXFPMD2	0x0137
+#define DP83867_RXFPMD3	0x0138
+#define DP83867_RXFSOP1	0x0139
+#define DP83867_RXFSOP2	0x013A
+#define DP83867_RXFSOP3	0x013B
 #define DP83867_IO_MUX_CFG	0x0170
 #define DP83867_SGMIICTL	0x00D3
 #define DP83867_10M_SGMII_CFG   0x016F
@@ -65,6 +75,13 @@
 /* SGMIICTL bits */
 #define DP83867_SGMII_TYPE		BIT(14)
 
+/* RXFCFG bits*/
+#define DP83867_WOL_MAGIC_EN		BIT(0)
+#define DP83867_WOL_BCAST_EN		BIT(2)
+#define DP83867_WOL_UCAST_EN		BIT(4)
+#define DP83867_WOL_SEC_EN		BIT(5)
+#define DP83867_WOL_ENH_MAC		BIT(7)
+
 /* STRAP_STS1 bits */
 #define DP83867_STRAP_STS1_RESERVED		BIT(11)
 
@@ -126,6 +143,115 @@ static int dp83867_ack_interrupt(struct phy_device *phydev)
 	return 0;
 }
 
+static int dp83867_set_wol(struct phy_device *phydev,
+			   struct ethtool_wolinfo *wol)
+{
+	struct net_device *ndev = phydev->attached_dev;
+	u16 val_rxcfg, val_micr;
+	const u8 *mac;
+
+	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
+	val_micr = phy_read(phydev, MII_DP83867_MICR);
+
+	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
+			    WAKE_BCAST)) {
+		val_rxcfg |= DP83867_WOL_ENH_MAC;
+		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
+
+		if (wol->wolopts & WAKE_MAGIC) {
+			mac = (const u8 *)ndev->dev_addr;
+
+			if (!is_valid_ether_addr(mac))
+				return -EINVAL;
+
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD1,
+				      (mac[1] << 8 | mac[0]));
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD2,
+				      (mac[3] << 8 | mac[2]));
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD3,
+				      (mac[5] << 8 | mac[4]));
+
+			val_rxcfg |= DP83867_WOL_MAGIC_EN;
+		} else {
+			val_rxcfg &= ~DP83867_WOL_MAGIC_EN;
+		}
+
+		if (wol->wolopts & WAKE_MAGICSECURE) {
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[1] << 8) | wol->sopass[0]);
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[3] << 8) | wol->sopass[2]);
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[5] << 8) | wol->sopass[4]);
+
+			val_rxcfg |= DP83867_WOL_SEC_EN;
+		} else {
+			val_rxcfg &= ~DP83867_WOL_SEC_EN;
+		}
+
+		if (wol->wolopts & WAKE_UCAST)
+			val_rxcfg |= DP83867_WOL_UCAST_EN;
+		else
+			val_rxcfg &= ~DP83867_WOL_UCAST_EN;
+
+		if (wol->wolopts & WAKE_BCAST)
+			val_rxcfg |= DP83867_WOL_BCAST_EN;
+		else
+			val_rxcfg &= ~DP83867_WOL_BCAST_EN;
+	} else {
+		val_rxcfg &= ~DP83867_WOL_ENH_MAC;
+		val_micr &= ~MII_DP83867_MICR_WOL_INT_EN;
+	}
+
+	phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG, val_rxcfg);
+	phy_write(phydev, MII_DP83867_MICR, val_micr);
+
+	return 0;
+}
+
+static void dp83867_get_wol(struct phy_device *phydev,
+			    struct ethtool_wolinfo *wol)
+{
+	u16 value, sopass_val;
+
+	wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |
+			WAKE_MAGICSECURE);
+	wol->wolopts = 0;
+
+	value = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
+
+	if (value & DP83867_WOL_UCAST_EN)
+		wol->wolopts |= WAKE_UCAST;
+
+	if (value & DP83867_WOL_BCAST_EN)
+		wol->wolopts |= WAKE_BCAST;
+
+	if (value & DP83867_WOL_MAGIC_EN)
+		wol->wolopts |= WAKE_MAGIC;
+
+	if (value & DP83867_WOL_SEC_EN) {
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP1);
+		wol->sopass[0] = (sopass_val & 0xff);
+		wol->sopass[1] = (sopass_val >> 8);
+
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP2);
+		wol->sopass[2] = (sopass_val & 0xff);
+		wol->sopass[3] = (sopass_val >> 8);
+
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP3);
+		wol->sopass[4] = (sopass_val & 0xff);
+		wol->sopass[5] = (sopass_val >> 8);
+
+		wol->wolopts |= WAKE_MAGICSECURE;
+	}
+
+	if (!(value & DP83867_WOL_ENH_MAC))
+		wol->wolopts = 0;
+}
+
 static int dp83867_config_intr(struct phy_device *phydev)
 {
 	int micr_status;
@@ -463,6 +589,9 @@ static struct phy_driver dp83867_driver[] = {
 		.config_init	= dp83867_config_init,
 		.soft_reset	= dp83867_phy_reset,
 
+		.get_wol	= dp83867_get_wol,
+		.set_wol	= dp83867_set_wol,
+
 		/* IRQ related */
 		.ack_interrupt	= dp83867_ack_interrupt,
 		.config_intr	= dp83867_config_intr,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] net: phy: dp83867: support Wake on LAN
  2019-10-22 13:06 ` [PATCH v2] " Thomas Hämmerle
@ 2019-10-22 13:30   ` Michael Tretter
  2019-10-22 14:00   ` Andrew Lunn
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Michael Tretter @ 2019-10-22 13:30 UTC (permalink / raw)
  To: Thomas Hämmerle
  Cc: netdev, andrew, f.fainelli, hkallweit1, davem, kernel

On Tue, 22 Oct 2019 13:06:35 +0000, Thomas Hämmerle wrote:
> From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
> 
> This adds WoL support on TI DP83867 for magic, magic secure, unicast and
> broadcast.
> 
> Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>

Reviewed-by: Michael Tretter <michael.tretter@pengutronix.de>

> ---
>  drivers/net/phy/dp83867.c | 131 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 130 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
> index 37fceaf..1a3f8f1 100644
> --- a/drivers/net/phy/dp83867.c
> +++ b/drivers/net/phy/dp83867.c
> @@ -12,6 +12,8 @@
>  #include <linux/of.h>
>  #include <linux/phy.h>
>  #include <linux/delay.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
>  
>  #include <dt-bindings/net/ti-dp83867.h>
>  
> @@ -21,8 +23,9 @@
>  #define MII_DP83867_PHYCTRL	0x10
>  #define MII_DP83867_MICR	0x12
>  #define MII_DP83867_ISR		0x13
> -#define DP83867_CTRL		0x1f
> +#define DP83867_CFG2		0x14
>  #define DP83867_CFG3		0x1e
> +#define DP83867_CTRL		0x1f
>  
>  /* Extended Registers */
>  #define DP83867_CFG4            0x0031
> @@ -36,6 +39,13 @@
>  #define DP83867_STRAP_STS1	0x006E
>  #define DP83867_STRAP_STS2	0x006f
>  #define DP83867_RGMIIDCTL	0x0086
> +#define DP83867_RXFCFG		0x0134
> +#define DP83867_RXFPMD1	0x0136
> +#define DP83867_RXFPMD2	0x0137
> +#define DP83867_RXFPMD3	0x0138
> +#define DP83867_RXFSOP1	0x0139
> +#define DP83867_RXFSOP2	0x013A
> +#define DP83867_RXFSOP3	0x013B
>  #define DP83867_IO_MUX_CFG	0x0170
>  #define DP83867_SGMIICTL	0x00D3
>  #define DP83867_10M_SGMII_CFG   0x016F
> @@ -65,6 +75,13 @@
>  /* SGMIICTL bits */
>  #define DP83867_SGMII_TYPE		BIT(14)
>  
> +/* RXFCFG bits*/
> +#define DP83867_WOL_MAGIC_EN		BIT(0)
> +#define DP83867_WOL_BCAST_EN		BIT(2)
> +#define DP83867_WOL_UCAST_EN		BIT(4)
> +#define DP83867_WOL_SEC_EN		BIT(5)
> +#define DP83867_WOL_ENH_MAC		BIT(7)
> +
>  /* STRAP_STS1 bits */
>  #define DP83867_STRAP_STS1_RESERVED		BIT(11)
>  
> @@ -126,6 +143,115 @@ static int dp83867_ack_interrupt(struct phy_device *phydev)
>  	return 0;
>  }
>  
> +static int dp83867_set_wol(struct phy_device *phydev,
> +			   struct ethtool_wolinfo *wol)
> +{
> +	struct net_device *ndev = phydev->attached_dev;
> +	u16 val_rxcfg, val_micr;
> +	const u8 *mac;
> +
> +	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
> +	val_micr = phy_read(phydev, MII_DP83867_MICR);
> +
> +	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
> +			    WAKE_BCAST)) {
> +		val_rxcfg |= DP83867_WOL_ENH_MAC;
> +		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
> +
> +		if (wol->wolopts & WAKE_MAGIC) {
> +			mac = (const u8 *)ndev->dev_addr;
> +
> +			if (!is_valid_ether_addr(mac))
> +				return -EINVAL;
> +
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD1,
> +				      (mac[1] << 8 | mac[0]));
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD2,
> +				      (mac[3] << 8 | mac[2]));
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD3,
> +				      (mac[5] << 8 | mac[4]));
> +
> +			val_rxcfg |= DP83867_WOL_MAGIC_EN;
> +		} else {
> +			val_rxcfg &= ~DP83867_WOL_MAGIC_EN;
> +		}
> +
> +		if (wol->wolopts & WAKE_MAGICSECURE) {
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[1] << 8) | wol->sopass[0]);
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[3] << 8) | wol->sopass[2]);
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[5] << 8) | wol->sopass[4]);
> +
> +			val_rxcfg |= DP83867_WOL_SEC_EN;
> +		} else {
> +			val_rxcfg &= ~DP83867_WOL_SEC_EN;
> +		}
> +
> +		if (wol->wolopts & WAKE_UCAST)
> +			val_rxcfg |= DP83867_WOL_UCAST_EN;
> +		else
> +			val_rxcfg &= ~DP83867_WOL_UCAST_EN;
> +
> +		if (wol->wolopts & WAKE_BCAST)
> +			val_rxcfg |= DP83867_WOL_BCAST_EN;
> +		else
> +			val_rxcfg &= ~DP83867_WOL_BCAST_EN;
> +	} else {
> +		val_rxcfg &= ~DP83867_WOL_ENH_MAC;
> +		val_micr &= ~MII_DP83867_MICR_WOL_INT_EN;
> +	}
> +
> +	phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG, val_rxcfg);
> +	phy_write(phydev, MII_DP83867_MICR, val_micr);
> +
> +	return 0;
> +}
> +
> +static void dp83867_get_wol(struct phy_device *phydev,
> +			    struct ethtool_wolinfo *wol)
> +{
> +	u16 value, sopass_val;
> +
> +	wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |
> +			WAKE_MAGICSECURE);
> +	wol->wolopts = 0;
> +
> +	value = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
> +
> +	if (value & DP83867_WOL_UCAST_EN)
> +		wol->wolopts |= WAKE_UCAST;
> +
> +	if (value & DP83867_WOL_BCAST_EN)
> +		wol->wolopts |= WAKE_BCAST;
> +
> +	if (value & DP83867_WOL_MAGIC_EN)
> +		wol->wolopts |= WAKE_MAGIC;
> +
> +	if (value & DP83867_WOL_SEC_EN) {
> +		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
> +					  DP83867_RXFSOP1);
> +		wol->sopass[0] = (sopass_val & 0xff);
> +		wol->sopass[1] = (sopass_val >> 8);
> +
> +		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
> +					  DP83867_RXFSOP2);
> +		wol->sopass[2] = (sopass_val & 0xff);
> +		wol->sopass[3] = (sopass_val >> 8);
> +
> +		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
> +					  DP83867_RXFSOP3);
> +		wol->sopass[4] = (sopass_val & 0xff);
> +		wol->sopass[5] = (sopass_val >> 8);
> +
> +		wol->wolopts |= WAKE_MAGICSECURE;
> +	}
> +
> +	if (!(value & DP83867_WOL_ENH_MAC))
> +		wol->wolopts = 0;
> +}
> +
>  static int dp83867_config_intr(struct phy_device *phydev)
>  {
>  	int micr_status;
> @@ -463,6 +589,9 @@ static struct phy_driver dp83867_driver[] = {
>  		.config_init	= dp83867_config_init,
>  		.soft_reset	= dp83867_phy_reset,
>  
> +		.get_wol	= dp83867_get_wol,
> +		.set_wol	= dp83867_set_wol,
> +
>  		/* IRQ related */
>  		.ack_interrupt	= dp83867_ack_interrupt,
>  		.config_intr	= dp83867_config_intr,

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] net: phy: dp83867: support Wake on LAN
  2019-10-22 13:06 ` [PATCH v2] " Thomas Hämmerle
  2019-10-22 13:30   ` Michael Tretter
@ 2019-10-22 14:00   ` Andrew Lunn
  2019-10-22 18:40   ` Heiner Kallweit
  2019-10-24 22:16   ` David Miller
  3 siblings, 0 replies; 11+ messages in thread
From: Andrew Lunn @ 2019-10-22 14:00 UTC (permalink / raw)
  To: Thomas Hämmerle; +Cc: netdev, f.fainelli, hkallweit1, davem, m.tretter

On Tue, Oct 22, 2019 at 01:06:35PM +0000, Thomas Hämmerle wrote:
> From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
> 
> This adds WoL support on TI DP83867 for magic, magic secure, unicast and
> broadcast.
> 
> Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] net: phy: dp83867: support Wake on LAN
  2019-10-22 13:06 ` [PATCH v2] " Thomas Hämmerle
  2019-10-22 13:30   ` Michael Tretter
  2019-10-22 14:00   ` Andrew Lunn
@ 2019-10-22 18:40   ` Heiner Kallweit
  2019-10-22 19:15     ` Andrew Lunn
  2019-10-24 22:16   ` David Miller
  3 siblings, 1 reply; 11+ messages in thread
From: Heiner Kallweit @ 2019-10-22 18:40 UTC (permalink / raw)
  To: Thomas Hämmerle, netdev; +Cc: andrew, f.fainelli, davem, m.tretter

On 22.10.2019 15:06, Thomas Hämmerle wrote:
> From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
> 
> This adds WoL support on TI DP83867 for magic, magic secure, unicast and
> broadcast.
> 
> Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
> ---
>  drivers/net/phy/dp83867.c | 131 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 130 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
> index 37fceaf..1a3f8f1 100644
> --- a/drivers/net/phy/dp83867.c
> +++ b/drivers/net/phy/dp83867.c
> @@ -12,6 +12,8 @@
>  #include <linux/of.h>
>  #include <linux/phy.h>
>  #include <linux/delay.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
>  
>  #include <dt-bindings/net/ti-dp83867.h>
>  
> @@ -21,8 +23,9 @@
>  #define MII_DP83867_PHYCTRL	0x10
>  #define MII_DP83867_MICR	0x12
>  #define MII_DP83867_ISR		0x13
> -#define DP83867_CTRL		0x1f
> +#define DP83867_CFG2		0x14
>  #define DP83867_CFG3		0x1e
> +#define DP83867_CTRL		0x1f
>  
>  /* Extended Registers */
>  #define DP83867_CFG4            0x0031
> @@ -36,6 +39,13 @@
>  #define DP83867_STRAP_STS1	0x006E
>  #define DP83867_STRAP_STS2	0x006f
>  #define DP83867_RGMIIDCTL	0x0086
> +#define DP83867_RXFCFG		0x0134
> +#define DP83867_RXFPMD1	0x0136
> +#define DP83867_RXFPMD2	0x0137
> +#define DP83867_RXFPMD3	0x0138
> +#define DP83867_RXFSOP1	0x0139
> +#define DP83867_RXFSOP2	0x013A
> +#define DP83867_RXFSOP3	0x013B
>  #define DP83867_IO_MUX_CFG	0x0170
>  #define DP83867_SGMIICTL	0x00D3
>  #define DP83867_10M_SGMII_CFG   0x016F
> @@ -65,6 +75,13 @@
>  /* SGMIICTL bits */
>  #define DP83867_SGMII_TYPE		BIT(14)
>  
> +/* RXFCFG bits*/
> +#define DP83867_WOL_MAGIC_EN		BIT(0)
> +#define DP83867_WOL_BCAST_EN		BIT(2)
> +#define DP83867_WOL_UCAST_EN		BIT(4)
> +#define DP83867_WOL_SEC_EN		BIT(5)
> +#define DP83867_WOL_ENH_MAC		BIT(7)
> +
>  /* STRAP_STS1 bits */
>  #define DP83867_STRAP_STS1_RESERVED		BIT(11)
>  
> @@ -126,6 +143,115 @@ static int dp83867_ack_interrupt(struct phy_device *phydev)
>  	return 0;
>  }
>  
> +static int dp83867_set_wol(struct phy_device *phydev,
> +			   struct ethtool_wolinfo *wol)
> +{
> +	struct net_device *ndev = phydev->attached_dev;
> +	u16 val_rxcfg, val_micr;
> +	const u8 *mac;
> +
> +	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
> +	val_micr = phy_read(phydev, MII_DP83867_MICR);
> +
> +	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
> +			    WAKE_BCAST)) {
> +		val_rxcfg |= DP83867_WOL_ENH_MAC;
> +		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
> +
> +		if (wol->wolopts & WAKE_MAGIC) {
> +			mac = (const u8 *)ndev->dev_addr;

Using a cast to add/remove a const qualifier usually isn't too nice.
Why not simply declare mac w/o const?

Also PHY might not be attached. I think ndev should be checked for NULL.

> +
> +			if (!is_valid_ether_addr(mac))
> +				return -EINVAL;
> +
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD1,
> +				      (mac[1] << 8 | mac[0]));
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD2,
> +				      (mac[3] << 8 | mac[2]));
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD3,
> +				      (mac[5] << 8 | mac[4]));
> +
> +			val_rxcfg |= DP83867_WOL_MAGIC_EN;
> +		} else {
> +			val_rxcfg &= ~DP83867_WOL_MAGIC_EN;
> +		}
> +
> +		if (wol->wolopts & WAKE_MAGICSECURE) {
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[1] << 8) | wol->sopass[0]);
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[3] << 8) | wol->sopass[2]);
> +			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
> +				      (wol->sopass[5] << 8) | wol->sopass[4]);
> +
> +			val_rxcfg |= DP83867_WOL_SEC_EN;
> +		} else {
> +			val_rxcfg &= ~DP83867_WOL_SEC_EN;
> +		}
> +
> +		if (wol->wolopts & WAKE_UCAST)
> +			val_rxcfg |= DP83867_WOL_UCAST_EN;
> +		else
> +			val_rxcfg &= ~DP83867_WOL_UCAST_EN;
> +
> +		if (wol->wolopts & WAKE_BCAST)
> +			val_rxcfg |= DP83867_WOL_BCAST_EN;
> +		else
> +			val_rxcfg &= ~DP83867_WOL_BCAST_EN;
> +	} else {
> +		val_rxcfg &= ~DP83867_WOL_ENH_MAC;
> +		val_micr &= ~MII_DP83867_MICR_WOL_INT_EN;
> +	}
> +
> +	phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG, val_rxcfg);
> +	phy_write(phydev, MII_DP83867_MICR, val_micr);
> +
> +	return 0;
> +}
> +
> +static void dp83867_get_wol(struct phy_device *phydev,
> +			    struct ethtool_wolinfo *wol)
> +{
> +	u16 value, sopass_val;
> +
> +	wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |
> +			WAKE_MAGICSECURE);
> +	wol->wolopts = 0;
> +
> +	value = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
> +
> +	if (value & DP83867_WOL_UCAST_EN)
> +		wol->wolopts |= WAKE_UCAST;
> +
> +	if (value & DP83867_WOL_BCAST_EN)
> +		wol->wolopts |= WAKE_BCAST;
> +
> +	if (value & DP83867_WOL_MAGIC_EN)
> +		wol->wolopts |= WAKE_MAGIC;
> +
> +	if (value & DP83867_WOL_SEC_EN) {
> +		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
> +					  DP83867_RXFSOP1);
> +		wol->sopass[0] = (sopass_val & 0xff);
> +		wol->sopass[1] = (sopass_val >> 8);
> +
> +		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
> +					  DP83867_RXFSOP2);
> +		wol->sopass[2] = (sopass_val & 0xff);
> +		wol->sopass[3] = (sopass_val >> 8);
> +
> +		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
> +					  DP83867_RXFSOP3);
> +		wol->sopass[4] = (sopass_val & 0xff);
> +		wol->sopass[5] = (sopass_val >> 8);
> +
> +		wol->wolopts |= WAKE_MAGICSECURE;
> +	}
> +
> +	if (!(value & DP83867_WOL_ENH_MAC))
> +		wol->wolopts = 0;
> +}
> +
>  static int dp83867_config_intr(struct phy_device *phydev)
>  {
>  	int micr_status;
> @@ -463,6 +589,9 @@ static struct phy_driver dp83867_driver[] = {
>  		.config_init	= dp83867_config_init,
>  		.soft_reset	= dp83867_phy_reset,
>  
> +		.get_wol	= dp83867_get_wol,
> +		.set_wol	= dp83867_set_wol,
> +
>  		/* IRQ related */
>  		.ack_interrupt	= dp83867_ack_interrupt,
>  		.config_intr	= dp83867_config_intr,
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] net: phy: dp83867: support Wake on LAN
  2019-10-22 18:40   ` Heiner Kallweit
@ 2019-10-22 19:15     ` Andrew Lunn
  0 siblings, 0 replies; 11+ messages in thread
From: Andrew Lunn @ 2019-10-22 19:15 UTC (permalink / raw)
  To: Heiner Kallweit
  Cc: Thomas Hämmerle, netdev, f.fainelli, davem, m.tretter

> > +static int dp83867_set_wol(struct phy_device *phydev,
> > +			   struct ethtool_wolinfo *wol)
> > +{
> > +	struct net_device *ndev = phydev->attached_dev;
> > +	u16 val_rxcfg, val_micr;
> > +	const u8 *mac;
> > +
> > +	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
> > +	val_micr = phy_read(phydev, MII_DP83867_MICR);
> > +
> > +	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
> > +			    WAKE_BCAST)) {
> > +		val_rxcfg |= DP83867_WOL_ENH_MAC;
> > +		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
> > +
> > +		if (wol->wolopts & WAKE_MAGIC) {
> > +			mac = (const u8 *)ndev->dev_addr;
> 
> Using a cast to add/remove a const qualifier usually isn't too nice.
> Why not simply declare mac w/o const?
> 
> Also PHY might not be attached. I think ndev should be checked for NULL.

Hi Heiner

I thought about that as well. But the ethtool API is invoked using a
network interface name. It would be odd to call into the PHY driver if
the PHY was not attached. And the resulting Oops would help us
identify the bug.

Plus all the other PHY drivers which implement magic packet WoL assume
the PHY is attached. It could be they are all broken i suppose...

    Andrew

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] net: phy: dp83867: support Wake on LAN
  2019-10-22 13:06 ` [PATCH v2] " Thomas Hämmerle
                     ` (2 preceding siblings ...)
  2019-10-22 18:40   ` Heiner Kallweit
@ 2019-10-24 22:16   ` David Miller
  2019-10-25  7:55     ` Thomas Hämmerle
  3 siblings, 1 reply; 11+ messages in thread
From: David Miller @ 2019-10-24 22:16 UTC (permalink / raw)
  To: Thomas.Haemmerle; +Cc: netdev, andrew, f.fainelli, hkallweit1, m.tretter

From: Thomas Hämmerle <Thomas.Haemmerle@wolfvision.net>
Date: Tue, 22 Oct 2019 13:06:35 +0000

> +	const u8 *mac;
> +
> +	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
> +	val_micr = phy_read(phydev, MII_DP83867_MICR);
> +
> +	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
> +			    WAKE_BCAST)) {
> +		val_rxcfg |= DP83867_WOL_ENH_MAC;
> +		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
> +
> +		if (wol->wolopts & WAKE_MAGIC) {
> +			mac = (const u8 *)ndev->dev_addr;

Please declare 'mac' non-const and get rid of this cast, as suggested by Heiner.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2] net: phy: dp83867: support Wake on LAN
  2019-10-24 22:16   ` David Miller
@ 2019-10-25  7:55     ` Thomas Hämmerle
  0 siblings, 0 replies; 11+ messages in thread
From: Thomas Hämmerle @ 2019-10-25  7:55 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, andrew, f.fainelli, hkallweit1, m.tretter

Hi David,

On 25.10.19 00:17, David Miller wrote:
> From: Thomas Hämmerle <Thomas.Haemmerle@wolfvision.net>
> Date: Tue, 22 Oct 2019 13:06:35 +0000
> 
>> +	const u8 *mac;
>> +
>> +	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
>> +	val_micr = phy_read(phydev, MII_DP83867_MICR);
>> +
>> +	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
>> +			    WAKE_BCAST)) {
>> +		val_rxcfg |= DP83867_WOL_ENH_MAC;
>> +		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
>> +
>> +		if (wol->wolopts & WAKE_MAGIC) {
>> +			mac = (const u8 *)ndev->dev_addr;
> 
> Please declare 'mac' non-const and get rid of this cast, as suggested by Heiner.
> 

I agree with Heiner and you, however since I first took a into other phy
drivers (at803x, dp83822, dp83tc811) and how set_wol() is done there,
I've implemented it the same way.

So maybe we should also change it in the other drivers.

Thomas

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v3] net: phy: dp83867: support Wake on LAN
  2019-10-22 11:11 [PATCH] net: phy: dp83867: support Wake on LAN Thomas Hämmerle
  2019-10-22 12:34 ` Andrew Lunn
  2019-10-22 13:06 ` [PATCH v2] " Thomas Hämmerle
@ 2019-10-28  8:08 ` Thomas Hämmerle
  2019-10-29 23:43   ` David Miller
  2 siblings, 1 reply; 11+ messages in thread
From: Thomas Hämmerle @ 2019-10-28  8:08 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, hkallweit1, davem, m.tretter, Thomas Hämmerle

From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>

This adds WoL support on TI DP83867 for magic, magic secure, unicast and
broadcast.

Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
---
 drivers/net/phy/dp83867.c | 131 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 130 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 37fceaf..7874271 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -12,6 +12,8 @@
 #include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 
 #include <dt-bindings/net/ti-dp83867.h>
 
@@ -21,8 +23,9 @@
 #define MII_DP83867_PHYCTRL	0x10
 #define MII_DP83867_MICR	0x12
 #define MII_DP83867_ISR		0x13
-#define DP83867_CTRL		0x1f
+#define DP83867_CFG2		0x14
 #define DP83867_CFG3		0x1e
+#define DP83867_CTRL		0x1f
 
 /* Extended Registers */
 #define DP83867_CFG4            0x0031
@@ -36,6 +39,13 @@
 #define DP83867_STRAP_STS1	0x006E
 #define DP83867_STRAP_STS2	0x006f
 #define DP83867_RGMIIDCTL	0x0086
+#define DP83867_RXFCFG		0x0134
+#define DP83867_RXFPMD1	0x0136
+#define DP83867_RXFPMD2	0x0137
+#define DP83867_RXFPMD3	0x0138
+#define DP83867_RXFSOP1	0x0139
+#define DP83867_RXFSOP2	0x013A
+#define DP83867_RXFSOP3	0x013B
 #define DP83867_IO_MUX_CFG	0x0170
 #define DP83867_SGMIICTL	0x00D3
 #define DP83867_10M_SGMII_CFG   0x016F
@@ -65,6 +75,13 @@
 /* SGMIICTL bits */
 #define DP83867_SGMII_TYPE		BIT(14)
 
+/* RXFCFG bits*/
+#define DP83867_WOL_MAGIC_EN		BIT(0)
+#define DP83867_WOL_BCAST_EN		BIT(2)
+#define DP83867_WOL_UCAST_EN		BIT(4)
+#define DP83867_WOL_SEC_EN		BIT(5)
+#define DP83867_WOL_ENH_MAC		BIT(7)
+
 /* STRAP_STS1 bits */
 #define DP83867_STRAP_STS1_RESERVED		BIT(11)
 
@@ -126,6 +143,115 @@ static int dp83867_ack_interrupt(struct phy_device *phydev)
 	return 0;
 }
 
+static int dp83867_set_wol(struct phy_device *phydev,
+			   struct ethtool_wolinfo *wol)
+{
+	struct net_device *ndev = phydev->attached_dev;
+	u16 val_rxcfg, val_micr;
+	u8 *mac;
+
+	val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
+	val_micr = phy_read(phydev, MII_DP83867_MICR);
+
+	if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
+			    WAKE_BCAST)) {
+		val_rxcfg |= DP83867_WOL_ENH_MAC;
+		val_micr |= MII_DP83867_MICR_WOL_INT_EN;
+
+		if (wol->wolopts & WAKE_MAGIC) {
+			mac = (u8 *)ndev->dev_addr;
+
+			if (!is_valid_ether_addr(mac))
+				return -EINVAL;
+
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD1,
+				      (mac[1] << 8 | mac[0]));
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD2,
+				      (mac[3] << 8 | mac[2]));
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD3,
+				      (mac[5] << 8 | mac[4]));
+
+			val_rxcfg |= DP83867_WOL_MAGIC_EN;
+		} else {
+			val_rxcfg &= ~DP83867_WOL_MAGIC_EN;
+		}
+
+		if (wol->wolopts & WAKE_MAGICSECURE) {
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[1] << 8) | wol->sopass[0]);
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[3] << 8) | wol->sopass[2]);
+			phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
+				      (wol->sopass[5] << 8) | wol->sopass[4]);
+
+			val_rxcfg |= DP83867_WOL_SEC_EN;
+		} else {
+			val_rxcfg &= ~DP83867_WOL_SEC_EN;
+		}
+
+		if (wol->wolopts & WAKE_UCAST)
+			val_rxcfg |= DP83867_WOL_UCAST_EN;
+		else
+			val_rxcfg &= ~DP83867_WOL_UCAST_EN;
+
+		if (wol->wolopts & WAKE_BCAST)
+			val_rxcfg |= DP83867_WOL_BCAST_EN;
+		else
+			val_rxcfg &= ~DP83867_WOL_BCAST_EN;
+	} else {
+		val_rxcfg &= ~DP83867_WOL_ENH_MAC;
+		val_micr &= ~MII_DP83867_MICR_WOL_INT_EN;
+	}
+
+	phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG, val_rxcfg);
+	phy_write(phydev, MII_DP83867_MICR, val_micr);
+
+	return 0;
+}
+
+static void dp83867_get_wol(struct phy_device *phydev,
+			    struct ethtool_wolinfo *wol)
+{
+	u16 value, sopass_val;
+
+	wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |
+			WAKE_MAGICSECURE);
+	wol->wolopts = 0;
+
+	value = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
+
+	if (value & DP83867_WOL_UCAST_EN)
+		wol->wolopts |= WAKE_UCAST;
+
+	if (value & DP83867_WOL_BCAST_EN)
+		wol->wolopts |= WAKE_BCAST;
+
+	if (value & DP83867_WOL_MAGIC_EN)
+		wol->wolopts |= WAKE_MAGIC;
+
+	if (value & DP83867_WOL_SEC_EN) {
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP1);
+		wol->sopass[0] = (sopass_val & 0xff);
+		wol->sopass[1] = (sopass_val >> 8);
+
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP2);
+		wol->sopass[2] = (sopass_val & 0xff);
+		wol->sopass[3] = (sopass_val >> 8);
+
+		sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
+					  DP83867_RXFSOP3);
+		wol->sopass[4] = (sopass_val & 0xff);
+		wol->sopass[5] = (sopass_val >> 8);
+
+		wol->wolopts |= WAKE_MAGICSECURE;
+	}
+
+	if (!(value & DP83867_WOL_ENH_MAC))
+		wol->wolopts = 0;
+}
+
 static int dp83867_config_intr(struct phy_device *phydev)
 {
 	int micr_status;
@@ -463,6 +589,9 @@ static struct phy_driver dp83867_driver[] = {
 		.config_init	= dp83867_config_init,
 		.soft_reset	= dp83867_phy_reset,
 
+		.get_wol	= dp83867_get_wol,
+		.set_wol	= dp83867_set_wol,
+
 		/* IRQ related */
 		.ack_interrupt	= dp83867_ack_interrupt,
 		.config_intr	= dp83867_config_intr,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v3] net: phy: dp83867: support Wake on LAN
  2019-10-28  8:08 ` [PATCH v3] " Thomas Hämmerle
@ 2019-10-29 23:43   ` David Miller
  0 siblings, 0 replies; 11+ messages in thread
From: David Miller @ 2019-10-29 23:43 UTC (permalink / raw)
  To: Thomas.Haemmerle; +Cc: netdev, andrew, f.fainelli, hkallweit1, m.tretter

From: Thomas Hämmerle <Thomas.Haemmerle@wolfvision.net>
Date: Mon, 28 Oct 2019 08:08:14 +0000

> From: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>
> 
> This adds WoL support on TI DP83867 for magic, magic secure, unicast and
> broadcast.
> 
> Signed-off-by: Thomas Haemmerle <thomas.haemmerle@wolfvision.net>

Applied to net-next, thanks Thomas.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-10-29 23:43 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-22 11:11 [PATCH] net: phy: dp83867: support Wake on LAN Thomas Hämmerle
2019-10-22 12:34 ` Andrew Lunn
2019-10-22 13:06 ` [PATCH v2] " Thomas Hämmerle
2019-10-22 13:30   ` Michael Tretter
2019-10-22 14:00   ` Andrew Lunn
2019-10-22 18:40   ` Heiner Kallweit
2019-10-22 19:15     ` Andrew Lunn
2019-10-24 22:16   ` David Miller
2019-10-25  7:55     ` Thomas Hämmerle
2019-10-28  8:08 ` [PATCH v3] " Thomas Hämmerle
2019-10-29 23:43   ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.