diff options
| -rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 122 | ||||
| -rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 98 |
2 files changed, 121 insertions, 99 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 3bf3c0194ad3..1f5487f4888c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
| @@ -122,6 +122,7 @@ | |||
| 122 | #include <linux/clk.h> | 122 | #include <linux/clk.h> |
| 123 | #include <linux/if_ether.h> | 123 | #include <linux/if_ether.h> |
| 124 | #include <linux/net_tstamp.h> | 124 | #include <linux/net_tstamp.h> |
| 125 | #include <linux/phy.h> | ||
| 125 | 126 | ||
| 126 | #include "xgbe.h" | 127 | #include "xgbe.h" |
| 127 | #include "xgbe-common.h" | 128 | #include "xgbe-common.h" |
| @@ -521,6 +522,114 @@ static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata) | |||
| 521 | DBGPR("<--xgbe_free_rx_skbuff\n"); | 522 | DBGPR("<--xgbe_free_rx_skbuff\n"); |
| 522 | } | 523 | } |
| 523 | 524 | ||
| 525 | static void xgbe_adjust_link(struct net_device *netdev) | ||
| 526 | { | ||
| 527 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | ||
| 528 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | ||
| 529 | struct phy_device *phydev = pdata->phydev; | ||
| 530 | int new_state = 0; | ||
| 531 | |||
| 532 | if (phydev == NULL) | ||
| 533 | return; | ||
| 534 | |||
| 535 | if (phydev->link) { | ||
| 536 | /* Flow control support */ | ||
| 537 | if (pdata->pause_autoneg) { | ||
| 538 | if (phydev->pause || phydev->asym_pause) { | ||
| 539 | pdata->tx_pause = 1; | ||
| 540 | pdata->rx_pause = 1; | ||
| 541 | } else { | ||
| 542 | pdata->tx_pause = 0; | ||
| 543 | pdata->rx_pause = 0; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | if (pdata->tx_pause != pdata->phy_tx_pause) { | ||
| 548 | hw_if->config_tx_flow_control(pdata); | ||
| 549 | pdata->phy_tx_pause = pdata->tx_pause; | ||
| 550 | } | ||
| 551 | |||
| 552 | if (pdata->rx_pause != pdata->phy_rx_pause) { | ||
| 553 | hw_if->config_rx_flow_control(pdata); | ||
| 554 | pdata->phy_rx_pause = pdata->rx_pause; | ||
| 555 | } | ||
| 556 | |||
| 557 | /* Speed support */ | ||
| 558 | if (phydev->speed != pdata->phy_speed) { | ||
| 559 | new_state = 1; | ||
| 560 | |||
| 561 | switch (phydev->speed) { | ||
| 562 | case SPEED_10000: | ||
| 563 | hw_if->set_xgmii_speed(pdata); | ||
| 564 | break; | ||
| 565 | |||
| 566 | case SPEED_2500: | ||
| 567 | hw_if->set_gmii_2500_speed(pdata); | ||
| 568 | break; | ||
| 569 | |||
| 570 | case SPEED_1000: | ||
| 571 | hw_if->set_gmii_speed(pdata); | ||
| 572 | break; | ||
| 573 | } | ||
| 574 | pdata->phy_speed = phydev->speed; | ||
| 575 | } | ||
| 576 | |||
| 577 | if (phydev->link != pdata->phy_link) { | ||
| 578 | new_state = 1; | ||
| 579 | pdata->phy_link = 1; | ||
| 580 | } | ||
| 581 | } else if (pdata->phy_link) { | ||
| 582 | new_state = 1; | ||
| 583 | pdata->phy_link = 0; | ||
| 584 | pdata->phy_speed = SPEED_UNKNOWN; | ||
| 585 | } | ||
| 586 | |||
| 587 | if (new_state) | ||
| 588 | phy_print_status(phydev); | ||
| 589 | } | ||
| 590 | |||
| 591 | static int xgbe_phy_init(struct xgbe_prv_data *pdata) | ||
| 592 | { | ||
| 593 | struct net_device *netdev = pdata->netdev; | ||
| 594 | struct phy_device *phydev = pdata->phydev; | ||
| 595 | int ret; | ||
| 596 | |||
| 597 | pdata->phy_link = -1; | ||
| 598 | pdata->phy_speed = SPEED_UNKNOWN; | ||
| 599 | pdata->phy_tx_pause = pdata->tx_pause; | ||
| 600 | pdata->phy_rx_pause = pdata->rx_pause; | ||
| 601 | |||
| 602 | ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link, | ||
| 603 | pdata->phy_mode); | ||
| 604 | if (ret) { | ||
| 605 | netdev_err(netdev, "phy_connect_direct failed\n"); | ||
| 606 | return ret; | ||
| 607 | } | ||
| 608 | |||
| 609 | if (!phydev->drv || (phydev->drv->phy_id == 0)) { | ||
| 610 | netdev_err(netdev, "phy_id not valid\n"); | ||
| 611 | ret = -ENODEV; | ||
| 612 | goto err_phy_connect; | ||
| 613 | } | ||
| 614 | DBGPR(" phy_connect_direct succeeded for PHY %s, link=%d\n", | ||
| 615 | dev_name(&phydev->dev), phydev->link); | ||
| 616 | |||
| 617 | return 0; | ||
| 618 | |||
| 619 | err_phy_connect: | ||
| 620 | phy_disconnect(phydev); | ||
| 621 | |||
| 622 | return ret; | ||
| 623 | } | ||
| 624 | |||
| 625 | static void xgbe_phy_exit(struct xgbe_prv_data *pdata) | ||
| 626 | { | ||
| 627 | if (!pdata->phydev) | ||
| 628 | return; | ||
| 629 | |||
| 630 | phy_disconnect(pdata->phydev); | ||
| 631 | } | ||
| 632 | |||
| 524 | int xgbe_powerdown(struct net_device *netdev, unsigned int caller) | 633 | int xgbe_powerdown(struct net_device *netdev, unsigned int caller) |
| 525 | { | 634 | { |
| 526 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | 635 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
| @@ -986,11 +1095,16 @@ static int xgbe_open(struct net_device *netdev) | |||
| 986 | 1095 | ||
| 987 | DBGPR("-->xgbe_open\n"); | 1096 | DBGPR("-->xgbe_open\n"); |
| 988 | 1097 | ||
| 1098 | /* Initialize the phy */ | ||
| 1099 | ret = xgbe_phy_init(pdata); | ||
| 1100 | if (ret) | ||
| 1101 | return ret; | ||
| 1102 | |||
| 989 | /* Enable the clocks */ | 1103 | /* Enable the clocks */ |
| 990 | ret = clk_prepare_enable(pdata->sysclk); | 1104 | ret = clk_prepare_enable(pdata->sysclk); |
| 991 | if (ret) { | 1105 | if (ret) { |
| 992 | netdev_alert(netdev, "dma clk_prepare_enable failed\n"); | 1106 | netdev_alert(netdev, "dma clk_prepare_enable failed\n"); |
| 993 | return ret; | 1107 | goto err_phy_init; |
| 994 | } | 1108 | } |
| 995 | 1109 | ||
| 996 | ret = clk_prepare_enable(pdata->ptpclk); | 1110 | ret = clk_prepare_enable(pdata->ptpclk); |
| @@ -1047,6 +1161,9 @@ err_ptpclk: | |||
| 1047 | err_sysclk: | 1161 | err_sysclk: |
| 1048 | clk_disable_unprepare(pdata->sysclk); | 1162 | clk_disable_unprepare(pdata->sysclk); |
| 1049 | 1163 | ||
| 1164 | err_phy_init: | ||
| 1165 | xgbe_phy_exit(pdata); | ||
| 1166 | |||
| 1050 | return ret; | 1167 | return ret; |
| 1051 | } | 1168 | } |
| 1052 | 1169 | ||
| @@ -1077,6 +1194,9 @@ static int xgbe_close(struct net_device *netdev) | |||
| 1077 | clk_disable_unprepare(pdata->ptpclk); | 1194 | clk_disable_unprepare(pdata->ptpclk); |
| 1078 | clk_disable_unprepare(pdata->sysclk); | 1195 | clk_disable_unprepare(pdata->sysclk); |
| 1079 | 1196 | ||
| 1197 | /* Release the phy */ | ||
| 1198 | xgbe_phy_exit(pdata); | ||
| 1199 | |||
| 1080 | DBGPR("<--xgbe_close\n"); | 1200 | DBGPR("<--xgbe_close\n"); |
| 1081 | 1201 | ||
| 1082 | return 0; | 1202 | return 0; |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index eecd360430a4..6d2221e023f4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | |||
| @@ -116,7 +116,6 @@ | |||
| 116 | 116 | ||
| 117 | #include <linux/module.h> | 117 | #include <linux/module.h> |
| 118 | #include <linux/kmod.h> | 118 | #include <linux/kmod.h> |
| 119 | #include <linux/spinlock.h> | ||
| 120 | #include <linux/mdio.h> | 119 | #include <linux/mdio.h> |
| 121 | #include <linux/phy.h> | 120 | #include <linux/phy.h> |
| 122 | #include <linux/of.h> | 121 | #include <linux/of.h> |
| @@ -158,77 +157,6 @@ static int xgbe_mdio_write(struct mii_bus *mii, int prtad, int mmd_reg, | |||
| 158 | return 0; | 157 | return 0; |
| 159 | } | 158 | } |
| 160 | 159 | ||
| 161 | static void xgbe_adjust_link(struct net_device *netdev) | ||
| 162 | { | ||
| 163 | struct xgbe_prv_data *pdata = netdev_priv(netdev); | ||
| 164 | struct xgbe_hw_if *hw_if = &pdata->hw_if; | ||
| 165 | struct phy_device *phydev = pdata->phydev; | ||
| 166 | int new_state = 0; | ||
| 167 | |||
| 168 | if (phydev == NULL) | ||
| 169 | return; | ||
| 170 | |||
| 171 | DBGPR_MDIO("-->xgbe_adjust_link: address=%d, newlink=%d, curlink=%d\n", | ||
| 172 | phydev->addr, phydev->link, pdata->phy_link); | ||
| 173 | |||
| 174 | if (phydev->link) { | ||
| 175 | /* Flow control support */ | ||
| 176 | if (pdata->pause_autoneg) { | ||
| 177 | if (phydev->pause || phydev->asym_pause) { | ||
| 178 | pdata->tx_pause = 1; | ||
| 179 | pdata->rx_pause = 1; | ||
| 180 | } else { | ||
| 181 | pdata->tx_pause = 0; | ||
| 182 | pdata->rx_pause = 0; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | if (pdata->tx_pause != pdata->phy_tx_pause) { | ||
| 187 | hw_if->config_tx_flow_control(pdata); | ||
| 188 | pdata->phy_tx_pause = pdata->tx_pause; | ||
| 189 | } | ||
| 190 | |||
| 191 | if (pdata->rx_pause != pdata->phy_rx_pause) { | ||
| 192 | hw_if->config_rx_flow_control(pdata); | ||
| 193 | pdata->phy_rx_pause = pdata->rx_pause; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* Speed support */ | ||
| 197 | if (phydev->speed != pdata->phy_speed) { | ||
| 198 | new_state = 1; | ||
| 199 | |||
| 200 | switch (phydev->speed) { | ||
| 201 | case SPEED_10000: | ||
| 202 | hw_if->set_xgmii_speed(pdata); | ||
| 203 | break; | ||
| 204 | |||
| 205 | case SPEED_2500: | ||
| 206 | hw_if->set_gmii_2500_speed(pdata); | ||
| 207 | break; | ||
| 208 | |||
| 209 | case SPEED_1000: | ||
| 210 | hw_if->set_gmii_speed(pdata); | ||
| 211 | break; | ||
| 212 | } | ||
| 213 | pdata->phy_speed = phydev->speed; | ||
| 214 | } | ||
| 215 | |||
| 216 | if (phydev->link != pdata->phy_link) { | ||
| 217 | new_state = 1; | ||
| 218 | pdata->phy_link = 1; | ||
| 219 | } | ||
| 220 | } else if (pdata->phy_link) { | ||
| 221 | new_state = 1; | ||
| 222 | pdata->phy_link = 0; | ||
| 223 | pdata->phy_speed = SPEED_UNKNOWN; | ||
| 224 | } | ||
| 225 | |||
| 226 | if (new_state) | ||
| 227 | phy_print_status(phydev); | ||
| 228 | |||
| 229 | DBGPR_MDIO("<--xgbe_adjust_link\n"); | ||
| 230 | } | ||
| 231 | |||
| 232 | void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata) | 160 | void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata) |
| 233 | { | 161 | { |
| 234 | struct device *dev = pdata->dev; | 162 | struct device *dev = pdata->dev; |
| @@ -278,7 +206,6 @@ void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata) | |||
| 278 | 206 | ||
| 279 | int xgbe_mdio_register(struct xgbe_prv_data *pdata) | 207 | int xgbe_mdio_register(struct xgbe_prv_data *pdata) |
| 280 | { | 208 | { |
| 281 | struct net_device *netdev = pdata->netdev; | ||
| 282 | struct device_node *phy_node; | 209 | struct device_node *phy_node; |
| 283 | struct mii_bus *mii; | 210 | struct mii_bus *mii; |
| 284 | struct phy_device *phydev; | 211 | struct phy_device *phydev; |
| @@ -293,7 +220,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata) | |||
| 293 | return -EINVAL; | 220 | return -EINVAL; |
| 294 | } | 221 | } |
| 295 | 222 | ||
| 296 | /* Register with the MDIO bus */ | ||
| 297 | mii = mdiobus_alloc(); | 223 | mii = mdiobus_alloc(); |
| 298 | if (mii == NULL) { | 224 | if (mii == NULL) { |
| 299 | dev_err(pdata->dev, "mdiobus_alloc failed\n"); | 225 | dev_err(pdata->dev, "mdiobus_alloc failed\n"); |
| @@ -348,26 +274,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata) | |||
| 348 | pdata->mii = mii; | 274 | pdata->mii = mii; |
| 349 | pdata->mdio_mmd = MDIO_MMD_PCS; | 275 | pdata->mdio_mmd = MDIO_MMD_PCS; |
| 350 | 276 | ||
| 351 | pdata->phy_link = -1; | ||
| 352 | pdata->phy_speed = SPEED_UNKNOWN; | ||
| 353 | pdata->phy_tx_pause = pdata->tx_pause; | ||
| 354 | pdata->phy_rx_pause = pdata->rx_pause; | ||
| 355 | |||
| 356 | ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link, | ||
| 357 | pdata->phy_mode); | ||
| 358 | if (ret) { | ||
| 359 | netdev_err(netdev, "phy_connect_direct failed\n"); | ||
| 360 | goto err_phy_device; | ||
| 361 | } | ||
| 362 | |||
| 363 | if (!phydev->drv || (phydev->drv->phy_id == 0)) { | ||
| 364 | netdev_err(netdev, "phy_id not valid\n"); | ||
| 365 | ret = -ENODEV; | ||
| 366 | goto err_phy_connect; | ||
| 367 | } | ||
| 368 | DBGPR(" phy_connect_direct succeeded for PHY %s, link=%d\n", | ||
| 369 | dev_name(&phydev->dev), phydev->link); | ||
| 370 | |||
| 371 | phydev->autoneg = pdata->default_autoneg; | 277 | phydev->autoneg = pdata->default_autoneg; |
| 372 | if (phydev->autoneg == AUTONEG_DISABLE) { | 278 | if (phydev->autoneg == AUTONEG_DISABLE) { |
| 373 | phydev->speed = pdata->default_speed; | 279 | phydev->speed = pdata->default_speed; |
| @@ -386,9 +292,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata) | |||
| 386 | 292 | ||
| 387 | return 0; | 293 | return 0; |
| 388 | 294 | ||
| 389 | err_phy_connect: | ||
| 390 | phy_disconnect(phydev); | ||
| 391 | |||
| 392 | err_phy_device: | 295 | err_phy_device: |
| 393 | phy_device_free(phydev); | 296 | phy_device_free(phydev); |
| 394 | 297 | ||
| @@ -408,7 +311,6 @@ void xgbe_mdio_unregister(struct xgbe_prv_data *pdata) | |||
| 408 | { | 311 | { |
| 409 | DBGPR("-->xgbe_mdio_unregister\n"); | 312 | DBGPR("-->xgbe_mdio_unregister\n"); |
| 410 | 313 | ||
| 411 | phy_disconnect(pdata->phydev); | ||
| 412 | pdata->phydev = NULL; | 314 | pdata->phydev = NULL; |
| 413 | 315 | ||
| 414 | module_put(pdata->phy_module); | 316 | module_put(pdata->phy_module); |
