Re: [PATCH v2 2/3] phylib: add support for reset-gpios

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sam,

Some comments inside.

On Wed, Aug 08, 2018 at 09:17:00PM +0200, Sam Ravnborg wrote:
> Add minimal support for reset-gpios.
> 
> Example DT that uses this:
> 
> 	mdio {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
> 		reset-gpios = <&pioE 17 GPIO_ACTIVE_LOW>;
> 		reset-delay-us = <1000>;
> 		ethphy0: ethernet-phy@1 {
> 			reg = <3>;
> 		};
> 	};
> 
> This was required to get the Davicom PHY operational on
> my proprietary board.
> I added the minimal mdio_reset() calls.
> 
> Another options was to use a bus reset, but then
> the net/ driver used should have dedicated reset support.
> 
> The reset-gpios solution is general and matches the
> binding specification in net/mdio.txt
> 
> Signed-off-by: Sam Ravnborg <sam@xxxxxxxxxxxx>
> ---
>  drivers/net/phy/mdio_bus.c | 64 ++++++++++++++++++++++++++++++++++++++++++++--
>  include/linux/phy.h        |  5 ++++
>  2 files changed, 67 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
> index d209716a1..ad358192d 100644
> --- a/drivers/net/phy/mdio_bus.c
> +++ b/drivers/net/phy/mdio_bus.c
> @@ -17,6 +17,8 @@
>  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>  
>  #include <common.h>
> +#include <of_gpio.h>
> +#include <gpio.h>
>  #include <driver.h>
>  #include <init.h>
>  #include <clock.h>
> @@ -25,6 +27,8 @@
>  #include <linux/phy.h>
>  #include <linux/err.h>
>  
> +#define DEFAULT_GPIO_RESET_DELAY	10 /* us */
> +
>  LIST_HEAD(mii_bus_list);
>  
>  int mdiobus_detect(struct device_d *dev)
> @@ -83,6 +87,45 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
>  }
>  
>  /**
> + * of_mdioibus_register_reset - register optional reset-gpios

s/mdioibus/mdiobus/

> + * @mdio: pointer to mii_bus structure
> + * @np: pointer to device_node of MDIO bus.
> + *
> + * Read optional reset-gpios from mido node in DT

s/mido/mdio/

> + */
> +static void of_mdiobus_register_reset(struct mii_bus *mdio,
> +				      struct device_node *np)
> +{
> +	enum of_gpio_flags of_flags;
> +	u32 reset_delay;
> +	int gpio;
> +
> +	if (!np)
> +		return;
> +
> +	reset_delay = DEFAULT_GPIO_RESET_DELAY;
> +	of_property_read_u32(np, "reset-delay-us", &reset_delay);
> +
> +	gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &of_flags);
> +	if (gpio_is_valid(gpio)) {
> +		unsigned long flags;
> +		char *name;
> +
> +		name = basprintf("%s-reset", dev_name(&mdio->dev));

Free after use?

> +		flags = GPIOF_OUT_INIT_INACTIVE;
> +
> +		if (of_flags & OF_GPIO_ACTIVE_LOW)
> +			flags |= GPIOF_ACTIVE_LOW;
> +
> +		if (gpio_request_one(gpio, flags, name) >= 0) {
> +			mdio->reset_gpio = gpio;
> +			mdio->reset_delay = reset_delay;
> +		}

This shouldn't fail silently. If we find a GPIO we should be able to
request it, otherwise it's a bug.

> +	}
> +
> +}
> +
> +/**
>   * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
>   * @mdio: pointer to mii_bus structure
>   * @np: pointer to device_node of MDIO bus.
> @@ -96,6 +139,9 @@ static int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
>  	u32 addr;
>  	int ret;
>  
> +	if (!np)
> +		return -ENODEV;
> +
>  	/* Loop over the child nodes and register a phy_device for each one */
>  	for_each_available_child_of_node(np, child) {
>  		ret = of_property_read_u32(child, "reg", &addr);
> @@ -128,6 +174,7 @@ static int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
>   */
>  int mdiobus_register(struct mii_bus *bus)
>  {
> +	struct device_node *np;
>  	int err;
>  
>  	if (NULL == bus ||
> @@ -147,6 +194,11 @@ int mdiobus_register(struct mii_bus *bus)
>  		return -EINVAL;
>  	}
>  
> +	np = bus->dev.device_node;
> +
> +	of_mdiobus_register_reset(bus, np);
> +
> +	mdio_reset(bus);
>  	if (bus->reset)
>  		bus->reset(bus);
>  
> @@ -154,8 +206,7 @@ int mdiobus_register(struct mii_bus *bus)
>  
>  	pr_info("%s: probed\n", dev_name(&bus->dev));
>  
> -	if (bus->dev.device_node)
> -		of_mdiobus_register(bus, bus->dev.device_node);
> +	of_mdiobus_register(bus, np);
>  
>  	return 0;
>  }
> @@ -190,6 +241,15 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
>  }
>  EXPORT_SYMBOL(mdiobus_scan);
>  
> +void mdio_reset(const struct mii_bus *bus)
> +{
> +	if (gpio_is_valid(bus->reset_gpio)) {

'0' is a valid GPIO, you have to initialize bus->reset_gpio explicitly
to a negative value for the general case when no reset GPIO is
available.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux