1 /* 2 * RealTek PHY drivers 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 * 6 * Copyright 2010-2011 Freescale Semiconductor, Inc. 7 * author Andy Fleming 8 */ 9 #include <config.h> 10 #include <common.h> 11 #include <phy.h> 12 13 #define PHY_AUTONEGOTIATE_TIMEOUT 5000 14 15 /* RTL8211x PHY Status Register */ 16 #define MIIM_RTL8211x_PHY_STATUS 0x11 17 #define MIIM_RTL8211x_PHYSTAT_SPEED 0xc000 18 #define MIIM_RTL8211x_PHYSTAT_GBIT 0x8000 19 #define MIIM_RTL8211x_PHYSTAT_100 0x4000 20 #define MIIM_RTL8211x_PHYSTAT_DUPLEX 0x2000 21 #define MIIM_RTL8211x_PHYSTAT_SPDDONE 0x0800 22 #define MIIM_RTL8211x_PHYSTAT_LINK 0x0400 23 24 25 /* RealTek RTL8211x */ 26 static int rtl8211x_config(struct phy_device *phydev) 27 { 28 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 29 30 genphy_config_aneg(phydev); 31 32 return 0; 33 } 34 35 static int rtl8211x_parse_status(struct phy_device *phydev) 36 { 37 unsigned int speed; 38 unsigned int mii_reg; 39 40 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS); 41 42 if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 43 int i = 0; 44 45 /* in case of timeout ->link is cleared */ 46 phydev->link = 1; 47 puts("Waiting for PHY realtime link"); 48 while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 49 /* Timeout reached ? */ 50 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 51 puts(" TIMEOUT !\n"); 52 phydev->link = 0; 53 break; 54 } 55 56 if ((i++ % 1000) == 0) 57 putc('.'); 58 udelay(1000); /* 1 ms */ 59 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 60 MIIM_RTL8211x_PHY_STATUS); 61 } 62 puts(" done\n"); 63 udelay(500000); /* another 500 ms (results in faster booting) */ 64 } else { 65 if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK) 66 phydev->link = 1; 67 else 68 phydev->link = 0; 69 } 70 71 if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX) 72 phydev->duplex = DUPLEX_FULL; 73 else 74 phydev->duplex = DUPLEX_HALF; 75 76 speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED); 77 78 switch (speed) { 79 case MIIM_RTL8211x_PHYSTAT_GBIT: 80 phydev->speed = SPEED_1000; 81 break; 82 case MIIM_RTL8211x_PHYSTAT_100: 83 phydev->speed = SPEED_100; 84 break; 85 default: 86 phydev->speed = SPEED_10; 87 } 88 89 return 0; 90 } 91 92 static int rtl8211x_startup(struct phy_device *phydev) 93 { 94 /* Read the Status (2x to make sure link is right) */ 95 genphy_update_link(phydev); 96 rtl8211x_parse_status(phydev); 97 98 return 0; 99 } 100 101 /* Support for RTL8211B PHY */ 102 static struct phy_driver RTL8211B_driver = { 103 .name = "RealTek RTL8211B", 104 .uid = 0x1cc910, 105 .mask = 0xfffff0, 106 .features = PHY_GBIT_FEATURES, 107 .config = &rtl8211x_config, 108 .startup = &rtl8211x_startup, 109 .shutdown = &genphy_shutdown, 110 }; 111 112 /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */ 113 static struct phy_driver RTL8211E_driver = { 114 .name = "RealTek RTL8211E", 115 .uid = 0x1cc915, 116 .mask = 0xfffff0, 117 .features = PHY_GBIT_FEATURES, 118 .config = &rtl8211x_config, 119 .startup = &rtl8211x_startup, 120 .shutdown = &genphy_shutdown, 121 }; 122 123 /* Support for RTL8211DN PHY */ 124 static struct phy_driver RTL8211DN_driver = { 125 .name = "RealTek RTL8211DN", 126 .uid = 0x1cc914, 127 .mask = 0xfffff0, 128 .features = PHY_GBIT_FEATURES, 129 .config = &rtl8211x_config, 130 .startup = &rtl8211x_startup, 131 .shutdown = &genphy_shutdown, 132 }; 133 134 int phy_realtek_init(void) 135 { 136 phy_register(&RTL8211B_driver); 137 phy_register(&RTL8211E_driver); 138 phy_register(&RTL8211DN_driver); 139 140 return 0; 141 } 142