Merge branch 'net-mdio-improve-reset-handling-of-mdio-devices'

Buday Csaba says:

====================
net: mdio: improve reset handling of mdio devices

This patchset refactors and slightly improves the reset handling of
`mdio_device`.

The patches were split from a larger series, discussed previously in the
links below.

The difference between v2 and v3, is that the helper function declarations
have been moved to a new header file: drivers/net/phy/mdio-private.h
See links for the previous versions, and for the now separate leak fix.
====================

Link: https://patch.msgid.link/cover.1763473655.git.buday.csaba@prolan.hu
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2025-11-20 17:41:40 -08:00
4 changed files with 68 additions and 42 deletions

View File

@@ -92,11 +92,6 @@ int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
if (fwnode_property_read_bool(child, "broken-turn-around"))
mdio->phy_ignore_ta_mask |= 1 << addr;
fwnode_property_read_u32(child, "reset-assert-us",
&phy->mdio.reset_assert_delay);
fwnode_property_read_u32(child, "reset-deassert-us",
&phy->mdio.reset_deassert_delay);
/* Associate the fwnode with the device structure so it
* can be looked up later
*/

View File

@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef __MDIO_PRIVATE_H
#define __MDIO_PRIVATE_H
/* MDIO internal helpers
*/
int mdio_device_register_reset(struct mdio_device *mdiodev);
void mdio_device_unregister_reset(struct mdio_device *mdiodev);
#endif /* __MDIO_PRIVATE_H */

View File

@@ -29,37 +29,11 @@
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
#include "mdio-private.h"
#define CREATE_TRACE_POINTS
#include <trace/events/mdio.h>
static int mdiobus_register_gpiod(struct mdio_device *mdiodev)
{
/* 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");
return 0;
}
static int mdiobus_register_reset(struct mdio_device *mdiodev)
{
struct reset_control *reset;
reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy");
if (IS_ERR(reset))
return PTR_ERR(reset);
mdiodev->reset_ctrl = reset;
return 0;
}
int mdiobus_register_device(struct mdio_device *mdiodev)
{
int err;
@@ -68,17 +42,10 @@ int mdiobus_register_device(struct mdio_device *mdiodev)
return -EBUSY;
if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) {
err = mdiobus_register_gpiod(mdiodev);
err = mdio_device_register_reset(mdiodev);
if (err)
return err;
err = mdiobus_register_reset(mdiodev);
if (err) {
gpiod_put(mdiodev->reset_gpio);
mdiodev->reset_gpio = NULL;
return err;
}
/* Assert the reset signal */
mdio_device_reset(mdiodev, 1);
}
@@ -94,8 +61,7 @@ int mdiobus_unregister_device(struct mdio_device *mdiodev)
if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
return -EINVAL;
gpiod_put(mdiodev->reset_gpio);
reset_control_put(mdiodev->reset_ctrl);
mdio_device_unregister_reset(mdiodev);
mdiodev->bus->mdio_map[mdiodev->addr] = NULL;

View File

@@ -22,6 +22,7 @@
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/property.h>
#include "mdio-private.h"
void mdio_device_free(struct mdio_device *mdiodev)
{
@@ -118,6 +119,59 @@ 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)
{
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
*/
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;