diff mbox series

[1/6] phy: handle optional regulator for PHY

Message ID 20220509074857.195302-2-clabbe@baylibre.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series arm64: add ethernet to orange pi 3 | expand

Checks

Context Check Description
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 416 this patch: 416
netdev/cc_maintainers success CCed 10 of 10 maintainers
netdev/build_clang success Errors and warnings before: 297 this patch: 297
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 401 this patch: 401
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 103 lines checked
netdev/kdoc fail Errors and warnings before: 0 this patch: 2
netdev/source_inline success Was 0 now: 0
netdev/tree_selection success Guessing tree name failed - patch did not apply

Commit Message

Corentin LABBE May 9, 2022, 7:48 a.m. UTC
Add handling of optional regulators for PHY.
Regulators need to be enabled before PHY scanning, so MDIO bus
initiate this task.

Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
---
 drivers/net/mdio/fwnode_mdio.c | 32 ++++++++++++++++++++++++++++++++
 drivers/net/phy/phy_device.c   | 20 ++++++++++++++++++++
 include/linux/phy.h            |  3 +++
 3 files changed, 55 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
index 1c1584fca632..c377cadc14c3 100644
--- a/drivers/net/mdio/fwnode_mdio.c
+++ b/drivers/net/mdio/fwnode_mdio.c
@@ -10,6 +10,7 @@ 
 #include <linux/fwnode_mdio.h>
 #include <linux/of.h>
 #include <linux/phy.h>
+#include <linux/regulator/consumer.h>
 
 MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
 MODULE_LICENSE("GPL");
@@ -95,6 +96,8 @@  int fwnode_mdiobus_register_phy(struct mii_bus *bus,
 	bool is_c45 = false;
 	u32 phy_id;
 	int rc;
+	struct regulator *regulator_phy;
+	struct regulator *regulator_phy_io;
 
 	mii_ts = fwnode_find_mii_timestamper(child);
 	if (IS_ERR(mii_ts))
@@ -104,6 +107,32 @@  int fwnode_mdiobus_register_phy(struct mii_bus *bus,
 					  "ethernet-phy-ieee802.3-c45");
 	if (rc >= 0)
 		is_c45 = true;
+	regulator_phy_io = devm_regulator_get_optional(&bus->dev, "phy-io");
+	if (IS_ERR(regulator_phy_io)) {
+		rc = PTR_ERR(regulator_phy_io);
+		if (rc == -ENODEV)
+			regulator_phy_io = NULL;
+		else
+			return rc;
+	}
+	regulator_phy = devm_regulator_get_optional(&bus->dev, "phy");
+	if (IS_ERR(regulator_phy)) {
+		rc = PTR_ERR(regulator_phy);
+		if (rc == -ENODEV)
+			regulator_phy = NULL;
+		else
+			return rc;
+	}
+	if (regulator_phy_io) {
+		rc = regulator_enable(regulator_phy_io);
+		if (rc)
+			return rc;
+	}
+	if (regulator_phy) {
+		rc = regulator_enable(regulator_phy);
+		if (rc)
+			return rc;
+	}
 
 	if (is_c45 || fwnode_get_phy_id(child, &phy_id))
 		phy = get_phy_device(bus, addr, is_c45);
@@ -114,6 +143,9 @@  int fwnode_mdiobus_register_phy(struct mii_bus *bus,
 		return PTR_ERR(phy);
 	}
 
+	phy->regulator_phy = regulator_phy;
+	phy->regulator_phy_io = regulator_phy_io;
+
 	if (is_acpi_node(child)) {
 		phy->irq = bus->irq[addr];
 
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 431a8719c635..ce64df596580 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -27,6 +27,7 @@ 
 #include <linux/phy.h>
 #include <linux/phy_led_triggers.h>
 #include <linux/property.h>
+#include <linux/regulator/consumer.h>
 #include <linux/sfp.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
@@ -1785,6 +1786,11 @@  int phy_suspend(struct phy_device *phydev)
 	if (!ret)
 		phydev->suspended = true;
 
+	if (phydev->regulator_phy)
+		regulator_disable(phydev->regulator_phy);
+	if (phydev->regulator_phy_io)
+		regulator_disable(phydev->regulator_phy_io);
+
 	return ret;
 }
 EXPORT_SYMBOL(phy_suspend);
@@ -1811,6 +1817,20 @@  int phy_resume(struct phy_device *phydev)
 {
 	int ret;
 
+	if (phydev->regulator_phy_io) {
+		ret = regulator_enable(phydev->regulator_phy_io);
+		if (ret)
+			return ret;
+	}
+	if (phydev->regulator_phy) {
+		ret = regulator_enable(phydev->regulator_phy);
+		if (ret) {
+			if (phydev->regulator_phy_io)
+				regulator_disable(phydev->regulator_phy_io);
+			return ret;
+		}
+	}
+
 	mutex_lock(&phydev->lock);
 	ret = __phy_resume(phydev);
 	mutex_unlock(&phydev->lock);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 2d12054932ba..c29f45668d94 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -704,6 +704,9 @@  struct phy_device {
 	void (*phy_link_change)(struct phy_device *phydev, bool up);
 	void (*adjust_link)(struct net_device *dev);
 
+	struct regulator *regulator_phy;
+	struct regulator *regulator_phy_io;
+
 #if IS_ENABLED(CONFIG_MACSEC)
 	/* MACsec management functions */
 	const struct macsec_ops *macsec_ops;