diff options
-rw-r--r-- | Documentation/devicetree/bindings/net/fsl-fec.txt | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 76 |
3 files changed, 84 insertions, 22 deletions
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt index 6bc84adb10c0..8a2c7b55ec16 100644 --- a/Documentation/devicetree/bindings/net/fsl-fec.txt +++ b/Documentation/devicetree/bindings/net/fsl-fec.txt | |||
@@ -12,7 +12,14 @@ Optional properties: | |||
12 | only if property "phy-reset-gpios" is available. Missing the property | 12 | only if property "phy-reset-gpios" is available. Missing the property |
13 | will have the duration be 1 millisecond. Numbers greater than 1000 are | 13 | will have the duration be 1 millisecond. Numbers greater than 1000 are |
14 | invalid and 1 millisecond will be used instead. | 14 | invalid and 1 millisecond will be used instead. |
15 | - phy-supply: regulator that powers the Ethernet PHY. | 15 | - phy-supply : regulator that powers the Ethernet PHY. |
16 | - phy-handle : phandle to the PHY device connected to this device. | ||
17 | - fixed-link : Assume a fixed link. See fixed-link.txt in the same directory. | ||
18 | Use instead of phy-handle. | ||
19 | |||
20 | Optional subnodes: | ||
21 | - mdio : specifies the mdio bus in the FEC, used as a container for phy nodes | ||
22 | according to phy.txt in the same directory | ||
16 | 23 | ||
17 | Example: | 24 | Example: |
18 | 25 | ||
@@ -25,3 +32,23 @@ ethernet@83fec000 { | |||
25 | local-mac-address = [00 04 9F 01 1B B9]; | 32 | local-mac-address = [00 04 9F 01 1B B9]; |
26 | phy-supply = <®_fec_supply>; | 33 | phy-supply = <®_fec_supply>; |
27 | }; | 34 | }; |
35 | |||
36 | Example with phy specified: | ||
37 | |||
38 | ethernet@83fec000 { | ||
39 | compatible = "fsl,imx51-fec", "fsl,imx27-fec"; | ||
40 | reg = <0x83fec000 0x4000>; | ||
41 | interrupts = <87>; | ||
42 | phy-mode = "mii"; | ||
43 | phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */ | ||
44 | local-mac-address = [00 04 9F 01 1B B9]; | ||
45 | phy-supply = <®_fec_supply>; | ||
46 | phy-handle = <ðphy>; | ||
47 | mdio { | ||
48 | ethphy: ethernet-phy@6 { | ||
49 | compatible = "ethernet-phy-ieee802.3-c22"; | ||
50 | reg = <6>; | ||
51 | max-speed = <100>; | ||
52 | }; | ||
53 | }; | ||
54 | }; | ||
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index bd53caf1c1eb..9f7fa644a397 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h | |||
@@ -310,6 +310,7 @@ struct fec_enet_private { | |||
310 | int mii_timeout; | 310 | int mii_timeout; |
311 | uint phy_speed; | 311 | uint phy_speed; |
312 | phy_interface_t phy_interface; | 312 | phy_interface_t phy_interface; |
313 | struct device_node *phy_node; | ||
313 | int link; | 314 | int link; |
314 | int full_duplex; | 315 | int full_duplex; |
315 | int speed; | 316 | int speed; |
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; |