diff options
| author | Caesar Wang <wxt@rock-chips.com> | 2016-03-14 04:01:54 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-03-16 19:28:01 -0400 |
| commit | 1bddd96cba03da0a14b3e5144e98c9a6ff17e983 (patch) | |
| tree | bdd4e8de5e6d5afc74f49ae86c404e2bd73b79e7 /drivers/net/ethernet/arc | |
| parent | 8700eee6271c932b2747a6b157655f546c27e7ad (diff) | |
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>
Diffstat (limited to 'drivers/net/ethernet/arc')
| -rw-r--r-- | drivers/net/ethernet/arc/emac.h | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/arc/emac_mdio.c | 37 |
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h index dae1ac300a49..1a4040397a4b 100644 --- a/drivers/net/ethernet/arc/emac.h +++ b/drivers/net/ethernet/arc/emac.h | |||
| @@ -102,6 +102,11 @@ struct buffer_state { | |||
| 102 | DEFINE_DMA_UNMAP_LEN(len); | 102 | DEFINE_DMA_UNMAP_LEN(len); |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | struct arc_emac_mdio_bus_data { | ||
| 106 | struct gpio_desc *reset_gpio; | ||
| 107 | int msec; | ||
| 108 | }; | ||
| 109 | |||
| 105 | /** | 110 | /** |
| 106 | * struct arc_emac_priv - Storage of EMAC's private information. | 111 | * struct arc_emac_priv - Storage of EMAC's private information. |
| 107 | * @dev: Pointer to the current device. | 112 | * @dev: Pointer to the current device. |
| @@ -131,6 +136,7 @@ struct arc_emac_priv { | |||
| 131 | struct device *dev; | 136 | struct device *dev; |
| 132 | struct phy_device *phy_dev; | 137 | struct phy_device *phy_dev; |
| 133 | struct mii_bus *bus; | 138 | struct mii_bus *bus; |
| 139 | struct arc_emac_mdio_bus_data bus_data; | ||
| 134 | 140 | ||
| 135 | void __iomem *regs; | 141 | void __iomem *regs; |
| 136 | struct clk *clk; | 142 | struct clk *clk; |
diff --git a/drivers/net/ethernet/arc/emac_mdio.c b/drivers/net/ethernet/arc/emac_mdio.c index d5ee986936da..caf704264eba 100644 --- a/drivers/net/ethernet/arc/emac_mdio.c +++ b/drivers/net/ethernet/arc/emac_mdio.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
| 8 | #include <linux/of_mdio.h> | 8 | #include <linux/of_mdio.h> |
| 9 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
| 10 | #include <linux/gpio/consumer.h> | ||
| 10 | 11 | ||
| 11 | #include "emac.h" | 12 | #include "emac.h" |
| 12 | 13 | ||
| @@ -99,6 +100,25 @@ static int arc_mdio_write(struct mii_bus *bus, int phy_addr, | |||
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | /** | 102 | /** |
| 103 | * arc_mdio_reset | ||
| 104 | * @bus: points to the mii_bus structure | ||
| 105 | * Description: reset the MII bus | ||
| 106 | */ | ||
| 107 | int arc_mdio_reset(struct mii_bus *bus) | ||
| 108 | { | ||
| 109 | struct arc_emac_priv *priv = bus->priv; | ||
| 110 | struct arc_emac_mdio_bus_data *data = &priv->bus_data; | ||
| 111 | |||
| 112 | if (data->reset_gpio) { | ||
| 113 | gpiod_set_value_cansleep(data->reset_gpio, 1); | ||
| 114 | msleep(data->msec); | ||
| 115 | gpiod_set_value_cansleep(data->reset_gpio, 0); | ||
| 116 | } | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | /** | ||
| 102 | * arc_mdio_probe - MDIO probe function. | 122 | * arc_mdio_probe - MDIO probe function. |
| 103 | * @priv: Pointer to ARC EMAC private data structure. | 123 | * @priv: Pointer to ARC EMAC private data structure. |
| 104 | * | 124 | * |
| @@ -109,6 +129,8 @@ static int arc_mdio_write(struct mii_bus *bus, int phy_addr, | |||
| 109 | */ | 129 | */ |
| 110 | int arc_mdio_probe(struct arc_emac_priv *priv) | 130 | int arc_mdio_probe(struct arc_emac_priv *priv) |
| 111 | { | 131 | { |
| 132 | struct arc_emac_mdio_bus_data *data = &priv->bus_data; | ||
| 133 | struct device_node *np = priv->dev->of_node; | ||
| 112 | struct mii_bus *bus; | 134 | struct mii_bus *bus; |
| 113 | int error; | 135 | int error; |
| 114 | 136 | ||
| @@ -122,6 +144,21 @@ int arc_mdio_probe(struct arc_emac_priv *priv) | |||
| 122 | bus->name = "Synopsys MII Bus", | 144 | bus->name = "Synopsys MII Bus", |
| 123 | bus->read = &arc_mdio_read; | 145 | bus->read = &arc_mdio_read; |
| 124 | bus->write = &arc_mdio_write; | 146 | bus->write = &arc_mdio_write; |
| 147 | bus->reset = &arc_mdio_reset; | ||
| 148 | |||
| 149 | /* optional reset-related properties */ | ||
| 150 | data->reset_gpio = devm_gpiod_get_optional(priv->dev, "phy-reset", | ||
| 151 | GPIOD_OUT_LOW); | ||
| 152 | if (IS_ERR(data->reset_gpio)) { | ||
| 153 | error = PTR_ERR(data->reset_gpio); | ||
| 154 | dev_err(priv->dev, "Failed to request gpio: %d\n", error); | ||
| 155 | return error; | ||
| 156 | } | ||
| 157 | |||
| 158 | of_property_read_u32(np, "phy-reset-duration", &data->msec); | ||
| 159 | /* A sane reset duration should not be longer than 1s */ | ||
| 160 | if (data->msec > 1000) | ||
| 161 | data->msec = 1; | ||
| 125 | 162 | ||
| 126 | snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name); | 163 | snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name); |
| 127 | 164 | ||
