[net-next,PATCH v2 2/5] net: ethernet: stmmac: stm32: support the phy-supply regulator binding
Christophe Roullier <[email protected]>
| Newsgroups | org.kernel.vger.netdev,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Configure the phy regulator if defined by the "phy-supply" DT phandle. Signed-off-by: Christophe Roullier <[email protected]> --- .../net/ethernet/stmicro/stmmac/dwmac-stm32.c | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c index e1b260ed4790b..4597f605ec1bb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c @@ -14,6 +14,7 @@ #include <linux/of_net.h> #include <linux/phy.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <linux/pm_wakeirq.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -98,6 +99,7 @@ struct stm32_dwmac { u32 mode_reg; /* MAC glue-logic mode register */ u32 mode_mask; struct regmap *regmap; + struct regulator *regulator; u32 speed; const struct stm32_ops *ops; struct device *dev; @@ -423,6 +425,16 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, if (IS_ERR(dwmac->regmap)) return PTR_ERR(dwmac->regmap); + dwmac->regulator = devm_regulator_get_optional(dev, "phy"); + if (IS_ERR(dwmac->regulator)) { + if (PTR_ERR(dwmac->regulator) == -EPROBE_DEFER) { + dev_dbg(dev, "phy regulator is not available yet, deferred probing\n"); + return -EPROBE_DEFER; + } + dev_dbg(dev, "no regulator found\n"); + dwmac->regulator = NULL; + } + if (dwmac->ops->is_mp2) return 0; @@ -522,6 +534,27 @@ static int stm32_dwmac_resume(struct device *dev, void *bsp_priv) return stm32_dwmac_init(priv->plat); } +static int phy_power_on(struct stm32_dwmac *bsp_priv, bool enable) +{ + int ret; + struct device *dev = bsp_priv->dev; + + if (!bsp_priv->regulator) + return 0; + + if (enable) { + ret = regulator_enable(bsp_priv->regulator); + if (ret) + dev_err(dev, "fail to enable phy-supply\n"); + } else { + ret = regulator_disable(bsp_priv->regulator); + if (ret) + dev_err(dev, "fail to disable phy-supply\n"); + } + + return 0; +} + static int stm32_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; @@ -576,12 +609,18 @@ static int stm32_dwmac_probe(struct platform_device *pdev) goto err_clk_disable; } - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + ret = phy_power_on(plat_dat->bsp_priv, true); if (ret) goto err_clk_disable_suspend; + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + goto err_gmac_powerdown; + return 0; +err_gmac_powerdown: + phy_power_on(plat_dat->bsp_priv, false); err_clk_disable_suspend: if (dwmac->ops->clk_rx_enable_in_suspend) clk_disable_unprepare(dwmac->clk_rx); @@ -614,16 +653,26 @@ static void stm32_dwmac_remove(struct platform_device *pdev) dev_pm_clear_wake_irq(&pdev->dev); device_init_wakeup(&pdev->dev, false); } + + phy_power_on(priv->plat->bsp_priv, false); } static int stm32mp1_suspend(struct stm32_dwmac *dwmac) { + /* Keep the PHY up if we use Wake-on-Lan. */ + if (!device_may_wakeup(dwmac->dev)) + phy_power_on(dwmac, false); + return clk_prepare_enable(dwmac->clk_ethstp); } static void stm32mp1_resume(struct stm32_dwmac *dwmac) { clk_disable_unprepare(dwmac->clk_ethstp); + + /* The PHY was up for Wake-on-Lan. */ + if (!device_may_wakeup(dwmac->dev)) + phy_power_on(dwmac, true); } static struct stm32_ops stm32mcu_dwmac_data = { -- 2.43.0