1 /* 2 * Vitesse PHY drivers 3 * 4 * Copyright 2010-2014 Freescale Semiconductor, Inc. 5 * Original Author: Andy Fleming 6 * Add vsc8662 phy support - Priyanka Jain 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 #include <miiphy.h> 10 11 /* Cicada Auxiliary Control/Status Register */ 12 #define MIIM_CIS82xx_AUX_CONSTAT 0x1c 13 #define MIIM_CIS82xx_AUXCONSTAT_INIT 0x0004 14 #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX 0x0020 15 #define MIIM_CIS82xx_AUXCONSTAT_SPEED 0x0018 16 #define MIIM_CIS82xx_AUXCONSTAT_GBIT 0x0010 17 #define MIIM_CIS82xx_AUXCONSTAT_100 0x0008 18 19 /* Cicada Extended Control Register 1 */ 20 #define MIIM_CIS82xx_EXT_CON1 0x17 21 #define MIIM_CIS8201_EXTCON1_INIT 0x0000 22 23 /* Cicada 8204 Extended PHY Control Register 1 */ 24 #define MIIM_CIS8204_EPHY_CON 0x17 25 #define MIIM_CIS8204_EPHYCON_INIT 0x0006 26 #define MIIM_CIS8204_EPHYCON_RGMII 0x1100 27 28 /* Cicada 8204 Serial LED Control Register */ 29 #define MIIM_CIS8204_SLED_CON 0x1b 30 #define MIIM_CIS8204_SLEDCON_INIT 0x1115 31 32 /* Vitesse VSC8601 Extended PHY Control Register 1 */ 33 #define MIIM_VSC8601_EPHY_CON 0x17 34 #define MIIM_VSC8601_EPHY_CON_INIT_SKEW 0x1120 35 #define MIIM_VSC8601_SKEW_CTRL 0x1c 36 37 #define PHY_EXT_PAGE_ACCESS 0x1f 38 #define PHY_EXT_PAGE_ACCESS_GENERAL 0x10 39 #define PHY_EXT_PAGE_ACCESS_EXTENDED3 0x3 40 41 /* Vitesse VSC8574 control register */ 42 #define MIIM_VSC8574_MAC_SERDES_CON 0x10 43 #define MIIM_VSC8574_MAC_SERDES_ANEG 0x80 44 #define MIIM_VSC8574_GENERAL18 0x12 45 #define MIIM_VSC8574_GENERAL19 0x13 46 47 /* Vitesse VSC8574 gerenal purpose register 18 */ 48 #define MIIM_VSC8574_18G_SGMII 0x80f0 49 #define MIIM_VSC8574_18G_QSGMII 0x80e0 50 #define MIIM_VSC8574_18G_CMDSTAT 0x8000 51 52 /* Vitesse VSC8514 control register */ 53 #define MIIM_VSC8514_MAC_SERDES_CON 0x10 54 #define MIIM_VSC8514_GENERAL18 0x12 55 #define MIIM_VSC8514_GENERAL19 0x13 56 #define MIIM_VSC8514_GENERAL23 0x17 57 58 /* Vitesse VSC8514 gerenal purpose register 18 */ 59 #define MIIM_VSC8514_18G_QSGMII 0x80e0 60 #define MIIM_VSC8514_18G_CMDSTAT 0x8000 61 62 /* Vitesse VSC8664 Control/Status Register */ 63 #define MIIM_VSC8664_SERDES_AND_SIGDET 0x13 64 #define MIIM_VSC8664_ADDITIONAL_DEV 0x16 65 #define MIIM_VSC8664_EPHY_CON 0x17 66 #define MIIM_VSC8664_LED_CON 0x1E 67 68 #define PHY_EXT_PAGE_ACCESS_EXTENDED 0x0001 69 70 /* CIS8201 */ 71 static int vitesse_config(struct phy_device *phydev) 72 { 73 /* Override PHY config settings */ 74 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, 75 MIIM_CIS82xx_AUXCONSTAT_INIT); 76 /* Set up the interface mode */ 77 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1, 78 MIIM_CIS8201_EXTCON1_INIT); 79 80 genphy_config_aneg(phydev); 81 82 return 0; 83 } 84 85 static int vitesse_parse_status(struct phy_device *phydev) 86 { 87 int speed; 88 int mii_reg; 89 90 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT); 91 92 if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX) 93 phydev->duplex = DUPLEX_FULL; 94 else 95 phydev->duplex = DUPLEX_HALF; 96 97 speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED; 98 switch (speed) { 99 case MIIM_CIS82xx_AUXCONSTAT_GBIT: 100 phydev->speed = SPEED_1000; 101 break; 102 case MIIM_CIS82xx_AUXCONSTAT_100: 103 phydev->speed = SPEED_100; 104 break; 105 default: 106 phydev->speed = SPEED_10; 107 break; 108 } 109 110 return 0; 111 } 112 113 static int vitesse_startup(struct phy_device *phydev) 114 { 115 int ret; 116 117 ret = genphy_update_link(phydev); 118 if (ret) 119 return ret; 120 return vitesse_parse_status(phydev); 121 } 122 123 static int cis8204_config(struct phy_device *phydev) 124 { 125 /* Override PHY config settings */ 126 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, 127 MIIM_CIS82xx_AUXCONSTAT_INIT); 128 129 genphy_config_aneg(phydev); 130 131 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 132 (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) || 133 (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) 134 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, 135 MIIM_CIS8204_EPHYCON_INIT | 136 MIIM_CIS8204_EPHYCON_RGMII); 137 else 138 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, 139 MIIM_CIS8204_EPHYCON_INIT); 140 141 return 0; 142 } 143 144 /* Vitesse VSC8601 */ 145 static int vsc8601_config(struct phy_device *phydev) 146 { 147 /* Configure some basic stuff */ 148 #ifdef CONFIG_SYS_VSC8601_SKEWFIX 149 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON, 150 MIIM_VSC8601_EPHY_CON_INIT_SKEW); 151 #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX) 152 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1); 153 #define VSC8101_SKEW \ 154 ((CONFIG_SYS_VSC8601_SKEW_TX << 14) \ 155 | (CONFIG_SYS_VSC8601_SKEW_RX << 12)) 156 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL, 157 VSC8101_SKEW); 158 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 159 #endif 160 #endif 161 162 genphy_config_aneg(phydev); 163 164 return 0; 165 } 166 167 static int vsc8574_config(struct phy_device *phydev) 168 { 169 u32 val; 170 /* configure register 19G for MAC */ 171 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 172 PHY_EXT_PAGE_ACCESS_GENERAL); 173 174 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19); 175 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) { 176 /* set bit 15:14 to '01' for QSGMII mode */ 177 val = (val & 0x3fff) | (1 << 14); 178 phy_write(phydev, MDIO_DEVAD_NONE, 179 MIIM_VSC8574_GENERAL19, val); 180 /* Enable 4 ports MAC QSGMII */ 181 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, 182 MIIM_VSC8574_18G_QSGMII); 183 } else { 184 /* set bit 15:14 to '00' for SGMII mode */ 185 val = val & 0x3fff; 186 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val); 187 /* Enable 4 ports MAC SGMII */ 188 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, 189 MIIM_VSC8574_18G_SGMII); 190 } 191 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); 192 /* When bit 15 is cleared the command has completed */ 193 while (val & MIIM_VSC8574_18G_CMDSTAT) 194 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); 195 196 /* Enable Serdes Auto-negotiation */ 197 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 198 PHY_EXT_PAGE_ACCESS_EXTENDED3); 199 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON); 200 val = val | MIIM_VSC8574_MAC_SERDES_ANEG; 201 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val); 202 203 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 204 205 genphy_config_aneg(phydev); 206 207 return 0; 208 } 209 210 static int vsc8514_config(struct phy_device *phydev) 211 { 212 u32 val; 213 int timeout = 1000000; 214 215 /* configure register to access 19G */ 216 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 217 PHY_EXT_PAGE_ACCESS_GENERAL); 218 219 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL19); 220 if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) { 221 /* set bit 15:14 to '01' for QSGMII mode */ 222 val = (val & 0x3fff) | (1 << 14); 223 phy_write(phydev, MDIO_DEVAD_NONE, 224 MIIM_VSC8514_GENERAL19, val); 225 /* Enable 4 ports MAC QSGMII */ 226 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18, 227 MIIM_VSC8514_18G_QSGMII); 228 } else { 229 /*TODO Add SGMII functionality once spec sheet 230 * for VSC8514 defines complete functionality 231 */ 232 } 233 234 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18); 235 /* When bit 15 is cleared the command has completed */ 236 while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--) 237 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18); 238 239 if (0 == timeout) { 240 printf("PHY 8514 config failed\n"); 241 return -1; 242 } 243 244 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 245 246 /* configure register to access 23 */ 247 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23); 248 /* set bits 10:8 to '000' */ 249 val = (val & 0xf8ff); 250 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val); 251 252 /* Enable Serdes Auto-negotiation */ 253 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 254 PHY_EXT_PAGE_ACCESS_EXTENDED3); 255 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON); 256 val = val | MIIM_VSC8574_MAC_SERDES_ANEG; 257 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON, val); 258 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 259 260 genphy_config_aneg(phydev); 261 262 return 0; 263 } 264 265 static int vsc8664_config(struct phy_device *phydev) 266 { 267 u32 val; 268 269 /* Enable MAC interface auto-negotiation */ 270 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 271 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_EPHY_CON); 272 val |= (1 << 13); 273 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_EPHY_CON, val); 274 275 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 276 PHY_EXT_PAGE_ACCESS_EXTENDED); 277 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_SERDES_AND_SIGDET); 278 val |= (1 << 11); 279 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_SERDES_AND_SIGDET, val); 280 phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); 281 282 /* Enable LED blink */ 283 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_LED_CON); 284 val &= ~(1 << 2); 285 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_LED_CON, val); 286 287 genphy_config_aneg(phydev); 288 289 return 0; 290 } 291 292 static struct phy_driver VSC8211_driver = { 293 .name = "Vitesse VSC8211", 294 .uid = 0xfc4b0, 295 .mask = 0xffff0, 296 .features = PHY_GBIT_FEATURES, 297 .config = &vitesse_config, 298 .startup = &vitesse_startup, 299 .shutdown = &genphy_shutdown, 300 }; 301 302 static struct phy_driver VSC8221_driver = { 303 .name = "Vitesse VSC8221", 304 .uid = 0xfc550, 305 .mask = 0xffff0, 306 .features = PHY_GBIT_FEATURES, 307 .config = &genphy_config_aneg, 308 .startup = &vitesse_startup, 309 .shutdown = &genphy_shutdown, 310 }; 311 312 static struct phy_driver VSC8244_driver = { 313 .name = "Vitesse VSC8244", 314 .uid = 0xfc6c0, 315 .mask = 0xffff0, 316 .features = PHY_GBIT_FEATURES, 317 .config = &genphy_config_aneg, 318 .startup = &vitesse_startup, 319 .shutdown = &genphy_shutdown, 320 }; 321 322 static struct phy_driver VSC8234_driver = { 323 .name = "Vitesse VSC8234", 324 .uid = 0xfc620, 325 .mask = 0xffff0, 326 .features = PHY_GBIT_FEATURES, 327 .config = &genphy_config_aneg, 328 .startup = &vitesse_startup, 329 .shutdown = &genphy_shutdown, 330 }; 331 332 static struct phy_driver VSC8574_driver = { 333 .name = "Vitesse VSC8574", 334 .uid = 0x704a0, 335 .mask = 0xffff0, 336 .features = PHY_GBIT_FEATURES, 337 .config = &vsc8574_config, 338 .startup = &vitesse_startup, 339 .shutdown = &genphy_shutdown, 340 }; 341 342 static struct phy_driver VSC8514_driver = { 343 .name = "Vitesse VSC8514", 344 .uid = 0x70670, 345 .mask = 0xffff0, 346 .features = PHY_GBIT_FEATURES, 347 .config = &vsc8514_config, 348 .startup = &vitesse_startup, 349 .shutdown = &genphy_shutdown, 350 }; 351 352 static struct phy_driver VSC8584_driver = { 353 .name = "Vitesse VSC8584", 354 .uid = 0x707c0, 355 .mask = 0xffff0, 356 .features = PHY_GBIT_FEATURES, 357 .config = &vsc8574_config, 358 .startup = &vitesse_startup, 359 .shutdown = &genphy_shutdown, 360 }; 361 362 static struct phy_driver VSC8601_driver = { 363 .name = "Vitesse VSC8601", 364 .uid = 0x70420, 365 .mask = 0xffff0, 366 .features = PHY_GBIT_FEATURES, 367 .config = &vsc8601_config, 368 .startup = &vitesse_startup, 369 .shutdown = &genphy_shutdown, 370 }; 371 372 static struct phy_driver VSC8641_driver = { 373 .name = "Vitesse VSC8641", 374 .uid = 0x70430, 375 .mask = 0xffff0, 376 .features = PHY_GBIT_FEATURES, 377 .config = &genphy_config_aneg, 378 .startup = &vitesse_startup, 379 .shutdown = &genphy_shutdown, 380 }; 381 382 static struct phy_driver VSC8662_driver = { 383 .name = "Vitesse VSC8662", 384 .uid = 0x70660, 385 .mask = 0xffff0, 386 .features = PHY_GBIT_FEATURES, 387 .config = &genphy_config_aneg, 388 .startup = &vitesse_startup, 389 .shutdown = &genphy_shutdown, 390 }; 391 392 static struct phy_driver VSC8664_driver = { 393 .name = "Vitesse VSC8664", 394 .uid = 0x70660, 395 .mask = 0xffff0, 396 .features = PHY_GBIT_FEATURES, 397 .config = &vsc8664_config, 398 .startup = &vitesse_startup, 399 .shutdown = &genphy_shutdown, 400 }; 401 402 /* Vitesse bought Cicada, so we'll put these here */ 403 static struct phy_driver cis8201_driver = { 404 .name = "CIS8201", 405 .uid = 0xfc410, 406 .mask = 0xffff0, 407 .features = PHY_GBIT_FEATURES, 408 .config = &vitesse_config, 409 .startup = &vitesse_startup, 410 .shutdown = &genphy_shutdown, 411 }; 412 413 static struct phy_driver cis8204_driver = { 414 .name = "Cicada Cis8204", 415 .uid = 0xfc440, 416 .mask = 0xffff0, 417 .features = PHY_GBIT_FEATURES, 418 .config = &cis8204_config, 419 .startup = &vitesse_startup, 420 .shutdown = &genphy_shutdown, 421 }; 422 423 int phy_vitesse_init(void) 424 { 425 phy_register(&VSC8641_driver); 426 phy_register(&VSC8601_driver); 427 phy_register(&VSC8234_driver); 428 phy_register(&VSC8244_driver); 429 phy_register(&VSC8211_driver); 430 phy_register(&VSC8221_driver); 431 phy_register(&VSC8574_driver); 432 phy_register(&VSC8584_driver); 433 phy_register(&VSC8514_driver); 434 phy_register(&VSC8662_driver); 435 phy_register(&VSC8664_driver); 436 phy_register(&cis8201_driver); 437 phy_register(&cis8204_driver); 438 439 return 0; 440 } 441