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