1 /* 2 * RealTek PHY drivers 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 * 6 * Copyright 2010-2011, 2015 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 1000BASE-T Control Register */ 16 #define MIIM_RTL8211x_CTRL1000T_MSCE (1 << 12); 17 #define MIIM_RTL8211X_CTRL1000T_MASTER (1 << 11); 18 19 /* RTL8211x PHY Status Register */ 20 #define MIIM_RTL8211x_PHY_STATUS 0x11 21 #define MIIM_RTL8211x_PHYSTAT_SPEED 0xc000 22 #define MIIM_RTL8211x_PHYSTAT_GBIT 0x8000 23 #define MIIM_RTL8211x_PHYSTAT_100 0x4000 24 #define MIIM_RTL8211x_PHYSTAT_DUPLEX 0x2000 25 #define MIIM_RTL8211x_PHYSTAT_SPDDONE 0x0800 26 #define MIIM_RTL8211x_PHYSTAT_LINK 0x0400 27 28 /* RTL8211x PHY Interrupt Enable Register */ 29 #define MIIM_RTL8211x_PHY_INER 0x12 30 #define MIIM_RTL8211x_PHY_INTR_ENA 0x9f01 31 #define MIIM_RTL8211x_PHY_INTR_DIS 0x0000 32 33 /* RTL8211x PHY Interrupt Status Register */ 34 #define MIIM_RTL8211x_PHY_INSR 0x13 35 36 /* RTL8211F PHY Status Register */ 37 #define MIIM_RTL8211F_PHY_STATUS 0x1a 38 #define MIIM_RTL8211F_AUTONEG_ENABLE 0x1000 39 #define MIIM_RTL8211F_PHYSTAT_SPEED 0x0030 40 #define MIIM_RTL8211F_PHYSTAT_GBIT 0x0020 41 #define MIIM_RTL8211F_PHYSTAT_100 0x0010 42 #define MIIM_RTL8211F_PHYSTAT_DUPLEX 0x0008 43 #define MIIM_RTL8211F_PHYSTAT_SPDDONE 0x0800 44 #define MIIM_RTL8211F_PHYSTAT_LINK 0x0004 45 46 #define MIIM_RTL8211F_PAGE_SELECT 0x1f 47 #define MIIM_RTL8211F_TX_DELAY 0x100 48 #define MIIM_RTL8211F_LCR 0x10 49 50 /* RealTek RTL8211x */ 51 static int rtl8211x_config(struct phy_device *phydev) 52 { 53 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 54 55 /* mask interrupt at init; if the interrupt is 56 * needed indeed, it should be explicitly enabled 57 */ 58 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER, 59 MIIM_RTL8211x_PHY_INTR_DIS); 60 #ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER 61 unsigned int reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); 62 /* force manual master/slave configuration */ 63 reg |= MIIM_RTL8211x_CTRL1000T_MSCE; 64 /* force master mode */ 65 reg |= MIIM_RTL8211X_CTRL1000T_MASTER; 66 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg); 67 #endif 68 /* read interrupt status just to clear it */ 69 phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER); 70 71 genphy_config_aneg(phydev); 72 73 return 0; 74 } 75 76 static int rtl8211f_config(struct phy_device *phydev) 77 { 78 u16 reg; 79 80 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 81 82 if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { 83 /* enable TXDLY */ 84 phy_write(phydev, MDIO_DEVAD_NONE, 85 MIIM_RTL8211F_PAGE_SELECT, 0xd08); 86 reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11); 87 reg |= MIIM_RTL8211F_TX_DELAY; 88 phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg); 89 /* restore to default page 0 */ 90 phy_write(phydev, MDIO_DEVAD_NONE, 91 MIIM_RTL8211F_PAGE_SELECT, 0x0); 92 } 93 94 /* Set green LED for Link, yellow LED for Active */ 95 phy_write(phydev, MDIO_DEVAD_NONE, 96 MIIM_RTL8211F_PAGE_SELECT, 0xd04); 97 phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x617f); 98 phy_write(phydev, MDIO_DEVAD_NONE, 99 MIIM_RTL8211F_PAGE_SELECT, 0x0); 100 101 genphy_config_aneg(phydev); 102 103 return 0; 104 } 105 106 static int rtl8211x_parse_status(struct phy_device *phydev) 107 { 108 unsigned int speed; 109 unsigned int mii_reg; 110 111 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS); 112 113 if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 114 int i = 0; 115 116 /* in case of timeout ->link is cleared */ 117 phydev->link = 1; 118 puts("Waiting for PHY realtime link"); 119 while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 120 /* Timeout reached ? */ 121 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 122 puts(" TIMEOUT !\n"); 123 phydev->link = 0; 124 break; 125 } 126 127 if ((i++ % 1000) == 0) 128 putc('.'); 129 udelay(1000); /* 1 ms */ 130 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 131 MIIM_RTL8211x_PHY_STATUS); 132 } 133 puts(" done\n"); 134 udelay(500000); /* another 500 ms (results in faster booting) */ 135 } else { 136 if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK) 137 phydev->link = 1; 138 else 139 phydev->link = 0; 140 } 141 142 if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX) 143 phydev->duplex = DUPLEX_FULL; 144 else 145 phydev->duplex = DUPLEX_HALF; 146 147 speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED); 148 149 switch (speed) { 150 case MIIM_RTL8211x_PHYSTAT_GBIT: 151 phydev->speed = SPEED_1000; 152 break; 153 case MIIM_RTL8211x_PHYSTAT_100: 154 phydev->speed = SPEED_100; 155 break; 156 default: 157 phydev->speed = SPEED_10; 158 } 159 160 return 0; 161 } 162 163 static int rtl8211f_parse_status(struct phy_device *phydev) 164 { 165 unsigned int speed; 166 unsigned int mii_reg; 167 int i = 0; 168 169 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0xa43); 170 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PHY_STATUS); 171 172 phydev->link = 1; 173 while (!(mii_reg & MIIM_RTL8211F_PHYSTAT_LINK)) { 174 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 175 puts(" TIMEOUT !\n"); 176 phydev->link = 0; 177 break; 178 } 179 180 if ((i++ % 1000) == 0) 181 putc('.'); 182 udelay(1000); 183 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 184 MIIM_RTL8211F_PHY_STATUS); 185 } 186 187 if (mii_reg & MIIM_RTL8211F_PHYSTAT_DUPLEX) 188 phydev->duplex = DUPLEX_FULL; 189 else 190 phydev->duplex = DUPLEX_HALF; 191 192 speed = (mii_reg & MIIM_RTL8211F_PHYSTAT_SPEED); 193 194 switch (speed) { 195 case MIIM_RTL8211F_PHYSTAT_GBIT: 196 phydev->speed = SPEED_1000; 197 break; 198 case MIIM_RTL8211F_PHYSTAT_100: 199 phydev->speed = SPEED_100; 200 break; 201 default: 202 phydev->speed = SPEED_10; 203 } 204 205 return 0; 206 } 207 208 static int rtl8211x_startup(struct phy_device *phydev) 209 { 210 /* Read the Status (2x to make sure link is right) */ 211 genphy_update_link(phydev); 212 rtl8211x_parse_status(phydev); 213 214 return 0; 215 } 216 217 static int rtl8211e_startup(struct phy_device *phydev) 218 { 219 genphy_update_link(phydev); 220 genphy_parse_link(phydev); 221 222 return 0; 223 } 224 225 static int rtl8211f_startup(struct phy_device *phydev) 226 { 227 /* Read the Status (2x to make sure link is right) */ 228 genphy_update_link(phydev); 229 rtl8211f_parse_status(phydev); 230 231 return 0; 232 } 233 234 /* Support for RTL8211B PHY */ 235 static struct phy_driver RTL8211B_driver = { 236 .name = "RealTek RTL8211B", 237 .uid = 0x1cc910, 238 .mask = 0xffffff, 239 .features = PHY_GBIT_FEATURES, 240 .config = &rtl8211x_config, 241 .startup = &rtl8211x_startup, 242 .shutdown = &genphy_shutdown, 243 }; 244 245 /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */ 246 static struct phy_driver RTL8211E_driver = { 247 .name = "RealTek RTL8211E", 248 .uid = 0x1cc915, 249 .mask = 0xffffff, 250 .features = PHY_GBIT_FEATURES, 251 .config = &rtl8211x_config, 252 .startup = &rtl8211e_startup, 253 .shutdown = &genphy_shutdown, 254 }; 255 256 /* Support for RTL8211DN PHY */ 257 static struct phy_driver RTL8211DN_driver = { 258 .name = "RealTek RTL8211DN", 259 .uid = 0x1cc914, 260 .mask = 0xffffff, 261 .features = PHY_GBIT_FEATURES, 262 .config = &rtl8211x_config, 263 .startup = &rtl8211x_startup, 264 .shutdown = &genphy_shutdown, 265 }; 266 267 /* Support for RTL8211F PHY */ 268 static struct phy_driver RTL8211F_driver = { 269 .name = "RealTek RTL8211F", 270 .uid = 0x1cc916, 271 .mask = 0xffffff, 272 .features = PHY_GBIT_FEATURES, 273 .config = &rtl8211f_config, 274 .startup = &rtl8211f_startup, 275 .shutdown = &genphy_shutdown, 276 }; 277 278 int phy_realtek_init(void) 279 { 280 phy_register(&RTL8211B_driver); 281 phy_register(&RTL8211E_driver); 282 phy_register(&RTL8211F_driver); 283 phy_register(&RTL8211DN_driver); 284 285 return 0; 286 } 287