airoha: add pending patch to fix Aeonsemi AS21xxx PHY

Add pending patch to make address some workaround needed to make the
Aeonsemi AS21xxx PHY working on the Airoha AN7581/AN7583 board.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
Christian Marangi 2025-10-24 11:51:40 +02:00
parent 26da4bf552
commit 927fe598db
No known key found for this signature in database
GPG key ID: AC001D09ADBFEAD7
6 changed files with 590 additions and 0 deletions

View file

@ -0,0 +1,129 @@
From f2c6f8711c3866caafee997cfa60af4f38879be0 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Wed, 25 Jun 2025 00:45:11 +0200
Subject: [PATCH 1/2] net: phy: add PHY_DETACH_NO_HW_RESET PHY flag
Some PHY require a firmware to correctly work and such firmware might
get reset when the GPIO reset is assert.
This is the case for the Aeonsemi PHY where when the PHY is torn down,
phy_detach() is called that assert the GPIO reset pin resetting the
firmware.
To handle this introduce a flag, PHY_DETACH_NO_HW_RESET that instruct
phy_detach() to skip asserting the GPIO reset on detaching the PHY.
The PHY is still reset in all other case where it's removed or the PHY
fails to probe.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/as21xxx.c | 10 ++++++++++
drivers/net/phy/phy_device.c | 3 ++-
include/linux/phy.h | 1 +
3 files changed, 13 insertions(+), 1 deletion(-)
--- a/drivers/net/phy/as21xxx.c
+++ b/drivers/net/phy/as21xxx.c
@@ -964,6 +964,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
@@ -976,6 +977,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
@@ -988,6 +990,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
@@ -1000,6 +1003,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
@@ -1012,6 +1016,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
@@ -1024,6 +1029,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
@@ -1036,6 +1042,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
@@ -1048,6 +1055,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
@@ -1060,6 +1068,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
@@ -1072,6 +1081,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
+ .flags = PHY_DETACH_NO_RESET,
},
};
module_phy_driver(as21xxx_drivers);
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2074,7 +2074,8 @@ void phy_detach(struct phy_device *phyde
device_release_driver(&phydev->mdio.dev);
/* Assert the reset signal */
- phy_device_reset(phydev, 1);
+ if (!(phydev->drv->flags & PHY_DETACH_NO_HW_RESET))
+ phy_device_reset(phydev, 1);
/*
* The phydev might go away on the put_device() below, so avoid
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -90,6 +90,7 @@ extern const int phy_10gbit_features_arr
#define PHY_RST_AFTER_CLK_EN 0x00000002
#define PHY_POLL_CABLE_TEST 0x00000004
#define PHY_ALWAYS_CALL_SUSPEND 0x00000008
+#define PHY_DETACH_NO_HW_RESET 0x00000010
#define MDIO_DEVICE_IS_PHY 0x80000000
/**

View file

@ -0,0 +1,108 @@
From 7ad1470c3d08c1abea747aa0c789e924f63fcbc4 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Wed, 25 Jun 2025 00:51:45 +0200
Subject: [PATCH 2/2] net: phy: as21xxx: add flag PHY_DETACH_NO_HW_RESET
Add flag PHY_DETACH_NO_HW_RESET to handle firmware getting reset on
calling phy_detach() if the GPIO reset PIN is defined in DT.
This will skip the firmware from getting reset permitting the PHY to
continue work when the PHY is torn down and gets up again.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/as21xxx.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/net/phy/as21xxx.c
+++ b/drivers/net/phy/as21xxx.c
@@ -964,7 +964,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
@@ -977,7 +977,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
@@ -990,7 +990,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
@@ -1003,7 +1003,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
@@ -1016,7 +1016,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
@@ -1029,7 +1029,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
@@ -1042,7 +1042,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
@@ -1055,7 +1055,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
@@ -1068,7 +1068,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
@@ -1081,7 +1081,7 @@ static struct phy_driver as21xxx_drivers
.led_hw_control_set = as21xxx_led_hw_control_set,
.led_hw_control_get = as21xxx_led_hw_control_get,
.led_polarity_set = as21xxx_led_polarity_set,
- .flags = PHY_DETACH_NO_RESET,
+ .flags = PHY_DETACH_NO_HW_RESET,
},
};
module_phy_driver(as21xxx_drivers);

View file

@ -0,0 +1,31 @@
From 0146a02d9d182796c3d8e4a432c4d94cac042f8e Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Mon, 7 Jul 2025 18:58:25 +0200
Subject: [PATCH 1/4] net: phy: as21xxx: handle corner case with link and
autoneg complete
Add missing case in custom read_link, when autoneg is started, autoneg
complete bit is reset but link is still not up.
Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs")
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/as21xxx.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/net/phy/as21xxx.c
+++ b/drivers/net/phy/as21xxx.c
@@ -658,6 +658,13 @@ static int as21xxx_read_link(struct phy_
return status;
phydev->link = !!(status & MDIO_STAT1_LSTATUS);
+ phydev->autoneg_complete = !!(status & MDIO_AN_STAT1_COMPLETE);
+
+ /* Consider the case that autoneg was started and "aneg complete"
+ * bit has been reset, but "link up" bit not yet.
+ */
+ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
+ phydev->link = 0;
return 0;
}

