From 2f6245594e1f11db00efcaa5ac122918f019e0b4 Mon Sep 17 00:00:00 2001 From: Alex Marginean Date: Mon, 25 Nov 2019 17:15:12 +0200 Subject: [PATCH] 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 Acked-by: Joe Hershberger --- include/miiphy.h | 12 +++++++ net/mdio-uclass.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/include/miiphy.h b/include/miiphy.h index 94bf0da24a..61c136b114 100644 --- a/include/miiphy.h +++ b/include/miiphy.h @@ -165,6 +165,18 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *mdiodev, int phyaddr, struct udevice *ethdev, phy_interface_t interface); +/** + * dm_eth_phy_connect - Connect an Eth device to a PHY based on device tree + * + * Picks up the DT phy-handle and phy-mode from ethernet device node and + * connects the ethernet device to the linked PHY. + * + * @ethdev: ethernet device + * + * @return pointer to phy_device, or 0 on error + */ +struct phy_device *dm_eth_phy_connect(struct udevice *ethdev); + #endif #ifdef CONFIG_DM_MDIO_MUX 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 #include +/* 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", -- 2.39.5