1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * RealTek PHY drivers 4 * 5 * Copyright 2010-2011, 2015 Freescale Semiconductor, Inc. 6 * author Andy Fleming 7 * Copyright 2016 Karsten Merker <merker@debian.org> 8 */ 9 #include <common.h> 10 #include <linux/bitops.h> 11 #include <phy.h> 12 13 #define PHY_RTL8211x_FORCE_MASTER BIT(1) 14 #define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2) 15 16 #define PHY_AUTONEGOTIATE_TIMEOUT 5000 17 18 /* RTL8211x 1000BASE-T Control Register */ 19 #define MIIM_RTL8211x_CTRL1000T_MSCE BIT(12); 20 #define MIIM_RTL8211x_CTRL1000T_MASTER BIT(11); 21 22 /* RTL8211x PHY Status Register */ 23 #define MIIM_RTL8211x_PHY_STATUS 0x11 24 #define MIIM_RTL8211x_PHYSTAT_SPEED 0xc000 25 #define MIIM_RTL8211x_PHYSTAT_GBIT 0x8000 26 #define MIIM_RTL8211x_PHYSTAT_100 0x4000 27 #define MIIM_RTL8211x_PHYSTAT_DUPLEX 0x2000 28 #define MIIM_RTL8211x_PHYSTAT_SPDDONE 0x0800 29 #define MIIM_RTL8211x_PHYSTAT_LINK 0x0400 30 31 /* RTL8211x PHY Interrupt Enable Register */ 32 #define MIIM_RTL8211x_PHY_INER 0x12 33 #define MIIM_RTL8211x_PHY_INTR_ENA 0x9f01 34 #define MIIM_RTL8211x_PHY_INTR_DIS 0x0000 35 36 /* RTL8211x PHY Interrupt Status Register */ 37 #define MIIM_RTL8211x_PHY_INSR 0x13 38 39 /* RTL8211F PHY Status Register */ 40 #define MIIM_RTL8211F_PHY_STATUS 0x1a 41 #define MIIM_RTL8211F_AUTONEG_ENABLE 0x1000 42 #define MIIM_RTL8211F_PHYSTAT_SPEED 0x0030 43 #define MIIM_RTL8211F_PHYSTAT_GBIT 0x0020 44 #define MIIM_RTL8211F_PHYSTAT_100 0x0010 45 #define MIIM_RTL8211F_PHYSTAT_DUPLEX 0x0008 46 #define MIIM_RTL8211F_PHYSTAT_SPDDONE 0x0800 47 #define MIIM_RTL8211F_PHYSTAT_LINK 0x0004 48 49 #define MIIM_RTL8211E_CONFREG 0x1c 50 #define MIIM_RTL8211E_CONFREG_TXD 0x0002 51 #define MIIM_RTL8211E_CONFREG_RXD 0x0004 52 #define MIIM_RTL8211E_CONFREG_MAGIC 0xb400 /* Undocumented */ 53 54 #define MIIM_RTL8211E_EXT_PAGE_SELECT 0x1e 55 56 #define MIIM_RTL8211F_PAGE_SELECT 0x1f 57 #define MIIM_RTL8211F_TX_DELAY 0x100 58 #define MIIM_RTL8211F_RX_DELAY 0x8 59 #define MIIM_RTL8211F_LCR 0x10 60 61 static int rtl8211f_phy_extread(struct phy_device *phydev, int addr, 62 int devaddr, int regnum) 63 { 64 int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, 65 MIIM_RTL8211F_PAGE_SELECT); 66 int val; 67 68 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, devaddr); 69 val = phy_read(phydev, MDIO_DEVAD_NONE, regnum); 70 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, oldpage); 71 72 return val; 73 } 74 75 static int rtl8211f_phy_extwrite(struct phy_device *phydev, int addr, 76 int devaddr, int regnum, u16 val) 77 { 78 int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, 79 MIIM_RTL8211F_PAGE_SELECT); 80 81 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, devaddr); 82 phy_write(phydev, MDIO_DEVAD_NONE, regnum, val); 83 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, oldpage); 84 85 return 0; 86 } 87 88 static int rtl8211b_probe(struct phy_device *phydev) 89 { 90 #ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER 91 phydev->flags |= PHY_RTL8211x_FORCE_MASTER; 92 #endif 93 94 return 0; 95 } 96 97 static int rtl8211e_probe(struct phy_device *phydev) 98 { 99 #ifdef CONFIG_RTL8211E_PINE64_GIGABIT_FIX 100 phydev->flags |= PHY_RTL8211E_PINE64_GIGABIT_FIX; 101 #endif 102 103 return 0; 104 } 105 106 /* RealTek RTL8211x */ 107 static int rtl8211x_config(struct phy_device *phydev) 108 { 109 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 110 111 /* mask interrupt at init; if the interrupt is 112 * needed indeed, it should be explicitly enabled 113 */ 114 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER, 115 MIIM_RTL8211x_PHY_INTR_DIS); 116 117 if (phydev->flags & PHY_RTL8211x_FORCE_MASTER) { 118 unsigned int reg; 119 120 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); 121 /* force manual master/slave configuration */ 122 reg |= MIIM_RTL8211x_CTRL1000T_MSCE; 123 /* force master mode */ 124 reg |= MIIM_RTL8211x_CTRL1000T_MASTER; 125 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg); 126 } 127 if (phydev->flags & PHY_RTL8211E_PINE64_GIGABIT_FIX) { 128 unsigned int reg; 129 130 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 131 7); 132 phy_write(phydev, MDIO_DEVAD_NONE, 133 MIIM_RTL8211E_EXT_PAGE_SELECT, 0xa4); 134 reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG); 135 /* Ensure both internal delays are turned off */ 136 reg &= ~(MIIM_RTL8211E_CONFREG_TXD | MIIM_RTL8211E_CONFREG_RXD); 137 /* Flip the magic undocumented bits */ 138 reg |= MIIM_RTL8211E_CONFREG_MAGIC; 139 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG, reg); 140 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 141 0); 142 } 143 /* read interrupt status just to clear it */ 144 phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER); 145 146 genphy_config_aneg(phydev); 147 148 return 0; 149 } 150 151 static int rtl8211f_config(struct phy_device *phydev) 152 { 153 u16 reg; 154 155 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 156 157 phy_write(phydev, MDIO_DEVAD_NONE, 158 MIIM_RTL8211F_PAGE_SELECT, 0xd08); 159 reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11); 160 161 /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ 162 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 163 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 164 reg |= MIIM_RTL8211F_TX_DELAY; 165 else 166 reg &= ~MIIM_RTL8211F_TX_DELAY; 167 168 phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg); 169 170 /* enable RX-delay for rgmii-id and rgmii-rxid, otherwise disable it */ 171 reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x15); 172 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 173 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 174 reg |= MIIM_RTL8211F_RX_DELAY; 175 else 176 reg &= ~MIIM_RTL8211F_RX_DELAY; 177 phy_write(phydev, MDIO_DEVAD_NONE, 0x15, reg); 178 179 /* restore to default page 0 */ 180 phy_write(phydev, MDIO_DEVAD_NONE, 181 MIIM_RTL8211F_PAGE_SELECT, 0x0); 182 183 /* Set green LED for Link, yellow LED for Active */ 184 phy_write(phydev, MDIO_DEVAD_NONE, 185 MIIM_RTL8211F_PAGE_SELECT, 0xd04); 186 phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x617f); 187 phy_write(phydev, MDIO_DEVAD_NONE, 188 MIIM_RTL8211F_PAGE_SELECT, 0x0); 189 190 genphy_config_aneg(phydev); 191 192 return 0; 193 } 194 195 static int rtl8211x_parse_status(struct phy_device *phydev) 196 { 197 unsigned int speed; 198 unsigned int mii_reg; 199 200 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS); 201 202 if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 203 int i = 0; 204 205 /* in case of timeout ->link is cleared */ 206 phydev->link = 1; 207 puts("Waiting for PHY realtime link"); 208 while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) { 209 /* Timeout reached ? */ 210 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 211 puts(" TIMEOUT !\n"); 212 phydev->link = 0; 213 break; 214 } 215 216 if ((i++ % 1000) == 0) 217 putc('.'); 218 udelay(1000); /* 1 ms */ 219 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 220 MIIM_RTL8211x_PHY_STATUS); 221 } 222 puts(" done\n"); 223 udelay(500000); /* another 500 ms (results in faster booting) */ 224 } else { 225 if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK) 226 phydev->link = 1; 227 else 228 phydev->link = 0; 229 } 230 231 if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX) 232 phydev->duplex = DUPLEX_FULL; 233 else 234 phydev->duplex = DUPLEX_HALF; 235 236 speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED); 237 238 switch (speed) { 239 case MIIM_RTL8211x_PHYSTAT_GBIT: 240 phydev->speed = SPEED_1000; 241 break; 242 case MIIM_RTL8211x_PHYSTAT_100: 243 phydev->speed = SPEED_100; 244 break; 245 default: 246 phydev->speed = SPEED_10; 247 } 248 249 return 0; 250 } 251 252 static int rtl8211f_parse_status(struct phy_device *phydev) 253 { 254 unsigned int speed; 255 unsigned int mii_reg; 256 int i = 0; 257 258 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0xa43); 259 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PHY_STATUS); 260 261 phydev->link = 1; 262 while (!(mii_reg & MIIM_RTL8211F_PHYSTAT_LINK)) { 263 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 264 puts(" TIMEOUT !\n"); 265 phydev->link = 0; 266 break; 267 } 268 269 if ((i++ % 1000) == 0) 270 putc('.'); 271 udelay(1000); 272 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 273 MIIM_RTL8211F_PHY_STATUS); 274 } 275 276 if (mii_reg & MIIM_RTL8211F_PHYSTAT_DUPLEX) 277 phydev->duplex = DUPLEX_FULL; 278 else 279 phydev->duplex = DUPLEX_HALF; 280 281 speed = (mii_reg & MIIM_RTL8211F_PHYSTAT_SPEED); 282 283 switch (speed) { 284 case MIIM_RTL8211F_PHYSTAT_GBIT: 285 phydev->speed = SPEED_1000; 286 break; 287 case MIIM_RTL8211F_PHYSTAT_100: 288 phydev->speed = SPEED_100; 289 break; 290 default: 291 phydev->speed = SPEED_10; 292 } 293 294 return 0; 295 } 296 297 static int rtl8211x_startup(struct phy_device *phydev) 298 { 299 int ret; 300 301 /* Read the Status (2x to make sure link is right) */ 302 ret = genphy_update_link(phydev); 303 if (ret) 304 return ret; 305 306 return rtl8211x_parse_status(phydev); 307 } 308 309 static int rtl8211e_startup(struct phy_device *phydev) 310 { 311 int ret; 312 313 ret = genphy_update_link(phydev); 314 if (ret) 315 return ret; 316 317 return genphy_parse_link(phydev); 318 } 319 320 static int rtl8211f_startup(struct phy_device *phydev) 321 { 322 int ret; 323 324 /* Read the Status (2x to make sure link is right) */ 325 ret = genphy_update_link(phydev); 326 if (ret) 327 return ret; 328 /* Read the Status (2x to make sure link is right) */ 329 330 return rtl8211f_parse_status(phydev); 331 } 332 333 /* Support for RTL8211B PHY */ 334 static struct phy_driver RTL8211B_driver = { 335 .name = "RealTek RTL8211B", 336 .uid = 0x1cc912, 337 .mask = 0xffffff, 338 .features = PHY_GBIT_FEATURES, 339 .probe = &rtl8211b_probe, 340 .config = &rtl8211x_config, 341 .startup = &rtl8211x_startup, 342 .shutdown = &genphy_shutdown, 343 }; 344 345 /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */ 346 static struct phy_driver RTL8211E_driver = { 347 .name = "RealTek RTL8211E", 348 .uid = 0x1cc915, 349 .mask = 0xffffff, 350 .features = PHY_GBIT_FEATURES, 351 .probe = &rtl8211e_probe, 352 .config = &rtl8211x_config, 353 .startup = &rtl8211e_startup, 354 .shutdown = &genphy_shutdown, 355 }; 356 357 /* Support for RTL8211DN PHY */ 358 static struct phy_driver RTL8211DN_driver = { 359 .name = "RealTek RTL8211DN", 360 .uid = 0x1cc914, 361 .mask = 0xffffff, 362 .features = PHY_GBIT_FEATURES, 363 .config = &rtl8211x_config, 364 .startup = &rtl8211x_startup, 365 .shutdown = &genphy_shutdown, 366 }; 367 368 /* Support for RTL8211F PHY */ 369 static struct phy_driver RTL8211F_driver = { 370 .name = "RealTek RTL8211F", 371 .uid = 0x1cc916, 372 .mask = 0xffffff, 373 .features = PHY_GBIT_FEATURES, 374 .config = &rtl8211f_config, 375 .startup = &rtl8211f_startup, 376 .shutdown = &genphy_shutdown, 377 .readext = &rtl8211f_phy_extread, 378 .writeext = &rtl8211f_phy_extwrite, 379 }; 380 381 int phy_realtek_init(void) 382 { 383 phy_register(&RTL8211B_driver); 384 phy_register(&RTL8211E_driver); 385 phy_register(&RTL8211F_driver); 386 phy_register(&RTL8211DN_driver); 387 388 return 0; 389 } 390