[PATCH net-next 1/3] net: phy: add phy_reset_after_power_on() function

Philippe Schenker
2021-12-14T12:17:03Z

Some PHY requires a reset after being powered on (e.g. KSZ9131), add a
new function and related PHY_RST_AFTER_POWER_ON phy flag to be called
after the PHY regulator is enabled.

Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
---

drivers/net/phy/phy_device.c | 24 ++++++++++++++++++++++++
include/linux/phy.h | 2 ++
2 files changed, 26 insertions(+)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 74d8e1dc125f..bad836a7ee01 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1878,6 +1878,30 @@ int phy_reset_after_clk_enable(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_reset_after_clk_enable);

+/**
+ * phy_reset_after_power_on - perform a PHY reset if needed
+ * @phydev: target phy_device struct
+ *
+ * Description: Some PHYs or hardware design, need a reset after power was
+ * enabled and rely on that software reset. This function evaluates the flags
+ * and perform the reset if it's needed.
+ * Returns < 0 on error, 0 if the phy wasn't reset and 1 if the phy was reset.
+ */
+int phy_reset_after_power_on(struct phy_device *phydev)
+{
+ if (!phydev || !phydev->drv)
+ return -ENODEV;
+
+ if (phydev->drv->flags & PHY_RST_AFTER_POWER_ON) {
+ phy_device_reset(phydev, 1);
+ phy_device_reset(phydev, 0);
+ return 1;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_reset_after_power_on);
+
/* Generic PHY support and helper functions */

/**
diff --git a/include/linux/phy.h b/include/linux/phy.h
index cbf03a5f9cf5..0d88cdc97dbd 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -80,6 +80,7 @@ extern const int phy_10gbit_features_array[1];
#define PHY_IS_INTERNAL 0x00000001
#define PHY_RST_AFTER_CLK_EN 0x00000002
#define PHY_POLL_CABLE_TEST 0x00000004
+#define PHY_RST_AFTER_POWER_ON 0x00000008
#define MDIO_DEVICE_IS_PHY 0x80000000

/**
@@ -1499,6 +1500,7 @@ int phy_speed_up(struct phy_device *phydev);

int phy_restart_aneg(struct phy_device *phydev);
int phy_reset_after_clk_enable(struct phy_device *phydev);
+int phy_reset_after_power_on(struct phy_device *phydev);

#if IS_ENABLED(CONFIG_PHYLIB)
int phy_start_cable_test(struct phy_device *phydev,
--
2.34.1