[PATCH v3 1/6] net: eth-phy: add support of device tree configuration for gpio reset

Patrick Delaunay patrick.delaunay at foss.st.com
Tue Jul 20 20:09:51 CEST 2021


The gpio reset and the assert or deassert delay are defined in generic
binding of the ethernet phy in Linux:
Documentation/devicetree/bindings/net/ethernet-phy.yaml

  reset-gpios:
    maxItems: 1
    description:
      The GPIO phandle and specifier for the PHY reset signal.

  reset-assert-us:
    description:
      Delay after the reset was asserted in microseconds. If this
      property is missing the delay will be skipped.

  reset-deassert-us:
    description:
      Delay after the reset was deasserted in microseconds. If
      this property is missing the delay will be skipped.

See also U-Boot: doc/device-tree-bindings/net/phy.txt

This patch adds the parsing of this common DT properties in the
u-class "eth_phy_generic", used by default in the associated driver
"eth_phy_generic_drv"

This parsing function eth_phy_of_to_plat can be reused by other
ethernet phy drivers for this uclass UCLASS_ETH_PHY.

Signed-off-by: Patrick Delaunay <patrick.delaunay at foss.st.com>
---

Changes in v3:
- allow compilation without DM_GPIO

Changes in v2:
- Update eth-phy driver (NEW)

 drivers/net/eth-phy-uclass.c | 56 ++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/net/eth-phy-uclass.c b/drivers/net/eth-phy-uclass.c
index 07aebd935e..7abed14392 100644
--- a/drivers/net/eth-phy-uclass.c
+++ b/drivers/net/eth-phy-uclass.c
@@ -6,12 +6,17 @@
 #include <common.h>
 #include <dm.h>
 #include <net.h>
+#include <asm-generic/gpio.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 #include <dm/lists.h>
+#include <linux/delay.h>
 
 struct eth_phy_device_priv {
 	struct mii_dev *mdio_bus;
+	struct gpio_desc reset_gpio;
+	u32 reset_assert_delay;
+	u32 reset_deassert_delay;
 };
 
 int eth_phy_binds_nodes(struct udevice *eth_dev)
@@ -110,13 +115,64 @@ int eth_phy_get_addr(struct udevice *dev)
 	return reg;
 }
 
+/* parsing generic properties of devicetree/bindings/net/ethernet-phy.yaml */
+static int eth_phy_of_to_plat(struct udevice *dev)
+{
+	struct eth_phy_device_priv *uc_priv = dev_get_uclass_priv(dev);
+	int ret;
+
+	if (!CONFIG_IS_ENABLED(DM_GPIO))
+		return 0;
+
+	/* search "reset-gpios" in phy node */
+	ret = gpio_request_by_name(dev, "reset-gpios", 0,
+				   &uc_priv->reset_gpio,
+				   GPIOD_IS_OUT);
+	if (ret != -ENOENT)
+		return ret;
+
+	uc_priv->reset_assert_delay = dev_read_u32_default(dev, "reset-assert-us", 0);
+	uc_priv->reset_deassert_delay = dev_read_u32_default(dev, "reset-deassert-us", 0);
+
+	return 0;
+}
+
+void eth_phy_reset(struct udevice *dev, int value)
+{
+	struct eth_phy_device_priv *uc_priv = dev_get_uclass_priv(dev);
+	u32 delay;
+
+	if (!CONFIG_IS_ENABLED(DM_GPIO))
+		return;
+
+	if (!dm_gpio_is_valid(&uc_priv->reset_gpio))
+		return;
+
+	dm_gpio_set_value(&uc_priv->reset_gpio, value);
+
+	delay = value ? uc_priv->reset_assert_delay : uc_priv->reset_deassert_delay;
+	if (delay)
+		udelay(delay);
+}
+
+static int eth_phy_pre_probe(struct udevice *dev)
+{
+	/* Assert and deassert the reset signal */
+	eth_phy_reset(dev, 1);
+	eth_phy_reset(dev, 0);
+
+	return 0;
+}
+
 UCLASS_DRIVER(eth_phy_generic) = {
 	.id		= UCLASS_ETH_PHY,
 	.name		= "eth_phy_generic",
 	.per_device_auto	= sizeof(struct eth_phy_device_priv),
+	.pre_probe	= eth_phy_pre_probe,
 };
 
 U_BOOT_DRIVER(eth_phy_generic_drv) = {
 	.name		= "eth_phy_generic_drv",
 	.id		= UCLASS_ETH_PHY,
+	.of_to_plat	= eth_phy_of_to_plat,
 };
-- 
2.25.1



More information about the U-Boot mailing list