diff mbox series

[14/15] net: phy: add PHY regulator support

Message ID 20200622093744.13685-15-brgl@bgdev.pl
State New
Headers show
Series net: phy: correctly model the PHY voltage supply in DT | expand

Commit Message

Bartosz Golaszewski June 22, 2020, 9:37 a.m. UTC
From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

The MDIO sub-system now supports PHY regulators. Let's reuse the code
to extend this support over to the PHY device.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/net/phy/phy_device.c | 49 ++++++++++++++++++++++++++++--------
 include/linux/phy.h          | 10 ++++++++
 2 files changed, 48 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 58923826838b..d755adb748a5 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -827,7 +827,12 @@  int phy_device_register(struct phy_device *phydev)
 
 	err = mdiobus_register_device(&phydev->mdio);
 	if (err)
-		return err;
+		goto err_out;
+
+	/* Enable the PHY regulator */
+	err = phy_device_power_on(phydev);
+	if (err)
+		goto err_unregister_mdio;
 
 	/* Deassert the reset signal */
 	phy_device_reset(phydev, 0);
@@ -846,22 +851,25 @@  int phy_device_register(struct phy_device *phydev)
 	err = phy_scan_fixups(phydev);
 	if (err) {
 		phydev_err(phydev, "failed to initialize\n");
-		goto out;
+		goto err_reset;
 	}
 
 	err = device_add(&phydev->mdio.dev);
 	if (err) {
 		phydev_err(phydev, "failed to add\n");
-		goto out;
+		goto err_reset;
 	}
 
 	return 0;
 
- out:
+err_reset:
 	/* Assert the reset signal */
 	phy_device_reset(phydev, 1);
-
+	/* Disable the PHY regulator */
+	phy_device_power_off(phydev);
+err_unregister_mdio:
 	mdiobus_unregister_device(&phydev->mdio);
+err_out:
 	return err;
 }
 EXPORT_SYMBOL(phy_device_register);
@@ -883,6 +891,8 @@  void phy_device_remove(struct phy_device *phydev)
 
 	/* Assert the reset signal */
 	phy_device_reset(phydev, 1);
+	/* Disable the PHY regulator */
+	phy_device_power_off(phydev);
 
 	mdiobus_unregister_device(&phydev->mdio);
 }
@@ -1064,6 +1074,11 @@  int phy_init_hw(struct phy_device *phydev)
 {
 	int ret = 0;
 
+	/* Enable the PHY regulator */
+	ret = phy_device_power_on(phydev);
+	if (ret)
+		return ret;
+
 	/* Deassert the reset signal */
 	phy_device_reset(phydev, 0);
 
@@ -1644,6 +1659,8 @@  void phy_detach(struct phy_device *phydev)
 
 	/* Assert the reset signal */
 	phy_device_reset(phydev, 1);
+	/* Disable the PHY regulator */
+	phy_device_power_off(phydev);
 }
 EXPORT_SYMBOL(phy_detach);
 
@@ -2684,13 +2701,18 @@  static int phy_probe(struct device *dev)
 
 	mutex_lock(&phydev->lock);
 
+	/* Enable the PHY regulator */
+	err = phy_device_power_on(phydev);
+	if (err)
+		goto out;
+
 	/* Deassert the reset signal */
 	phy_device_reset(phydev, 0);
 
 	if (phydev->drv->probe) {
 		err = phydev->drv->probe(phydev);
 		if (err)
-			goto out;
+			goto out_reset;
 	}
 
 	/* Start out supporting everything. Eventually,
@@ -2708,7 +2730,7 @@  static int phy_probe(struct device *dev)
 	}
 
 	if (err)
-		goto out;
+		goto out_reset;
 
 	if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 			       phydev->supported))
@@ -2751,11 +2773,16 @@  static int phy_probe(struct device *dev)
 	/* Set the state to READY by default */
 	phydev->state = PHY_READY;
 
-out:
-	/* Assert the reset signal */
-	if (err)
-		phy_device_reset(phydev, 1);
+	mutex_unlock(&phydev->lock);
+
+	return 0;
 
+out_reset:
+	/* Assert the reset signal */
+	phy_device_reset(phydev, 1);
+	/* Disable the PHY regulator */
+	phy_device_power_off(phydev);
+out:
 	mutex_unlock(&phydev->lock);
 
 	return err;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 01d24a934ad1..585ce8db32cf 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1291,6 +1291,16 @@  static inline void phy_device_reset(struct phy_device *phydev, int value)
 	mdio_device_reset(&phydev->mdio, value);
 }
 
+static inline int phy_device_power_on(struct phy_device *phydev)
+{
+	return mdio_device_power_on(&phydev->mdio);
+}
+
+static inline int phy_device_power_off(struct phy_device *phydev)
+{
+	return mdio_device_power_off(&phydev->mdio);
+}
+
 #define phydev_err(_phydev, format, args...)	\
 	dev_err(&_phydev->mdio.dev, format, ##args)