diff options
Diffstat (limited to 'drivers/net/phy/mdio_device.c')
| -rw-r--r-- | drivers/net/phy/mdio_device.c | 165 |
1 files changed, 99 insertions, 66 deletions
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c index b8a5a1838196..56080d3d2d25 100644 --- a/drivers/net/phy/mdio_device.c +++ b/drivers/net/phy/mdio_device.c @@ -22,7 +22,88 @@ #include <linux/string.h> #include <linux/unistd.h> #include <linux/property.h> -#include "mdio-private.h" +#include "phylib-internal.h" + +/** + * mdio_device_register_reset - Read and initialize the reset properties of + * an mdio device + * @mdiodev: mdio_device structure + * + * Return: Zero if successful, negative error code on failure + */ +static int mdio_device_register_reset(struct mdio_device *mdiodev) +{ + struct reset_control *reset; + + /* Deassert the optional reset signal */ + mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev, + "reset", GPIOD_OUT_LOW); + if (IS_ERR(mdiodev->reset_gpio)) + return PTR_ERR(mdiodev->reset_gpio); + + if (mdiodev->reset_gpio) + gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset"); + + reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy"); + if (IS_ERR(reset)) { + gpiod_put(mdiodev->reset_gpio); + mdiodev->reset_gpio = NULL; + return PTR_ERR(reset); + } + + mdiodev->reset_ctrl = reset; + + /* Read optional firmware properties */ + device_property_read_u32(&mdiodev->dev, "reset-assert-us", + &mdiodev->reset_assert_delay); + device_property_read_u32(&mdiodev->dev, "reset-deassert-us", + &mdiodev->reset_deassert_delay); + + return 0; +} + +/** + * mdio_device_unregister_reset - uninitialize the reset properties of + * an mdio device + * @mdiodev: mdio_device structure + */ +static void mdio_device_unregister_reset(struct mdio_device *mdiodev) +{ + gpiod_put(mdiodev->reset_gpio); + mdiodev->reset_gpio = NULL; + reset_control_put(mdiodev->reset_ctrl); + mdiodev->reset_ctrl = NULL; + mdiodev->reset_assert_delay = 0; + mdiodev->reset_deassert_delay = 0; +} + +void mdio_device_reset(struct mdio_device *mdiodev, int value) +{ + unsigned int d; + + if (!mdiodev->reset_gpio && !mdiodev->reset_ctrl) + return; + + if (mdiodev->reset_state == value) + return; + + if (mdiodev->reset_gpio) + gpiod_set_value_cansleep(mdiodev->reset_gpio, 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) + fsleep(d); + + mdiodev->reset_state = value; +} +EXPORT_SYMBOL(mdio_device_reset); void mdio_device_free(struct mdio_device *mdiodev) { @@ -108,86 +189,38 @@ void mdio_device_remove(struct mdio_device *mdiodev) } EXPORT_SYMBOL(mdio_device_remove); -/** - * mdio_device_register_reset - Read and initialize the reset properties of - * an mdio device - * @mdiodev: mdio_device structure - * - * Return: Zero if successful, negative error code on failure - */ -int mdio_device_register_reset(struct mdio_device *mdiodev) +int mdiobus_register_device(struct mdio_device *mdiodev) { - struct reset_control *reset; + int err; - /* Deassert the optional reset signal */ - mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev, - "reset", GPIOD_OUT_LOW); - if (IS_ERR(mdiodev->reset_gpio)) - return PTR_ERR(mdiodev->reset_gpio); + if (mdiodev->bus->mdio_map[mdiodev->addr]) + return -EBUSY; - if (mdiodev->reset_gpio) - gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset"); + if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) { + err = mdio_device_register_reset(mdiodev); + if (err) + return err; - reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy"); - if (IS_ERR(reset)) { - gpiod_put(mdiodev->reset_gpio); - mdiodev->reset_gpio = NULL; - return PTR_ERR(reset); + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); } - mdiodev->reset_ctrl = reset; - - /* Read optional firmware properties */ - device_property_read_u32(&mdiodev->dev, "reset-assert-us", - &mdiodev->reset_assert_delay); - device_property_read_u32(&mdiodev->dev, "reset-deassert-us", - &mdiodev->reset_deassert_delay); + mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev; return 0; } -/** - * mdio_device_unregister_reset - uninitialize the reset properties of - * an mdio device - * @mdiodev: mdio_device structure - */ -void mdio_device_unregister_reset(struct mdio_device *mdiodev) -{ - gpiod_put(mdiodev->reset_gpio); - mdiodev->reset_gpio = NULL; - reset_control_put(mdiodev->reset_ctrl); - mdiodev->reset_ctrl = NULL; - mdiodev->reset_assert_delay = 0; - mdiodev->reset_deassert_delay = 0; -} - -void mdio_device_reset(struct mdio_device *mdiodev, int value) +int mdiobus_unregister_device(struct mdio_device *mdiodev) { - unsigned int d; - - if (!mdiodev->reset_gpio && !mdiodev->reset_ctrl) - return; + if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev) + return -EINVAL; - if (mdiodev->reset_state == value) - return; - - if (mdiodev->reset_gpio) - gpiod_set_value_cansleep(mdiodev->reset_gpio, value); - - if (mdiodev->reset_ctrl) { - if (value) - reset_control_assert(mdiodev->reset_ctrl); - else - reset_control_deassert(mdiodev->reset_ctrl); - } + mdio_device_unregister_reset(mdiodev); - d = value ? mdiodev->reset_assert_delay : mdiodev->reset_deassert_delay; - if (d) - fsleep(d); + mdiodev->bus->mdio_map[mdiodev->addr] = NULL; - mdiodev->reset_state = value; + return 0; } -EXPORT_SYMBOL(mdio_device_reset); /** * mdio_probe - probe an MDIO device |
