1 /* 2 * Microsemi PHY drivers 3 * 4 * SPDX-License-Identifier: The MIT License (MIT) 5 * 6 * Copyright (c) 2016 Microsemi Corporation 7 * 8 * Author: John Haechten 9 * 10 */ 11 12 #include <miiphy.h> 13 #include <bitfield.h> 14 15 /* Microsemi PHY ID's */ 16 #define PHY_ID_VSC8530 0x00070560 17 #define PHY_ID_VSC8531 0x00070570 18 #define PHY_ID_VSC8540 0x00070760 19 #define PHY_ID_VSC8541 0x00070770 20 21 /* Microsemi VSC85xx PHY Register Pages */ 22 #define MSCC_EXT_PAGE_ACCESS 31 /* Page Access Register */ 23 #define MSCC_PHY_PAGE_STD 0x0000 /* Standard registers */ 24 #define MSCC_PHY_PAGE_EXT1 0x0001 /* Extended registers - page 1 */ 25 #define MSCC_PHY_PAGE_EXT2 0x0002 /* Extended registers - page 2 */ 26 #define MSCC_PHY_PAGE_EXT3 0x0003 /* Extended registers - page 3 */ 27 #define MSCC_PHY_PAGE_EXT4 0x0004 /* Extended registers - page 4 */ 28 #define MSCC_PHY_PAGE_GPIO 0x0010 /* GPIO registers */ 29 #define MSCC_PHY_PAGE_TEST 0x2A30 /* TEST Page registers */ 30 #define MSCC_PHY_PAGE_TR 0x52B5 /* Token Ring Page registers */ 31 32 /* Std Page Register 28 - PHY AUX Control/Status */ 33 #define MIIM_AUX_CNTRL_STAT_REG 28 34 #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO (0x0004) 35 #define MIIM_AUX_CNTRL_STAT_F_DUPLEX (0x0020) 36 #define MIIM_AUX_CNTRL_STAT_SPEED_MASK (0x0018) 37 #define MIIM_AUX_CNTRL_STAT_SPEED_POS (3) 38 #define MIIM_AUX_CNTRL_STAT_SPEED_10M (0x0) 39 #define MIIM_AUX_CNTRL_STAT_SPEED_100M (0x1) 40 #define MIIM_AUX_CNTRL_STAT_SPEED_1000M (0x2) 41 42 /* Std Page Register 23 - Extended PHY CTRL_1 */ 43 #define MSCC_PHY_EXT_PHY_CNTL_1_REG 23 44 #define MAC_IF_SELECTION_MASK (0x1800) 45 #define MAC_IF_SELECTION_GMII (0) 46 #define MAC_IF_SELECTION_RMII (1) 47 #define MAC_IF_SELECTION_RGMII (2) 48 #define MAC_IF_SELECTION_POS (11) 49 #define MAC_IF_SELECTION_WIDTH (2) 50 51 /* Extended Page 2 Register 20E2 */ 52 #define MSCC_PHY_RGMII_CNTL_REG 20 53 #define VSC_FAST_LINK_FAIL2_ENA_MASK (0x8000) 54 #define RX_CLK_OUT_MASK (0x0800) 55 #define RX_CLK_OUT_POS (11) 56 #define RX_CLK_OUT_WIDTH (1) 57 #define RX_CLK_OUT_NORMAL (0) 58 #define RX_CLK_OUT_DISABLE (1) 59 #define RGMII_RX_CLK_DELAY_POS (4) 60 #define RGMII_RX_CLK_DELAY_WIDTH (3) 61 #define RGMII_RX_CLK_DELAY_MASK (0x0070) 62 #define RGMII_TX_CLK_DELAY_POS (0) 63 #define RGMII_TX_CLK_DELAY_WIDTH (3) 64 #define RGMII_TX_CLK_DELAY_MASK (0x0007) 65 66 /* Extended Page 2 Register 27E2 */ 67 #define MSCC_PHY_WOL_MAC_CONTROL 27 68 #define EDGE_RATE_CNTL_POS (5) 69 #define EDGE_RATE_CNTL_WIDTH (3) 70 #define EDGE_RATE_CNTL_MASK (0x00E0) 71 #define RMII_CLK_OUT_ENABLE_POS (4) 72 #define RMII_CLK_OUT_ENABLE_WIDTH (1) 73 #define RMII_CLK_OUT_ENABLE_MASK (0x10) 74 75 /* Token Ring Page 0x52B5 Registers */ 76 #define MSCC_PHY_REG_TR_ADDR_16 16 77 #define MSCC_PHY_REG_TR_DATA_17 17 78 #define MSCC_PHY_REG_TR_DATA_18 18 79 80 /* Token Ring - Read Value in */ 81 #define MSCC_PHY_TR_16_READ (0xA000) 82 /* Token Ring - Write Value out */ 83 #define MSCC_PHY_TR_16_WRITE (0x8000) 84 85 /* Token Ring Registers */ 86 #define MSCC_PHY_TR_LINKDETCTRL_POS (3) 87 #define MSCC_PHY_TR_LINKDETCTRL_WIDTH (2) 88 #define MSCC_PHY_TR_LINKDETCTRL_VAL (3) 89 #define MSCC_PHY_TR_LINKDETCTRL_MASK (0x0018) 90 #define MSCC_PHY_TR_LINKDETCTRL_ADDR (0x07F8) 91 92 #define MSCC_PHY_TR_VGATHRESH100_POS (0) 93 #define MSCC_PHY_TR_VGATHRESH100_WIDTH (7) 94 #define MSCC_PHY_TR_VGATHRESH100_VAL (0x0018) 95 #define MSCC_PHY_TR_VGATHRESH100_MASK (0x007f) 96 #define MSCC_PHY_TR_VGATHRESH100_ADDR (0x0FA4) 97 98 #define MSCC_PHY_TR_VGAGAIN10_U_POS (0) 99 #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH (1) 100 #define MSCC_PHY_TR_VGAGAIN10_U_MASK (0x0001) 101 #define MSCC_PHY_TR_VGAGAIN10_U_VAL (0) 102 103 #define MSCC_PHY_TR_VGAGAIN10_L_POS (12) 104 #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH (4) 105 #define MSCC_PHY_TR_VGAGAIN10_L_MASK (0xf000) 106 #define MSCC_PHY_TR_VGAGAIN10_L_VAL (0x0001) 107 #define MSCC_PHY_TR_VGAGAIN10_ADDR (0x0F92) 108 109 /* General Timeout Values */ 110 #define MSCC_PHY_RESET_TIMEOUT (100) 111 #define MSCC_PHY_MICRO_TIMEOUT (500) 112 113 /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew { 114 VSC_PHY_RGMII_DELAY_200_PS, 115 VSC_PHY_RGMII_DELAY_800_PS, 116 VSC_PHY_RGMII_DELAY_1100_PS, 117 VSC_PHY_RGMII_DELAY_1700_PS, 118 VSC_PHY_RGMII_DELAY_2000_PS, 119 VSC_PHY_RGMII_DELAY_2300_PS, 120 VSC_PHY_RGMII_DELAY_2600_PS, 121 VSC_PHY_RGMII_DELAY_3400_PS, 122 }; 123 124 /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2 */ enum 125 vsc_phy_clk_slew { 126 VSC_PHY_CLK_SLEW_RATE_0, 127 VSC_PHY_CLK_SLEW_RATE_1, 128 VSC_PHY_CLK_SLEW_RATE_2, 129 VSC_PHY_CLK_SLEW_RATE_3, 130 VSC_PHY_CLK_SLEW_RATE_4, 131 VSC_PHY_CLK_SLEW_RATE_5, 132 VSC_PHY_CLK_SLEW_RATE_6, 133 VSC_PHY_CLK_SLEW_RATE_7, 134 }; 135 136 137 static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev) 138 { 139 u16 reg_val; 140 141 /* Set to Access Token Ring Registers */ 142 phy_write(phydev, MDIO_DEVAD_NONE, 143 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR); 144 145 /* Update LinkDetectCtrl default to optimized values */ 146 /* Determined during Silicon Validation Testing */ 147 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 148 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ)); 149 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17); 150 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS, 151 MSCC_PHY_TR_LINKDETCTRL_WIDTH, 152 MSCC_PHY_TR_LINKDETCTRL_VAL); 153 154 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val); 155 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 156 (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE)); 157 158 /* Update VgaThresh100 defaults to optimized values */ 159 /* Determined during Silicon Validation Testing */ 160 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 161 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ)); 162 163 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18); 164 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS, 165 MSCC_PHY_TR_VGATHRESH100_WIDTH, 166 MSCC_PHY_TR_VGATHRESH100_VAL); 167 168 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val); 169 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 170 (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE)); 171 172 /* Update VgaGain10 defaults to optimized values */ 173 /* Determined during Silicon Validation Testing */ 174 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 175 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ)); 176 177 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18); 178 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS, 179 MSCC_PHY_TR_VGAGAIN10_U_WIDTH, 180 MSCC_PHY_TR_VGAGAIN10_U_VAL); 181 182 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val); 183 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17); 184 reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS, 185 MSCC_PHY_TR_VGAGAIN10_L_WIDTH, 186 MSCC_PHY_TR_VGAGAIN10_L_VAL); 187 188 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val); 189 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 190 (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE)); 191 192 /* Set back to Access Standard Page Registers */ 193 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 194 MSCC_PHY_PAGE_STD); 195 196 return 0; 197 } 198 199 static int mscc_parse_status(struct phy_device *phydev) 200 { 201 u16 speed; 202 u16 mii_reg; 203 204 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG); 205 206 if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX) 207 phydev->duplex = DUPLEX_FULL; 208 else 209 phydev->duplex = DUPLEX_HALF; 210 211 speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK; 212 speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS; 213 214 switch (speed) { 215 case MIIM_AUX_CNTRL_STAT_SPEED_1000M: 216 phydev->speed = SPEED_1000; 217 break; 218 case MIIM_AUX_CNTRL_STAT_SPEED_100M: 219 phydev->speed = SPEED_100; 220 break; 221 case MIIM_AUX_CNTRL_STAT_SPEED_10M: 222 phydev->speed = SPEED_10; 223 break; 224 default: 225 phydev->speed = SPEED_10; 226 break; 227 } 228 229 return 0; 230 } 231 232 static int mscc_startup(struct phy_device *phydev) 233 { 234 int retval; 235 236 retval = genphy_update_link(phydev); 237 238 if (retval) 239 return retval; 240 241 return mscc_parse_status(phydev); 242 } 243 244 static int mscc_phy_soft_reset(struct phy_device *phydev) 245 { 246 int retval = 0; 247 u16 timeout = MSCC_PHY_RESET_TIMEOUT; 248 u16 reg_val = 0; 249 250 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 251 MSCC_PHY_PAGE_STD); 252 253 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 254 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET)); 255 256 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 257 258 while ((reg_val & BMCR_RESET) && (timeout > 0)) { 259 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 260 timeout--; 261 udelay(1000); /* 1 ms */ 262 } 263 264 if (timeout == 0) { 265 printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n", 266 phydev->interface); 267 retval = -ETIME; 268 } 269 270 return retval; 271 } 272 273 static int vsc8531_vsc8541_mac_config(struct phy_device *phydev) 274 { 275 u16 reg_val = 0; 276 u16 mac_if = 0; 277 u16 rx_clk_out = 0; 278 279 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */ 280 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */ 281 /* Setup MAC Configuration */ 282 switch (phydev->interface) { 283 case PHY_INTERFACE_MODE_MII: 284 case PHY_INTERFACE_MODE_GMII: 285 /* Set Reg23.12:11=0 */ 286 mac_if = MAC_IF_SELECTION_GMII; 287 /* Set Reg20E2.11=1 */ 288 rx_clk_out = RX_CLK_OUT_DISABLE; 289 break; 290 291 case PHY_INTERFACE_MODE_RMII: 292 /* Set Reg23.12:11=1 */ 293 mac_if = MAC_IF_SELECTION_RMII; 294 /* Set Reg20E2.11=0 */ 295 rx_clk_out = RX_CLK_OUT_NORMAL; 296 break; 297 298 case PHY_INTERFACE_MODE_RGMII: 299 /* Set Reg23.12:11=2 */ 300 mac_if = MAC_IF_SELECTION_RGMII; 301 /* Set Reg20E2.11=0 */ 302 rx_clk_out = RX_CLK_OUT_NORMAL; 303 break; 304 305 default: 306 printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n", 307 phydev->interface); 308 return -EINVAL; 309 } 310 311 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 312 MSCC_PHY_PAGE_STD); 313 314 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, 315 MSCC_PHY_EXT_PHY_CNTL_1_REG); 316 /* Set MAC i/f bits Reg23.12:11 */ 317 reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS, 318 MAC_IF_SELECTION_WIDTH, mac_if); 319 /* Update Reg23.12:11 */ 320 phy_write(phydev, MDIO_DEVAD_NONE, 321 MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val); 322 /* Setup ExtPg_2 Register Access */ 323 phy_write(phydev, MDIO_DEVAD_NONE, 324 MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2); 325 /* Read Reg20E2 */ 326 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, 327 MSCC_PHY_RGMII_CNTL_REG); 328 reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS, 329 RX_CLK_OUT_WIDTH, rx_clk_out); 330 /* Update Reg20E2.11 */ 331 phy_write(phydev, MDIO_DEVAD_NONE, 332 MSCC_PHY_RGMII_CNTL_REG, reg_val); 333 /* Before leaving - Change back to Std Page Register Access */ 334 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 335 MSCC_PHY_PAGE_STD); 336 337 return 0; 338 } 339 340 static int vsc8531_config(struct phy_device *phydev) 341 { 342 int retval = -EINVAL; 343 u16 reg_val; 344 u16 rmii_clk_out; 345 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS; 346 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS; 347 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4; 348 349 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */ 350 mscc_vsc8531_vsc8541_init_scripts(phydev); 351 352 /* For VSC8530/31 the only MAC modes are RMII/RGMII. */ 353 switch (phydev->interface) { 354 case PHY_INTERFACE_MODE_RMII: 355 case PHY_INTERFACE_MODE_RGMII: 356 retval = vsc8531_vsc8541_mac_config(phydev); 357 if (retval != 0) 358 return retval; 359 360 retval = mscc_phy_soft_reset(phydev); 361 if (retval != 0) 362 return retval; 363 break; 364 default: 365 printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n", 366 phydev->interface); 367 return -EINVAL; 368 } 369 /* Default RMII Clk Output to 0=OFF/1=ON */ 370 rmii_clk_out = 0; 371 372 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 373 MSCC_PHY_PAGE_EXT2); 374 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG); 375 376 /* Reg20E2 - Update RGMII RX_Clk Skews. */ 377 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS, 378 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew); 379 /* Reg20E2 - Update RGMII TX_Clk Skews. */ 380 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS, 381 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew); 382 383 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val); 384 385 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL); 386 /* Reg27E2 - Update Clk Slew Rate. */ 387 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS, 388 EDGE_RATE_CNTL_WIDTH, edge_rate); 389 /* Reg27E2 - Update RMII Clk Out. */ 390 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS, 391 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out); 392 /* Update Reg27E2 */ 393 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val); 394 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 395 MSCC_PHY_PAGE_STD); 396 397 return genphy_config_aneg(phydev); 398 } 399 400 static int vsc8541_config(struct phy_device *phydev) 401 { 402 int retval = -EINVAL; 403 u16 reg_val; 404 u16 rmii_clk_out; 405 enum vsc_phy_rgmii_skew rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS; 406 enum vsc_phy_rgmii_skew tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS; 407 enum vsc_phy_clk_slew edge_rate = VSC_PHY_CLK_SLEW_RATE_4; 408 409 /* For VSC8530/31 and VSC8540/41 the init scripts are the same */ 410 mscc_vsc8531_vsc8541_init_scripts(phydev); 411 412 /* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */ 413 switch (phydev->interface) { 414 case PHY_INTERFACE_MODE_MII: 415 case PHY_INTERFACE_MODE_GMII: 416 case PHY_INTERFACE_MODE_RMII: 417 case PHY_INTERFACE_MODE_RGMII: 418 retval = vsc8531_vsc8541_mac_config(phydev); 419 if (retval != 0) 420 return retval; 421 422 retval = mscc_phy_soft_reset(phydev); 423 if (retval != 0) 424 return retval; 425 break; 426 default: 427 printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n", 428 phydev->interface); 429 return -EINVAL; 430 } 431 /* Default RMII Clk Output to 0=OFF/1=ON */ 432 rmii_clk_out = 0; 433 434 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 435 MSCC_PHY_PAGE_EXT2); 436 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG); 437 /* Reg20E2 - Update RGMII RX_Clk Skews. */ 438 reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS, 439 RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew); 440 /* Reg20E2 - Update RGMII TX_Clk Skews. */ 441 reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS, 442 RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew); 443 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val); 444 445 reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL); 446 /* Reg27E2 - Update Clk Slew Rate. */ 447 reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS, 448 EDGE_RATE_CNTL_WIDTH, edge_rate); 449 /* Reg27E2 - Update RMII Clk Out. */ 450 reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS, 451 RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out); 452 /* Update Reg27E2 */ 453 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val); 454 phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS, 455 MSCC_PHY_PAGE_STD); 456 457 return genphy_config_aneg(phydev); 458 } 459 460 static struct phy_driver VSC8530_driver = { 461 .name = "Microsemi VSC8530", 462 .uid = PHY_ID_VSC8530, 463 .mask = 0x000ffff0, 464 .features = PHY_BASIC_FEATURES, 465 .config = &vsc8531_config, 466 .startup = &mscc_startup, 467 .shutdown = &genphy_shutdown, 468 }; 469 470 static struct phy_driver VSC8531_driver = { 471 .name = "Microsemi VSC8531", 472 .uid = PHY_ID_VSC8531, 473 .mask = 0x000ffff0, 474 .features = PHY_GBIT_FEATURES, 475 .config = &vsc8531_config, 476 .startup = &mscc_startup, 477 .shutdown = &genphy_shutdown, 478 }; 479 480 static struct phy_driver VSC8540_driver = { 481 .name = "Microsemi VSC8540", 482 .uid = PHY_ID_VSC8540, 483 .mask = 0x000ffff0, 484 .features = PHY_BASIC_FEATURES, 485 .config = &vsc8541_config, 486 .startup = &mscc_startup, 487 .shutdown = &genphy_shutdown, 488 }; 489 490 static struct phy_driver VSC8541_driver = { 491 .name = "Microsemi VSC8541", 492 .uid = PHY_ID_VSC8541, 493 .mask = 0x000ffff0, 494 .features = PHY_GBIT_FEATURES, 495 .config = &vsc8541_config, 496 .startup = &mscc_startup, 497 .shutdown = &genphy_shutdown, 498 }; 499 500 int phy_mscc_init(void) 501 { 502 phy_register(&VSC8530_driver); 503 phy_register(&VSC8531_driver); 504 phy_register(&VSC8540_driver); 505 phy_register(&VSC8541_driver); 506 507 return 0; 508 } 509