19082eeacSAndy Fleming /* 29082eeacSAndy Fleming * RealTek PHY drivers 39082eeacSAndy Fleming * 41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 59082eeacSAndy Fleming * 69082eeacSAndy Fleming * Copyright 2010-2011 Freescale Semiconductor, Inc. 79082eeacSAndy Fleming * author Andy Fleming 89082eeacSAndy Fleming */ 99082eeacSAndy Fleming #include <config.h> 109082eeacSAndy Fleming #include <common.h> 119082eeacSAndy Fleming #include <phy.h> 129082eeacSAndy Fleming 139082eeacSAndy Fleming #define PHY_AUTONEGOTIATE_TIMEOUT 5000 149082eeacSAndy Fleming 15*c624d168SBhupesh Sharma /* RTL8211x PHY Status Register */ 16*c624d168SBhupesh Sharma #define MIIM_RTL8211x_PHY_STATUS 0x11 17*c624d168SBhupesh Sharma #define MIIM_RTL8211x_PHYSTAT_SPEED 0xc000 18*c624d168SBhupesh Sharma #define MIIM_RTL8211x_PHYSTAT_GBIT 0x8000 19*c624d168SBhupesh Sharma #define MIIM_RTL8211x_PHYSTAT_100 0x4000 20*c624d168SBhupesh Sharma #define MIIM_RTL8211x_PHYSTAT_DUPLEX 0x2000 21*c624d168SBhupesh Sharma #define MIIM_RTL8211x_PHYSTAT_SPDDONE 0x0800 22*c624d168SBhupesh Sharma #define MIIM_RTL8211x_PHYSTAT_LINK 0x0400 239082eeacSAndy Fleming 249082eeacSAndy Fleming 25*c624d168SBhupesh Sharma /* RealTek RTL8211x */ 26*c624d168SBhupesh Sharma static int rtl8211x_config(struct phy_device *phydev) 279082eeacSAndy Fleming { 289082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 299082eeacSAndy Fleming 309082eeacSAndy Fleming genphy_config_aneg(phydev); 319082eeacSAndy Fleming 329082eeacSAndy Fleming return 0; 339082eeacSAndy Fleming } 349082eeacSAndy Fleming 35*c624d168SBhupesh Sharma static int rtl8211x_parse_status(struct phy_device *phydev) 369082eeacSAndy Fleming { 379082eeacSAndy Fleming unsigned int speed; 389082eeacSAndy Fleming unsigned int mii_reg; 399082eeacSAndy Fleming 40*c624d168SBhupesh Sharma mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS); 419082eeacSAndy Fleming 42*c624d168SBhupesh Sharma if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 439082eeacSAndy Fleming int i = 0; 449082eeacSAndy Fleming 459082eeacSAndy Fleming /* in case of timeout ->link is cleared */ 469082eeacSAndy Fleming phydev->link = 1; 479082eeacSAndy Fleming puts("Waiting for PHY realtime link"); 48*c624d168SBhupesh Sharma while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 499082eeacSAndy Fleming /* Timeout reached ? */ 509082eeacSAndy Fleming if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 519082eeacSAndy Fleming puts(" TIMEOUT !\n"); 529082eeacSAndy Fleming phydev->link = 0; 539082eeacSAndy Fleming break; 549082eeacSAndy Fleming } 559082eeacSAndy Fleming 569082eeacSAndy Fleming if ((i++ % 1000) == 0) 579082eeacSAndy Fleming putc('.'); 589082eeacSAndy Fleming udelay(1000); /* 1 ms */ 599082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 60*c624d168SBhupesh Sharma MIIM_RTL8211x_PHY_STATUS); 619082eeacSAndy Fleming } 629082eeacSAndy Fleming puts(" done\n"); 639082eeacSAndy Fleming udelay(500000); /* another 500 ms (results in faster booting) */ 649082eeacSAndy Fleming } else { 65*c624d168SBhupesh Sharma if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK) 669082eeacSAndy Fleming phydev->link = 1; 679082eeacSAndy Fleming else 689082eeacSAndy Fleming phydev->link = 0; 699082eeacSAndy Fleming } 709082eeacSAndy Fleming 71*c624d168SBhupesh Sharma if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX) 729082eeacSAndy Fleming phydev->duplex = DUPLEX_FULL; 739082eeacSAndy Fleming else 749082eeacSAndy Fleming phydev->duplex = DUPLEX_HALF; 759082eeacSAndy Fleming 76*c624d168SBhupesh Sharma speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED); 779082eeacSAndy Fleming 789082eeacSAndy Fleming switch (speed) { 79*c624d168SBhupesh Sharma case MIIM_RTL8211x_PHYSTAT_GBIT: 809082eeacSAndy Fleming phydev->speed = SPEED_1000; 819082eeacSAndy Fleming break; 82*c624d168SBhupesh Sharma case MIIM_RTL8211x_PHYSTAT_100: 839082eeacSAndy Fleming phydev->speed = SPEED_100; 849082eeacSAndy Fleming break; 859082eeacSAndy Fleming default: 869082eeacSAndy Fleming phydev->speed = SPEED_10; 879082eeacSAndy Fleming } 889082eeacSAndy Fleming 899082eeacSAndy Fleming return 0; 909082eeacSAndy Fleming } 919082eeacSAndy Fleming 92*c624d168SBhupesh Sharma static int rtl8211x_startup(struct phy_device *phydev) 939082eeacSAndy Fleming { 949082eeacSAndy Fleming /* Read the Status (2x to make sure link is right) */ 959082eeacSAndy Fleming genphy_update_link(phydev); 96*c624d168SBhupesh Sharma rtl8211x_parse_status(phydev); 979082eeacSAndy Fleming 989082eeacSAndy Fleming return 0; 999082eeacSAndy Fleming } 1009082eeacSAndy Fleming 101*c624d168SBhupesh Sharma /* Support for RTL8211B PHY */ 1029082eeacSAndy Fleming static struct phy_driver RTL8211B_driver = { 1039082eeacSAndy Fleming .name = "RealTek RTL8211B", 1049082eeacSAndy Fleming .uid = 0x1cc910, 1059082eeacSAndy Fleming .mask = 0xfffff0, 1069082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 107*c624d168SBhupesh Sharma .config = &rtl8211x_config, 108*c624d168SBhupesh Sharma .startup = &rtl8211x_startup, 109*c624d168SBhupesh Sharma .shutdown = &genphy_shutdown, 110*c624d168SBhupesh Sharma }; 111*c624d168SBhupesh Sharma 112*c624d168SBhupesh Sharma /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */ 113*c624d168SBhupesh Sharma static struct phy_driver RTL8211E_driver = { 114*c624d168SBhupesh Sharma .name = "RealTek RTL8211E", 115*c624d168SBhupesh Sharma .uid = 0x1cc915, 116*c624d168SBhupesh Sharma .mask = 0xfffff0, 117*c624d168SBhupesh Sharma .features = PHY_GBIT_FEATURES, 118*c624d168SBhupesh Sharma .config = &rtl8211x_config, 119*c624d168SBhupesh Sharma .startup = &rtl8211x_startup, 120*c624d168SBhupesh Sharma .shutdown = &genphy_shutdown, 121*c624d168SBhupesh Sharma }; 122*c624d168SBhupesh Sharma 123*c624d168SBhupesh Sharma /* Support for RTL8211DN PHY */ 124*c624d168SBhupesh Sharma static struct phy_driver RTL8211DN_driver = { 125*c624d168SBhupesh Sharma .name = "RealTek RTL8211DN", 126*c624d168SBhupesh Sharma .uid = 0x1cc914, 127*c624d168SBhupesh Sharma .mask = 0xfffff0, 128*c624d168SBhupesh Sharma .features = PHY_GBIT_FEATURES, 129*c624d168SBhupesh Sharma .config = &rtl8211x_config, 130*c624d168SBhupesh Sharma .startup = &rtl8211x_startup, 1319082eeacSAndy Fleming .shutdown = &genphy_shutdown, 1329082eeacSAndy Fleming }; 1339082eeacSAndy Fleming 1349082eeacSAndy Fleming int phy_realtek_init(void) 1359082eeacSAndy Fleming { 1369082eeacSAndy Fleming phy_register(&RTL8211B_driver); 137*c624d168SBhupesh Sharma phy_register(&RTL8211E_driver); 138*c624d168SBhupesh Sharma phy_register(&RTL8211DN_driver); 1399082eeacSAndy Fleming 1409082eeacSAndy Fleming return 0; 1419082eeacSAndy Fleming } 142