我对icplus的修改(内核版本6.12.0):
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index a00a667454a9..411ca8fbb30e 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -21,6 +21,7 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/property.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -89,6 +90,7 @@ static struct ip101g_hw_stat ip101g_hw_stats[] = {
struct ip101a_g_phy_priv {
enum ip101gr_sel_intr32 sel_intr32;
u64 stats[ARRAY_SIZE(ip101g_hw_stats)];
+ struct clk *clk;
};
static int ip175c_config_init(struct phy_device *phydev)
@@ -210,6 +212,11 @@ static int ip101a_g_probe(struct phy_device *phydev)
if (!priv)
return -ENOMEM;
+ priv->clk = devm_clk_get_optional_enabled(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get phy clock\n");
+
/* Both functions (RX error and interrupt status) are sharing the same
* pin on the 32-pin IP101GR, so this is an exclusive choice.
*/
@@ -571,6 +578,33 @@ static void ip101g_get_stats(struct phy_device *phydev,
data[i] = ip101g_get_stat(phydev, i);
}
+static int ip101a_g_suspend(struct phy_device *phydev)
+{
+ struct ip101a_g_phy_priv *priv = phydev->priv;
+ int ret = 0;
+
+ if (!phydev->wol_enabled) {
+ ret = genphy_suspend(phydev);
+
+ if (ret)
+ return ret;
+
+ clk_disable_unprepare(priv->clk);
+ }
+
+ return ret;
+}
+
+static int ip101a_g_resume(struct phy_device *phydev)
+{
+ struct ip101a_g_phy_priv *priv = phydev->priv;
+
+ if (!phydev->wol_enabled)
++ clk_prepare_enable(priv->clk);
+
+ return genphy_resume(phydev);
+}
+
static struct phy_driver icplus_driver[] = {
{
PHY_ID_MATCH_MODEL(IP175C_PHY_ID),
@@ -601,8 +635,9 @@ static struct phy_driver icplus_driver[] = {
.config_aneg = ip101a_g_config_aneg,
.read_status = ip101a_g_read_status,
.soft_reset = genphy_soft_reset,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
+ .suspend = ip101a_g_suspend,
+ .resume = ip101a_g_resume,
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
}, {
.name = "ICPlus IP101G",
.match_phy_device = ip101g_match_phy_device,
@@ -618,8 +653,9 @@ static struct phy_driver icplus_driver[] = {
.get_sset_count = ip101g_get_sset_count,
.get_strings = ip101g_get_strings,
.get_stats = ip101g_get_stats,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
+ .suspend = ip101a_g_suspend,
+ .resume = ip101a_g_resume,
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
} };
module_phy_driver(icplus_driver);
&emac {
pinctrl-names = "default";
pinctrl-0 = <&rmii_pg_pins>;
phy-mode = "rmii";
phy-handle = <&phy1>;
phy-supply = <®_vcc3v3>;
status = "okay";
};
&mdio {
status = "okay";
phy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
reset-gpios = <&pio 6 6 GPIO_ACTIVE_LOW>; /* PG6 */
reset-assert-us = <5000>;
reset-deassert-us = <5000>;
clocks = <&ccu CLK_EMAC_25M>;
};
};