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