diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt index c05479f5ac7cc837b39808cd030b50273ea1e083..72860ce7f61016b6bd91186d2cb7a77103357b27 100644 --- a/Documentation/devicetree/bindings/net/phy.txt +++ b/Documentation/devicetree/bindings/net/phy.txt @@ -55,6 +55,12 @@ Optional Properties: - reset-gpios: The GPIO phandle and specifier for the PHY reset signal. +- reset-delay-us: Delay after the reset was asserted in microseconds. + If this property is missing the delay will be skipped. + +- reset-post-delay-us: Delay after the reset was deasserted in microseconds. + If this property is missing the delay will be skipped. + Example: ethernet-phy@0 { @@ -62,4 +68,8 @@ ethernet-phy@0 { interrupt-parent = <&PIC>; interrupts = <35 IRQ_TYPE_EDGE_RISING>; reg = <0>; + + reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + reset-delay-us = <1000>; + reset-post-delay-us = <2000>; }; diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c index 75d97dd9fb281704ce955ac516d878cd92124ed8..843c1dde93e4552880841dfb535d676a6ad58ed3 100644 --- a/drivers/net/phy/mdio_device.c +++ b/drivers/net/phy/mdio_device.c @@ -24,6 +24,7 @@ #include #include #include +#include void mdio_device_free(struct mdio_device *mdiodev) { @@ -118,8 +119,16 @@ EXPORT_SYMBOL(mdio_device_remove); void mdio_device_reset(struct mdio_device *mdiodev, int value) { - if (mdiodev->reset) - gpiod_set_value(mdiodev->reset, value); + unsigned int d; + + if (!mdiodev->reset) + return; + + gpiod_set_value(mdiodev->reset, value); + + d = value ? mdiodev->reset_delay : mdiodev->reset_post_delay; + if (d) + usleep_range(d, d + max_t(unsigned int, d / 10, 100)); } EXPORT_SYMBOL(mdio_device_reset); diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 98258583abb0b40529056767c91401296e0013d4..7c87671763156b4d76707a3af041d49a897e3c58 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -77,6 +77,10 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, if (of_property_read_bool(child, "broken-turn-around")) mdio->phy_ignore_ta_mask |= 1 << addr; + of_property_read_u32(child, "reset-delay-us", &phy->mdio.reset_delay); + of_property_read_u32(child, "reset-post-delay-us", + &phy->mdio.reset_post_delay); + /* Associate the OF node with the device structure so it * can be looked up later */ of_node_get(child); diff --git a/include/linux/mdio.h b/include/linux/mdio.h index 92d4e55ffe6756378eaa8cf48eb2f6dbe08f65e2..e37c21d8eb19da5f375d0e4d41b70e659dc827b6 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -41,6 +41,8 @@ struct mdio_device { int addr; int flags; struct gpio_desc *reset; + unsigned int reset_delay; + unsigned int reset_post_delay; }; #define to_mdio_device(d) container_of(d, struct mdio_device, dev)