From 71dd6c0dff51b5f1fef2e9dfa6f6a948aac975f3 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 17 Apr 2019 23:59:21 +0200 Subject: net: phy: add support for reset-controller This commit adds support for PHY reset pins handled by a reset controller. Signed-off-by: David Bauer Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 27 +++++++++++++++++++++++++-- drivers/net/phy/mdio_device.c | 13 +++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'drivers/net/phy') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 4be4cc09eb90..ba3d2523808b 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -57,8 +58,23 @@ static int mdiobus_register_gpiod(struct mdio_device *mdiodev) mdiodev->reset = gpiod; - /* Assert the reset signal again */ - mdio_device_reset(mdiodev, 1); + return 0; +} + +static int mdiobus_register_reset(struct mdio_device *mdiodev) +{ + struct reset_control *reset = NULL; + + if (mdiodev->dev.of_node) + reset = devm_reset_control_get_exclusive(&mdiodev->dev, + "phy"); + if (PTR_ERR(reset) == -ENOENT || + PTR_ERR(reset) == -ENOTSUPP) + reset = NULL; + else if (IS_ERR(reset)) + return PTR_ERR(reset); + + mdiodev->reset_ctrl = reset; return 0; } @@ -74,6 +90,13 @@ int mdiobus_register_device(struct mdio_device *mdiodev) err = mdiobus_register_gpiod(mdiodev); if (err) return err; + + err = mdiobus_register_reset(mdiodev); + if (err) + return err; + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); } mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev; diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c index 887076292e50..57668e0f9256 100644 --- a/drivers/net/phy/mdio_device.c +++ b/drivers/net/phy/mdio_device.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -116,10 +117,18 @@ void mdio_device_reset(struct mdio_device *mdiodev, int value) { unsigned int d; - if (!mdiodev->reset) + if (!mdiodev->reset && !mdiodev->reset_ctrl) return; - gpiod_set_value(mdiodev->reset, value); + if (mdiodev->reset) + gpiod_set_value(mdiodev->reset, value); + + if (mdiodev->reset_ctrl) { + if (value) + reset_control_assert(mdiodev->reset_ctrl); + else + reset_control_deassert(mdiodev->reset_ctrl); + } d = value ? mdiodev->reset_assert_delay : mdiodev->reset_deassert_delay; if (d) -- cgit v1.2.3