From: Josep Orga Date: Mon, 6 May 2019 08:45:17 +0000 (+0200) Subject: Enable PHY reset line when the fec is probed X-Git-Tag: C0P2-H0.0--20200415~24 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=6c9ec1de7d18e5cd0a719bcd835b11566e532dd4;p=linux.git Enable PHY reset line when the fec is probed Based on: https://github.com/digi-embedded/linux/commit/f0ddbc0153b269bfd21b84dbd4ad16acdfd21f29#diff-28c0935b4b5bf1738a0ee788d25a18ff Signed-off-by: Josep Orga --- diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 71d6222c5273..df0c1d66ca9e 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -582,6 +582,9 @@ struct fec_enet_private { int wake_irq; u32 quirks; u32 fixups; + int phy_reset_gpio; + u32 phy_reset_duration; + bool active_high; struct napi_struct napi; int csum_flags; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 6ab85fdf32eb..3482309bc990 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3458,47 +3458,74 @@ static int fec_enet_init(struct net_device *ndev) } #ifdef CONFIG_OF -static int fec_reset_phy(struct platform_device *pdev) +static int fec_reset_phy_init(struct platform_device *pdev) { - int err, phy_reset; - bool active_high = false; - int msec = 1; + int err; struct device_node *np = pdev->dev.of_node; + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); if (!np) return 0; - err = of_property_read_u32(np, "phy-reset-duration", &msec); + err = of_property_read_u32(np, "phy-reset-duration", &fep->phy_reset_duration); /* A sane reset duration should not be longer than 1s */ - if (!err && msec > 1000) - msec = 1; - - phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); - if (phy_reset == -EPROBE_DEFER) - return phy_reset; - else if (!gpio_is_valid(phy_reset)) + if (!err && fep->phy_reset_duration > 1000) + fep->phy_reset_duration = 1; + + fep->phy_reset_gpio = of_get_named_gpio(np, "phy-reset-gpios", 0); + if (fep->phy_reset_gpio == -EPROBE_DEFER) + return fep->phy_reset_gpio; + else if (!gpio_is_valid(fep->phy_reset_gpio)) { + fep->phy_reset_gpio = -1; return 0; + } - active_high = of_property_read_bool(np, "phy-reset-active-high"); + fep->active_high = of_property_read_bool(np, "phy-reset-active-high"); - err = devm_gpio_request_one(&pdev->dev, phy_reset, - active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, + err = devm_gpio_request_one(&pdev->dev, fep->phy_reset_gpio, + fep->active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, "phy-reset"); if (err) { dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err); return err; } - - if (msec > 20) - msleep(msec); + /* Enable PHY and wait for stabilization */ + gpio_set_value_cansleep(fep->phy_reset_gpio, !fep->active_high); + if (fep->phy_reset_duration < 20) + msleep(20); else - usleep_range(msec * 1000, msec * 1000 + 1000); + msleep(fep->phy_reset_duration); + return 0; +} - gpio_set_value_cansleep(phy_reset, !active_high); +static int fec_reset_phy(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + if (fep->phy_reset_gpio < 0) + return 0; + + gpio_set_value_cansleep(fep->phy_reset_gpio, fep->active_high); + if (fep->phy_reset_duration > 20) + msleep(fep->phy_reset_duration); + else + usleep_range(fep->phy_reset_duration * 1000, fep->phy_reset_duration * 1000 + 1000); + gpio_set_value_cansleep(fep->phy_reset_gpio, !fep->active_high); return 0; } + #else /* CONFIG_OF */ +static int fec_reset_phy_init(struct platform_device *pdev) +{ + /* + * In case of platform probe, the reset has been done + * by machine code. + */ + return 0; +} + static int fec_reset_phy(struct platform_device *pdev) { /* @@ -3689,6 +3716,9 @@ fec_probe(struct platform_device *pdev) } fep->itr_clk_rate = clk_get_rate(fep->clk_ahb); + /* Enable reset PHY line */ + fec_reset_phy_init(pdev); + /* enet_out is optional, depends on board */ fep->clk_enet_out = devm_clk_get(&pdev->dev, "enet_out"); if (IS_ERR(fep->clk_enet_out))