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);
|
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.
|
* struct arc_emac_priv - Storage of EMAC's private information.
|
||||||
* @dev: Pointer to the current device.
|
* @dev: Pointer to the current device.
|
||||||
|
@ -131,6 +136,7 @@ struct arc_emac_priv {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct phy_device *phy_dev;
|
struct phy_device *phy_dev;
|
||||||
struct mii_bus *bus;
|
struct mii_bus *bus;
|
||||||
|
struct arc_emac_mdio_bus_data bus_data;
|
||||||
|
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/of_mdio.h>
|
#include <linux/of_mdio.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
|
|
||||||
#include "emac.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);
|
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.
|
* arc_mdio_probe - MDIO probe function.
|
||||||
* @priv: Pointer to ARC EMAC private data structure.
|
* @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)
|
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;
|
struct mii_bus *bus;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
@ -122,6 +144,21 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
|
||||||
bus->name = "Synopsys MII Bus",
|
bus->name = "Synopsys MII Bus",
|
||||||
bus->read = &arc_mdio_read;
|
bus->read = &arc_mdio_read;
|
||||||
bus->write = &arc_mdio_write;
|
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);
|
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче