Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c2e6e14 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-add-reset-controller-driven-PHY-reset'



David Bauer says:

====================
net: add reset-controller driven PHY reset

This patchset adds support for a PHY reset driven by a reset-controller.
Currently, only GPIO driven resets are supported by the PHY subsystem.
It also renames the reset-gpio from 'reset' to 'reset_gpio' to
better differentiate between resets wired to a GPIO and resets wired to
a reset-controller driven pin.

Some systems have the PHY reset-line wired to a pin controlled by a
reset-controller (eg. some Atheros AR9132 based boards). In case the
bootloader asserts reset before loading the kernel, we currently do not
have a clean way of deasserting reset to probe the PHY.

v3:
 - add missing newline in mdio_bus.c

v2:
 - fixed missed rename of "reset" in at803x.c
 - move initial reset to mdio_device_reset
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8a99aa5d 6110ed2d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -51,6 +51,10 @@ Optional Properties:
  to ensure the integrated PHY is used. The absence of this property indicates
  the muxers should be configured so that the external PHY is used.

- resets: The reset-controller phandle and specifier for the PHY reset signal.

- reset-names: Must be "phy" for the PHY reset signal.

- reset-gpios: The GPIO phandle and specifier for the PHY reset signal.

- reset-assert-us: Delay after the reset was asserted in microseconds.
@@ -67,6 +71,8 @@ ethernet-phy@0 {
	interrupts = <35 IRQ_TYPE_EDGE_RISING>;
	reg = <0>;

	resets = <&rst 8>;
	reset-names = "phy";
	reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
	reset-assert-us = <1000>;
	reset-deassert-us = <2000>;
+1 −1
Original line number Diff line number Diff line
@@ -331,7 +331,7 @@ static void at803x_link_change_notify(struct phy_device *phydev)
	 * in the FIFO. In such cases, the FIFO enters an error mode it
	 * cannot recover from by software.
	 */
	if (phydev->state == PHY_NOLINK && phydev->mdio.reset) {
	if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) {
		struct at803x_context context;

		at803x_context_save(phydev, &context);
+28 −5
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/of_gpio.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/reset.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
@@ -55,10 +56,25 @@ static int mdiobus_register_gpiod(struct mdio_device *mdiodev)
			return PTR_ERR(gpiod);
	}

	mdiodev->reset = gpiod;
	mdiodev->reset_gpio = 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;
@@ -446,8 +469,8 @@ void mdiobus_unregister(struct mii_bus *bus)
		if (!mdiodev)
			continue;

		if (mdiodev->reset)
			gpiod_put(mdiodev->reset);
		if (mdiodev->reset_gpio)
			gpiod_put(mdiodev->reset_gpio);

		mdiodev->device_remove(mdiodev);
		mdiodev->device_free(mdiodev);
+11 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/mii.h>
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/unistd.h>
@@ -116,10 +117,18 @@ void mdio_device_reset(struct mdio_device *mdiodev, int value)
{
	unsigned int d;

	if (!mdiodev->reset)
	if (!mdiodev->reset_gpio && !mdiodev->reset_ctrl)
		return;

	gpiod_set_value(mdiodev->reset, value);
	if (mdiodev->reset_gpio)
		gpiod_set_value(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)
+2 −1
Original line number Diff line number Diff line
@@ -39,7 +39,8 @@ struct mdio_device {
	/* Bus address of the MDIO device (0-31) */
	int addr;
	int flags;
	struct gpio_desc *reset;
	struct gpio_desc *reset_gpio;
	struct reset_control *reset_ctrl;
	unsigned int reset_assert_delay;
	unsigned int reset_deassert_delay;
};