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_RCSR 0x17 30 #define MII_DP83822_RESET_CTRL 0x1f 31 #define MII_DP83822_GENCFG 0x465 32 33 #define DP83822_HW_RESET BIT(15) 34 #define DP83822_SW_RESET BIT(14) 35 36 /* PHYSCR Register Fields */ 37 #define DP83822_PHYSCR_INT_OE BIT(0) /* Interrupt Output Enable */ 38 #define DP83822_PHYSCR_INTEN BIT(1) /* Interrupt Enable */ 39 40 /* MISR1 bits */ 41 #define DP83822_RX_ERR_HF_INT_EN BIT(0) 42 #define DP83822_FALSE_CARRIER_HF_INT_EN BIT(1) 43 #define DP83822_ANEG_COMPLETE_INT_EN BIT(2) 44 #define DP83822_DUP_MODE_CHANGE_INT_EN BIT(3) 45 #define DP83822_SPEED_CHANGED_INT_EN BIT(4) 46 #define DP83822_LINK_STAT_INT_EN BIT(5) 47 #define DP83822_ENERGY_DET_INT_EN BIT(6) 48 #define DP83822_LINK_QUAL_INT_EN BIT(7) 49 50 /* MISR2 bits */ 51 #define DP83822_JABBER_DET_INT_EN BIT(0) 52 #define DP83822_WOL_PKT_INT_EN BIT(1) 53 #define DP83822_SLEEP_MODE_INT_EN BIT(2) 54 #define DP83822_MDI_XOVER_INT_EN BIT(3) 55 #define DP83822_LB_FIFO_INT_EN BIT(4) 56 #define DP83822_PAGE_RX_INT_EN BIT(5) 57 #define DP83822_ANEG_ERR_INT_EN BIT(6) 58 #define DP83822_EEE_ERROR_CHANGE_INT_EN BIT(7) 59 60 /* INT_STAT1 bits */ 61 #define DP83822_WOL_INT_EN BIT(4) 62 #define DP83822_WOL_INT_STAT BIT(12) 63 64 #define MII_DP83822_RXSOP1 0x04a5 65 #define MII_DP83822_RXSOP2 0x04a6 66 #define MII_DP83822_RXSOP3 0x04a7 67 68 /* WoL Registers */ 69 #define MII_DP83822_WOL_CFG 0x04a0 70 #define MII_DP83822_WOL_STAT 0x04a1 71 #define MII_DP83822_WOL_DA1 0x04a2 72 #define MII_DP83822_WOL_DA2 0x04a3 73 #define MII_DP83822_WOL_DA3 0x04a4 74 75 /* WoL bits */ 76 #define DP83822_WOL_MAGIC_EN BIT(0) 77 #define DP83822_WOL_SECURE_ON BIT(5) 78 #define DP83822_WOL_EN BIT(7) 79 #define DP83822_WOL_INDICATION_SEL BIT(8) 80 #define DP83822_WOL_CLR_INDICATION BIT(11) 81 82 /* RSCR bits */ 83 #define DP83822_RX_CLK_SHIFT BIT(12) 84 #define DP83822_TX_CLK_SHIFT BIT(11) 85 86 static int dp83822_ack_interrupt(struct phy_device *phydev) 87 { 88 int err; 89 90 err = phy_read(phydev, MII_DP83822_MISR1); 91 if (err < 0) 92 return err; 93 94 err = phy_read(phydev, MII_DP83822_MISR2); 95 if (err < 0) 96 return err; 97 98 return 0; 99 } 100 101 static int dp83822_set_wol(struct phy_device *phydev, 102 struct ethtool_wolinfo *wol) 103 { 104 struct net_device *ndev = phydev->attached_dev; 105 u16 value; 106 const u8 *mac; 107 108 if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { 109 mac = (const u8 *)ndev->dev_addr; 110 111 if (!is_valid_ether_addr(mac)) 112 return -EINVAL; 113 114 /* MAC addresses start with byte 5, but stored in mac[0]. 115 * 822 PHYs store bytes 4|5, 2|3, 0|1 116 */ 117 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA1, 118 (mac[1] << 8) | mac[0]); 119 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA2, 120 (mac[3] << 8) | mac[2]); 121 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA3, 122 (mac[5] << 8) | mac[4]); 123 124 value = phy_read_mmd(phydev, DP83822_DEVADDR, 125 MII_DP83822_WOL_CFG); 126 if (wol->wolopts & WAKE_MAGIC) 127 value |= DP83822_WOL_MAGIC_EN; 128 else 129 value &= ~DP83822_WOL_MAGIC_EN; 130 131 if (wol->wolopts & WAKE_MAGICSECURE) { 132 phy_write_mmd(phydev, DP83822_DEVADDR, 133 MII_DP83822_RXSOP1, 134 (wol->sopass[1] << 8) | wol->sopass[0]); 135 phy_write_mmd(phydev, DP83822_DEVADDR, 136 MII_DP83822_RXSOP2, 137 (wol->sopass[3] << 8) | wol->sopass[2]); 138 phy_write_mmd(phydev, DP83822_DEVADDR, 139 MII_DP83822_RXSOP3, 140 (wol->sopass[5] << 8) | wol->sopass[4]); 141 value |= DP83822_WOL_SECURE_ON; 142 } else { 143 value &= ~DP83822_WOL_SECURE_ON; 144 } 145 146 /* Clear any pending WoL interrupt */ 147 phy_read(phydev, MII_DP83822_MISR2); 148 149 value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL | 150 DP83822_WOL_CLR_INDICATION; 151 152 return phy_write_mmd(phydev, DP83822_DEVADDR, 153 MII_DP83822_WOL_CFG, value); 154 } else { 155 return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, 156 MII_DP83822_WOL_CFG, DP83822_WOL_EN); 157 } 158 } 159 160 static void dp83822_get_wol(struct phy_device *phydev, 161 struct ethtool_wolinfo *wol) 162 { 163 int value; 164 u16 sopass_val; 165 166 wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE); 167 wol->wolopts = 0; 168 169 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 170 171 if (value & DP83822_WOL_MAGIC_EN) 172 wol->wolopts |= WAKE_MAGIC; 173 174 if (value & DP83822_WOL_SECURE_ON) { 175 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 176 MII_DP83822_RXSOP1); 177 wol->sopass[0] = (sopass_val & 0xff); 178 wol->sopass[1] = (sopass_val >> 8); 179 180 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 181 MII_DP83822_RXSOP2); 182 wol->sopass[2] = (sopass_val & 0xff); 183 wol->sopass[3] = (sopass_val >> 8); 184 185 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 186 MII_DP83822_RXSOP3); 187 wol->sopass[4] = (sopass_val & 0xff); 188 wol->sopass[5] = (sopass_val >> 8); 189 190 wol->wolopts |= WAKE_MAGICSECURE; 191 } 192 193 /* WoL is not enabled so set wolopts to 0 */ 194 if (!(value & DP83822_WOL_EN)) 195 wol->wolopts = 0; 196 } 197 198 static int dp83822_config_intr(struct phy_device *phydev) 199 { 200 int misr_status; 201 int physcr_status; 202 int err; 203 204 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 205 misr_status = phy_read(phydev, MII_DP83822_MISR1); 206 if (misr_status < 0) 207 return misr_status; 208 209 misr_status |= (DP83822_RX_ERR_HF_INT_EN | 210 DP83822_FALSE_CARRIER_HF_INT_EN | 211 DP83822_ANEG_COMPLETE_INT_EN | 212 DP83822_DUP_MODE_CHANGE_INT_EN | 213 DP83822_SPEED_CHANGED_INT_EN | 214 DP83822_LINK_STAT_INT_EN | 215 DP83822_ENERGY_DET_INT_EN | 216 DP83822_LINK_QUAL_INT_EN); 217 218 err = phy_write(phydev, MII_DP83822_MISR1, misr_status); 219 if (err < 0) 220 return err; 221 222 misr_status = phy_read(phydev, MII_DP83822_MISR2); 223 if (misr_status < 0) 224 return misr_status; 225 226 misr_status |= (DP83822_JABBER_DET_INT_EN | 227 DP83822_WOL_PKT_INT_EN | 228 DP83822_SLEEP_MODE_INT_EN | 229 DP83822_MDI_XOVER_INT_EN | 230 DP83822_LB_FIFO_INT_EN | 231 DP83822_PAGE_RX_INT_EN | 232 DP83822_ANEG_ERR_INT_EN | 233 DP83822_EEE_ERROR_CHANGE_INT_EN); 234 235 err = phy_write(phydev, MII_DP83822_MISR2, misr_status); 236 if (err < 0) 237 return err; 238 239 physcr_status = phy_read(phydev, MII_DP83822_PHYSCR); 240 if (physcr_status < 0) 241 return physcr_status; 242 243 physcr_status |= DP83822_PHYSCR_INT_OE | DP83822_PHYSCR_INTEN; 244 245 } else { 246 err = phy_write(phydev, MII_DP83822_MISR1, 0); 247 if (err < 0) 248 return err; 249 250 err = phy_write(phydev, MII_DP83822_MISR1, 0); 251 if (err < 0) 252 return err; 253 254 physcr_status = phy_read(phydev, MII_DP83822_PHYSCR); 255 if (physcr_status < 0) 256 return physcr_status; 257 258 physcr_status &= ~DP83822_PHYSCR_INTEN; 259 } 260 261 return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status); 262 } 263 264 static int dp8382x_disable_wol(struct phy_device *phydev) 265 { 266 int value = DP83822_WOL_EN | DP83822_WOL_MAGIC_EN | 267 DP83822_WOL_SECURE_ON; 268 269 return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, 270 MII_DP83822_WOL_CFG, value); 271 } 272 273 static int dp83822_config_init(struct phy_device *phydev) 274 { 275 struct device *dev = &phydev->mdio.dev; 276 int rgmii_delay; 277 s32 rx_int_delay; 278 s32 tx_int_delay; 279 int err = 0; 280 281 if (phy_interface_is_rgmii(phydev)) { 282 rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, 283 true); 284 285 if (rx_int_delay <= 0) 286 rgmii_delay = 0; 287 else 288 rgmii_delay = DP83822_RX_CLK_SHIFT; 289 290 tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, 291 false); 292 if (tx_int_delay <= 0) 293 rgmii_delay &= ~DP83822_TX_CLK_SHIFT; 294 else 295 rgmii_delay |= DP83822_TX_CLK_SHIFT; 296 297 if (rgmii_delay) { 298 err = phy_set_bits_mmd(phydev, DP83822_DEVADDR, 299 MII_DP83822_RCSR, rgmii_delay); 300 if (err) 301 return err; 302 } 303 } 304 305 return dp8382x_disable_wol(phydev); 306 } 307 308 static int dp8382x_config_init(struct phy_device *phydev) 309 { 310 return dp8382x_disable_wol(phydev); 311 } 312 313 static int dp83822_phy_reset(struct phy_device *phydev) 314 { 315 int err; 316 317 err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_HW_RESET); 318 if (err < 0) 319 return err; 320 321 return phydev->drv->config_init(phydev); 322 } 323 324 static int dp83822_suspend(struct phy_device *phydev) 325 { 326 int value; 327 328 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 329 330 if (!(value & DP83822_WOL_EN)) 331 genphy_suspend(phydev); 332 333 return 0; 334 } 335 336 static int dp83822_resume(struct phy_device *phydev) 337 { 338 int value; 339 340 genphy_resume(phydev); 341 342 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 343 344 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, value | 345 DP83822_WOL_CLR_INDICATION); 346 347 return 0; 348 } 349 350 #define DP83822_PHY_DRIVER(_id, _name) \ 351 { \ 352 PHY_ID_MATCH_MODEL(_id), \ 353 .name = (_name), \ 354 /* PHY_BASIC_FEATURES */ \ 355 .soft_reset = dp83822_phy_reset, \ 356 .config_init = dp83822_config_init, \ 357 .get_wol = dp83822_get_wol, \ 358 .set_wol = dp83822_set_wol, \ 359 .ack_interrupt = dp83822_ack_interrupt, \ 360 .config_intr = dp83822_config_intr, \ 361 .suspend = dp83822_suspend, \ 362 .resume = dp83822_resume, \ 363 } 364 365 #define DP8382X_PHY_DRIVER(_id, _name) \ 366 { \ 367 PHY_ID_MATCH_MODEL(_id), \ 368 .name = (_name), \ 369 /* PHY_BASIC_FEATURES */ \ 370 .soft_reset = dp83822_phy_reset, \ 371 .config_init = dp8382x_config_init, \ 372 .get_wol = dp83822_get_wol, \ 373 .set_wol = dp83822_set_wol, \ 374 .ack_interrupt = dp83822_ack_interrupt, \ 375 .config_intr = dp83822_config_intr, \ 376 .suspend = dp83822_suspend, \ 377 .resume = dp83822_resume, \ 378 } 379 380 static struct phy_driver dp83822_driver[] = { 381 DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"), 382 DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"), 383 DP8382X_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"), 384 DP8382X_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"), 385 DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"), 386 DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"), 387 DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"), 388 }; 389 module_phy_driver(dp83822_driver); 390 391 static struct mdio_device_id __maybe_unused dp83822_tbl[] = { 392 { DP83822_PHY_ID, 0xfffffff0 }, 393 { DP83825I_PHY_ID, 0xfffffff0 }, 394 { DP83826C_PHY_ID, 0xfffffff0 }, 395 { DP83826NC_PHY_ID, 0xfffffff0 }, 396 { DP83825S_PHY_ID, 0xfffffff0 }, 397 { DP83825CM_PHY_ID, 0xfffffff0 }, 398 { DP83825CS_PHY_ID, 0xfffffff0 }, 399 { }, 400 }; 401 MODULE_DEVICE_TABLE(mdio, dp83822_tbl); 402 403 MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver"); 404 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com"); 405 MODULE_LICENSE("GPL v2"); 406