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>
This commit is contained in:
committed by
Ramon Fried
parent
b8da46fda6
commit
d33982d5bc
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user