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