From 5196c3da4d9c659b6b92b8c45a148212f00d3ad5 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sun, 17 Dec 2023 10:55:30 +0100 Subject: [PATCH] Allwinner: linux: Fix patch for ethernet PHY regulators --- ...hy-handle-optional-regulator-for-PHY.patch | 156 ++++++++++-------- 1 file changed, 88 insertions(+), 68 deletions(-) diff --git a/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch b/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch index caf406b8ac..ed9cf3f055 100644 --- a/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch +++ b/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch @@ -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 Date: Fri, 14 Oct 2022 12:54:21 +0200 Subject: [PATCH] phy: handle optional regulator for PHY 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 +Signed-off-by: Jernej Skrabec --- - drivers/net/mdio/fwnode_mdio.c | 31 ++++++++++++++++++++++++++++++- - drivers/net/phy/phy_device.c | 13 +++++++++++++ - include/linux/phy.h | 3 +++ - 3 files changed, 46 insertions(+), 1 deletion(-) + drivers/net/mdio/fwnode_mdio.c | 53 ++++++++++++++++++++++++++++++++-- + drivers/net/phy/phy_device.c | 6 ++++ + include/linux/phy.h | 3 ++ + 3 files changed, 60 insertions(+), 2 deletions(-) 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 +++ b/drivers/net/mdio/fwnode_mdio.c @@ -11,6 +11,7 @@ @@ -26,45 +28,81 @@ index 1183ef5e203e..7ef42098df6e 100644 MODULE_AUTHOR("Calvin Johnson "); 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; ++ int rc, reg_cnt; bool is_c45; u32 phy_id; - 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); 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; } -+ for_each_child_of_node(bus->dev.of_node, nchild) { -+ u32 reg; -+ -+ of_property_read_u32(nchild, "reg", ®); -+ 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; -+ } ++ reg_cnt = fwnode_regulator_get_bulk_enabled(&bus->dev, child, &consumers); ++ if (reg_cnt < 0) { ++ rc = reg_cnt; ++ goto clean_mii_ts; + } + is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); if (is_c45 || fwnode_get_phy_id(child, &phy_id)) phy = get_phy_device(bus, addr, is_c45); -@@ -139,6 +161,9 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, - goto clean_mii_ts; +@@ -137,9 +179,12 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, + 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; @@ -73,67 +111,46 @@ index 1183ef5e203e..7ef42098df6e 100644 if (is_acpi_node(child)) { phy->irq = bus->irq[addr]; -@@ -178,6 +203,10 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, - clean_pse: - pse_control_put(psec); +@@ -174,6 +219,10 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, + clean_phy: + phy_device_free(phy); ++clean_regulators: + if (reg_cnt > 0) + regulator_bulk_disable(reg_cnt, consumers); -+clean_kfree: + kfree(consumers); - return rc; - } - EXPORT_SYMBOL(fwnode_mdiobus_register_phy); + clean_mii_ts: + unregister_mii_timestamper(mii_ts); + clean_pse: 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 +++ b/drivers/net/phy/phy_device.c -@@ -30,6 +30,7 @@ +@@ -31,6 +31,7 @@ + #include #include #include - #include +#include + #include #include #include - #include -@@ -1871,6 +1872,9 @@ int phy_suspend(struct phy_device *phydev) - if (!ret) - phydev->suspended = true; +@@ -3400,6 +3401,11 @@ static int phy_remove(struct device *dev) + + phydev->drv = NULL; + if (phydev->regulator_cnt > 0) + regulator_bulk_disable(phydev->regulator_cnt, phydev->consumers); + - return ret; - } - 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); ++ kfree(phydev->consumers); + return 0; } 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 +++ 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 (*adjust_link)(struct net_device *dev); @@ -143,3 +160,6 @@ index 11c1e91563d4..2d058595d1a1 100644 #if IS_ENABLED(CONFIG_MACSEC) /* MACsec management functions */ const struct macsec_ops *macsec_ops; +-- +2.43.0 +