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