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