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 14 /* Vitesse Extended Page Magic Register(s) */ 15 #define MII_VSC82X4_EXT_PAGE_16E 0x10 16 #define MII_VSC82X4_EXT_PAGE_17E 0x11 17 #define MII_VSC82X4_EXT_PAGE_18E 0x12 18 19 /* Vitesse Extended Control Register 1 */ 20 #define MII_VSC8244_EXT_CON1 0x17 21 #define MII_VSC8244_EXTCON1_INIT 0x0000 22 #define MII_VSC8244_EXTCON1_TX_SKEW_MASK 0x0c00 23 #define MII_VSC8244_EXTCON1_RX_SKEW_MASK 0x0300 24 #define MII_VSC8244_EXTCON1_TX_SKEW 0x0800 25 #define MII_VSC8244_EXTCON1_RX_SKEW 0x0200 26 27 /* Vitesse Interrupt Mask Register */ 28 #define MII_VSC8244_IMASK 0x19 29 #define MII_VSC8244_IMASK_IEN 0x8000 30 #define MII_VSC8244_IMASK_SPEED 0x4000 31 #define MII_VSC8244_IMASK_LINK 0x2000 32 #define MII_VSC8244_IMASK_DUPLEX 0x1000 33 #define MII_VSC8244_IMASK_MASK 0xf000 34 35 #define MII_VSC8221_IMASK_MASK 0xa000 36 37 /* Vitesse Interrupt Status Register */ 38 #define MII_VSC8244_ISTAT 0x1a 39 #define MII_VSC8244_ISTAT_STATUS 0x8000 40 #define MII_VSC8244_ISTAT_SPEED 0x4000 41 #define MII_VSC8244_ISTAT_LINK 0x2000 42 #define MII_VSC8244_ISTAT_DUPLEX 0x1000 43 44 /* Vitesse Auxiliary Control/Status Register */ 45 #define MII_VSC8244_AUX_CONSTAT 0x1c 46 #define MII_VSC8244_AUXCONSTAT_INIT 0x0000 47 #define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 48 #define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 49 #define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 50 #define MII_VSC8244_AUXCONSTAT_100 0x0008 51 52 #define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */ 53 #define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004 54 55 /* Vitesse Extended Page Access Register */ 56 #define MII_VSC82X4_EXT_PAGE_ACCESS 0x1f 57 58 /* Vitesse VSC8601 Extended PHY Control Register 1 */ 59 #define MII_VSC8601_EPHY_CTL 0x17 60 #define MII_VSC8601_EPHY_CTL_RGMII_SKEW (1 << 8) 61 62 #define PHY_ID_VSC8234 0x000fc620 63 #define PHY_ID_VSC8244 0x000fc6c0 64 #define PHY_ID_VSC8572 0x000704d0 65 #define PHY_ID_VSC8601 0x00070420 66 #define PHY_ID_VSC7385 0x00070450 67 #define PHY_ID_VSC7388 0x00070480 68 #define PHY_ID_VSC7395 0x00070550 69 #define PHY_ID_VSC7398 0x00070580 70 #define PHY_ID_VSC8662 0x00070660 71 #define PHY_ID_VSC8221 0x000fc550 72 #define PHY_ID_VSC8211 0x000fc4b0 73 74 MODULE_DESCRIPTION("Vitesse PHY driver"); 75 MODULE_AUTHOR("Kriston Carson"); 76 MODULE_LICENSE("GPL"); 77 78 static int vsc824x_add_skew(struct phy_device *phydev) 79 { 80 int err; 81 int extcon; 82 83 extcon = phy_read(phydev, MII_VSC8244_EXT_CON1); 84 85 if (extcon < 0) 86 return extcon; 87 88 extcon &= ~(MII_VSC8244_EXTCON1_TX_SKEW_MASK | 89 MII_VSC8244_EXTCON1_RX_SKEW_MASK); 90 91 extcon |= (MII_VSC8244_EXTCON1_TX_SKEW | 92 MII_VSC8244_EXTCON1_RX_SKEW); 93 94 err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon); 95 96 return err; 97 } 98 99 static int vsc824x_config_init(struct phy_device *phydev) 100 { 101 int err; 102 103 err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, 104 MII_VSC8244_AUXCONSTAT_INIT); 105 if (err < 0) 106 return err; 107 108 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 109 err = vsc824x_add_skew(phydev); 110 111 return err; 112 } 113 114 #define VSC73XX_EXT_PAGE_ACCESS 0x1f 115 116 static int vsc73xx_read_page(struct phy_device *phydev) 117 { 118 return __phy_read(phydev, VSC73XX_EXT_PAGE_ACCESS); 119 } 120 121 static int vsc73xx_write_page(struct phy_device *phydev, int page) 122 { 123 return __phy_write(phydev, VSC73XX_EXT_PAGE_ACCESS, page); 124 } 125 126 static void vsc73xx_config_init(struct phy_device *phydev) 127 { 128 /* Receiver init */ 129 phy_write(phydev, 0x1f, 0x2a30); 130 phy_modify(phydev, 0x0c, 0x0300, 0x0200); 131 phy_write(phydev, 0x1f, 0x0000); 132 133 /* Config LEDs 0x61 */ 134 phy_modify(phydev, MII_TPISTATUS, 0xff00, 0x0061); 135 } 136 137 static int vsc738x_config_init(struct phy_device *phydev) 138 { 139 u16 rev; 140 /* This magic sequence appear in the application note 141 * "VSC7385/7388 PHY Configuration". 142 * 143 * Maybe one day we will get to know what it all means. 144 */ 145 phy_write(phydev, 0x1f, 0x2a30); 146 phy_modify(phydev, 0x08, 0x0200, 0x0200); 147 phy_write(phydev, 0x1f, 0x52b5); 148 phy_write(phydev, 0x10, 0xb68a); 149 phy_modify(phydev, 0x12, 0xff07, 0x0003); 150 phy_modify(phydev, 0x11, 0x00ff, 0x00a2); 151 phy_write(phydev, 0x10, 0x968a); 152 phy_write(phydev, 0x1f, 0x2a30); 153 phy_modify(phydev, 0x08, 0x0200, 0x0000); 154 phy_write(phydev, 0x1f, 0x0000); 155 156 /* Read revision */ 157 rev = phy_read(phydev, MII_PHYSID2); 158 rev &= 0x0f; 159 160 /* Special quirk for revision 0 */ 161 if (rev == 0) { 162 phy_write(phydev, 0x1f, 0x2a30); 163 phy_modify(phydev, 0x08, 0x0200, 0x0200); 164 phy_write(phydev, 0x1f, 0x52b5); 165 phy_write(phydev, 0x12, 0x0000); 166 phy_write(phydev, 0x11, 0x0689); 167 phy_write(phydev, 0x10, 0x8f92); 168 phy_write(phydev, 0x1f, 0x52b5); 169 phy_write(phydev, 0x12, 0x0000); 170 phy_write(phydev, 0x11, 0x0e35); 171 phy_write(phydev, 0x10, 0x9786); 172 phy_write(phydev, 0x1f, 0x2a30); 173 phy_modify(phydev, 0x08, 0x0200, 0x0000); 174 phy_write(phydev, 0x17, 0xff80); 175 phy_write(phydev, 0x17, 0x0000); 176 } 177 178 phy_write(phydev, 0x1f, 0x0000); 179 phy_write(phydev, 0x12, 0x0048); 180 181 if (rev == 0) { 182 phy_write(phydev, 0x1f, 0x2a30); 183 phy_write(phydev, 0x14, 0x6600); 184 phy_write(phydev, 0x1f, 0x0000); 185 phy_write(phydev, 0x18, 0xa24e); 186 } else { 187 phy_write(phydev, 0x1f, 0x2a30); 188 phy_modify(phydev, 0x16, 0x0fc0, 0x0240); 189 phy_modify(phydev, 0x14, 0x6000, 0x4000); 190 /* bits 14-15 in extended register 0x14 controls DACG amplitude 191 * 6 = -8%, 2 is hardware default 192 */ 193 phy_write(phydev, 0x1f, 0x0001); 194 phy_modify(phydev, 0x14, 0xe000, 0x6000); 195 phy_write(phydev, 0x1f, 0x0000); 196 } 197 198 vsc73xx_config_init(phydev); 199 200 return genphy_config_init(phydev); 201 } 202 203 static int vsc739x_config_init(struct phy_device *phydev) 204 { 205 /* This magic sequence appears in the VSC7395 SparX-G5e application 206 * note "VSC7395/VSC7398 PHY Configuration" 207 * 208 * Maybe one day we will get to know what it all means. 209 */ 210 phy_write(phydev, 0x1f, 0x2a30); 211 phy_modify(phydev, 0x08, 0x0200, 0x0200); 212 phy_write(phydev, 0x1f, 0x52b5); 213 phy_write(phydev, 0x10, 0xb68a); 214 phy_modify(phydev, 0x12, 0xff07, 0x0003); 215 phy_modify(phydev, 0x11, 0x00ff, 0x00a2); 216 phy_write(phydev, 0x10, 0x968a); 217 phy_write(phydev, 0x1f, 0x2a30); 218 phy_modify(phydev, 0x08, 0x0200, 0x0000); 219 phy_write(phydev, 0x1f, 0x0000); 220 221 phy_write(phydev, 0x1f, 0x0000); 222 phy_write(phydev, 0x12, 0x0048); 223 phy_write(phydev, 0x1f, 0x2a30); 224 phy_modify(phydev, 0x16, 0x0fc0, 0x0240); 225 phy_modify(phydev, 0x14, 0x6000, 0x4000); 226 phy_write(phydev, 0x1f, 0x0001); 227 phy_modify(phydev, 0x14, 0xe000, 0x6000); 228 phy_write(phydev, 0x1f, 0x0000); 229 230 vsc73xx_config_init(phydev); 231 232 return genphy_config_init(phydev); 233 } 234 235 static int vsc73xx_config_aneg(struct phy_device *phydev) 236 { 237 /* The VSC73xx switches does not like to be instructed to 238 * do autonegotiation in any way, it prefers that you just go 239 * with the power-on/reset defaults. Writing some registers will 240 * just make autonegotiation permanently fail. 241 */ 242 return 0; 243 } 244 245 /* This adds a skew for both TX and RX clocks, so the skew should only be 246 * applied to "rgmii-id" interfaces. It may not work as expected 247 * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */ 248 static int vsc8601_add_skew(struct phy_device *phydev) 249 { 250 int ret; 251 252 ret = phy_read(phydev, MII_VSC8601_EPHY_CTL); 253 if (ret < 0) 254 return ret; 255 256 ret |= MII_VSC8601_EPHY_CTL_RGMII_SKEW; 257 return phy_write(phydev, MII_VSC8601_EPHY_CTL, ret); 258 } 259 260 static int vsc8601_config_init(struct phy_device *phydev) 261 { 262 int ret = 0; 263 264 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 265 ret = vsc8601_add_skew(phydev); 266 267 if (ret < 0) 268 return ret; 269 270 return genphy_config_init(phydev); 271 } 272 273 static int vsc824x_ack_interrupt(struct phy_device *phydev) 274 { 275 int err = 0; 276 277 /* Don't bother to ACK the interrupts if interrupts 278 * are disabled. The 824x cannot clear the interrupts 279 * if they are disabled. 280 */ 281 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 282 err = phy_read(phydev, MII_VSC8244_ISTAT); 283 284 return (err < 0) ? err : 0; 285 } 286 287 static int vsc82xx_config_intr(struct phy_device *phydev) 288 { 289 int err; 290 291 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 292 err = phy_write(phydev, MII_VSC8244_IMASK, 293 (phydev->drv->phy_id == PHY_ID_VSC8234 || 294 phydev->drv->phy_id == PHY_ID_VSC8244 || 295 phydev->drv->phy_id == PHY_ID_VSC8572 || 296 phydev->drv->phy_id == PHY_ID_VSC8601) ? 297 MII_VSC8244_IMASK_MASK : 298 MII_VSC8221_IMASK_MASK); 299 else { 300 /* The Vitesse PHY cannot clear the interrupt 301 * once it has disabled them, so we clear them first 302 */ 303 err = phy_read(phydev, MII_VSC8244_ISTAT); 304 305 if (err < 0) 306 return err; 307 308 err = phy_write(phydev, MII_VSC8244_IMASK, 0); 309 } 310 311 return err; 312 } 313 314 static int vsc8221_config_init(struct phy_device *phydev) 315 { 316 int err; 317 318 err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, 319 MII_VSC8221_AUXCONSTAT_INIT); 320 return err; 321 322 /* Perhaps we should set EXT_CON1 based on the interface? 323 * Options are 802.3Z SerDes or SGMII 324 */ 325 } 326 327 /* vsc82x4_config_autocross_enable - Enable auto MDI/MDI-X for forced links 328 * @phydev: target phy_device struct 329 * 330 * Enable auto MDI/MDI-X when in 10/100 forced link speeds by writing 331 * special values in the VSC8234/VSC8244 extended reserved registers 332 */ 333 static int vsc82x4_config_autocross_enable(struct phy_device *phydev) 334 { 335 int ret; 336 337 if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed > SPEED_100) 338 return 0; 339 340 /* map extended registers set 0x10 - 0x1e */ 341 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x52b5); 342 if (ret >= 0) 343 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_18E, 0x0012); 344 if (ret >= 0) 345 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_17E, 0x2803); 346 if (ret >= 0) 347 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_16E, 0x87fa); 348 /* map standard registers set 0x10 - 0x1e */ 349 if (ret >= 0) 350 ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000); 351 else 352 phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000); 353 354 return ret; 355 } 356 357 /* vsc82x4_config_aneg - restart auto-negotiation or write BMCR 358 * @phydev: target phy_device struct 359 * 360 * Description: If auto-negotiation is enabled, we configure the 361 * advertising, and then restart auto-negotiation. If it is not 362 * enabled, then we write the BMCR and also start the auto 363 * MDI/MDI-X feature 364 */ 365 static int vsc82x4_config_aneg(struct phy_device *phydev) 366 { 367 int ret; 368 369 /* Enable auto MDI/MDI-X when in 10/100 forced link speeds by 370 * writing special values in the VSC8234 extended reserved registers 371 */ 372 if (phydev->autoneg != AUTONEG_ENABLE && phydev->speed <= SPEED_100) { 373 ret = genphy_setup_forced(phydev); 374 375 if (ret < 0) /* error */ 376 return ret; 377 378 return vsc82x4_config_autocross_enable(phydev); 379 } 380 381 return genphy_config_aneg(phydev); 382 } 383 384 /* Vitesse 82xx */ 385 static struct phy_driver vsc82xx_driver[] = { 386 { 387 .phy_id = PHY_ID_VSC8234, 388 .name = "Vitesse VSC8234", 389 .phy_id_mask = 0x000ffff0, 390 /* PHY_GBIT_FEATURES */ 391 .config_init = &vsc824x_config_init, 392 .config_aneg = &vsc82x4_config_aneg, 393 .ack_interrupt = &vsc824x_ack_interrupt, 394 .config_intr = &vsc82xx_config_intr, 395 }, { 396 .phy_id = PHY_ID_VSC8244, 397 .name = "Vitesse VSC8244", 398 .phy_id_mask = 0x000fffc0, 399 /* PHY_GBIT_FEATURES */ 400 .config_init = &vsc824x_config_init, 401 .config_aneg = &vsc82x4_config_aneg, 402 .ack_interrupt = &vsc824x_ack_interrupt, 403 .config_intr = &vsc82xx_config_intr, 404 }, { 405 .phy_id = PHY_ID_VSC8572, 406 .name = "Vitesse VSC8572", 407 .phy_id_mask = 0x000ffff0, 408 /* PHY_GBIT_FEATURES */ 409 .config_init = &vsc824x_config_init, 410 .config_aneg = &vsc82x4_config_aneg, 411 .ack_interrupt = &vsc824x_ack_interrupt, 412 .config_intr = &vsc82xx_config_intr, 413 }, { 414 .phy_id = PHY_ID_VSC8601, 415 .name = "Vitesse VSC8601", 416 .phy_id_mask = 0x000ffff0, 417 /* PHY_GBIT_FEATURES */ 418 .config_init = &vsc8601_config_init, 419 .ack_interrupt = &vsc824x_ack_interrupt, 420 .config_intr = &vsc82xx_config_intr, 421 }, { 422 .phy_id = PHY_ID_VSC7385, 423 .name = "Vitesse VSC7385", 424 .phy_id_mask = 0x000ffff0, 425 /* PHY_GBIT_FEATURES */ 426 .config_init = vsc738x_config_init, 427 .config_aneg = vsc73xx_config_aneg, 428 .read_page = vsc73xx_read_page, 429 .write_page = vsc73xx_write_page, 430 }, { 431 .phy_id = PHY_ID_VSC7388, 432 .name = "Vitesse VSC7388", 433 .phy_id_mask = 0x000ffff0, 434 /* PHY_GBIT_FEATURES */ 435 .config_init = vsc738x_config_init, 436 .config_aneg = vsc73xx_config_aneg, 437 .read_page = vsc73xx_read_page, 438 .write_page = vsc73xx_write_page, 439 }, { 440 .phy_id = PHY_ID_VSC7395, 441 .name = "Vitesse VSC7395", 442 .phy_id_mask = 0x000ffff0, 443 /* PHY_GBIT_FEATURES */ 444 .config_init = vsc739x_config_init, 445 .config_aneg = vsc73xx_config_aneg, 446 .read_page = vsc73xx_read_page, 447 .write_page = vsc73xx_write_page, 448 }, { 449 .phy_id = PHY_ID_VSC7398, 450 .name = "Vitesse VSC7398", 451 .phy_id_mask = 0x000ffff0, 452 /* PHY_GBIT_FEATURES */ 453 .config_init = vsc739x_config_init, 454 .config_aneg = vsc73xx_config_aneg, 455 .read_page = vsc73xx_read_page, 456 .write_page = vsc73xx_write_page, 457 }, { 458 .phy_id = PHY_ID_VSC8662, 459 .name = "Vitesse VSC8662", 460 .phy_id_mask = 0x000ffff0, 461 /* PHY_GBIT_FEATURES */ 462 .config_init = &vsc824x_config_init, 463 .config_aneg = &vsc82x4_config_aneg, 464 .ack_interrupt = &vsc824x_ack_interrupt, 465 .config_intr = &vsc82xx_config_intr, 466 }, { 467 /* Vitesse 8221 */ 468 .phy_id = PHY_ID_VSC8221, 469 .phy_id_mask = 0x000ffff0, 470 .name = "Vitesse VSC8221", 471 /* PHY_GBIT_FEATURES */ 472 .config_init = &vsc8221_config_init, 473 .ack_interrupt = &vsc824x_ack_interrupt, 474 .config_intr = &vsc82xx_config_intr, 475 }, { 476 /* Vitesse 8211 */ 477 .phy_id = PHY_ID_VSC8211, 478 .phy_id_mask = 0x000ffff0, 479 .name = "Vitesse VSC8211", 480 /* PHY_GBIT_FEATURES */ 481 .config_init = &vsc8221_config_init, 482 .ack_interrupt = &vsc824x_ack_interrupt, 483 .config_intr = &vsc82xx_config_intr, 484 } }; 485 486 module_phy_driver(vsc82xx_driver); 487 488 static struct mdio_device_id __maybe_unused vitesse_tbl[] = { 489 { PHY_ID_VSC8234, 0x000ffff0 }, 490 { PHY_ID_VSC8244, 0x000fffc0 }, 491 { PHY_ID_VSC8572, 0x000ffff0 }, 492 { PHY_ID_VSC7385, 0x000ffff0 }, 493 { PHY_ID_VSC7388, 0x000ffff0 }, 494 { PHY_ID_VSC7395, 0x000ffff0 }, 495 { PHY_ID_VSC7398, 0x000ffff0 }, 496 { PHY_ID_VSC8662, 0x000ffff0 }, 497 { PHY_ID_VSC8221, 0x000ffff0 }, 498 { PHY_ID_VSC8211, 0x000ffff0 }, 499 { } 500 }; 501 502 MODULE_DEVICE_TABLE(mdio, vitesse_tbl); 503