Loading drivers/net/phy/dp83867.c +130 −1 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -130,6 +147,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; Loading Loading @@ -464,6 +590,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, Loading Loading
drivers/net/phy/dp83867.c +130 −1 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -130,6 +147,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; Loading Loading @@ -464,6 +590,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, Loading