View file

@ -0,0 +1,156 @@
From d90186b1e48dd4a428abf889b1eb17d2469de08b Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 8 Jul 2025 10:50:42 +0200
Subject: [PATCH 2/4] net: phy: as21xxx: fix read_status speed handling
With further test with 2.5G NIC it was discovered that
phy_resolve_aneg_linkmode is not enough to detect speed higher that 1G
when autoneg is enabled.
Also in the switch case there is a typo where the speed mask is AND with
VEND1_SPEED_STATUS instead of the correct mask VEND1_SPEED_MASK.
Rework the read_status code to always read the speed from the vendor
register and parse the generic bit only for the pause frame.
Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs")
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/as21xxx.c | 96 +++++++++++++++++++++------------------
1 file changed, 53 insertions(+), 43 deletions(-)
--- a/drivers/net/phy/as21xxx.c
+++ b/drivers/net/phy/as21xxx.c
@@ -671,7 +671,7 @@ static int as21xxx_read_link(struct phy_
static int as21xxx_read_c22_lpa(struct phy_device *phydev)
{
- int lpagb;
+ int lpagb, lpa;
/* MII_STAT1000 are only filled in the mapped C22
* in C45, use that to fill lpagb values and check.
@@ -698,12 +698,20 @@ static int as21xxx_read_c22_lpa(struct p
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
lpagb);
+ lpa = phy_read_mmd(phydev, MDIO_MMD_AN,
+ AS21XXX_MDIO_AN_C22 + MII_LPA);
+ if (lpa < 0)
+ return lpa;
+
+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa);
+
return 0;
}
static int as21xxx_read_status(struct phy_device *phydev)
{
int bmcr, old_link = phydev->link;
+ int speed;
int ret;
ret = as21xxx_read_link(phydev, &bmcr);
@@ -720,58 +728,60 @@ static int as21xxx_read_status(struct ph
phydev->asym_pause = 0;
if (phydev->autoneg == AUTONEG_ENABLE) {
- ret = genphy_c45_read_lpa(phydev);
- if (ret)
- return ret;
+ if (!phydev->autoneg_complete) {
+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
+ 0);
+ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
+ return 0;
+ }
ret = as21xxx_read_c22_lpa(phydev);
if (ret)
return ret;
-
- phy_resolve_aneg_linkmode(phydev);
} else {
- int speed;
-
linkmode_zero(phydev->lp_advertising);
+ }
- speed = phy_read_mmd(phydev, MDIO_MMD_VEND1,
- VEND1_SPEED_STATUS);
- if (speed < 0)
- return speed;
-
- switch (speed & VEND1_SPEED_STATUS) {
- case VEND1_SPEED_10000:
- phydev->speed = SPEED_10000;
+ speed = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_SPEED_STATUS);
+ if (speed < 0)
+ return speed;
+
+ switch (speed & VEND1_SPEED_MASK) {
+ case VEND1_SPEED_10000:
+ phydev->speed = SPEED_10000;
+ phydev->duplex = DUPLEX_FULL;
+ break;
+ case VEND1_SPEED_5000:
+ phydev->speed = SPEED_5000;
+ phydev->duplex = DUPLEX_FULL;
+ break;
+ case VEND1_SPEED_2500:
+ phydev->speed = SPEED_2500;
+ phydev->duplex = DUPLEX_FULL;
+ break;
+ case VEND1_SPEED_1000:
+ phydev->speed = SPEED_1000;
+ if (bmcr & BMCR_FULLDPLX)
phydev->duplex = DUPLEX_FULL;
- break;
- case VEND1_SPEED_5000:
- phydev->speed = SPEED_5000;
- phydev->duplex = DUPLEX_FULL;
- break;
- case VEND1_SPEED_2500:
- phydev->speed = SPEED_2500;
- phydev->duplex = DUPLEX_FULL;
- break;
- case VEND1_SPEED_1000:
- phydev->speed = SPEED_1000;
- if (bmcr & BMCR_FULLDPLX)
- phydev->duplex = DUPLEX_FULL;
- else
- phydev->duplex = DUPLEX_HALF;
- break;
- case VEND1_SPEED_100:
- phydev->speed = SPEED_100;
- phydev->duplex = DUPLEX_FULL;
- break;
- case VEND1_SPEED_10:
- phydev->speed = SPEED_10;
- phydev->duplex = DUPLEX_FULL;
- break;
- default:
- return -EINVAL;
- }
+ else
+ phydev->duplex = DUPLEX_HALF;
+ break;
+ case VEND1_SPEED_100:
+ phydev->speed = SPEED_100;
+ phydev->duplex = DUPLEX_FULL;
+ break;
+ case VEND1_SPEED_10:
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_FULL;
+ break;
+ default:
+ return -EINVAL;
}
+ if (phydev->autoneg == AUTONEG_ENABLE)
+ phy_resolve_aneg_pause(phydev);
+
return 0;
}

View file

@ -0,0 +1,34 @@
From 6003da596beb6b8974e61b7ff494476a323fbef5 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 8 Jul 2025 11:29:49 +0200
Subject: [PATCH 3/4] net: phy: as21xxx: force C45 OPs for AUTONEG
With further testing with 2.5G NIC, it was discovered that the PHY
require the C45 OPs to configure and restart ANEG or speed higher than
1G doesn't function correctly.
To force C45 OPs with generic PHY function, clear the C22 bit from
devices_in_package bitmask.
Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs")
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/as21xxx.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/net/phy/as21xxx.c
+++ b/drivers/net/phy/as21xxx.c
@@ -616,6 +616,13 @@ static int as21xxx_probe(struct phy_devi
if (ret)
return ret;
+ /* Even if PHY declare support for Clause 22 register,
+ * Clause 45 register should be used for ANEG configuration
+ * and restart. Clear the C22 bit for devices_in_package to
+ * force C45 generic OPs in generic PHY ANGE OPs.
+ */
+ phydev->c45_ids.devices_in_package &= ~BIT(0);
+
ret = aeon_ipc_sync_parity(phydev, priv);
if (ret)
return ret;

View file

@ -0,0 +1,132 @@
From fabaa8a7183d10217e14af437fd3805bd6dd9eba Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Sat, 18 Oct 2025 04:12:41 +0200
Subject: [PATCH] net: phy: as21xxx: implement read workaround for C45 read
This PHY have lots of problems with MDIO read operation. We somehow
workaround this with using C45 operation for pretty much everything but
this is not enough. The reference code for this PHY makes a write to an
unused PHY to workaround this read problem. This was also confirmed by
Aeonsemi.
Various test were made to try to workaround this ins alternative way
than the random write.
One effective solution was to limit the write only to BMSR. And also
write to BMSR is safe since they are only read only registers.
This is only done for read operation as write operation doesn't suffer
from this problem.
Worth to mention that when multiple Aeonsemi PHY are mounted, the
workaround doesn't work if we write to another Aeonsemi PHY.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/as21xxx.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
--- a/drivers/net/phy/as21xxx.c
+++ b/drivers/net/phy/as21xxx.c
@@ -966,6 +966,21 @@ out:
return ret;
}
+static int as21xxx_read_mmd(struct phy_device *phydev, int devad,
+ u16 regnum)
+{
+ struct mii_bus *bus = phydev->mdio.bus;
+ int val;
+
+ val = __mdiobus_c45_read(bus, phydev->mdio.addr, devad,
+ regnum);
+
+ /* FIXME: verify if it's actually ok to limit this to MII_BMSR */
+ __mdiobus_write(bus, 0x0, MII_BMSR, 0x1);
+
+ return val;
+}
+
static struct phy_driver as21xxx_drivers[] = {
{
/* PHY expose in C45 as 0x7500 0x9410
@@ -983,6 +998,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -996,6 +1012,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1009,6 +1026,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1022,6 +1040,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1035,6 +1054,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1048,6 +1068,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1061,6 +1082,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1074,6 +1096,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1087,6 +1110,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,
@@ -1100,6 +1124,7 @@ static struct phy_driver as21xxx_drivers
.probe = as21xxx_probe,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
+ .read_mmd = as21xxx_read_mmd,
.led_brightness_set = as21xxx_led_brightness_set,
.led_hw_is_supported = as21xxx_led_hw_is_supported,
.led_hw_control_set = as21xxx_led_hw_control_set,