1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Driver for Vitesse PHYs 4 * 5 * Author: Kriston Carson 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/mii.h> 11 #include <linux/ethtool.h> 12 #include <linux/phy.h> 13 #include <linux/bitfield.h> 14 15 /* Vitesse Extended Page Magic Register(s) */ 16 #define MII_VSC73XX_EXT_PAGE_1E 0x01 17 #define MII_VSC82X4_EXT_PAGE_16E 0x10 18 #define MII_VSC82X4_EXT_PAGE_17E 0x11 19 #define MII_VSC82X4_EXT_PAGE_18E 0x12 20 21 /* Vitesse Extended Control Register 1 */ 22 #define MII_VSC8244_EXT_CON1 0x17 23 #define MII_VSC8244_EXTCON1_INIT 0x0000 24 #define MII_VSC8244_EXTCON1_TX_SKEW_MASK 0x0c00 25 #define MII_VSC8244_EXTCON1_RX_SKEW_MASK 0x0300 26 #define MII_VSC8244_EXTCON1_TX_SKEW 0x0800 27 #define MII_VSC8244_EXTCON1_RX_SKEW 0x0200 28 29 /* Vitesse Interrupt Mask Register */ 30 #define MII_VSC8244_IMASK 0x19 31 #define MII_VSC8244_IMASK_IEN 0x8000 32 #define MII_VSC8244_IMASK_SPEED 0x4000 33 #define MII_VSC8244_IMASK_LINK 0x2000 34 #define MII_VSC8244_IMASK_DUPLEX 0x1000 35 #define MII_VSC8244_IMASK_MASK 0xf000 36 37 #define MII_VSC8221_IMASK_MASK 0xa000 38 39 /* Vitesse Interrupt Status Register */ 40 #define MII_VSC8244_ISTAT 0x1a 41 #define MII_VSC8244_ISTAT_STATUS 0x8000 42 #define MII_VSC8244_ISTAT_SPEED 0x4000 43 #define MII_VSC8244_ISTAT_LINK 0x2000 44 #define MII_VSC8244_ISTAT_DUPLEX 0x1000 45 #define MII_VSC8244_ISTAT_MASK (MII_VSC8244_ISTAT_SPEED | \ 46 MII_VSC8244_ISTAT_LINK | \ 47 MII_VSC8244_ISTAT_DUPLEX) 48 49 #define MII_VSC8221_ISTAT_MASK MII_VSC8244_ISTAT_LINK 50 51 /* Vitesse Auxiliary Control/Status Register */ 52 #define MII_VSC8244_AUX_CONSTAT 0x1c 53 #define MII_VSC8244_AUXCONSTAT_INIT 0x0000 54 #define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 55 #define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 56 #define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 57 #define MII_VSC8244_AUXCONSTAT_100 0x0008 58 59 #define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */ 60 #define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004 61 62 /* Vitesse Extended Page Access Register */ 63 #define MII_VSC82X4_EXT_PAGE_ACCESS 0x1f 64 65 /* Vitesse VSC8662 extended control register */ 66 #define VSC8662_EXT_CON1 0x17 67 #define VSC8662_EXT_CON_MAC_AN BIT(13) 68 69 #define VSC8662_MAC_AN 0x1b 70 #define VSC8662_MAC_AN_BYPASS BIT(13) 71 72 /* Vitesse VSC73XX Extended Control Register */ 73 #define MII_VSC73XX_PHY_CTRL_EXT3 0x14 74 75 #define MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_EN BIT(4) 76 #define MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_CNT GENMASK(3, 2) 77 #define MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_STA BIT(1) 78 #define MII_VSC73XX_DOWNSHIFT_MAX 5 79 #define MII_VSC73XX_DOWNSHIFT_INVAL 1 80 81 /* VSC73XX PHY_BYPASS_CTRL register*/ 82 #define MII_VSC73XX_PHY_BYPASS_CTRL MII_DCOUNTER 83 #define MII_VSC73XX_PBC_TX_DIS BIT(15) 84 #define MII_VSC73XX_PBC_FOR_SPD_AUTO_MDIX_DIS BIT(7) 85 #define MII_VSC73XX_PBC_PAIR_SWAP_DIS BIT(5) 86 #define MII_VSC73XX_PBC_POL_INV_DIS BIT(4) 87 #define MII_VSC73XX_PBC_PARALLEL_DET_DIS BIT(3) 88 #define MII_VSC73XX_PBC_AUTO_NP_EXCHANGE_DIS BIT(1) 89 90 /* VSC73XX PHY_AUX_CTRL_STAT register */ 91 #define MII_VSC73XX_PHY_AUX_CTRL_STAT MII_NCONFIG 92 #define MII_VSC73XX_PACS_NO_MDI_X_IND BIT(13) 93 94 /* Vitesse VSC8601 Extended PHY Control Register 1 */ 95 #define MII_VSC8601_EPHY_CTL 0x17 96 #define MII_VSC8601_EPHY_CTL_RGMII_SKEW (1 << 8) 97 98 #define PHY_ID_VSC8234 0x000fc620 99 #define PHY_ID_VSC8244 0x000fc6c0 100 #define PHY_ID_VSC8572 0x000704d0 101 #define PHY_ID_VSC8601 0x00070420 102 #define PHY_ID_VSC7385 0x00070450 103 #define PHY_ID_VSC7388 0x00070480 104 #define PHY_ID_VSC7395 0x00070550 105 #define PHY_ID_VSC7398 0x00070580 106 #define PHY_ID_VSC8662 0x00070660 107 #define PHY_ID_VSC8221 0x000fc550 108 #define PHY_ID_VSC8211 0x000fc4b0 109 110 MODULE_DESCRIPTION("Vitesse PHY driver"); 111 MODULE_AUTHOR("Kriston Carson"); 112 MODULE_LICENSE("GPL"); 113 114 static int vsc824x_add_skew(struct phy_device *phydev) 115 { 116 int err; 117 int extcon; 118 119 extcon = phy_read(phydev, MII_VSC8244_EXT_CON1); 120 121 if (extcon < 0) 122 return extcon; 123 124 extcon &= ~(MII_VSC8244_EXTCON1_TX_SKEW_MASK | 125 MII_VSC8244_EXTCON1_RX_SKEW_MASK); 126 127 extcon |= (MII_VSC8244_EXTCON1_TX_SKEW | 128 MII_VSC8244_EXTCON1_RX_SKEW); 129 130 err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon); 131 132 return err; 133 } 134 135 static int vsc824x_config_init(struct phy_device *phydev) 136 { 137 int err; 138 139 err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, 140 MII_VSC8244_AUXCONSTAT_INIT); 141 if (err < 0) 142 return err; 143 144 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 145 err = vsc824x_add_skew(phydev); 146 147 return err; 148 } 149 150 static unsigned int vsc8662_inband_caps(struct phy_device *phydev, 151 phy_interface_t interface) 152 { 153 if (interface == PHY_INTERFACE_MODE_SGMII) 154 return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE | 155 LINK_INBAND_BYPASS; 156 157 return 0; 158 } 159 160 static int vsc8662_config_inband(struct phy_device *phydev, unsigned int modes) 161 { 162 u16 mask, set; 163 int ret; 164 165 mask = VSC8662_MAC_AN_BYPASS; 166 set = modes & LINK_INBAND_BYPASS ? mask : 0; 167 ret = phy_modify(phydev, VSC8662_MAC_AN, mask, set); 168 if (ret < 0) 169 return ret; 170 171 mask = VSC8662_EXT_CON_MAC_AN; 172 set = modes & (LINK_INBAND_ENABLE | LINK_INBAND_BYPASS) ? mask : 0; 173 174 ret = phy_modify_changed(phydev, VSC8662_EXT_CON1, mask, set); 175 if (ret <= 0) 176 return ret; 177 178 /* We need to soft-reset the PHY when changing VSC8662_EXT_CON_MAC_AN */ 179 return genphy_soft_reset(phydev); 180 } 181 182 #define VSC73XX_EXT_PAGE_ACCESS 0x1f 183 184 static int vsc73xx_read_page(struct phy_device *phydev) 185 { 186 return __phy_read(phydev, VSC73XX_EXT_PAGE_ACCESS); 187 } 188 189 static int vsc73xx_write_page(struct phy_device *phydev, int page) 190 { 191 return __phy_write(phydev, VSC73XX_EXT_PAGE_ACCESS, page); 192 } 193 194 static int vsc73xx_get_downshift(struct phy_device *phydev, u8 *data) 195 { 196 int val, enable, cnt; 197 198 val = phy_read_paged(phydev, MII_VSC73XX_EXT_PAGE_1E, 199 MII_VSC73XX_PHY_CTRL_EXT3); 200 if (val < 0) 201 return val; 202 203 enable = FIELD_GET(MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_EN, val); 204 cnt = FIELD_GET(MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_CNT, val) + 2; 205 206 *data = enable ? cnt : DOWNSHIFT_DEV_DISABLE; 207 208 return 0; 209 } 210 211 static int vsc73xx_set_downshift(struct phy_device *phydev, u8 cnt) 212 { 213 u16 mask, val; 214 int ret; 215 216 if (cnt > MII_VSC73XX_DOWNSHIFT_MAX) 217 return -E2BIG; 218 else if (cnt == MII_VSC73XX_DOWNSHIFT_INVAL) 219 return -EINVAL; 220 221 mask = MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_EN; 222 223 if (!cnt) { 224 val = 0; 225 } else { 226 mask |= MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_CNT; 227 val = MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_EN | 228 FIELD_PREP(MII_VSC73XX_PHY_CTRL_EXT3_DOWNSHIFT_CNT, 229 cnt - 2); 230 } 231 232 ret = phy_modify_paged(phydev, MII_VSC73XX_EXT_PAGE_1E, 233 MII_VSC73XX_PHY_CTRL_EXT3, mask, val); 234 if (ret < 0) 235 return ret; 236 237 return genphy_soft_reset(phydev); 238 } 239 240 static int vsc73xx_get_tunable(struct phy_device *phydev, 241 struct ethtool_tunable *tuna, void *data) 242 { 243 switch (tuna->id) { 244 case ETHTOOL_PHY_DOWNSHIFT: 245 return vsc73xx_get_downshift(phydev, data); 246 default: 247 return -EOPNOTSUPP; 248 } 249 } 250 251 static int vsc73xx_set_tunable(struct phy_device *phydev, 252 struct ethtool_tunable *tuna, const void *data) 253 { 254 switch (tuna->id) { 255 case ETHTOOL_PHY_DOWNSHIFT: 256 return vsc73xx_set_downshift(phydev, *(const u8 *)data); 257 default: 258 return -EOPNOTSUPP; 259 } 260 } 261 262 static void vsc73xx_config_init(struct phy_device *phydev) 263 { 264 /* Receiver init */ 265 phy_write(phydev, 0x1f, 0x2a30); 266 phy_modify(phydev, 0x0c, 0x0300, 0x0200); 267 phy_write(phydev, 0x1f, 0x0000); 268 269 /* Config LEDs 0x61 */ 270 phy_modify(phydev, MII_TPISTATUS, 0xff00, 0x0061); 271 272 /* Enable downshift by default */ 273 vsc73xx_set_downshift(phydev, MII_VSC73XX_DOWNSHIFT_MAX); 274 275 /* Set Auto MDI-X by default */ 276 phydev->mdix_ctrl = ETH_TP_MDI_AUTO; 277 } 278 279 static int vsc738x_config_init(struct phy_device *phydev) 280 { 281 u16 rev; 282 /* This magic sequence appear in the application note 283 * "VSC7385/7388 PHY Configuration". 284 * 285 * Maybe one day we will get to know what it all means. 286 */ 287 phy_write(phydev, 0x1f, 0x2a30); 288 phy_modify(phydev, 0x08, 0x0200, 0x0200); 289 phy_write(phydev, 0x1f, 0x52b5); 290 phy_write(phydev, 0x10, 0xb68a); 291 phy_modify(phydev, 0x12, 0xff07, 0x0003); 292 phy_modify(phydev, 0x11, 0x00ff, 0x00a2); 293 phy_write(phydev, 0x10, 0x968a); 294 phy_write(phydev, 0x1f, 0x2a30); 295 phy_modify(phydev, 0x08, 0x0200, 0x0000); 296 phy_write(phydev, 0x1f, 0x0000); 297 298 /* Read revision */ 299 rev = phy_read(phydev, MII_PHYSID2); 300 rev &= 0x0f; 301 302 /* Special quirk for revision 0 */ 303 if (rev == 0) { 304 phy_write(phydev, 0x1f, 0x2a30); 305 phy_modify(phydev, 0x08, 0x0200, 0x0200); 306 phy_write(phydev, 0x1f, 0x52b5); 307 phy_write(phydev, 0x12, 0x0000); 308 phy_write(phydev, 0x11, 0x0689); 309 phy_write(phydev, 0x10, 0x8f92); 310 phy_write(phydev, 0x1f, 0x52b5); 311 phy_write(phydev, 0x12, 0x0000); 312 phy_write(phydev, 0x11, 0x0e35); 313 phy_write(phydev, 0x10, 0x9786); 314 phy_write(phydev, 0x1f, 0x2a30); 315 phy_modify(phydev, 0x08, 0x0200, 0x0000); 316 phy_write(phydev, 0x17, 0xff80); 317 phy_write(phydev, 0x17, 0x0000); 318 } 319 320 phy_write(phydev, 0x1f, 0x0000); 321 phy_write(phydev, 0x12, 0x0048); 322 323 if (rev == 0) { 324 phy_write(phydev, 0x1f, 0x2a30); 325 phy_write(phydev, 0x14, 0x6600); 326 phy_write(phydev, 0x1f, 0x0000); 327 phy_write(phydev, 0x18, 0xa24e); 328 } else { 329 phy_write(phydev, 0x1f, 0x2a30); 330 phy_modify(phydev, 0x16, 0x0fc0, 0x0240); 331 phy_modify(phydev, 0x14, 0x6000, 0x4000); 332 /* bits 14-15 in extended register 0x14 controls DACG amplitude 333 * 6 = -8%, 2 is hardware default 334 */ 335 phy_write(phydev, 0x1f, 0x0001); 336 phy_modify(phydev, 0x14, 0xe000, 0x6000); 337 phy_write(phydev, 0x1f, 0x0000); 338 } 339 340 vsc73xx_config_init(phydev); 341 342 return 0; 343 } 344 345 static int vsc739x_config_init(struct phy_device *phydev) 346 { 347 /* This magic sequence appears in the VSC7395 SparX-G5e application 348 * note "VSC7395/VSC7398 PHY Configuration" 349 * 350 * Maybe one day we will get to know what it all means. 351 */ 352 phy_write(phydev, 0x1f, 0x2a30); 353 phy_modify(phydev, 0x08, 0x0200, 0x0200); 354 phy_write(phydev, 0x1f, 0x52b5); 355 phy_write(phydev, 0x10, 0xb68a); 356 phy_modify(phydev, 0x12, 0xff07, 0x0003); 357 phy_modify(phydev, 0x11, 0x00ff, 0x00a2); 358 phy_write(phydev, 0x10, 0x968a); 359 phy_write(phydev, 0x1f, 0x2a30); 360 phy_modify(phydev, 0x08, 0x0200, 0x0000); 361 phy_write(phydev, 0x1f, 0x0000); 362 363 phy_write(phydev, 0x1f, 0x0000); 364 phy_write(phydev, 0x12, 0x0048); 365 phy_write(phydev, 0x1f, 0x2a30); 366 phy_modify(phydev, 0x16, 0x0fc0, 0x0240); 367 phy_modify(phydev, 0x14, 0x6000, 0x4000); 368 phy_write(phydev, 0x1f, 0x0001); 369 phy_modify(phydev, 0x14, 0xe000, 0x6000); 370 phy_write(phydev, 0x1f, 0x0000); 371 372 vsc73xx_config_init(phydev); 373 374 return 0; 375 } 376 377 static int vsc73xx_mdix_set(struct phy_device *phydev, u8 mdix) 378 { 379 int ret; 380 u16 val; 381 382 val = phy_read(phydev, MII_VSC73XX_PHY_BYPASS_CTRL); 383 384 switch (mdix) { 385 case ETH_TP_MDI: 386 val |= MII_VSC73XX_PBC_FOR_SPD_AUTO_MDIX_DIS | 387 MII_VSC73XX_PBC_PAIR_SWAP_DIS | 388 MII_VSC73XX_PBC_POL_INV_DIS; 389 break; 390 case ETH_TP_MDI_X: 391 /* When MDI-X auto configuration is disabled, is possible 392 * to force only MDI mode. Let's use autoconfig for forced 393 * MDIX mode. 394 */ 395 case ETH_TP_MDI_AUTO: 396 val &= ~(MII_VSC73XX_PBC_FOR_SPD_AUTO_MDIX_DIS | 397 MII_VSC73XX_PBC_PAIR_SWAP_DIS | 398 MII_VSC73XX_PBC_POL_INV_DIS); 399 break; 400 default: 401 return -EINVAL; 402 } 403 404 ret = phy_write(phydev, MII_VSC73XX_PHY_BYPASS_CTRL, val); 405 if (ret) 406 return ret; 407 408 return genphy_restart_aneg(phydev); 409 } 410 411 static int vsc73xx_config_aneg(struct phy_device *phydev) 412 { 413 int ret; 414 415 ret = vsc73xx_mdix_set(phydev, phydev->mdix_ctrl); 416 if (ret) 417 return ret; 418 419 return genphy_config_aneg(phydev); 420 } 421 422 static int vsc73xx_mdix_get(struct phy_device *phydev, u8 *mdix) 423 { 424 u16 reg_val; 425 426 reg_val = phy_read(phydev, MII_VSC73XX_PHY_AUX_CTRL_STAT); 427 if (reg_val & MII_VSC73XX_PACS_NO_MDI_X_IND) 428 *mdix = ETH_TP_MDI; 429 else 430 *mdix = ETH_TP_MDI_X; 431 432 return 0; 433 } 434 435 static int vsc73xx_read_status(struct phy_device *phydev) 436 { 437 int ret; 438 439 ret = vsc73xx_mdix_get(phydev, &phydev->mdix); 440 if (ret < 0) 441 return ret; 442 443 return genphy_read_status(phydev); 444 } 445 446 /* This adds a skew for both TX and RX clocks, so the skew should only be 447 * applied to "rgmii-id" interfaces. It may not work as expected 448 * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. 449 */ 450 static int vsc8601_add_skew(struct phy_device *phydev) 451 { 452 int ret; 453 454 ret = phy_read(phydev, MII_VSC8601_EPHY_CTL); 455 if (ret < 0) 456 return ret; 457 458 ret |= MII_VSC8601_EPHY_CTL_RGMII_SKEW; 459 return phy_write(phydev, MII_VSC8601_EPHY_CTL, ret); 460 } 461 462 static int vsc8601_config_init(struct phy_device *phydev) 463 { 464 int ret = 0; 465 466 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 467 ret = vsc8601_add_skew(phydev); 468 469 if (ret < 0) 470 return ret; 471 472 return 0; 473 } 474 475 static int vsc82xx_config_intr(struct phy_device *phydev) 476 { 477 int err; 478 479 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 480 /* Don't bother to ACK the interrupts since the 824x cannot 481 * clear the interrupts if they are disabled. 482 */ 483 err = phy_write(phydev, MII_VSC8244_IMASK, 484 (phydev->drv->phy_id == PHY_ID_VSC8234 || 485 phydev->drv->phy_id == PHY_ID_VSC8244 || 486 phydev->drv->phy_id == PHY_ID_VSC8572 || 487 phydev->drv->phy_id == PHY_ID_VSC8601) ? 488 MII_VSC8244_IMASK_MASK : 489 MII_VSC8221_IMASK_MASK); 490 else { 491 /* The Vitesse PHY cannot clear the interrupt 492 * once it has disabled them, so we clear them first 493 */ 494 err = phy_read(phydev, MII_VSC8244_ISTAT); 495 496 if (err < 0) 497 return err; 498 499 err = phy_write(phydev, MII_VSC8244_IMASK, 0); 500 } 501 502 return err; 503 } 504 505 static irqreturn_t vsc82xx_handle_interrupt(struct phy_device *phydev) 506 { 507 int irq_status, irq_mask; 508 509 if (phydev->drv->phy_id == PHY_ID_VSC8244 || 510 phydev->drv->phy_id == PHY_ID_VSC8572 || 511 phydev->drv->phy_id == PHY_ID_VSC8601) 512 irq_mask = MII_VSC8244_ISTAT_MASK; 513 else 514 irq_mask = MII_VSC8221_ISTAT_MASK; 515 516 irq_status = phy_read(phydev, MII_VSC8244_ISTAT); 517 if (irq_status < 0) { 518 phy_error(phydev); 519 return IRQ_NONE; 520 } 521 522 if (!(irq_status & irq_mask)) 523 return IRQ_NONE; 524 525 phy_trigger_machine(phydev); 526 527 return IRQ_HANDLED; 528 } 529 530 static int vsc8221_config_init(struct phy_device *phydev) 531 { 532 int err; 533 534 err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, 535 MII_VSC8221_AUXCONSTAT_INIT); 536 return err; 537 538 /* Perhaps we should set EXT_CON1 based on the interface? 539 * Options are 802.3Z SerDes or SGMII 540 */ 541 } 542 543 /* vsc82x4_config_autocross_enable - Enable auto MDI/MDI-X for forced links 544 * @phydev: target phy_device struct 545 * 546 * Enable auto MDI/MDI-X when in 10/100 forced link speeds by writing 547 * special values in the VSC8234/VSC8244 extended reserved registers 548 */ 549 static int vsc82x4_config_autocross_enable(struct phy_device *phydev) 550 { 551 int ret; 552 553 if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed > SPEED_100) 554 return 0; 555 556 /* map extended registers set 0x10 - 0x1e */ 557 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x52b5); 558 if (ret >= 0) 559 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_18E, 0x0012); 560 if (ret >= 0) 561 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_17E, 0x2803); 562 if (ret >= 0) 563 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_16E, 0x87fa); 564 /* map standard registers set 0x10 - 0x1e */ 565 if (ret >= 0) 566 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000); 567 else 568 phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000); 569 570 return ret; 571 } 572 573 /* vsc82x4_config_aneg - restart auto-negotiation or write BMCR 574 * @phydev: target phy_device struct 575 * 576 * Description: If auto-negotiation is enabled, we configure the 577 * advertising, and then restart auto-negotiation. If it is not 578 * enabled, then we write the BMCR and also start the auto 579 * MDI/MDI-X feature 580 */ 581 static int vsc82x4_config_aneg(struct phy_device *phydev) 582 { 583 int ret; 584 585 /* Enable auto MDI/MDI-X when in 10/100 forced link speeds by 586 * writing special values in the VSC8234 extended reserved registers 587 */ 588 if (phydev->autoneg != AUTONEG_ENABLE && phydev->speed <= SPEED_100) { 589 ret = genphy_setup_forced(phydev); 590 591 if (ret < 0) /* error */ 592 return ret; 593 594 return vsc82x4_config_autocross_enable(phydev); 595 } 596 597 return genphy_config_aneg(phydev); 598 } 599 600 /* Vitesse 82xx */ 601 static struct phy_driver vsc82xx_driver[] = { 602 { 603 .phy_id = PHY_ID_VSC8234, 604 .name = "Vitesse VSC8234", 605 .phy_id_mask = 0x000ffff0, 606 /* PHY_GBIT_FEATURES */ 607 .config_init = &vsc824x_config_init, 608 .config_aneg = &vsc82x4_config_aneg, 609 .config_intr = &vsc82xx_config_intr, 610 .handle_interrupt = &vsc82xx_handle_interrupt, 611 }, { 612 .phy_id = PHY_ID_VSC8244, 613 .name = "Vitesse VSC8244", 614 .phy_id_mask = 0x000fffc0, 615 /* PHY_GBIT_FEATURES */ 616 .config_init = &vsc824x_config_init, 617 .config_aneg = &vsc82x4_config_aneg, 618 .config_intr = &vsc82xx_config_intr, 619 .handle_interrupt = &vsc82xx_handle_interrupt, 620 }, { 621 .phy_id = PHY_ID_VSC8572, 622 .name = "Vitesse VSC8572", 623 .phy_id_mask = 0x000ffff0, 624 /* PHY_GBIT_FEATURES */ 625 .config_init = &vsc824x_config_init, 626 .config_aneg = &vsc82x4_config_aneg, 627 .config_intr = &vsc82xx_config_intr, 628 .handle_interrupt = &vsc82xx_handle_interrupt, 629 }, { 630 .phy_id = PHY_ID_VSC8601, 631 .name = "Vitesse VSC8601", 632 .phy_id_mask = 0x000ffff0, 633 /* PHY_GBIT_FEATURES */ 634 .config_init = &vsc8601_config_init, 635 .config_intr = &vsc82xx_config_intr, 636 .handle_interrupt = &vsc82xx_handle_interrupt, 637 }, { 638 .phy_id = PHY_ID_VSC7385, 639 .name = "Vitesse VSC7385", 640 .phy_id_mask = 0x000ffff0, 641 /* PHY_GBIT_FEATURES */ 642 .config_init = vsc738x_config_init, 643 .config_aneg = vsc73xx_config_aneg, 644 .read_status = vsc73xx_read_status, 645 .read_page = vsc73xx_read_page, 646 .write_page = vsc73xx_write_page, 647 .get_tunable = vsc73xx_get_tunable, 648 .set_tunable = vsc73xx_set_tunable, 649 }, { 650 .phy_id = PHY_ID_VSC7388, 651 .name = "Vitesse VSC7388", 652 .phy_id_mask = 0x000ffff0, 653 /* PHY_GBIT_FEATURES */ 654 .config_init = vsc738x_config_init, 655 .config_aneg = vsc73xx_config_aneg, 656 .read_status = vsc73xx_read_status, 657 .read_page = vsc73xx_read_page, 658 .write_page = vsc73xx_write_page, 659 .get_tunable = vsc73xx_get_tunable, 660 .set_tunable = vsc73xx_set_tunable, 661 }, { 662 .phy_id = PHY_ID_VSC7395, 663 .name = "Vitesse VSC7395", 664 .phy_id_mask = 0x000ffff0, 665 /* PHY_GBIT_FEATURES */ 666 .config_init = vsc739x_config_init, 667 .config_aneg = vsc73xx_config_aneg, 668 .read_status = vsc73xx_read_status, 669 .read_page = vsc73xx_read_page, 670 .write_page = vsc73xx_write_page, 671 .get_tunable = vsc73xx_get_tunable, 672 .set_tunable = vsc73xx_set_tunable, 673 }, { 674 .phy_id = PHY_ID_VSC7398, 675 .name = "Vitesse VSC7398", 676 .phy_id_mask = 0x000ffff0, 677 /* PHY_GBIT_FEATURES */ 678 .config_init = vsc739x_config_init, 679 .config_aneg = vsc73xx_config_aneg, 680 .read_status = vsc73xx_read_status, 681 .read_page = vsc73xx_read_page, 682 .write_page = vsc73xx_write_page, 683 .get_tunable = vsc73xx_get_tunable, 684 .set_tunable = vsc73xx_set_tunable, 685 }, { 686 .phy_id = PHY_ID_VSC8662, 687 .name = "Vitesse VSC8662", 688 .phy_id_mask = 0x000ffff0, 689 /* PHY_GBIT_FEATURES */ 690 .config_init = &vsc824x_config_init, 691 .inband_caps = vsc8662_inband_caps, 692 .config_inband = vsc8662_config_inband, 693 .config_aneg = &vsc82x4_config_aneg, 694 .config_intr = &vsc82xx_config_intr, 695 .handle_interrupt = &vsc82xx_handle_interrupt, 696 }, { 697 /* Vitesse 8221 */ 698 .phy_id = PHY_ID_VSC8221, 699 .phy_id_mask = 0x000ffff0, 700 .name = "Vitesse VSC8221", 701 /* PHY_GBIT_FEATURES */ 702 .config_init = &vsc8221_config_init, 703 .config_intr = &vsc82xx_config_intr, 704 .handle_interrupt = &vsc82xx_handle_interrupt, 705 }, { 706 /* Vitesse 8211 */ 707 .phy_id = PHY_ID_VSC8211, 708 .phy_id_mask = 0x000ffff0, 709 .name = "Vitesse VSC8211", 710 /* PHY_GBIT_FEATURES */ 711 .config_init = &vsc8221_config_init, 712 .config_intr = &vsc82xx_config_intr, 713 .handle_interrupt = &vsc82xx_handle_interrupt, 714 } }; 715 716 module_phy_driver(vsc82xx_driver); 717 718 static const struct mdio_device_id __maybe_unused vitesse_tbl[] = { 719 { PHY_ID_VSC8234, 0x000ffff0 }, 720 { PHY_ID_VSC8244, 0x000fffc0 }, 721 { PHY_ID_VSC8572, 0x000ffff0 }, 722 { PHY_ID_VSC7385, 0x000ffff0 }, 723 { PHY_ID_VSC7388, 0x000ffff0 }, 724 { PHY_ID_VSC7395, 0x000ffff0 }, 725 { PHY_ID_VSC7398, 0x000ffff0 }, 726 { PHY_ID_VSC8662, 0x000ffff0 }, 727 { PHY_ID_VSC8221, 0x000ffff0 }, 728 { PHY_ID_VSC8211, 0x000ffff0 }, 729 { } 730 }; 731 732 MODULE_DEVICE_TABLE(mdio, vitesse_tbl); 733