diff options
author | Alex Marginean <alexandru.marginean@nxp.com> | 2019-11-25 17:15:12 +0200 |
---|---|---|
committer | Joe Hershberger <joe.hershberger@ni.com> | 2019-12-09 09:47:43 -0600 |
commit | 2f6245594e1f11db00efcaa5ac122918f019e0b4 (patch) | |
tree | 1b8933734b1754fe0e5c1213913c0950370e1ecf /net | |
parent | a5d32c37d9eec2f819273536a5600a0fbde09acb (diff) |
net: mdio-uclass: add dm_eth_phy_connect helper function
The function connects an ethernet device to a PHY using DT information.
This API is only available for eth devices with an associated device tree
node.
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mdio-uclass.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c index 7a5f1d6dcc..f75e4df626 100644 --- a/net/mdio-uclass.c +++ b/net/mdio-uclass.c @@ -10,6 +10,16 @@ #include <dm/device-internal.h> #include <dm/uclass-internal.h> +/* DT node properties for MAC-PHY interface */ +#define PHY_MODE_STR_CNT 2 +static const char *phy_mode_str[PHY_MODE_STR_CNT] = { "phy-mode", + "phy-connection-type" }; +/* DT node properties that reference a PHY node */ +#define PHY_HANDLE_STR_CNT 3 +const char *phy_handle_str[PHY_HANDLE_STR_CNT] = { "phy-handle", + "phy", + "phy-device" }; + void dm_mdio_probe_devices(void) { struct udevice *it; @@ -116,6 +126,86 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr, return phy_connect(pdata->mii_bus, phyaddr, ethdev, interface); } +static struct phy_device *dm_eth_connect_phy_handle(struct udevice *ethdev, + phy_interface_t interface) +{ + u32 phy_addr; + struct udevice *mdiodev; + struct phy_device *phy; + struct ofnode_phandle_args phandle = {.node = ofnode_null()}; + int i; + + for (i = 0; i < PHY_HANDLE_STR_CNT; i++) + if (!dev_read_phandle_with_args(ethdev, phy_handle_str[i], NULL, + 0, 0, &phandle)) + break; + + if (!ofnode_valid(phandle.node)) { + dev_dbg(dev, "can't find PHY node\n"); + return NULL; + } + + /* + * reading 'reg' directly should be fine. This is a PHY node, the + * address is always size 1 and requires no translation + */ + if (ofnode_read_u32(phandle.node, "reg", &phy_addr)) { + dev_dbg(ethdev, "missing reg property in phy node\n"); + return NULL; + } + + if (uclass_get_device_by_ofnode(UCLASS_MDIO, + ofnode_get_parent(phandle.node), + &mdiodev)) { + dev_dbg(dev, "can't find MDIO bus for node %s\n", + ofnode_get_name(ofnode_get_parent(phandle.node))); + return NULL; + } + + phy = dm_mdio_phy_connect(mdiodev, phy_addr, ethdev, interface); + + if (phy) + phy->node = phandle.node; + + return phy; +} + +/* Connect to a PHY linked in eth DT node */ +struct phy_device *dm_eth_phy_connect(struct udevice *ethdev) +{ + const char *if_str; + phy_interface_t interface; + struct phy_device *phy; + int i; + + if (!ofnode_valid(ethdev->node)) { + debug("%s: supplied eth dev has no DT node!\n", ethdev->name); + return NULL; + } + + interface = PHY_INTERFACE_MODE_NONE; + for (i = 0; i < PHY_MODE_STR_CNT; i++) { + if_str = ofnode_read_string(ethdev->node, phy_mode_str[i]); + if (if_str) { + interface = phy_get_interface_by_name(if_str); + break; + } + } + if (interface < 0) + interface = PHY_INTERFACE_MODE_NONE; + if (interface == PHY_INTERFACE_MODE_NONE) + dev_dbg(ethdev, "can't find interface mode, default to NONE\n"); + + phy = dm_eth_connect_phy_handle(ethdev, interface); + + if (!phy) + return NULL; + + phy->interface = interface; + + return phy; +} + UCLASS_DRIVER(mdio) = { .id = UCLASS_MDIO, .name = "mdio", |