diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 66fe1f672499..4f87dffcb9b2 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/of.h> | 52 | #include <linux/of.h> |
53 | #include <linux/of_device.h> | 53 | #include <linux/of_device.h> |
54 | #include <linux/of_gpio.h> | 54 | #include <linux/of_gpio.h> |
55 | #include <linux/of_mdio.h> | ||
55 | #include <linux/of_net.h> | 56 | #include <linux/of_net.h> |
56 | #include <linux/regulator/consumer.h> | 57 | #include <linux/regulator/consumer.h> |
57 | #include <linux/if_vlan.h> | 58 | #include <linux/if_vlan.h> |
@@ -1648,29 +1649,37 @@ static int fec_enet_mii_probe(struct net_device *ndev) | |||
1648 | 1649 | ||
1649 | fep->phy_dev = NULL; | 1650 | fep->phy_dev = NULL; |
1650 | 1651 | ||
1651 | /* check for attached phy */ | 1652 | if (fep->phy_node) { |
1652 | for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { | 1653 | phy_dev = of_phy_connect(ndev, fep->phy_node, |
1653 | if ((fep->mii_bus->phy_mask & (1 << phy_id))) | 1654 | &fec_enet_adjust_link, 0, |
1654 | continue; | 1655 | fep->phy_interface); |
1655 | if (fep->mii_bus->phy_map[phy_id] == NULL) | 1656 | } else { |
1656 | continue; | 1657 | /* check for attached phy */ |
1657 | if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) | 1658 | for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { |
1658 | continue; | 1659 | if ((fep->mii_bus->phy_mask & (1 << phy_id))) |
1659 | if (dev_id--) | 1660 | continue; |
1660 | continue; | 1661 | if (fep->mii_bus->phy_map[phy_id] == NULL) |
1661 | strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); | 1662 | continue; |
1662 | break; | 1663 | if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) |
1663 | } | 1664 | continue; |
1665 | if (dev_id--) | ||
1666 | continue; | ||
1667 | strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); | ||
1668 | break; | ||
1669 | } | ||
1664 | 1670 | ||
1665 | if (phy_id >= PHY_MAX_ADDR) { | 1671 | if (phy_id >= PHY_MAX_ADDR) { |
1666 | netdev_info(ndev, "no PHY, assuming direct connection to switch\n"); | 1672 | netdev_info(ndev, "no PHY, assuming direct connection to switch\n"); |
1667 | strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); | 1673 | strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); |
1668 | phy_id = 0; | 1674 | phy_id = 0; |
1675 | } | ||
1676 | |||
1677 | snprintf(phy_name, sizeof(phy_name), | ||
1678 | PHY_ID_FMT, mdio_bus_id, phy_id); | ||
1679 | phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, | ||
1680 | fep->phy_interface); | ||
1669 | } | 1681 | } |
1670 | 1682 | ||
1671 | snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id); | ||
1672 | phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, | ||
1673 | fep->phy_interface); | ||
1674 | if (IS_ERR(phy_dev)) { | 1683 | if (IS_ERR(phy_dev)) { |
1675 | netdev_err(ndev, "could not attach to PHY\n"); | 1684 | netdev_err(ndev, "could not attach to PHY\n"); |
1676 | return PTR_ERR(phy_dev); | 1685 | return PTR_ERR(phy_dev); |
@@ -1707,6 +1716,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) | |||
1707 | struct fec_enet_private *fep = netdev_priv(ndev); | 1716 | struct fec_enet_private *fep = netdev_priv(ndev); |
1708 | const struct platform_device_id *id_entry = | 1717 | const struct platform_device_id *id_entry = |
1709 | platform_get_device_id(fep->pdev); | 1718 | platform_get_device_id(fep->pdev); |
1719 | struct device_node *node; | ||
1710 | int err = -ENXIO, i; | 1720 | int err = -ENXIO, i; |
1711 | 1721 | ||
1712 | /* | 1722 | /* |
@@ -1774,7 +1784,15 @@ static int fec_enet_mii_init(struct platform_device *pdev) | |||
1774 | for (i = 0; i < PHY_MAX_ADDR; i++) | 1784 | for (i = 0; i < PHY_MAX_ADDR; i++) |
1775 | fep->mii_bus->irq[i] = PHY_POLL; | 1785 | fep->mii_bus->irq[i] = PHY_POLL; |
1776 | 1786 | ||
1777 | if (mdiobus_register(fep->mii_bus)) | 1787 | node = of_get_child_by_name(pdev->dev.of_node, "mdio"); |
1788 | if (node) { | ||
1789 | err = of_mdiobus_register(fep->mii_bus, node); | ||
1790 | of_node_put(node); | ||
1791 | } else { | ||
1792 | err = mdiobus_register(fep->mii_bus); | ||
1793 | } | ||
1794 | |||
1795 | if (err) | ||
1778 | goto err_out_free_mdio_irq; | 1796 | goto err_out_free_mdio_irq; |
1779 | 1797 | ||
1780 | mii_cnt++; | 1798 | mii_cnt++; |
@@ -2527,6 +2545,7 @@ fec_probe(struct platform_device *pdev) | |||
2527 | struct resource *r; | 2545 | struct resource *r; |
2528 | const struct of_device_id *of_id; | 2546 | const struct of_device_id *of_id; |
2529 | static int dev_id; | 2547 | static int dev_id; |
2548 | struct device_node *np = pdev->dev.of_node, *phy_node; | ||
2530 | 2549 | ||
2531 | of_id = of_match_device(fec_dt_ids, &pdev->dev); | 2550 | of_id = of_match_device(fec_dt_ids, &pdev->dev); |
2532 | if (of_id) | 2551 | if (of_id) |
@@ -2566,6 +2585,18 @@ fec_probe(struct platform_device *pdev) | |||
2566 | 2585 | ||
2567 | platform_set_drvdata(pdev, ndev); | 2586 | platform_set_drvdata(pdev, ndev); |
2568 | 2587 | ||
2588 | phy_node = of_parse_phandle(np, "phy-handle", 0); | ||
2589 | if (!phy_node && of_phy_is_fixed_link(np)) { | ||
2590 | ret = of_phy_register_fixed_link(np); | ||
2591 | if (ret < 0) { | ||
2592 | dev_err(&pdev->dev, | ||
2593 | "broken fixed-link specification\n"); | ||
2594 | goto failed_phy; | ||
2595 | } | ||
2596 | phy_node = of_node_get(np); | ||
2597 | } | ||
2598 | fep->phy_node = phy_node; | ||
2599 | |||
2569 | ret = of_get_phy_mode(pdev->dev.of_node); | 2600 | ret = of_get_phy_mode(pdev->dev.of_node); |
2570 | if (ret < 0) { | 2601 | if (ret < 0) { |
2571 | pdata = dev_get_platdata(&pdev->dev); | 2602 | pdata = dev_get_platdata(&pdev->dev); |
@@ -2670,6 +2701,8 @@ failed_init: | |||
2670 | failed_regulator: | 2701 | failed_regulator: |
2671 | fec_enet_clk_enable(ndev, false); | 2702 | fec_enet_clk_enable(ndev, false); |
2672 | failed_clk: | 2703 | failed_clk: |
2704 | failed_phy: | ||
2705 | of_node_put(phy_node); | ||
2673 | failed_ioremap: | 2706 | failed_ioremap: |
2674 | free_netdev(ndev); | 2707 | free_netdev(ndev); |
2675 | 2708 | ||
@@ -2691,6 +2724,7 @@ fec_drv_remove(struct platform_device *pdev) | |||
2691 | if (fep->ptp_clock) | 2724 | if (fep->ptp_clock) |
2692 | ptp_clock_unregister(fep->ptp_clock); | 2725 | ptp_clock_unregister(fep->ptp_clock); |
2693 | fec_enet_clk_enable(ndev, false); | 2726 | fec_enet_clk_enable(ndev, false); |
2727 | of_node_put(fep->phy_node); | ||
2694 | free_netdev(ndev); | 2728 | free_netdev(ndev); |
2695 | 2729 | ||
2696 | return 0; | 2730 | return 0; |