}
#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)
{
/*
}
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))