[PATCH net-next v2 02/14] net: phy: qcom: qca808x: Add regulator management

From: Alex Elder

Date: Thu Jun 04 2026 - 21:08:32 EST


From: Daniel Thompson <daniel@xxxxxxxxxxxx>

QCA8081 appears in embedded board designs paired with GPIO controlled
regulators for its power rails. Add logic to allow these regulators to
be turned on during a probe.

In order to avoid the complexity of tracking state for suspend with and
without WoL we take a tremendously simple "always-on" approach to
regulator management, essentially relying on BMCR_PDOWN to conserve
power when the phy device exists.

Signed-off-by: Daniel Thompson <daniel@xxxxxxxxxxxx>
Signed-off-by: Alex Elder <elder@xxxxxxxxxxxx>
---
drivers/net/phy/qcom/qca808x.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/drivers/net/phy/qcom/qca808x.c b/drivers/net/phy/qcom/qca808x.c
index 8eb51b1a006c4..fc3f2cf2e55d0 100644
--- a/drivers/net/phy/qcom/qca808x.c
+++ b/drivers/net/phy/qcom/qca808x.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+

#include <linux/phy.h>
+#include <linux/regulator/consumer.h>
#include <linux/module.h>

#include "qcom.h"
@@ -178,15 +179,44 @@ static void qca808x_fill_possible_interfaces(struct phy_device *phydev)
__set_bit(PHY_INTERFACE_MODE_2500BASEX, possible);
}

+static int qca808x_power_on(struct phy_device *phydev)
+{
+#ifdef CONFIG_OF
+ static const char * const regulator_names[] = {
+ "avdd18", "vdd", "vdd18", "vdd125"
+ };
+ struct device *dev = &phydev->mdio.dev;
+ u32 count = 0;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(regulator_names); i++) {
+ ret = devm_regulator_get_enable_optional(dev, regulator_names[i]);
+ if (!ret)
+ count++;
+ else if (ret != -ENODEV)
+ return ret;
+ }
+
+ if (count)
+ fsleep(phydev->mdio.reset_assert_delay);
+#endif
+ return 0;
+}
+
static int qca808x_probe(struct phy_device *phydev)
{
struct device *dev = &phydev->mdio.dev;
struct qca808x_priv *priv;
+ int ret;

priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

+ ret = qca808x_power_on(phydev);
+ if (ret)
+ return ret;
+
/* Init LED polarity mode to -1 */
priv->led_polarity_mode = -1;

--
2.51.0