net: arc_emac: support the phy reset for emac driver
This patch adds to support the emac phy reset. Different boards may require different phy reset duration. Add property phy-reset-duration for emac driver, so that the boards that need a longer reset duration can specify it in their device tree. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Caesar Wang <wxt@rock-chips.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: netdev@vger.kernel.org Cc: Alexander Kochetkov <al.kochet@gmail.com> Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
8700eee627
Коммит
1bddd96cba
|
@ -102,6 +102,11 @@ struct buffer_state {
|
|||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
};
|
||||
|
||||
struct arc_emac_mdio_bus_data {
|
||||
struct gpio_desc *reset_gpio;
|
||||
int msec;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct arc_emac_priv - Storage of EMAC's private information.
|
||||
* @dev: Pointer to the current device.
|
||||
|
@ -131,6 +136,7 @@ struct arc_emac_priv {
|
|||
struct device *dev;
|
||||
struct phy_device *phy_dev;
|
||||
struct mii_bus *bus;
|
||||
struct arc_emac_mdio_bus_data bus_data;
|
||||
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
#include "emac.h"
|
||||
|
||||
|
@ -98,6 +99,25 @@ static int arc_mdio_write(struct mii_bus *bus, int phy_addr,
|
|||
return arc_mdio_complete_wait(priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* arc_mdio_reset
|
||||
* @bus: points to the mii_bus structure
|
||||
* Description: reset the MII bus
|
||||
*/
|
||||
int arc_mdio_reset(struct mii_bus *bus)
|
||||
{
|
||||
struct arc_emac_priv *priv = bus->priv;
|
||||
struct arc_emac_mdio_bus_data *data = &priv->bus_data;
|
||||
|
||||
if (data->reset_gpio) {
|
||||
gpiod_set_value_cansleep(data->reset_gpio, 1);
|
||||
msleep(data->msec);
|
||||
gpiod_set_value_cansleep(data->reset_gpio, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* arc_mdio_probe - MDIO probe function.
|
||||
* @priv: Pointer to ARC EMAC private data structure.
|
||||
|
@ -109,6 +129,8 @@ static int arc_mdio_write(struct mii_bus *bus, int phy_addr,
|
|||
*/
|
||||
int arc_mdio_probe(struct arc_emac_priv *priv)
|
||||
{
|
||||
struct arc_emac_mdio_bus_data *data = &priv->bus_data;
|
||||
struct device_node *np = priv->dev->of_node;
|
||||
struct mii_bus *bus;
|
||||
int error;
|
||||
|
||||
|
@ -122,6 +144,21 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
|
|||
bus->name = "Synopsys MII Bus",
|
||||
bus->read = &arc_mdio_read;
|
||||
bus->write = &arc_mdio_write;
|
||||
bus->reset = &arc_mdio_reset;
|
||||
|
||||
/* optional reset-related properties */
|
||||
data->reset_gpio = devm_gpiod_get_optional(priv->dev, "phy-reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(data->reset_gpio)) {
|
||||
error = PTR_ERR(data->reset_gpio);
|
||||
dev_err(priv->dev, "Failed to request gpio: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
of_property_read_u32(np, "phy-reset-duration", &data->msec);
|
||||
/* A sane reset duration should not be longer than 1s */
|
||||
if (data->msec > 1000)
|
||||
data->msec = 1;
|
||||
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче