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 phy_write(phydev, MDIO_DEVAD_NONE, 99 MIIM_RTL8211F_PAGE_SELECT, 0xd08); 100 reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11); 101 102 /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ 103 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 104 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 105 reg |= MIIM_RTL8211F_TX_DELAY; 106 else 107 reg &= ~MIIM_RTL8211F_TX_DELAY; 108 109 phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg); 110 /* restore to default page 0 */ 111 phy_write(phydev, MDIO_DEVAD_NONE, 112 MIIM_RTL8211F_PAGE_SELECT, 0x0); 113 114 /* Set green LED for Link, yellow LED for Active */ 115 phy_write(phydev, MDIO_DEVAD_NONE, 116 MIIM_RTL8211F_PAGE_SELECT, 0xd04); 117 phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x617f); 118 phy_write(phydev, MDIO_DEVAD_NONE, 119 MIIM_RTL8211F_PAGE_SELECT, 0x0); 120 121 genphy_config_aneg(phydev); 122 123 return 0; 124 } 125 126 static int rtl8211x_parse_status(struct phy_device *phydev) 127 { 128 unsigned int speed; 129 unsigned int mii_reg; 130 131 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS); 132 133 if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 134 int i = 0; 135 136 /* in case of timeout ->link is cleared */ 137 phydev->link = 1; 138 puts("Waiting for PHY realtime link"); 139 while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 140 /* Timeout reached ? */ 141 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 142 puts(" TIMEOUT !\n"); 143 phydev->link = 0; 144 break; 145 } 146 147 if ((i++ % 1000) == 0) 148 putc('.'); 149 udelay(1000); /* 1 ms */ 150 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 151 MIIM_RTL8211x_PHY_STATUS); 152 } 153 puts(" done\n"); 154 udelay(500000); /* another 500 ms (results in faster booting) */ 155 } else { 156 if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK) 157 phydev->link = 1; 158 else 159 phydev->link = 0; 160 } 161 162 if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX) 163 phydev->duplex = DUPLEX_FULL; 164 else 165 phydev->duplex = DUPLEX_HALF; 166 167 speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED); 168 169 switch (speed) { 170 case MIIM_RTL8211x_PHYSTAT_GBIT: 171 phydev->speed = SPEED_1000; 172 break; 173 case MIIM_RTL8211x_PHYSTAT_100: 174 phydev->speed = SPEED_100; 175 break; 176 default: 177 phydev->speed = SPEED_10; 178 } 179 180 return 0; 181 } 182 183 static int rtl8211f_parse_status(struct phy_device *phydev) 184 { 185 unsigned int speed; 186 unsigned int mii_reg; 187 int i = 0; 188 189 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0xa43); 190 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PHY_STATUS); 191 192 phydev->link = 1; 193 while (!(mii_reg & MIIM_RTL8211F_PHYSTAT_LINK)) { 194 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 195 puts(" TIMEOUT !\n"); 196 phydev->link = 0; 197 break; 198 } 199 200 if ((i++ % 1000) == 0) 201 putc('.'); 202 udelay(1000); 203 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 204 MIIM_RTL8211F_PHY_STATUS); 205 } 206 207 if (mii_reg & MIIM_RTL8211F_PHYSTAT_DUPLEX) 208 phydev->duplex = DUPLEX_FULL; 209 else 210 phydev->duplex = DUPLEX_HALF; 211 212 speed = (mii_reg & MIIM_RTL8211F_PHYSTAT_SPEED); 213 214 switch (speed) { 215 case MIIM_RTL8211F_PHYSTAT_GBIT: 216 phydev->speed = SPEED_1000; 217 break; 218 case MIIM_RTL8211F_PHYSTAT_100: 219 phydev->speed = SPEED_100; 220 break; 221 default: 222 phydev->speed = SPEED_10; 223 } 224 225 return 0; 226 } 227 228 static int rtl8211x_startup(struct phy_device *phydev) 229 { 230 int ret; 231 232 /* Read the Status (2x to make sure link is right) */ 233 ret = genphy_update_link(phydev); 234 if (ret) 235 return ret; 236 237 return rtl8211x_parse_status(phydev); 238 } 239 240 static int rtl8211e_startup(struct phy_device *phydev) 241 { 242 int ret; 243 244 ret = genphy_update_link(phydev); 245 if (ret) 246 return ret; 247 248 return genphy_parse_link(phydev); 249 } 250 251 static int rtl8211f_startup(struct phy_device *phydev) 252 { 253 int ret; 254 255 /* Read the Status (2x to make sure link is right) */ 256 ret = genphy_update_link(phydev); 257 if (ret) 258 return ret; 259 /* Read the Status (2x to make sure link is right) */ 260 261 return rtl8211f_parse_status(phydev); 262 } 263 264 /* Support for RTL8211B PHY */ 265 static struct phy_driver RTL8211B_driver = { 266 .name = "RealTek RTL8211B", 267 .uid = 0x1cc912, 268 .mask = 0xffffff, 269 .features = PHY_GBIT_FEATURES, 270 .probe = &rtl8211b_probe, 271 .config = &rtl8211x_config, 272 .startup = &rtl8211x_startup, 273 .shutdown = &genphy_shutdown, 274 }; 275 276 /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */ 277 static struct phy_driver RTL8211E_driver = { 278 .name = "RealTek RTL8211E", 279 .uid = 0x1cc915, 280 .mask = 0xffffff, 281 .features = PHY_GBIT_FEATURES, 282 .config = &rtl8211x_config, 283 .startup = &rtl8211e_startup, 284 .shutdown = &genphy_shutdown, 285 }; 286 287 /* Support for RTL8211DN PHY */ 288 static struct phy_driver RTL8211DN_driver = { 289 .name = "RealTek RTL8211DN", 290 .uid = 0x1cc914, 291 .mask = 0xffffff, 292 .features = PHY_GBIT_FEATURES, 293 .config = &rtl8211x_config, 294 .startup = &rtl8211x_startup, 295 .shutdown = &genphy_shutdown, 296 }; 297 298 /* Support for RTL8211F PHY */ 299 static struct phy_driver RTL8211F_driver = { 300 .name = "RealTek RTL8211F", 301 .uid = 0x1cc916, 302 .mask = 0xffffff, 303 .features = PHY_GBIT_FEATURES, 304 .config = &rtl8211f_config, 305 .startup = &rtl8211f_startup, 306 .shutdown = &genphy_shutdown, 307 }; 308 309 int phy_realtek_init(void) 310 { 311 phy_register(&RTL8211B_driver); 312 phy_register(&RTL8211E_driver); 313 phy_register(&RTL8211F_driver); 314 phy_register(&RTL8211DN_driver); 315 316 return 0; 317 } 318