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