From 90b7fc924adfe7f1745dcf6a1dabb9e77aa762a7 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sun, 28 Feb 2016 22:24:55 +0100 Subject: 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 Reviewed-by: Simon Glass --- drivers/net/designware.c | 76 ++++++++++++++++++++++++++++++++++++++++++++---- drivers/net/designware.h | 10 +++++++ 2 files changed, 80 insertions(+), 6 deletions(-) (limited to 'drivers') 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 + #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 -- cgit v1.2.1 From 70f7a2cdac6a7f75f27848d689a13ca244b0792b Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sun, 28 Feb 2016 22:24:58 +0100 Subject: rockchip: rk3288: pinctrl: support more pins The rgmii_pins node in rk3288.dtsi configures 15 pins. Increase the size of the cell array to accomedate that, otherwise only the first 10 get configured. Signed-off-by: Sjoerd Simons Reviewed-by: Simon Glass --- drivers/pinctrl/rockchip/pinctrl_rk3288.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c index 7c769bdb01..1fa1daa939 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3288.c +++ b/drivers/pinctrl/rockchip/pinctrl_rk3288.c @@ -623,7 +623,7 @@ static int rk3288_pinctrl_set_state(struct udevice *dev, struct udevice *config) { const void *blob = gd->fdt_blob; int pcfg_node, ret, flags, count, i; - u32 cell[40], *ptr; + u32 cell[60], *ptr; debug("%s: %s %s\n", __func__, dev->name, config->name); ret = fdtdec_get_int_array_count(blob, config->of_offset, -- cgit v1.2.1 From 0aefc0b0c7eba963c88eca893a546f3e786615ac Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sun, 28 Feb 2016 22:24:59 +0100 Subject: rockchip: rk3288: Add clock support for the gmac ethernet interface Setup the clocks for the gmac ethernet interface. This assumes the mac clock is fed by an external clock which is common on RK3288 based devices. Signed-off-by: Sjoerd Simons Reviewed-by: Simon Glass --- drivers/clk/clk_rk3288.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c index 2a85e93a6c..a110a1c160 100644 --- a/drivers/clk/clk_rk3288.c +++ b/drivers/clk/clk_rk3288.c @@ -326,6 +326,17 @@ static int pll_para_config(ulong freq_hz, struct pll_div *div, uint *ext_div) return 0; } +static int rockchip_mac_set_clk(struct rk3288_cru *cru, + int periph, uint freq) +{ + /* Assuming mac_clk is fed by an external clock */ + rk_clrsetreg(&cru->cru_clksel_con[21], + RMII_EXTCLK_MASK << RMII_EXTCLK_SHIFT, + RMII_EXTCLK_SELECT_EXT_CLK << RMII_EXTCLK_SHIFT); + + return 0; +} + static int rockchip_vop_set_clk(struct rk3288_cru *cru, struct rk3288_grf *grf, int periph, unsigned int rate_hz) { @@ -759,6 +770,9 @@ static ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate) new_rate = rockchip_spi_set_clk(cru, gclk_rate, periph, rate); break; #ifndef CONFIG_SPL_BUILD + case SCLK_MAC: + new_rate = rockchip_mac_set_clk(priv->cru, periph, rate); + break; case DCLK_VOP0: case DCLK_VOP1: new_rate = rockchip_vop_set_clk(cru, priv->grf, periph, rate); -- cgit v1.2.1