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: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
200d7db76e
commit
407066f8f3
@ -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 {
|
|||||||
local-mac-address = [00 04 9F 01 1B B9];
|
local-mac-address = [00 04 9F 01 1B B9];
|
||||||
phy-supply = <®_fec_supply>;
|
phy-supply = <®_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 = <®_fec_supply>;
|
||||||
|
phy-handle = <ðphy>;
|
||||||
|
mdio {
|
||||||
|
ethphy: ethernet-phy@6 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c22";
|
||||||
|
reg = <6>;
|
||||||
|
max-speed = <100>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -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 @@
|
|||||||
#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)
|
|||||||
|
|
||||||
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) {
|
||||||
|
netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
|
||||||
|
strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phy_id >= PHY_MAX_ADDR) {
|
|
||||||
netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
|
|
||||||
strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
|
|
||||||
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);
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 @@ failed_init:
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user