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

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
...@@ -51,6 +51,10 @@ Optional Properties: ...@@ -51,6 +51,10 @@ Optional Properties:
to ensure the integrated PHY is used. The absence of this property indicates 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. 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-gpios: The GPIO phandle and specifier for the PHY reset signal.
- reset-assert-us: Delay after the reset was asserted in microseconds. - reset-assert-us: Delay after the reset was asserted in microseconds.
...@@ -67,6 +71,8 @@ ethernet-phy@0 { ...@@ -67,6 +71,8 @@ ethernet-phy@0 {
interrupts = <35 IRQ_TYPE_EDGE_RISING>; interrupts = <35 IRQ_TYPE_EDGE_RISING>;
reg = <0>; reg = <0>;
resets = <&rst 8>;
reset-names = "phy";
reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
reset-assert-us = <1000>; reset-assert-us = <1000>;
reset-deassert-us = <2000>; reset-deassert-us = <2000>;
......
...@@ -331,7 +331,7 @@ static void at803x_link_change_notify(struct phy_device *phydev) ...@@ -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 * in the FIFO. In such cases, the FIFO enters an error mode it
* cannot recover from by software. * 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; struct at803x_context context;
at803x_context_save(phydev, &context); at803x_context_save(phydev, &context);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/reset.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -55,10 +56,25 @@ static int mdiobus_register_gpiod(struct mdio_device *mdiodev) ...@@ -55,10 +56,25 @@ static int mdiobus_register_gpiod(struct mdio_device *mdiodev)
return PTR_ERR(gpiod); return PTR_ERR(gpiod);
} }
mdiodev->reset = gpiod; mdiodev->reset_gpio = gpiod;
/* Assert the reset signal again */ return 0;
mdio_device_reset(mdiodev, 1); }
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; return 0;
} }
...@@ -74,6 +90,13 @@ int mdiobus_register_device(struct mdio_device *mdiodev) ...@@ -74,6 +90,13 @@ int mdiobus_register_device(struct mdio_device *mdiodev)
err = mdiobus_register_gpiod(mdiodev); err = mdiobus_register_gpiod(mdiodev);
if (err) if (err)
return 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; mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
...@@ -446,8 +469,8 @@ void mdiobus_unregister(struct mii_bus *bus) ...@@ -446,8 +469,8 @@ void mdiobus_unregister(struct mii_bus *bus)
if (!mdiodev) if (!mdiodev)
continue; continue;
if (mdiodev->reset) if (mdiodev->reset_gpio)
gpiod_put(mdiodev->reset); gpiod_put(mdiodev->reset_gpio);
mdiodev->device_remove(mdiodev); mdiodev->device_remove(mdiodev);
mdiodev->device_free(mdiodev); mdiodev->device_free(mdiodev);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/mii.h> #include <linux/mii.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/reset.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/unistd.h> #include <linux/unistd.h>
...@@ -116,10 +117,18 @@ void mdio_device_reset(struct mdio_device *mdiodev, int value) ...@@ -116,10 +117,18 @@ void mdio_device_reset(struct mdio_device *mdiodev, int value)
{ {
unsigned int d; unsigned int d;
if (!mdiodev->reset) if (!mdiodev->reset_gpio && !mdiodev->reset_ctrl)
return; 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; d = value ? mdiodev->reset_assert_delay : mdiodev->reset_deassert_delay;
if (d) if (d)
......
...@@ -39,7 +39,8 @@ struct mdio_device { ...@@ -39,7 +39,8 @@ struct mdio_device {
/* Bus address of the MDIO device (0-31) */ /* Bus address of the MDIO device (0-31) */
int addr; int addr;
int flags; int flags;
struct gpio_desc *reset; struct gpio_desc *reset_gpio;
struct reset_control *reset_ctrl;
unsigned int reset_assert_delay; unsigned int reset_assert_delay;
unsigned int reset_deassert_delay; unsigned int reset_deassert_delay;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment