1 /* 2 * Marvell PHY drivers 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of 7 * the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 17 * MA 02111-1307 USA 18 * 19 * Copyright 2010-2011 Freescale Semiconductor, Inc. 20 * author Andy Fleming 21 * 22 */ 23 #include <config.h> 24 #include <common.h> 25 #include <phy.h> 26 27 #define PHY_AUTONEGOTIATE_TIMEOUT 5000 28 29 /* 88E1011 PHY Status Register */ 30 #define MIIM_88E1xxx_PHY_STATUS 0x11 31 #define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000 32 #define MIIM_88E1xxx_PHYSTAT_GBIT 0x8000 33 #define MIIM_88E1xxx_PHYSTAT_100 0x4000 34 #define MIIM_88E1xxx_PHYSTAT_DUPLEX 0x2000 35 #define MIIM_88E1xxx_PHYSTAT_SPDDONE 0x0800 36 #define MIIM_88E1xxx_PHYSTAT_LINK 0x0400 37 38 #define MIIM_88E1xxx_PHY_SCR 0x10 39 #define MIIM_88E1xxx_PHY_MDI_X_AUTO 0x0060 40 41 /* 88E1111 PHY LED Control Register */ 42 #define MIIM_88E1111_PHY_LED_CONTROL 24 43 #define MIIM_88E1111_PHY_LED_DIRECT 0x4100 44 #define MIIM_88E1111_PHY_LED_COMBINE 0x411C 45 46 /* 88E1111 Extended PHY Specific Control Register */ 47 #define MIIM_88E1111_PHY_EXT_CR 0x14 48 #define MIIM_88E1111_RX_DELAY 0x80 49 #define MIIM_88E1111_TX_DELAY 0x2 50 51 /* 88E1111 Extended PHY Specific Status Register */ 52 #define MIIM_88E1111_PHY_EXT_SR 0x1b 53 #define MIIM_88E1111_HWCFG_MODE_MASK 0xf 54 #define MIIM_88E1111_HWCFG_MODE_COPPER_RGMII 0xb 55 #define MIIM_88E1111_HWCFG_MODE_FIBER_RGMII 0x3 56 #define MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK 0x4 57 #define MIIM_88E1111_HWCFG_MODE_COPPER_RTBI 0x9 58 #define MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO 0x8000 59 #define MIIM_88E1111_HWCFG_FIBER_COPPER_RES 0x2000 60 61 #define MIIM_88E1111_COPPER 0 62 #define MIIM_88E1111_FIBER 1 63 64 /* 88E1118 PHY defines */ 65 #define MIIM_88E1118_PHY_PAGE 22 66 #define MIIM_88E1118_PHY_LED_PAGE 3 67 68 /* 88E1121 PHY LED Control Register */ 69 #define MIIM_88E1121_PHY_LED_CTRL 16 70 #define MIIM_88E1121_PHY_LED_PAGE 3 71 #define MIIM_88E1121_PHY_LED_DEF 0x0030 72 73 /* 88E1121 PHY IRQ Enable/Status Register */ 74 #define MIIM_88E1121_PHY_IRQ_EN 18 75 #define MIIM_88E1121_PHY_IRQ_STATUS 19 76 77 #define MIIM_88E1121_PHY_PAGE 22 78 79 /* 88E1145 Extended PHY Specific Control Register */ 80 #define MIIM_88E1145_PHY_EXT_CR 20 81 #define MIIM_M88E1145_RGMII_RX_DELAY 0x0080 82 #define MIIM_M88E1145_RGMII_TX_DELAY 0x0002 83 84 #define MIIM_88E1145_PHY_LED_CONTROL 24 85 #define MIIM_88E1145_PHY_LED_DIRECT 0x4100 86 87 #define MIIM_88E1145_PHY_PAGE 29 88 #define MIIM_88E1145_PHY_CAL_OV 30 89 90 #define MIIM_88E1149_PHY_PAGE 29 91 92 /* 88E1310 PHY defines */ 93 #define MIIM_88E1310_PHY_LED_CTRL 16 94 #define MIIM_88E1310_PHY_IRQ_EN 18 95 #define MIIM_88E1310_PHY_RGMII_CTRL 21 96 #define MIIM_88E1310_PHY_PAGE 22 97 98 /* Marvell 88E1011S */ 99 static int m88e1011s_config(struct phy_device *phydev) 100 { 101 /* Reset and configure the PHY */ 102 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 103 104 phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f); 105 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 106 phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); 107 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0); 108 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 109 110 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 111 112 genphy_config_aneg(phydev); 113 114 return 0; 115 } 116 117 /* Parse the 88E1011's status register for speed and duplex 118 * information 119 */ 120 static uint m88e1xxx_parse_status(struct phy_device *phydev) 121 { 122 unsigned int speed; 123 unsigned int mii_reg; 124 125 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS); 126 127 if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) && 128 !(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 129 int i = 0; 130 131 puts("Waiting for PHY realtime link"); 132 while (!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 133 /* Timeout reached ? */ 134 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 135 puts(" TIMEOUT !\n"); 136 phydev->link = 0; 137 break; 138 } 139 140 if ((i++ % 1000) == 0) 141 putc('.'); 142 udelay(1000); 143 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 144 MIIM_88E1xxx_PHY_STATUS); 145 } 146 puts(" done\n"); 147 udelay(500000); /* another 500 ms (results in faster booting) */ 148 } else { 149 if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) 150 phydev->link = 1; 151 else 152 phydev->link = 0; 153 } 154 155 if (mii_reg & MIIM_88E1xxx_PHYSTAT_DUPLEX) 156 phydev->duplex = DUPLEX_FULL; 157 else 158 phydev->duplex = DUPLEX_HALF; 159 160 speed = mii_reg & MIIM_88E1xxx_PHYSTAT_SPEED; 161 162 switch (speed) { 163 case MIIM_88E1xxx_PHYSTAT_GBIT: 164 phydev->speed = SPEED_1000; 165 break; 166 case MIIM_88E1xxx_PHYSTAT_100: 167 phydev->speed = SPEED_100; 168 break; 169 default: 170 phydev->speed = SPEED_10; 171 break; 172 } 173 174 return 0; 175 } 176 177 static int m88e1011s_startup(struct phy_device *phydev) 178 { 179 genphy_update_link(phydev); 180 m88e1xxx_parse_status(phydev); 181 182 return 0; 183 } 184 185 /* Marvell 88E1111S */ 186 static int m88e1111s_config(struct phy_device *phydev) 187 { 188 int reg; 189 int timeout; 190 191 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 192 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 193 (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 194 (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 195 reg = phy_read(phydev, 196 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 197 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 198 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { 199 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 200 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 201 reg &= ~MIIM_88E1111_TX_DELAY; 202 reg |= MIIM_88E1111_RX_DELAY; 203 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 204 reg &= ~MIIM_88E1111_RX_DELAY; 205 reg |= MIIM_88E1111_TX_DELAY; 206 } 207 208 phy_write(phydev, 209 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 210 211 reg = phy_read(phydev, 212 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); 213 214 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); 215 216 if (reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES) 217 reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII; 218 else 219 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII; 220 221 phy_write(phydev, 222 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); 223 } 224 225 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 226 reg = phy_read(phydev, 227 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); 228 229 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); 230 reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; 231 reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 232 233 phy_write(phydev, MDIO_DEVAD_NONE, 234 MIIM_88E1111_PHY_EXT_SR, reg); 235 } 236 237 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { 238 reg = phy_read(phydev, 239 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 240 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 241 phy_write(phydev, 242 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 243 244 reg = phy_read(phydev, MDIO_DEVAD_NONE, 245 MIIM_88E1111_PHY_EXT_SR); 246 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 247 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 248 reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 249 phy_write(phydev, MDIO_DEVAD_NONE, 250 MIIM_88E1111_PHY_EXT_SR, reg); 251 252 /* soft reset */ 253 timeout = 1000; 254 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 255 udelay(1000); 256 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 257 while ((reg & BMCR_RESET) && --timeout) { 258 udelay(1000); 259 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 260 } 261 if (!timeout) 262 printf("%s: phy soft reset timeout\n", __func__); 263 264 reg = phy_read(phydev, MDIO_DEVAD_NONE, 265 MIIM_88E1111_PHY_EXT_SR); 266 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 267 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 268 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI | 269 MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 270 phy_write(phydev, MDIO_DEVAD_NONE, 271 MIIM_88E1111_PHY_EXT_SR, reg); 272 } 273 274 /* soft reset */ 275 timeout = 1000; 276 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 277 udelay(1000); 278 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 279 while ((reg & BMCR_RESET) && --timeout) { 280 udelay(1000); 281 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 282 } 283 if (!timeout) 284 printf("%s: phy soft reset timeout\n", __func__); 285 286 genphy_config_aneg(phydev); 287 288 phy_reset(phydev); 289 290 return 0; 291 } 292 293 /* Marvell 88E1118 */ 294 static int m88e1118_config(struct phy_device *phydev) 295 { 296 /* Change Page Number */ 297 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0002); 298 /* Delay RGMII TX and RX */ 299 phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070); 300 /* Change Page Number */ 301 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0003); 302 /* Adjust LED control */ 303 phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e); 304 /* Change Page Number */ 305 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 306 307 genphy_config_aneg(phydev); 308 309 phy_reset(phydev); 310 311 return 0; 312 } 313 314 static int m88e1118_startup(struct phy_device *phydev) 315 { 316 /* Change Page Number */ 317 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 318 319 genphy_update_link(phydev); 320 m88e1xxx_parse_status(phydev); 321 322 return 0; 323 } 324 325 /* Marvell 88E1121R */ 326 static int m88e1121_config(struct phy_device *phydev) 327 { 328 int pg; 329 330 /* Configure the PHY */ 331 genphy_config_aneg(phydev); 332 333 /* Switch the page to access the led register */ 334 pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE); 335 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, 336 MIIM_88E1121_PHY_LED_PAGE); 337 /* Configure leds */ 338 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL, 339 MIIM_88E1121_PHY_LED_DEF); 340 /* Restore the page pointer */ 341 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg); 342 343 /* Disable IRQs and de-assert interrupt */ 344 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_EN, 0); 345 phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_STATUS); 346 347 return 0; 348 } 349 350 /* Marvell 88E1145 */ 351 static int m88e1145_config(struct phy_device *phydev) 352 { 353 int reg; 354 355 /* Errata E0, E1 */ 356 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b); 357 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f); 358 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016); 359 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da); 360 361 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR, 362 MIIM_88E1xxx_PHY_MDI_X_AUTO); 363 364 reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR); 365 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 366 reg |= MIIM_M88E1145_RGMII_RX_DELAY | 367 MIIM_M88E1145_RGMII_TX_DELAY; 368 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg); 369 370 genphy_config_aneg(phydev); 371 372 phy_reset(phydev); 373 374 return 0; 375 } 376 377 static int m88e1145_startup(struct phy_device *phydev) 378 { 379 genphy_update_link(phydev); 380 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL, 381 MIIM_88E1145_PHY_LED_DIRECT); 382 m88e1xxx_parse_status(phydev); 383 384 return 0; 385 } 386 387 /* Marvell 88E1149S */ 388 static int m88e1149_config(struct phy_device *phydev) 389 { 390 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f); 391 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 392 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5); 393 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0); 394 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 395 396 genphy_config_aneg(phydev); 397 398 phy_reset(phydev); 399 400 return 0; 401 } 402 403 /* Marvell 88E1310 */ 404 static int m88e1310_config(struct phy_device *phydev) 405 { 406 u16 reg; 407 408 /* LED link and activity */ 409 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 410 reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL); 411 reg = (reg & ~0xf) | 0x1; 412 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg); 413 414 /* Set LED2/INT to INT mode, low active */ 415 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 416 reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN); 417 reg = (reg & 0x77ff) | 0x0880; 418 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg); 419 420 /* Set RGMII delay */ 421 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002); 422 reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL); 423 reg |= 0x0030; 424 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg); 425 426 /* Ensure to return to page 0 */ 427 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); 428 429 genphy_config_aneg(phydev); 430 phy_reset(phydev); 431 432 return 0; 433 } 434 435 static struct phy_driver M88E1011S_driver = { 436 .name = "Marvell 88E1011S", 437 .uid = 0x1410c60, 438 .mask = 0xffffff0, 439 .features = PHY_GBIT_FEATURES, 440 .config = &m88e1011s_config, 441 .startup = &m88e1011s_startup, 442 .shutdown = &genphy_shutdown, 443 }; 444 445 static struct phy_driver M88E1111S_driver = { 446 .name = "Marvell 88E1111S", 447 .uid = 0x1410cc0, 448 .mask = 0xffffff0, 449 .features = PHY_GBIT_FEATURES, 450 .config = &m88e1111s_config, 451 .startup = &m88e1011s_startup, 452 .shutdown = &genphy_shutdown, 453 }; 454 455 static struct phy_driver M88E1118_driver = { 456 .name = "Marvell 88E1118", 457 .uid = 0x1410e10, 458 .mask = 0xffffff0, 459 .features = PHY_GBIT_FEATURES, 460 .config = &m88e1118_config, 461 .startup = &m88e1118_startup, 462 .shutdown = &genphy_shutdown, 463 }; 464 465 static struct phy_driver M88E1118R_driver = { 466 .name = "Marvell 88E1118R", 467 .uid = 0x1410e40, 468 .mask = 0xffffff0, 469 .features = PHY_GBIT_FEATURES, 470 .config = &m88e1118_config, 471 .startup = &m88e1118_startup, 472 .shutdown = &genphy_shutdown, 473 }; 474 475 static struct phy_driver M88E1121R_driver = { 476 .name = "Marvell 88E1121R", 477 .uid = 0x1410cb0, 478 .mask = 0xffffff0, 479 .features = PHY_GBIT_FEATURES, 480 .config = &m88e1121_config, 481 .startup = &genphy_startup, 482 .shutdown = &genphy_shutdown, 483 }; 484 485 static struct phy_driver M88E1145_driver = { 486 .name = "Marvell 88E1145", 487 .uid = 0x1410cd0, 488 .mask = 0xffffff0, 489 .features = PHY_GBIT_FEATURES, 490 .config = &m88e1145_config, 491 .startup = &m88e1145_startup, 492 .shutdown = &genphy_shutdown, 493 }; 494 495 static struct phy_driver M88E1149S_driver = { 496 .name = "Marvell 88E1149S", 497 .uid = 0x1410ca0, 498 .mask = 0xffffff0, 499 .features = PHY_GBIT_FEATURES, 500 .config = &m88e1149_config, 501 .startup = &m88e1011s_startup, 502 .shutdown = &genphy_shutdown, 503 }; 504 505 static struct phy_driver M88E1518_driver = { 506 .name = "Marvell 88E1518", 507 .uid = 0x1410dd1, 508 .mask = 0xffffff0, 509 .features = PHY_GBIT_FEATURES, 510 .config = &m88e1111s_config, 511 .startup = &m88e1011s_startup, 512 .shutdown = &genphy_shutdown, 513 }; 514 515 static struct phy_driver M88E1310_driver = { 516 .name = "Marvell 88E1310", 517 .uid = 0x01410e90, 518 .mask = 0xffffff0, 519 .features = PHY_GBIT_FEATURES, 520 .config = &m88e1310_config, 521 .startup = &m88e1011s_startup, 522 .shutdown = &genphy_shutdown, 523 }; 524 525 int phy_marvell_init(void) 526 { 527 phy_register(&M88E1310_driver); 528 phy_register(&M88E1149S_driver); 529 phy_register(&M88E1145_driver); 530 phy_register(&M88E1121R_driver); 531 phy_register(&M88E1118_driver); 532 phy_register(&M88E1118R_driver); 533 phy_register(&M88E1111S_driver); 534 phy_register(&M88E1011S_driver); 535 phy_register(&M88E1518_driver); 536 537 return 0; 538 } 539