Allwinner: linux: Fix patch for ethernet PHY regulators

This commit is contained in:
Jernej Skrabec 2023-12-17 10:55:30 +01:00
parent 1833aeed55
commit 5196c3da4d

View File

@ -1,21 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 25b44143ea8162209beb02759ca3ea3bd3be7a74 Mon Sep 17 00:00:00 2001
From: Corentin Labbe <clabbe.montjoie@gmail.com> From: Corentin Labbe <clabbe.montjoie@gmail.com>
Date: Fri, 14 Oct 2022 12:54:21 +0200 Date: Fri, 14 Oct 2022 12:54:21 +0200
Subject: [PATCH] phy: handle optional regulator for PHY Subject: [PATCH] phy: handle optional regulator for PHY
Add handling of optional regulators for PHY. Add handling of optional regulators for PHY.
Regulators need to be enabled before PHY scanning, so MDIO bus Regulators need to be enabled before PHY scanning, so MDIO bus
initiate this task. initiate this task.
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
--- ---
drivers/net/mdio/fwnode_mdio.c | 31 ++++++++++++++++++++++++++++++- drivers/net/mdio/fwnode_mdio.c | 53 ++++++++++++++++++++++++++++++++--
drivers/net/phy/phy_device.c | 13 +++++++++++++ drivers/net/phy/phy_device.c | 6 ++++
include/linux/phy.h | 3 +++ include/linux/phy.h | 3 ++
3 files changed, 46 insertions(+), 1 deletion(-) 3 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
index 1183ef5e203e..7ef42098df6e 100644 index fd02f5cbc853..bd5a27eaf40c 100644
--- a/drivers/net/mdio/fwnode_mdio.c --- a/drivers/net/mdio/fwnode_mdio.c
+++ b/drivers/net/mdio/fwnode_mdio.c +++ b/drivers/net/mdio/fwnode_mdio.c
@@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
@ -26,45 +28,81 @@ index 1183ef5e203e..7ef42098df6e 100644
MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>"); MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@@ -117,7 +118,9 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, @@ -58,6 +59,40 @@ fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
return register_mii_timestamper(arg.np, arg.args[0]);
}
+static int
+fwnode_regulator_get_bulk_enabled(struct device *dev,
+ struct fwnode_handle *fwnode,
+ struct regulator_bulk_data **consumers)
+{
+ struct device_node *np;
+ int ret, reg_cnt;
+
+ np = to_of_node(fwnode);
+ if (!np)
+ return 0;
+
+ reg_cnt = of_regulator_bulk_get_all(dev, np, consumers);
+ if (reg_cnt < 0) {
+ ret = reg_cnt;
+ goto clean_consumers;
+ }
+
+ if (reg_cnt == 0)
+ return 0;
+
+ ret = regulator_bulk_enable(reg_cnt, *consumers);
+ if (ret)
+ goto clean_consumers;
+
+ return reg_cnt;
+
+clean_consumers:
+ kfree(*consumers);
+ *consumers = NULL;
+
+ return ret;
+}
+
int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
struct phy_device *phy,
struct fwnode_handle *child, u32 addr)
@@ -113,12 +148,13 @@ EXPORT_SYMBOL(fwnode_mdiobus_phy_device_register);
int fwnode_mdiobus_register_phy(struct mii_bus *bus,
struct fwnode_handle *child, u32 addr)
{
+ struct regulator_bulk_data *consumers = NULL;
struct mii_timestamper *mii_ts = NULL;
struct pse_control *psec = NULL;
struct phy_device *phy; struct phy_device *phy;
+ int rc, reg_cnt;
bool is_c45; bool is_c45;
u32 phy_id; u32 phy_id;
- int rc; - int rc;
+ struct device_node __maybe_unused *nchild = NULL;
+ struct regulator_bulk_data *consumers = NULL;
+ int rc, reg_cnt = 0;
psec = fwnode_find_pse_control(child); psec = fwnode_find_pse_control(child);
if (IS_ERR(psec)) if (IS_ERR(psec))
@@ -129,6 +132,25 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, @@ -130,6 +166,12 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
goto clean_pse; goto clean_pse;
} }
+ for_each_child_of_node(bus->dev.of_node, nchild) { + reg_cnt = fwnode_regulator_get_bulk_enabled(&bus->dev, child, &consumers);
+ u32 reg; + if (reg_cnt < 0) {
+ + rc = reg_cnt;
+ of_property_read_u32(nchild, "reg", &reg); + goto clean_mii_ts;
+ if (reg != addr)
+ continue;
+ reg_cnt = of_regulator_bulk_get_all(&bus->dev, nchild, &consumers);
+ if (reg_cnt > 0) {
+ rc = regulator_bulk_enable(reg_cnt, consumers);
+ if (rc)
+ goto clean_kfree;
+ }
+ if (reg_cnt < 0) {
+ dev_err(&bus->dev, "Fail to regulator_bulk_get_all err=%d\n", reg_cnt);
+ rc = reg_cnt;
+ goto clean_kfree;
+ }
+ } + }
+ +
is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45");
if (is_c45 || fwnode_get_phy_id(child, &phy_id)) if (is_c45 || fwnode_get_phy_id(child, &phy_id))
phy = get_phy_device(bus, addr, is_c45); phy = get_phy_device(bus, addr, is_c45);
@@ -139,6 +161,9 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, @@ -137,9 +179,12 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
goto clean_mii_ts; phy = phy_device_create(bus, addr, phy_id, 0, NULL);
if (IS_ERR(phy)) {
rc = PTR_ERR(phy);
- goto clean_mii_ts;
+ goto clean_regulators;
} }
+ phy->regulator_cnt = reg_cnt; + phy->regulator_cnt = reg_cnt;
@ -73,67 +111,46 @@ index 1183ef5e203e..7ef42098df6e 100644
if (is_acpi_node(child)) { if (is_acpi_node(child)) {
phy->irq = bus->irq[addr]; phy->irq = bus->irq[addr];
@@ -178,6 +203,10 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, @@ -174,6 +219,10 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
clean_pse:
pse_control_put(psec);
clean_phy:
phy_device_free(phy);
+clean_regulators:
+ if (reg_cnt > 0) + if (reg_cnt > 0)
+ regulator_bulk_disable(reg_cnt, consumers); + regulator_bulk_disable(reg_cnt, consumers);
+clean_kfree:
+ kfree(consumers); + kfree(consumers);
return rc; clean_mii_ts:
} unregister_mii_timestamper(mii_ts);
EXPORT_SYMBOL(fwnode_mdiobus_register_phy); clean_pse:
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index c7cf61fe41cf..3bfe9bf6b3ac 100644 index 2ce74593d6e4..31b6913ceed1 100644
--- a/drivers/net/phy/phy_device.c --- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c
@@ -30,6 +30,7 @@ @@ -31,6 +31,7 @@
#include <linux/phy_led_triggers.h>
#include <linux/pse-pd/pse.h> #include <linux/pse-pd/pse.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/rtnetlink.h>
+#include <linux/regulator/consumer.h> +#include <linux/regulator/consumer.h>
#include <linux/rtnetlink.h>
#include <linux/sfp.h> #include <linux/sfp.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/slab.h> @@ -3400,6 +3401,11 @@ static int phy_remove(struct device *dev)
@@ -1871,6 +1872,9 @@ int phy_suspend(struct phy_device *phydev)
if (!ret) phydev->drv = NULL;
phydev->suspended = true;
+ if (phydev->regulator_cnt > 0) + if (phydev->regulator_cnt > 0)
+ regulator_bulk_disable(phydev->regulator_cnt, phydev->consumers); + regulator_bulk_disable(phydev->regulator_cnt, phydev->consumers);
+ +
return ret; + kfree(phydev->consumers);
}
EXPORT_SYMBOL(phy_suspend);
@@ -1897,6 +1901,12 @@ int phy_resume(struct phy_device *phydev)
{
int ret;
+ if (phydev->regulator_cnt > 0) {
+ ret = regulator_bulk_enable(phydev->regulator_cnt, phydev->consumers);
+ if (ret)
+ return ret;
+ }
+
mutex_lock(&phydev->lock);
ret = __phy_resume(phydev);
mutex_unlock(&phydev->lock);
@@ -3332,6 +3342,9 @@ static int phy_remove(struct device *dev)
phydev->drv = NULL;
+ if (phydev->consumers)
+ kfree(phydev->consumers);
+ +
return 0; return 0;
} }
diff --git a/include/linux/phy.h b/include/linux/phy.h diff --git a/include/linux/phy.h b/include/linux/phy.h
index 11c1e91563d4..2d058595d1a1 100644 index 3cc52826f18e..832cb2d4f76a 100644
--- a/include/linux/phy.h --- a/include/linux/phy.h
+++ b/include/linux/phy.h +++ b/include/linux/phy.h
@@ -752,6 +752,9 @@ struct phy_device { @@ -757,6 +757,9 @@ struct phy_device {
void (*phy_link_change)(struct phy_device *phydev, bool up); void (*phy_link_change)(struct phy_device *phydev, bool up);
void (*adjust_link)(struct net_device *dev); void (*adjust_link)(struct net_device *dev);
@ -143,3 +160,6 @@ index 11c1e91563d4..2d058595d1a1 100644
#if IS_ENABLED(CONFIG_MACSEC) #if IS_ENABLED(CONFIG_MACSEC)
/* MACsec management functions */ /* MACsec management functions */
const struct macsec_ops *macsec_ops; const struct macsec_ops *macsec_ops;
--
2.43.0