^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Driver for the Texas Instruments DP83822, DP83825 and DP83826 PHYs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2017 Texas Instruments Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define DP83822_PHY_ID 0x2000a240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define DP83825S_PHY_ID 0x2000a140
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define DP83825I_PHY_ID 0x2000a150
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define DP83825CM_PHY_ID 0x2000a160
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define DP83825CS_PHY_ID 0x2000a170
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define DP83826C_PHY_ID 0x2000a130
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define DP83826NC_PHY_ID 0x2000a110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define DP83822_DEVADDR 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MII_DP83822_CTRL_2 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define MII_DP83822_PHYSTS 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MII_DP83822_PHYSCR 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MII_DP83822_MISR1 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MII_DP83822_MISR2 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MII_DP83822_FCSCR 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MII_DP83822_RCSR 0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define MII_DP83822_RESET_CTRL 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MII_DP83822_GENCFG 0x465
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MII_DP83822_SOR1 0x467
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* GENCFG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define DP83822_SIG_DET_LOW BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Control Register 2 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DP83822_FX_ENABLE BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DP83822_HW_RESET BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DP83822_SW_RESET BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* PHY STS bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DP83822_PHYSTS_DUPLEX BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DP83822_PHYSTS_10 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DP83822_PHYSTS_LINK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* PHYSCR Register Fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define DP83822_PHYSCR_INT_OE BIT(0) /* Interrupt Output Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define DP83822_PHYSCR_INTEN BIT(1) /* Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* MISR1 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define DP83822_RX_ERR_HF_INT_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define DP83822_FALSE_CARRIER_HF_INT_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define DP83822_ANEG_COMPLETE_INT_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define DP83822_DUP_MODE_CHANGE_INT_EN BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define DP83822_SPEED_CHANGED_INT_EN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define DP83822_LINK_STAT_INT_EN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define DP83822_ENERGY_DET_INT_EN BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define DP83822_LINK_QUAL_INT_EN BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* MISR2 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define DP83822_JABBER_DET_INT_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define DP83822_WOL_PKT_INT_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define DP83822_SLEEP_MODE_INT_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define DP83822_MDI_XOVER_INT_EN BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define DP83822_LB_FIFO_INT_EN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define DP83822_PAGE_RX_INT_EN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define DP83822_ANEG_ERR_INT_EN BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define DP83822_EEE_ERROR_CHANGE_INT_EN BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* INT_STAT1 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define DP83822_WOL_INT_EN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define DP83822_WOL_INT_STAT BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MII_DP83822_RXSOP1 0x04a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define MII_DP83822_RXSOP2 0x04a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define MII_DP83822_RXSOP3 0x04a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* WoL Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define MII_DP83822_WOL_CFG 0x04a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define MII_DP83822_WOL_STAT 0x04a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define MII_DP83822_WOL_DA1 0x04a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define MII_DP83822_WOL_DA2 0x04a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define MII_DP83822_WOL_DA3 0x04a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* WoL bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define DP83822_WOL_MAGIC_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define DP83822_WOL_SECURE_ON BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define DP83822_WOL_EN BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define DP83822_WOL_INDICATION_SEL BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define DP83822_WOL_CLR_INDICATION BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* RSCR bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define DP83822_RX_CLK_SHIFT BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define DP83822_TX_CLK_SHIFT BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* SOR1 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define DP83822_STRAP_MODE1 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define DP83822_STRAP_MODE2 BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define DP83822_STRAP_MODE3 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define DP83822_STRAP_MODE4 GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define DP83822_COL_STRAP_MASK GENMASK(11, 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define DP83822_COL_SHIFT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define DP83822_RX_ER_STR_MASK GENMASK(9, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define DP83822_RX_ER_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define MII_DP83822_FIBER_ADVERTISE (ADVERTISED_TP | ADVERTISED_MII | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ADVERTISED_FIBRE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ADVERTISED_Pause | ADVERTISED_Asym_Pause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct dp83822_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) bool fx_signal_det_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int fx_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u16 fx_sd_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int dp83822_ack_interrupt(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) err = phy_read(phydev, MII_DP83822_MISR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) err = phy_read(phydev, MII_DP83822_MISR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int dp83822_set_wol(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct ethtool_wolinfo *wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct net_device *ndev = phydev->attached_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) const u8 *mac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) mac = (const u8 *)ndev->dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (!is_valid_ether_addr(mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* MAC addresses start with byte 5, but stored in mac[0].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * 822 PHYs store bytes 4|5, 2|3, 0|1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) (mac[1] << 8) | mac[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) (mac[3] << 8) | mac[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) (mac[5] << 8) | mac[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) value = phy_read_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) MII_DP83822_WOL_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (wol->wolopts & WAKE_MAGIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) value |= DP83822_WOL_MAGIC_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) value &= ~DP83822_WOL_MAGIC_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (wol->wolopts & WAKE_MAGICSECURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) phy_write_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) MII_DP83822_RXSOP1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) (wol->sopass[1] << 8) | wol->sopass[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) phy_write_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) MII_DP83822_RXSOP2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) (wol->sopass[3] << 8) | wol->sopass[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) phy_write_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) MII_DP83822_RXSOP3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) (wol->sopass[5] << 8) | wol->sopass[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) value |= DP83822_WOL_SECURE_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) value &= ~DP83822_WOL_SECURE_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* Clear any pending WoL interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) phy_read(phydev, MII_DP83822_MISR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) DP83822_WOL_CLR_INDICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return phy_write_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) MII_DP83822_WOL_CFG, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) MII_DP83822_WOL_CFG, DP83822_WOL_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void dp83822_get_wol(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct ethtool_wolinfo *wol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u16 sopass_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) wol->wolopts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (value & DP83822_WOL_MAGIC_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) wol->wolopts |= WAKE_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (value & DP83822_WOL_SECURE_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) MII_DP83822_RXSOP1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) wol->sopass[0] = (sopass_val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) wol->sopass[1] = (sopass_val >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) MII_DP83822_RXSOP2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) wol->sopass[2] = (sopass_val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) wol->sopass[3] = (sopass_val >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) MII_DP83822_RXSOP3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) wol->sopass[4] = (sopass_val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) wol->sopass[5] = (sopass_val >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) wol->wolopts |= WAKE_MAGICSECURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* WoL is not enabled so set wolopts to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!(value & DP83822_WOL_EN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) wol->wolopts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int dp83822_config_intr(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct dp83822_private *dp83822 = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int misr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int physcr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) misr_status = phy_read(phydev, MII_DP83822_MISR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (misr_status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return misr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) misr_status |= (DP83822_RX_ERR_HF_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) DP83822_FALSE_CARRIER_HF_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) DP83822_LINK_STAT_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) DP83822_ENERGY_DET_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) DP83822_LINK_QUAL_INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!dp83822->fx_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) misr_status |= DP83822_ANEG_COMPLETE_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) DP83822_DUP_MODE_CHANGE_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) DP83822_SPEED_CHANGED_INT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) err = phy_write(phydev, MII_DP83822_MISR1, misr_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) misr_status = phy_read(phydev, MII_DP83822_MISR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (misr_status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return misr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) misr_status |= (DP83822_JABBER_DET_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) DP83822_SLEEP_MODE_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) DP83822_LB_FIFO_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) DP83822_PAGE_RX_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) DP83822_EEE_ERROR_CHANGE_INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!dp83822->fx_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) misr_status |= DP83822_MDI_XOVER_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) DP83822_ANEG_ERR_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) DP83822_WOL_PKT_INT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) err = phy_write(phydev, MII_DP83822_MISR2, misr_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) physcr_status = phy_read(phydev, MII_DP83822_PHYSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (physcr_status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return physcr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) physcr_status |= DP83822_PHYSCR_INT_OE | DP83822_PHYSCR_INTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) err = phy_write(phydev, MII_DP83822_MISR1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) err = phy_write(phydev, MII_DP83822_MISR2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) physcr_status = phy_read(phydev, MII_DP83822_PHYSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (physcr_status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return physcr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) physcr_status &= ~DP83822_PHYSCR_INTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int dp8382x_disable_wol(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) DP83822_WOL_EN | DP83822_WOL_MAGIC_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) DP83822_WOL_SECURE_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static int dp83822_read_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct dp83822_private *dp83822 = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int status = phy_read(phydev, MII_DP83822_PHYSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int ctrl2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (dp83822->fx_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (status & DP83822_PHYSTS_LINK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) phydev->speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) phydev->duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ctrl2 = phy_read(phydev, MII_DP83822_CTRL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (ctrl2 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ctrl2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!(ctrl2 & DP83822_FX_ENABLE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret = phy_write(phydev, MII_DP83822_CTRL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) DP83822_FX_ENABLE | ctrl2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ret = genphy_read_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (status & DP83822_PHYSTS_DUPLEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) phydev->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) phydev->duplex = DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (status & DP83822_PHYSTS_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) phydev->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) phydev->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int dp83822_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct dp83822_private *dp83822 = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct device *dev = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int rgmii_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) s32 rx_int_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) s32 tx_int_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int bmcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (phy_interface_is_rgmii(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (rx_int_delay <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) rgmii_delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) rgmii_delay = DP83822_RX_CLK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (tx_int_delay <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) rgmii_delay &= ~DP83822_TX_CLK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) rgmii_delay |= DP83822_TX_CLK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (rgmii_delay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) MII_DP83822_RCSR, rgmii_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (dp83822->fx_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) err = phy_modify(phydev, MII_DP83822_CTRL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) DP83822_FX_ENABLE, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* Only allow advertising what this PHY supports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) linkmode_and(phydev->advertising, phydev->advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* Auto neg is not supported in fiber mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) bmcr = phy_read(phydev, MII_BMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (bmcr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return bmcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (bmcr & BMCR_ANENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) err = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) phydev->autoneg = AUTONEG_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* Setup fiber advertisement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) err = phy_modify_changed(phydev, MII_ADVERTISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) MII_DP83822_FIBER_ADVERTISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) MII_DP83822_FIBER_ADVERTISE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (dp83822->fx_signal_det_low) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) MII_DP83822_GENCFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) DP83822_SIG_DET_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return dp8382x_disable_wol(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int dp8382x_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return dp8382x_disable_wol(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static int dp83822_phy_reset(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_SW_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return phydev->drv->config_init(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) #ifdef CONFIG_OF_MDIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static int dp83822_of_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct dp83822_private *dp83822 = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct device *dev = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* Signal detection for the PHY is only enabled if the FX_EN and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * SD_EN pins are strapped. Signal detection can only enabled if FX_EN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * is strapped otherwise signal detection is disabled for the PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (dp83822->fx_enabled && dp83822->fx_sd_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) dp83822->fx_signal_det_low = device_property_present(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) "ti,link-loss-low");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (!dp83822->fx_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) dp83822->fx_enabled = device_property_present(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) "ti,fiber-mode");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int dp83822_of_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) #endif /* CONFIG_OF_MDIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int dp83822_read_straps(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct dp83822_private *dp83822 = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int fx_enabled, fx_sd_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) val = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_SOR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) fx_enabled = (val & DP83822_COL_STRAP_MASK) >> DP83822_COL_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (fx_enabled == DP83822_STRAP_MODE2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) fx_enabled == DP83822_STRAP_MODE3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) dp83822->fx_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (dp83822->fx_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) fx_sd_enable = (val & DP83822_RX_ER_STR_MASK) >> DP83822_RX_ER_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (fx_sd_enable == DP83822_STRAP_MODE3 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) fx_sd_enable == DP83822_STRAP_MODE4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dp83822->fx_sd_enable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static int dp83822_probe(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct dp83822_private *dp83822;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) dp83822 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83822),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (!dp83822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) phydev->priv = dp83822;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ret = dp83822_read_straps(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dp83822_of_init(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (dp83822->fx_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) phydev->port = PORT_FIBRE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static int dp83822_suspend(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (!(value & DP83822_WOL_EN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) genphy_suspend(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static int dp83822_resume(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) genphy_resume(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, value |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) DP83822_WOL_CLR_INDICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) #define DP83822_PHY_DRIVER(_id, _name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) PHY_ID_MATCH_MODEL(_id), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .name = (_name), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* PHY_BASIC_FEATURES */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) .probe = dp83822_probe, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .soft_reset = dp83822_phy_reset, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .config_init = dp83822_config_init, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .read_status = dp83822_read_status, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .get_wol = dp83822_get_wol, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .set_wol = dp83822_set_wol, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) .ack_interrupt = dp83822_ack_interrupt, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) .config_intr = dp83822_config_intr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) .suspend = dp83822_suspend, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) .resume = dp83822_resume, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) #define DP8382X_PHY_DRIVER(_id, _name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) PHY_ID_MATCH_MODEL(_id), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .name = (_name), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* PHY_BASIC_FEATURES */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .soft_reset = dp83822_phy_reset, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .config_init = dp8382x_config_init, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .get_wol = dp83822_get_wol, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .set_wol = dp83822_set_wol, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .ack_interrupt = dp83822_ack_interrupt, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .config_intr = dp83822_config_intr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) .suspend = dp83822_suspend, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .resume = dp83822_resume, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static struct phy_driver dp83822_driver[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) DP8382X_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) DP8382X_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) module_phy_driver(dp83822_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static struct mdio_device_id __maybe_unused dp83822_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) { DP83822_PHY_ID, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) { DP83825I_PHY_ID, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) { DP83826C_PHY_ID, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) { DP83826NC_PHY_ID, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) { DP83825S_PHY_ID, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) { DP83825CM_PHY_ID, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) { DP83825CS_PHY_ID, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) MODULE_DEVICE_TABLE(mdio, dp83822_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) MODULE_LICENSE("GPL v2");