summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSjoerd Simons <sjoerd.simons@collabora.co.uk>2016-02-28 22:24:55 +0100
committerSimon Glass <sjg@chromium.org>2016-05-27 09:00:48 -0600
commit90b7fc924adfe7f1745dcf6a1dabb9e77aa762a7 (patch)
tree32909f2f1853af4f8553d713a6fedd41a5a2d8d0 /drivers
parent6523dbf7cce8d8c903346f756e0e41e46ce6d6b9 (diff)
downloadu-boot-90b7fc924adfe7f1745dcf6a1dabb9e77aa762a7.tar.gz
u-boot-90b7fc924adfe7f1745dcf6a1dabb9e77aa762a7.tar.bz2
u-boot-90b7fc924adfe7f1745dcf6a1dabb9e77aa762a7.zip
net: designware: support phy reset device-tree bindings
Add support for the snps,reset-gpio, snps,reset-active-low (optional) and snps,reset-delays-us device-tree bindings. The combination of these three define how the PHY should be reset to ensure it's in a sane state. Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/designware.c76
-rw-r--r--drivers/net/designware.h10
2 files changed, 80 insertions, 6 deletions
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index ca58f34f13..14dd7b8349 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -24,7 +24,12 @@ DECLARE_GLOBAL_DATA_PTR;
static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
{
+#ifdef CONFIG_DM_ETH
+ struct dw_eth_dev *priv = dev_get_priv((struct udevice *)bus->priv);
+ struct eth_mac_regs *mac_p = priv->mac_regs_p;
+#else
struct eth_mac_regs *mac_p = bus->priv;
+#endif
ulong start;
u16 miiaddr;
int timeout = CONFIG_MDIO_TIMEOUT;
@@ -47,7 +52,12 @@ static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
{
+#ifdef CONFIG_DM_ETH
+ struct dw_eth_dev *priv = dev_get_priv((struct udevice *)bus->priv);
+ struct eth_mac_regs *mac_p = priv->mac_regs_p;
+#else
struct eth_mac_regs *mac_p = bus->priv;
+#endif
ulong start;
u16 miiaddr;
int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT;
@@ -70,7 +80,41 @@ static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
return ret;
}
-static int dw_mdio_init(const char *name, struct eth_mac_regs *mac_regs_p)
+#if CONFIG_DM_ETH
+static int dw_mdio_reset(struct mii_dev *bus)
+{
+ struct udevice *dev = bus->priv;
+ struct dw_eth_dev *priv = dev_get_priv(dev);
+ struct dw_eth_pdata *pdata = dev_get_platdata(dev);
+ int ret;
+
+ if (!dm_gpio_is_valid(&priv->reset_gpio))
+ return 0;
+
+ /* reset the phy */
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret)
+ return ret;
+
+ udelay(pdata->reset_delays[0]);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret)
+ return ret;
+
+ udelay(pdata->reset_delays[1]);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret)
+ return ret;
+
+ udelay(pdata->reset_delays[2]);
+
+ return 0;
+}
+#endif
+
+static int dw_mdio_init(const char *name, void *priv)
{
struct mii_dev *bus = mdio_alloc();
@@ -82,8 +126,11 @@ static int dw_mdio_init(const char *name, struct eth_mac_regs *mac_regs_p)
bus->read = dw_mdio_read;
bus->write = dw_mdio_write;
snprintf(bus->name, sizeof(bus->name), "%s", name);
+#ifdef CONFIG_DM_ETH
+ bus->reset = dw_mdio_reset;
+#endif
- bus->priv = (void *)mac_regs_p;
+ bus->priv = priv;
return mdio_register(bus);
}
@@ -606,7 +653,7 @@ static int designware_eth_probe(struct udevice *dev)
priv->interface = pdata->phy_interface;
priv->max_speed = pdata->max_speed;
- dw_mdio_init(dev->name, priv->mac_regs_p);
+ dw_mdio_init(dev->name, dev);
priv->bus = miiphy_get_dev_by_name(dev->name);
ret = dw_phy_init(priv, dev);
@@ -637,9 +684,13 @@ static const struct eth_ops designware_eth_ops = {
static int designware_eth_ofdata_to_platdata(struct udevice *dev)
{
- struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev);
+ struct dw_eth_dev *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = &dw_pdata->eth_pdata;
const char *phy_mode;
const fdt32_t *cell;
+ int reset_flags = GPIOD_IS_OUT;
+ int ret = 0;
pdata->iobase = dev_get_addr(dev);
pdata->phy_interface = -1;
@@ -656,7 +707,20 @@ static int designware_eth_ofdata_to_platdata(struct udevice *dev)
if (cell)
pdata->max_speed = fdt32_to_cpu(*cell);
- return 0;
+ if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+ "snps,reset-active-low"))
+ reset_flags |= GPIOD_ACTIVE_LOW;
+
+ ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
+ &priv->reset_gpio, reset_flags);
+ if (ret == 0) {
+ ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+ "snps,reset-delays-us", dw_pdata->reset_delays, 3);
+ } else if (ret == -ENOENT) {
+ ret = 0;
+ }
+
+ return ret;
}
static const struct udevice_id designware_eth_ids[] = {
@@ -675,7 +739,7 @@ U_BOOT_DRIVER(eth_designware) = {
.remove = designware_eth_remove,
.ops = &designware_eth_ops,
.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
- .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+ .platdata_auto_alloc_size = sizeof(struct dw_eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index ed6344cc28..04a45e0509 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -8,6 +8,8 @@
#ifndef _DW_ETH_H
#define _DW_ETH_H
+#include <asm/gpio.h>
+
#define CONFIG_TX_DESCR_NUM 16
#define CONFIG_RX_DESCR_NUM 16
#define CONFIG_ETH_BUFSIZE 2048
@@ -232,8 +234,16 @@ struct dw_eth_dev {
#ifndef CONFIG_DM_ETH
struct eth_device *dev;
#endif
+ struct gpio_desc reset_gpio;
struct phy_device *phydev;
struct mii_dev *bus;
};
+#ifdef CONFIG_DM_ETH
+struct dw_eth_pdata {
+ struct eth_pdata eth_pdata;
+ u32 reset_delays[3];
+};
+#endif
+
#endif