[U-Boot] [PATCH 1/3] net: add dm_eth_phy_connect helper to link eth/PHY based on DT

The helper is useful for platforms that link ethernet interfaces and PHYs in device tree using current bindings. Drivers could do this directly, but the code is generic enough and helps keep drivers simpler.
Signed-off-by: Alex Marginean alexm.osslist@gmail.com --- include/miiphy.h | 12 +++++ net/mdio-uclass.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+)
diff --git a/include/miiphy.h b/include/miiphy.h index 9b97d09f18..c8483bb40d 100644 --- a/include/miiphy.h +++ b/include/miiphy.h @@ -165,6 +165,18 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr, 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/mdio-handle and phy-mode from ethernet device node + * and connects the ethernet device to the linked PHY. + * + * @dev: ethernet device + * + * @return pointer to phy_device, or 0 on error + */ +struct phy_device *dm_eth_phy_connect(struct udevice *dev); + #endif
#ifdef CONFIG_DM_MDIO_MUX diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c index 36a404ff44..3289ca15f1 100644 --- a/net/mdio-uclass.c +++ b/net/mdio-uclass.c @@ -105,6 +105,124 @@ struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr, return phy_connect(pdata->mii_bus, addr, ethdev, interface); }
+static struct phy_device *dm_eth_connect_phy_handle(struct udevice *dev, + phy_interface_t if_type) +{ + u32 phy_phandle, phy_addr; + struct udevice *mdio_dev; + struct phy_device *phy; + ofnode phy_node; + + if (ofnode_read_u32(dev->node, "phy-handle", &phy_phandle)) { + dev_dbg(dev, "phy-handle missing in ethernet node\n"); + return NULL; + } + + phy_node = ofnode_get_by_phandle(phy_phandle); + if (!ofnode_valid(phy_node)) { + dev_dbg(dev, "invalid phy node\n"); + return NULL; + } + + if (ofnode_read_u32(phy_node, "reg", &phy_addr)) { + dev_dbg(dev, "missing reg property in phy node\n"); + return NULL; + } + + if (uclass_get_device_by_ofnode(UCLASS_MDIO, + ofnode_get_parent(phy_node), + &mdio_dev)) { + dev_dbg(dev, "can't find MDIO bus for node %s\n", + ofnode_get_name(ofnode_get_parent(phy_node))); + return NULL; + } + + phy = dm_mdio_phy_connect(mdio_dev, phy_addr, dev, if_type); + phy->node = phy_node; + + return phy; +} + +static struct phy_device *dm_eth_connect_mdio_handle(struct udevice *dev, + phy_interface_t if_type) +{ + u32 mdio_phandle; + ofnode mdio_node; + struct udevice *mdio_dev; + struct phy_device *phy; + uint mask = (uint)-1; + struct mdio_perdev_priv *pdata; + + if (ofnode_read_u32(dev->node, "mdio-handle", &mdio_phandle)) { + dev_dbg(dev, "mdio-handle missing in ethernet node\n"); + return NULL; + } + + mdio_node = ofnode_get_by_phandle(mdio_phandle); + if (!ofnode_valid(mdio_node)) { + dev_dbg(dev, "invalid mdio node\n"); + return NULL; + } + + if (uclass_get_device_by_ofnode(UCLASS_MDIO, mdio_node, &mdio_dev)) { + dev_dbg(dev, "can't find MDIO bus for node %s\n", + ofnode_get_name(mdio_node)); + return NULL; + } + pdata = dev_get_uclass_priv(mdio_dev); + + phy = phy_find_by_mask(pdata->mii_bus, mask, if_type); + if (phy) + phy_connect_dev(phy, dev); + else + dev_dbg(dev, "no PHY detected on bus\n"); + + return phy; +} + +/* Connect to a PHY linked in eth DT node */ +struct phy_device *dm_eth_phy_connect(struct udevice *dev) +{ + const char *if_type_str; + phy_interface_t if_type; + struct phy_device *phy; + + if (!ofnode_valid(dev->node)) { + debug("%s: supplied eth dev has no DT node!\n", dev->name); + return NULL; + } + + /* + * The sequence should be as follows: + * - if there is a phy-handle property, follow that, + * - if there is a mdio-handle property, follow that and scan for the + * PHY, + * - if the above came out empty, just return NULL. + */ + + if_type = PHY_INTERFACE_MODE_NONE; + if_type_str = ofnode_read_string(dev->node, "phy-mode"); + if (if_type_str) + if_type = phy_get_interface_by_name(if_type_str); + if (if_type < 0) + if_type = PHY_INTERFACE_MODE_NONE; + + if (if_type == PHY_INTERFACE_MODE_NONE) + dev_dbg(dev, "can't find interface mode, default to NONE\n"); + + phy = dm_eth_connect_phy_handle(dev, if_type); + + if (!phy) + phy = dm_eth_connect_mdio_handle(dev, if_type); + + if (!phy) + return NULL; + + phy->interface = if_type; + + return phy; +} + UCLASS_DRIVER(mdio) = { .id = UCLASS_MDIO, .name = "mdio",

Adds an optional mdio-handle property which identifies a MDIO bus which can be scanned to find the relevant PHY. The property is ignored if phy-handle is also present.
Signed-off-by: Alex Marginean alexm.osslist@gmail.com --- doc/device-tree-bindings/net/ethernet.txt | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/doc/device-tree-bindings/net/ethernet.txt b/doc/device-tree-bindings/net/ethernet.txt index 3fc360523b..9f9629f8d6 100644 --- a/doc/device-tree-bindings/net/ethernet.txt +++ b/doc/device-tree-bindings/net/ethernet.txt @@ -9,6 +9,8 @@ The following properties are common to the Ethernet controllers: - max-speed: number, specifies maximum speed in Mbit/s supported by the device; - max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than the maximum frame size (there's contradiction in ePAPR). +- mdio-handle: phandle, specifies a reference to a MDIO bus to be scanned to + find the PHY device. Ignored if phy-handle is also present. - phy-mode: string, operation mode of the PHY interface; supported values are "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto

Uses the new dm_eth_phy_connect helper to connect to the PHY to simplify the code.
Signed-off-by: Alex Marginean alexm.osslist@gmail.com --- drivers/net/fsl_enetc.c | 52 ++++++----------------------------------- drivers/net/fsl_enetc.h | 1 + 2 files changed, 8 insertions(+), 45 deletions(-)
diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index e7c5062c39..145d66bb16 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -200,56 +200,17 @@ static void enetc_start_pcs(struct udevice *dev) }
/* Configure the actual/external ethernet PHY, if one is found */ -static void enetc_start_phy(struct udevice *dev) +static void enetc_config_phy(struct udevice *dev) { struct enetc_priv *priv = dev_get_priv(dev); - struct udevice *miidev; - struct phy_device *phy; - u32 phandle, phy_id; - ofnode phy_node; int supported;
- if (!ofnode_valid(dev->node)) { - enetc_dbg(dev, "no enetc ofnode found, skipping PHY set-up\n"); - return; - } - - if (ofnode_read_u32(dev->node, "phy-handle", &phandle)) { - enetc_dbg(dev, "phy-handle not found, skipping PHY set-up\n"); - return; - } - - phy_node = ofnode_get_by_phandle(phandle); - if (!ofnode_valid(phy_node)) { - enetc_dbg(dev, "invalid phy node, skipping PHY set-up\n"); - return; - } - enetc_dbg(dev, "phy node: %s\n", ofnode_get_name(phy_node)); - - if (ofnode_read_u32(phy_node, "reg", &phy_id)) { - enetc_dbg(dev, - "missing reg in PHY node, skipping PHY set-up\n"); - return; - } - - if (uclass_get_device_by_ofnode(UCLASS_MDIO, - ofnode_get_parent(phy_node), - &miidev)) { - enetc_dbg(dev, "can't find MDIO bus for node %s\n", - ofnode_get_name(ofnode_get_parent(phy_node))); - return; - } - - phy = dm_mdio_phy_connect(miidev, phy_id, dev, priv->if_type); - if (!phy) { - enetc_dbg(dev, "dm_mdio_phy_connect returned null\n"); - return; - } + priv->phy = dm_eth_phy_connect(dev);
supported = GENMASK(6, 0); /* speeds up to 1G & AN */ - phy->advertising = phy->supported & supported; - phy_config(phy); - phy_startup(phy); + priv->phy->advertising = priv->phy->supported & supported; + + phy_config(priv->phy); }
/* @@ -464,7 +425,8 @@ static int enetc_start(struct udevice *dev) enetc_setup_rx_bdr(dev);
enetc_start_pcs(dev); - enetc_start_phy(dev); + enetc_config_phy(dev); + phy_startup(priv->phy);
return 0; } diff --git a/drivers/net/fsl_enetc.h b/drivers/net/fsl_enetc.h index 0bb4cdff47..9a36cdad80 100644 --- a/drivers/net/fsl_enetc.h +++ b/drivers/net/fsl_enetc.h @@ -154,6 +154,7 @@ struct enetc_priv {
int if_type; struct mii_dev imdio; + struct phy_device *phy; };
/* register accessors */

On 8/7/2019 7:08 PM, Alex Marginean wrote:
The helper is useful for platforms that link ethernet interfaces and PHYs in device tree using current bindings. Drivers could do this directly, but the code is generic enough and helps keep drivers simpler.
Signed-off-by: Alex Marginean alexm.osslist@gmail.com
include/miiphy.h | 12 +++++ net/mdio-uclass.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+)
superseded by https://patchwork.ozlabs.org/project/uboot/list/?series=124537
Thanks! Alex
participants (2)
-
Alex Marginean
-
Alex Marginean