Commit 407066f8 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by David S. Miller

net: fec: Support phys probed from devicetree and fixed-link

This adds support for specifying the phy to be used with the fec in the
devicetree using the standard phy-handle property and also supports
fixed-link.
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 200d7db7
...@@ -12,7 +12,14 @@ Optional properties: ...@@ -12,7 +12,14 @@ Optional properties:
only if property "phy-reset-gpios" is available. Missing the property only if property "phy-reset-gpios" is available. Missing the property
will have the duration be 1 millisecond. Numbers greater than 1000 are will have the duration be 1 millisecond. Numbers greater than 1000 are
invalid and 1 millisecond will be used instead. invalid and 1 millisecond will be used instead.
- phy-supply: regulator that powers the Ethernet PHY. - phy-supply : regulator that powers the Ethernet PHY.
- phy-handle : phandle to the PHY device connected to this device.
- fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
Use instead of phy-handle.
Optional subnodes:
- mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
according to phy.txt in the same directory
Example: Example:
...@@ -25,3 +32,23 @@ ethernet@83fec000 { ...@@ -25,3 +32,23 @@ ethernet@83fec000 {
local-mac-address = [00 04 9F 01 1B B9]; local-mac-address = [00 04 9F 01 1B B9];
phy-supply = <&reg_fec_supply>; phy-supply = <&reg_fec_supply>;
}; };
Example with phy specified:
ethernet@83fec000 {
compatible = "fsl,imx51-fec", "fsl,imx27-fec";
reg = <0x83fec000 0x4000>;
interrupts = <87>;
phy-mode = "mii";
phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
local-mac-address = [00 04 9F 01 1B B9];
phy-supply = <&reg_fec_supply>;
phy-handle = <&ethphy>;
mdio {
ethphy: ethernet-phy@6 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <6>;
max-speed = <100>;
};
};
};
...@@ -310,6 +310,7 @@ struct fec_enet_private { ...@@ -310,6 +310,7 @@ struct fec_enet_private {
int mii_timeout; int mii_timeout;
uint phy_speed; uint phy_speed;
phy_interface_t phy_interface; phy_interface_t phy_interface;
struct device_node *phy_node;
int link; int link;
int full_duplex; int full_duplex;
int speed; int speed;
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
...@@ -1648,29 +1649,37 @@ static int fec_enet_mii_probe(struct net_device *ndev) ...@@ -1648,29 +1649,37 @@ static int fec_enet_mii_probe(struct net_device *ndev)
fep->phy_dev = NULL; fep->phy_dev = NULL;
/* check for attached phy */ if (fep->phy_node) {
for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { phy_dev = of_phy_connect(ndev, fep->phy_node,
if ((fep->mii_bus->phy_mask & (1 << phy_id))) &fec_enet_adjust_link, 0,
continue; fep->phy_interface);
if (fep->mii_bus->phy_map[phy_id] == NULL) } else {
continue; /* check for attached phy */
if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
continue; if ((fep->mii_bus->phy_mask & (1 << phy_id)))
if (dev_id--) continue;
continue; if (fep->mii_bus->phy_map[phy_id] == NULL)
strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); continue;
break; if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
} continue;
if (dev_id--)
continue;
strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
break;
}
if (phy_id >= PHY_MAX_ADDR) { if (phy_id >= PHY_MAX_ADDR) {
netdev_info(ndev, "no PHY, assuming direct connection to switch\n"); netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
phy_id = 0; phy_id = 0;
}
snprintf(phy_name, sizeof(phy_name),
PHY_ID_FMT, mdio_bus_id, phy_id);
phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
fep->phy_interface);
} }
snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
fep->phy_interface);
if (IS_ERR(phy_dev)) { if (IS_ERR(phy_dev)) {
netdev_err(ndev, "could not attach to PHY\n"); netdev_err(ndev, "could not attach to PHY\n");
return PTR_ERR(phy_dev); return PTR_ERR(phy_dev);
...@@ -1707,6 +1716,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) ...@@ -1707,6 +1716,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
const struct platform_device_id *id_entry = const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev); platform_get_device_id(fep->pdev);
struct device_node *node;
int err = -ENXIO, i; int err = -ENXIO, i;
/* /*
...@@ -1774,7 +1784,15 @@ static int fec_enet_mii_init(struct platform_device *pdev) ...@@ -1774,7 +1784,15 @@ static int fec_enet_mii_init(struct platform_device *pdev)
for (i = 0; i < PHY_MAX_ADDR; i++) for (i = 0; i < PHY_MAX_ADDR; i++)
fep->mii_bus->irq[i] = PHY_POLL; fep->mii_bus->irq[i] = PHY_POLL;
if (mdiobus_register(fep->mii_bus)) node = of_get_child_by_name(pdev->dev.of_node, "mdio");
if (node) {
err = of_mdiobus_register(fep->mii_bus, node);
of_node_put(node);
} else {
err = mdiobus_register(fep->mii_bus);
}
if (err)
goto err_out_free_mdio_irq; goto err_out_free_mdio_irq;
mii_cnt++; mii_cnt++;
...@@ -2527,6 +2545,7 @@ fec_probe(struct platform_device *pdev) ...@@ -2527,6 +2545,7 @@ fec_probe(struct platform_device *pdev)
struct resource *r; struct resource *r;
const struct of_device_id *of_id; const struct of_device_id *of_id;
static int dev_id; static int dev_id;
struct device_node *np = pdev->dev.of_node, *phy_node;
of_id = of_match_device(fec_dt_ids, &pdev->dev); of_id = of_match_device(fec_dt_ids, &pdev->dev);
if (of_id) if (of_id)
...@@ -2566,6 +2585,18 @@ fec_probe(struct platform_device *pdev) ...@@ -2566,6 +2585,18 @@ fec_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ndev); platform_set_drvdata(pdev, ndev);
phy_node = of_parse_phandle(np, "phy-handle", 0);
if (!phy_node && of_phy_is_fixed_link(np)) {
ret = of_phy_register_fixed_link(np);
if (ret < 0) {
dev_err(&pdev->dev,
"broken fixed-link specification\n");
goto failed_phy;
}
phy_node = of_node_get(np);
}
fep->phy_node = phy_node;
ret = of_get_phy_mode(pdev->dev.of_node); ret = of_get_phy_mode(pdev->dev.of_node);
if (ret < 0) { if (ret < 0) {
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
...@@ -2670,6 +2701,8 @@ fec_probe(struct platform_device *pdev) ...@@ -2670,6 +2701,8 @@ fec_probe(struct platform_device *pdev)
failed_regulator: failed_regulator:
fec_enet_clk_enable(ndev, false); fec_enet_clk_enable(ndev, false);
failed_clk: failed_clk:
failed_phy:
of_node_put(phy_node);
failed_ioremap: failed_ioremap:
free_netdev(ndev); free_netdev(ndev);
...@@ -2691,6 +2724,7 @@ fec_drv_remove(struct platform_device *pdev) ...@@ -2691,6 +2724,7 @@ fec_drv_remove(struct platform_device *pdev)
if (fep->ptp_clock) if (fep->ptp_clock)
ptp_clock_unregister(fep->ptp_clock); ptp_clock_unregister(fep->ptp_clock);
fec_enet_clk_enable(ndev, false); fec_enet_clk_enable(ndev, false);
of_node_put(fep->phy_node);
free_netdev(ndev); free_netdev(ndev);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment