Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mxl-gpy-MDI-X'

Raju Lakkaraju says:

====================
net: phy: mxl-gpy: Add MDI-X

This patch series add the MDI-X feature to GPY211 PHYs and
Also Change return type to gpy_update_interface() function
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+90 -8
+90 -8
drivers/net/phy/mxl-gpy.c
··· 29 29 #define PHY_ID_GPY241BM 0x67C9DE80 30 30 #define PHY_ID_GPY245B 0x67C9DEC0 31 31 32 + #define PHY_CTL1 0x13 33 + #define PHY_CTL1_MDICD BIT(3) 34 + #define PHY_CTL1_MDIAB BIT(2) 35 + #define PHY_CTL1_AMDIX BIT(0) 32 36 #define PHY_MIISTAT 0x18 /* MII state */ 33 37 #define PHY_IMASK 0x19 /* interrupt mask */ 34 38 #define PHY_ISTAT 0x1A /* interrupt status */ ··· 62 58 #define PHY_FWV_REL_MASK BIT(15) 63 59 #define PHY_FWV_MAJOR_MASK GENMASK(11, 8) 64 60 #define PHY_FWV_MINOR_MASK GENMASK(7, 0) 61 + 62 + #define PHY_PMA_MGBT_POLARITY 0x82 63 + #define PHY_MDI_MDI_X_MASK GENMASK(1, 0) 64 + #define PHY_MDI_MDI_X_NORMAL 0x3 65 + #define PHY_MDI_MDI_X_AB 0x2 66 + #define PHY_MDI_MDI_X_CD 0x1 67 + #define PHY_MDI_MDI_X_CROSS 0x0 65 68 66 69 /* SGMII */ 67 70 #define VSPEC1_SGMII_CTRL 0x08 ··· 300 289 return (ret & VSPEC1_SGMII_CTRL_ANEN) ? true : false; 301 290 } 302 291 292 + static int gpy_config_mdix(struct phy_device *phydev, u8 ctrl) 293 + { 294 + int ret; 295 + u16 val; 296 + 297 + switch (ctrl) { 298 + case ETH_TP_MDI_AUTO: 299 + val = PHY_CTL1_AMDIX; 300 + break; 301 + case ETH_TP_MDI_X: 302 + val = (PHY_CTL1_MDIAB | PHY_CTL1_MDICD); 303 + break; 304 + case ETH_TP_MDI: 305 + val = 0; 306 + break; 307 + default: 308 + return 0; 309 + } 310 + 311 + ret = phy_modify(phydev, PHY_CTL1, PHY_CTL1_AMDIX | PHY_CTL1_MDIAB | 312 + PHY_CTL1_MDICD, val); 313 + if (ret < 0) 314 + return ret; 315 + 316 + return genphy_c45_restart_aneg(phydev); 317 + } 318 + 303 319 static int gpy_config_aneg(struct phy_device *phydev) 304 320 { 305 321 bool changed = false; ··· 341 303 ? genphy_setup_forced(phydev) 342 304 : genphy_c45_pma_setup_forced(phydev); 343 305 } 306 + 307 + ret = gpy_config_mdix(phydev, phydev->mdix_ctrl); 308 + if (ret < 0) 309 + return ret; 344 310 345 311 ret = genphy_c45_an_config_aneg(phydev); 346 312 if (ret < 0) ··· 412 370 VSPEC1_SGMII_CTRL_ANRS, VSPEC1_SGMII_CTRL_ANRS); 413 371 } 414 372 415 - static void gpy_update_interface(struct phy_device *phydev) 373 + static int gpy_update_mdix(struct phy_device *phydev) 374 + { 375 + int ret; 376 + 377 + ret = phy_read(phydev, PHY_CTL1); 378 + if (ret < 0) 379 + return ret; 380 + 381 + if (ret & PHY_CTL1_AMDIX) 382 + phydev->mdix_ctrl = ETH_TP_MDI_AUTO; 383 + else 384 + if (ret & PHY_CTL1_MDICD || ret & PHY_CTL1_MDIAB) 385 + phydev->mdix_ctrl = ETH_TP_MDI_X; 386 + else 387 + phydev->mdix_ctrl = ETH_TP_MDI; 388 + 389 + ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PHY_PMA_MGBT_POLARITY); 390 + if (ret < 0) 391 + return ret; 392 + 393 + if ((ret & PHY_MDI_MDI_X_MASK) < PHY_MDI_MDI_X_NORMAL) 394 + phydev->mdix = ETH_TP_MDI_X; 395 + else 396 + phydev->mdix = ETH_TP_MDI; 397 + 398 + return 0; 399 + } 400 + 401 + static int gpy_update_interface(struct phy_device *phydev) 416 402 { 417 403 int ret; 418 404 419 405 /* Interface mode is fixed for USXGMII and integrated PHY */ 420 406 if (phydev->interface == PHY_INTERFACE_MODE_USXGMII || 421 407 phydev->interface == PHY_INTERFACE_MODE_INTERNAL) 422 - return; 408 + return -EINVAL; 423 409 424 410 /* Automatically switch SERDES interface between SGMII and 2500-BaseX 425 411 * according to speed. Disable ANEG in 2500-BaseX mode. ··· 457 387 phydev->interface = PHY_INTERFACE_MODE_2500BASEX; 458 388 ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, 459 389 VSPEC1_SGMII_CTRL_ANEN, 0); 460 - if (ret < 0) 390 + if (ret < 0) { 461 391 phydev_err(phydev, 462 392 "Error: Disable of SGMII ANEG failed: %d\n", 463 393 ret); 394 + return ret; 395 + } 464 396 break; 465 397 case SPEED_1000: 466 398 case SPEED_100: ··· 476 404 ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, 477 405 VSPEC1_SGMII_ANEN_ANRS, 478 406 VSPEC1_SGMII_ANEN_ANRS); 479 - if (ret < 0) 407 + if (ret < 0) { 480 408 phydev_err(phydev, 481 409 "Error: Enable of SGMII ANEG failed: %d\n", 482 410 ret); 411 + return ret; 412 + } 483 413 break; 484 414 } 485 415 486 - if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) 487 - genphy_read_master_slave(phydev); 416 + if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) { 417 + ret = genphy_read_master_slave(phydev); 418 + if (ret < 0) 419 + return ret; 420 + } 421 + 422 + return gpy_update_mdix(phydev); 488 423 } 489 424 490 425 static int gpy_read_status(struct phy_device *phydev) ··· 542 463 break; 543 464 } 544 465 545 - if (phydev->link) 546 - gpy_update_interface(phydev); 466 + if (phydev->link) { 467 + ret = gpy_update_interface(phydev); 468 + if (ret < 0) 469 + return ret; 470 + } 547 471 548 472 return 0; 549 473 }