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:
Родитель
200d7db76e
Коммит
407066f8f3
|
@ -12,7 +12,14 @@ Optional properties:
|
|||
only if property "phy-reset-gpios" is available. Missing the property
|
||||
will have the duration be 1 millisecond. Numbers greater than 1000 are
|
||||
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:
|
||||
|
||||
|
@ -25,3 +32,23 @@ ethernet@83fec000 {
|
|||
local-mac-address = [00 04 9F 01 1B B9];
|
||||
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;
|
||||
uint phy_speed;
|
||||
phy_interface_t phy_interface;
|
||||
struct device_node *phy_node;
|
||||
int link;
|
||||
int full_duplex;
|
||||
int speed;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
@ -1648,29 +1649,37 @@ static int fec_enet_mii_probe(struct net_device *ndev)
|
|||
|
||||
fep->phy_dev = NULL;
|
||||
|
||||
/* check for attached phy */
|
||||
for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
|
||||
if ((fep->mii_bus->phy_mask & (1 << phy_id)))
|
||||
continue;
|
||||
if (fep->mii_bus->phy_map[phy_id] == NULL)
|
||||
continue;
|
||||
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 (fep->phy_node) {
|
||||
phy_dev = of_phy_connect(ndev, fep->phy_node,
|
||||
&fec_enet_adjust_link, 0,
|
||||
fep->phy_interface);
|
||||
} else {
|
||||
/* check for attached phy */
|
||||
for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
|
||||
if ((fep->mii_bus->phy_mask & (1 << phy_id)))
|
||||
continue;
|
||||
if (fep->mii_bus->phy_map[phy_id] == NULL)
|
||||
continue;
|
||||
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)) {
|
||||
netdev_err(ndev, "could not attach to PHY\n");
|
||||
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);
|
||||
const struct platform_device_id *id_entry =
|
||||
platform_get_device_id(fep->pdev);
|
||||
struct device_node *node;
|
||||
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++)
|
||||
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;
|
||||
|
||||
mii_cnt++;
|
||||
|
@ -2527,6 +2545,7 @@ fec_probe(struct platform_device *pdev)
|
|||
struct resource *r;
|
||||
const struct of_device_id *of_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);
|
||||
if (of_id)
|
||||
|
@ -2566,6 +2585,18 @@ fec_probe(struct platform_device *pdev)
|
|||
|
||||
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);
|
||||
if (ret < 0) {
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
|
@ -2670,6 +2701,8 @@ failed_init:
|
|||
failed_regulator:
|
||||
fec_enet_clk_enable(ndev, false);
|
||||
failed_clk:
|
||||
failed_phy:
|
||||
of_node_put(phy_node);
|
||||
failed_ioremap:
|
||||
free_netdev(ndev);
|
||||
|
||||
|
@ -2691,6 +2724,7 @@ fec_drv_remove(struct platform_device *pdev)
|
|||
if (fep->ptp_clock)
|
||||
ptp_clock_unregister(fep->ptp_clock);
|
||||
fec_enet_clk_enable(ndev, false);
|
||||
of_node_put(fep->phy_node);
|
||||
free_netdev(ndev);
|
||||
|
||||
return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче