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