1 // SPDX-License-Identifier: GPL-2.0 2 /* Driver for the Texas Instruments DP83822, DP83825 and DP83826 PHYs. 3 * 4 * Copyright (C) 2017 Texas Instruments Inc. 5 */ 6 7 #include <linux/ethtool.h> 8 #include <linux/etherdevice.h> 9 #include <linux/kernel.h> 10 #include <linux/mii.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/phy.h> 14 #include <linux/netdevice.h> 15 16 #define DP83822_PHY_ID 0x2000a240 17 #define DP83825S_PHY_ID 0x2000a140 18 #define DP83825I_PHY_ID 0x2000a150 19 #define DP83825CM_PHY_ID 0x2000a160 20 #define DP83825CS_PHY_ID 0x2000a170 21 #define DP83826C_PHY_ID 0x2000a130 22 #define DP83826NC_PHY_ID 0x2000a110 23 24 #define DP83822_DEVADDR 0x1f 25 26 #define MII_DP83822_PHYSCR 0x11 27 #define MII_DP83822_MISR1 0x12 28 #define MII_DP83822_MISR2 0x13 29 #define MII_DP83822_RESET_CTRL 0x1f 30 31 #define DP83822_HW_RESET BIT(15) 32 #define DP83822_SW_RESET BIT(14) 33 34 /* PHYSCR Register Fields */ 35 #define DP83822_PHYSCR_INT_OE BIT(0) /* Interrupt Output Enable */ 36 #define DP83822_PHYSCR_INTEN BIT(1) /* Interrupt Enable */ 37 38 /* MISR1 bits */ 39 #define DP83822_RX_ERR_HF_INT_EN BIT(0) 40 #define DP83822_FALSE_CARRIER_HF_INT_EN BIT(1) 41 #define DP83822_ANEG_COMPLETE_INT_EN BIT(2) 42 #define DP83822_DUP_MODE_CHANGE_INT_EN BIT(3) 43 #define DP83822_SPEED_CHANGED_INT_EN BIT(4) 44 #define DP83822_LINK_STAT_INT_EN BIT(5) 45 #define DP83822_ENERGY_DET_INT_EN BIT(6) 46 #define DP83822_LINK_QUAL_INT_EN BIT(7) 47 48 /* MISR2 bits */ 49 #define DP83822_JABBER_DET_INT_EN BIT(0) 50 #define DP83822_WOL_PKT_INT_EN BIT(1) 51 #define DP83822_SLEEP_MODE_INT_EN BIT(2) 52 #define DP83822_MDI_XOVER_INT_EN BIT(3) 53 #define DP83822_LB_FIFO_INT_EN BIT(4) 54 #define DP83822_PAGE_RX_INT_EN BIT(5) 55 #define DP83822_ANEG_ERR_INT_EN BIT(6) 56 #define DP83822_EEE_ERROR_CHANGE_INT_EN BIT(7) 57 58 /* INT_STAT1 bits */ 59 #define DP83822_WOL_INT_EN BIT(4) 60 #define DP83822_WOL_INT_STAT BIT(12) 61 62 #define MII_DP83822_RXSOP1 0x04a5 63 #define MII_DP83822_RXSOP2 0x04a6 64 #define MII_DP83822_RXSOP3 0x04a7 65 66 /* WoL Registers */ 67 #define MII_DP83822_WOL_CFG 0x04a0 68 #define MII_DP83822_WOL_STAT 0x04a1 69 #define MII_DP83822_WOL_DA1 0x04a2 70 #define MII_DP83822_WOL_DA2 0x04a3 71 #define MII_DP83822_WOL_DA3 0x04a4 72 73 /* WoL bits */ 74 #define DP83822_WOL_MAGIC_EN BIT(0) 75 #define DP83822_WOL_SECURE_ON BIT(5) 76 #define DP83822_WOL_EN BIT(7) 77 #define DP83822_WOL_INDICATION_SEL BIT(8) 78 #define DP83822_WOL_CLR_INDICATION BIT(11) 79 80 static int dp83822_ack_interrupt(struct phy_device *phydev) 81 { 82 int err; 83 84 err = phy_read(phydev, MII_DP83822_MISR1); 85 if (err < 0) 86 return err; 87 88 err = phy_read(phydev, MII_DP83822_MISR2); 89 if (err < 0) 90 return err; 91 92 return 0; 93 } 94 95 static int dp83822_set_wol(struct phy_device *phydev, 96 struct ethtool_wolinfo *wol) 97 { 98 struct net_device *ndev = phydev->attached_dev; 99 u16 value; 100 const u8 *mac; 101 102 if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { 103 mac = (const u8 *)ndev->dev_addr; 104 105 if (!is_valid_ether_addr(mac)) 106 return -EINVAL; 107 108 /* MAC addresses start with byte 5, but stored in mac[0]. 109 * 822 PHYs store bytes 4|5, 2|3, 0|1 110 */ 111 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA1, 112 (mac[1] << 8) | mac[0]); 113 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA2, 114 (mac[3] << 8) | mac[2]); 115 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA3, 116 (mac[5] << 8) | mac[4]); 117 118 value = phy_read_mmd(phydev, DP83822_DEVADDR, 119 MII_DP83822_WOL_CFG); 120 if (wol->wolopts & WAKE_MAGIC) 121 value |= DP83822_WOL_MAGIC_EN; 122 else 123 value &= ~DP83822_WOL_MAGIC_EN; 124 125 if (wol->wolopts & WAKE_MAGICSECURE) { 126 phy_write_mmd(phydev, DP83822_DEVADDR, 127 MII_DP83822_RXSOP1, 128 (wol->sopass[1] << 8) | wol->sopass[0]); 129 phy_write_mmd(phydev, DP83822_DEVADDR, 130 MII_DP83822_RXSOP2, 131 (wol->sopass[3] << 8) | wol->sopass[2]); 132 phy_write_mmd(phydev, DP83822_DEVADDR, 133 MII_DP83822_RXSOP3, 134 (wol->sopass[5] << 8) | wol->sopass[4]); 135 value |= DP83822_WOL_SECURE_ON; 136 } else { 137 value &= ~DP83822_WOL_SECURE_ON; 138 } 139 140 /* Clear any pending WoL interrupt */ 141 phy_read(phydev, MII_DP83822_MISR2); 142 143 value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL | 144 DP83822_WOL_CLR_INDICATION; 145 146 return phy_write_mmd(phydev, DP83822_DEVADDR, 147 MII_DP83822_WOL_CFG, value); 148 } else { 149 return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, 150 MII_DP83822_WOL_CFG, DP83822_WOL_EN); 151 } 152 } 153 154 static void dp83822_get_wol(struct phy_device *phydev, 155 struct ethtool_wolinfo *wol) 156 { 157 int value; 158 u16 sopass_val; 159 160 wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE); 161 wol->wolopts = 0; 162 163 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 164 165 if (value & DP83822_WOL_MAGIC_EN) 166 wol->wolopts |= WAKE_MAGIC; 167 168 if (value & DP83822_WOL_SECURE_ON) { 169 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 170 MII_DP83822_RXSOP1); 171 wol->sopass[0] = (sopass_val & 0xff); 172 wol->sopass[1] = (sopass_val >> 8); 173 174 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 175 MII_DP83822_RXSOP2); 176 wol->sopass[2] = (sopass_val & 0xff); 177 wol->sopass[3] = (sopass_val >> 8); 178 179 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 180 MII_DP83822_RXSOP3); 181 wol->sopass[4] = (sopass_val & 0xff); 182 wol->sopass[5] = (sopass_val >> 8); 183 184 wol->wolopts |= WAKE_MAGICSECURE; 185 } 186 187 /* WoL is not enabled so set wolopts to 0 */ 188 if (!(value & DP83822_WOL_EN)) 189 wol->wolopts = 0; 190 } 191 192 static int dp83822_config_intr(struct phy_device *phydev) 193 { 194 int misr_status; 195 int physcr_status; 196 int err; 197 198 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 199 misr_status = phy_read(phydev, MII_DP83822_MISR1); 200 if (misr_status < 0) 201 return misr_status; 202 203 misr_status |= (DP83822_RX_ERR_HF_INT_EN | 204 DP83822_FALSE_CARRIER_HF_INT_EN | 205 DP83822_ANEG_COMPLETE_INT_EN | 206 DP83822_DUP_MODE_CHANGE_INT_EN | 207 DP83822_SPEED_CHANGED_INT_EN | 208 DP83822_LINK_STAT_INT_EN | 209 DP83822_ENERGY_DET_INT_EN | 210 DP83822_LINK_QUAL_INT_EN); 211 212 err = phy_write(phydev, MII_DP83822_MISR1, misr_status); 213 if (err < 0) 214 return err; 215 216 misr_status = phy_read(phydev, MII_DP83822_MISR2); 217 if (misr_status < 0) 218 return misr_status; 219 220 misr_status |= (DP83822_JABBER_DET_INT_EN | 221 DP83822_WOL_PKT_INT_EN | 222 DP83822_SLEEP_MODE_INT_EN | 223 DP83822_MDI_XOVER_INT_EN | 224 DP83822_LB_FIFO_INT_EN | 225 DP83822_PAGE_RX_INT_EN | 226 DP83822_ANEG_ERR_INT_EN | 227 DP83822_EEE_ERROR_CHANGE_INT_EN); 228 229 err = phy_write(phydev, MII_DP83822_MISR2, misr_status); 230 if (err < 0) 231 return err; 232 233 physcr_status = phy_read(phydev, MII_DP83822_PHYSCR); 234 if (physcr_status < 0) 235 return physcr_status; 236 237 physcr_status |= DP83822_PHYSCR_INT_OE | DP83822_PHYSCR_INTEN; 238 239 } else { 240 err = phy_write(phydev, MII_DP83822_MISR1, 0); 241 if (err < 0) 242 return err; 243 244 err = phy_write(phydev, MII_DP83822_MISR1, 0); 245 if (err < 0) 246 return err; 247 248 physcr_status = phy_read(phydev, MII_DP83822_PHYSCR); 249 if (physcr_status < 0) 250 return physcr_status; 251 252 physcr_status &= ~DP83822_PHYSCR_INTEN; 253 } 254 255 return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status); 256 } 257 258 static int dp83822_config_init(struct phy_device *phydev) 259 { 260 int value = DP83822_WOL_EN | DP83822_WOL_MAGIC_EN | 261 DP83822_WOL_SECURE_ON; 262 263 return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, 264 MII_DP83822_WOL_CFG, value); 265 } 266 267 static int dp83822_phy_reset(struct phy_device *phydev) 268 { 269 int err; 270 271 err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_HW_RESET); 272 if (err < 0) 273 return err; 274 275 dp83822_config_init(phydev); 276 277 return 0; 278 } 279 280 static int dp83822_suspend(struct phy_device *phydev) 281 { 282 int value; 283 284 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 285 286 if (!(value & DP83822_WOL_EN)) 287 genphy_suspend(phydev); 288 289 return 0; 290 } 291 292 static int dp83822_resume(struct phy_device *phydev) 293 { 294 int value; 295 296 genphy_resume(phydev); 297 298 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 299 300 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, value | 301 DP83822_WOL_CLR_INDICATION); 302 303 return 0; 304 } 305 306 #define DP83822_PHY_DRIVER(_id, _name) \ 307 { \ 308 PHY_ID_MATCH_MODEL(_id), \ 309 .name = (_name), \ 310 /* PHY_BASIC_FEATURES */ \ 311 .soft_reset = dp83822_phy_reset, \ 312 .config_init = dp83822_config_init, \ 313 .get_wol = dp83822_get_wol, \ 314 .set_wol = dp83822_set_wol, \ 315 .ack_interrupt = dp83822_ack_interrupt, \ 316 .config_intr = dp83822_config_intr, \ 317 .suspend = dp83822_suspend, \ 318 .resume = dp83822_resume, \ 319 } 320 321 static struct phy_driver dp83822_driver[] = { 322 DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"), 323 DP83822_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"), 324 DP83822_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"), 325 DP83822_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"), 326 DP83822_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"), 327 DP83822_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"), 328 DP83822_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"), 329 }; 330 module_phy_driver(dp83822_driver); 331 332 static struct mdio_device_id __maybe_unused dp83822_tbl[] = { 333 { DP83822_PHY_ID, 0xfffffff0 }, 334 { DP83825I_PHY_ID, 0xfffffff0 }, 335 { DP83826C_PHY_ID, 0xfffffff0 }, 336 { DP83826NC_PHY_ID, 0xfffffff0 }, 337 { DP83825S_PHY_ID, 0xfffffff0 }, 338 { DP83825CM_PHY_ID, 0xfffffff0 }, 339 { DP83825CS_PHY_ID, 0xfffffff0 }, 340 { }, 341 }; 342 MODULE_DEVICE_TABLE(mdio, dp83822_tbl); 343 344 MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver"); 345 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com"); 346 MODULE_LICENSE("GPL v2"); 347