diff options
author | Patrick Delaunay | 2021-07-20 20:09:51 +0200 |
---|---|---|
committer | Ramon Fried | 2021-07-22 22:05:28 +0300 |
commit | d33982d5bc442a0dc720962160019cad518d266e (patch) | |
tree | e379d8ae52ff69282b5fe505bde6e4828c3e1786 /drivers/net | |
parent | b8da46fda664d06f0afa2fbd0fab6e2acd603a93 (diff) |
net: eth-phy: add support of device tree configuration for gpio reset
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@foss.st.com>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/eth-phy-uclass.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/net/eth-phy-uclass.c b/drivers/net/eth-phy-uclass.c index 07aebd935e6..7abed14392f 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, }; |