From: Christian Marangi <ansuelsmth@gmail.com>
To: Christian Marangi <ansuelsmth@gmail.com>,
Andrew Lunn <andrew@lunn.ch>,
Heiner Kallweit <hkallweit1@gmail.com>,
Russell King <linux@armlinux.org.uk>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [net-next PATCH v2 3/3] net: phy: as21xxx: fill in inband caps and better handle inband
Date: Fri, 23 Jan 2026 13:00:31 +0100 [thread overview]
Message-ID: <20260123120117.10883-4-ansuelsmth@gmail.com> (raw)
In-Reply-To: <20260123120117.10883-1-ansuelsmth@gmail.com>
The as21xxx control In-Band support with the DPC RateAdapation
configuration.
Tested on a Banana Pi R4 PRO (MT7988a) and on Airoha AN7581/AN7583 where
In Band is controlled by disabling Autoneg on the PCS, where the PHY
correctly transfer packet with In Band disabled on the PCS and DPC RA
disabled on the PHY. It was also confirmed that with In Band enabled on
the PCS and DPC RA enabled on the PHY also packets gets transmitted
correctly.
With this new information, fill in the .inband_caps() OP and set the
.config_inband() to enable DPC RA when inband is enabled.
Support for this feature is enabled only on PHY firmware >= 1.9 as on
previous version the DPC RA could only be enabled and a PHY reset (and
Firmware reloaded) was needed to change this at runtime.
To keep compatibility with some HW configuration, we enable DPC RA by
default for older firmware. This is needed as on Banana Pi R4 PRO, one
of the 2 as21xxx PHY is attached to a Switch that requires the PHY in In
Band mode with Rate Adaption.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/phy/as21xxx.c | 111 +++++++++++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/as21xxx.c b/drivers/net/phy/as21xxx.c
index 2098fa6a2f63..60ec7af6e386 100644
--- a/drivers/net/phy/as21xxx.c
+++ b/drivers/net/phy/as21xxx.c
@@ -125,6 +125,10 @@
#define IPC_DATA_DBG_SEC GENMASK(15, 8)
#define IPC_DATA_DBG_CMD GENMASK(7, 0)
+/* DBG_DPC sub command */
+#define IPC_DPC_RA_SET_CFG 0x2
+#define IPC_DPC_RA_GET_CFG 0x7
+
#define AS21XXX_MDIO_AN_C22 0xffe0
#define PHY_ID_AS21XXX 0x75009410
@@ -724,6 +728,52 @@ static int aeon_ipc_dbg_write_buf(struct phy_device *phydev, u8 *data,
return ret;
}
+static int aeon_ipc_dpc_ra_set(struct phy_device *phydev, bool enable)
+{
+ u8 data[1];
+ int ret;
+
+ ret = aeon_ipc_dbg_cmd(phydev, IPC_DBG_DPC,
+ IPC_DPC_RA_SET_CFG,
+ sizeof(data));
+ if (ret)
+ return ret;
+
+ data[0] = enable;
+
+ ret = aeon_ipc_dbg_write_buf(phydev, data, sizeof(data));
+ if (ret)
+ return ret;
+
+ ret = aeon_ipc_poll(phydev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int aeon_ipc_dpc_ra_get(struct phy_device *phydev, bool *enabled)
+{
+ u16 ret_data[AEON_IPC_DATA_NUM_REGISTERS];
+ int ret;
+
+ ret = aeon_ipc_dbg_cmd(phydev, IPC_DBG_DPC,
+ IPC_DPC_RA_GET_CFG, 0);
+ if (ret)
+ return ret;
+
+ ret = aeon_ipc_poll(phydev);
+ if (ret)
+ return ret;
+
+ ret = aeon_ipc_dbg_read_buf(phydev, ret_data);
+ if (ret < 0)
+ return ret;
+
+ *enabled = !!ret_data[0];
+ return 0;
+}
+
static int aeon_dpc_ra_enable(struct phy_device *phydev)
{
u16 data[2];
@@ -765,7 +815,11 @@ static int as21xxx_probe(struct phy_device *phydev)
if (ret)
return ret;
- return aeon_dpc_ra_enable(phydev);
+ /* Enable DPC Rate Adaption by default on older firmware */
+ if (priv->fw_major_ver == 1 && priv->fw_minor_ver < 9)
+ return aeon_dpc_ra_enable(phydev);
+
+ return 0;
}
static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
@@ -1078,6 +1132,41 @@ static int as21xxx_match_phy_device(struct phy_device *phydev,
return ret;
}
+static unsigned int as21xxx_inband_caps(struct phy_device *phydev,
+ phy_interface_t interface)
+{
+ struct as21xxx_priv *priv = phydev->priv;
+
+ /* Configuring DPC Rate Adaption (to permit In Band support)
+ * is supported only from firmware version 1.9+
+ */
+ if (priv->fw_major_ver > 1 || priv->fw_minor_ver >= 9)
+ return LINK_INBAND_ENABLE | LINK_INBAND_DISABLE;
+
+ /* On older firmware we enforce In Band by default
+ * for compatibility reason.
+ */
+ return LINK_INBAND_ENABLE;
+}
+
+static int as21xxx_config_inband(struct phy_device *phydev,
+ unsigned int modes)
+{
+ bool enabled;
+ int ret;
+
+ ret = aeon_ipc_dpc_ra_get(phydev, &enabled);
+ if (ret)
+ return ret;
+
+ /* Ignore if already in the desired mode */
+ if ((modes == LINK_INBAND_ENABLE && enabled) ||
+ (modes == LINK_INBAND_DISABLE && !enabled))
+ return 0;
+
+ return aeon_ipc_dpc_ra_set(phydev, modes == LINK_INBAND_ENABLE);
+}
+
static struct phy_driver as21xxx_drivers[] = {
{
/* PHY expose in C45 as 0x7500 0x9410
@@ -1093,6 +1182,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21011JB1),
.name = "Aeonsemi AS21011JB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1105,6 +1196,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
.name = "Aeonsemi AS21011PB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1117,6 +1210,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
.name = "Aeonsemi AS21010PB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1129,6 +1224,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
.name = "Aeonsemi AS21010JB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1141,6 +1238,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
.name = "Aeonsemi AS21210PB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1153,6 +1252,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
.name = "Aeonsemi AS21510JB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1165,6 +1266,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
.name = "Aeonsemi AS21510PB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1177,6 +1280,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
.name = "Aeonsemi AS21511JB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1189,6 +1294,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
.name = "Aeonsemi AS21210JB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
@@ -1201,6 +1308,8 @@ static struct phy_driver as21xxx_drivers[] = {
PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
.name = "Aeonsemi AS21511PB1",
.probe = as21xxx_probe,
+ .inband_caps = as21xxx_inband_caps,
+ .config_inband = as21xxx_config_inband,
.match_phy_device = as21xxx_match_phy_device,
.read_status = as21xxx_read_status,
.led_brightness_set = as21xxx_led_brightness_set,
--
2.51.0
next prev parent reply other threads:[~2026-01-23 12:01 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-23 12:00 [net-next PATCH v2 0/3] net: phy: as21xxx: toggle In Band feature support Christian Marangi
2026-01-23 12:00 ` [net-next PATCH v2 1/3] net: phy: as21xxx: save firmware version major/minor version Christian Marangi
2026-01-23 12:00 ` [net-next PATCH v2 2/3] net: phy: as21xxx: add support for DBG command Christian Marangi
2026-01-25 22:33 ` Jakub Kicinski
2026-01-23 12:00 ` Christian Marangi [this message]
2026-01-23 12:16 ` [net-next PATCH v2 0/3] net: phy: as21xxx: toggle In Band feature support Russell King (Oracle)
2026-01-23 13:09 ` Christian Marangi
2026-01-23 13:35 ` Russell King (Oracle)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260123120117.10883-4-ansuelsmth@gmail.com \
--to=ansuelsmth@gmail.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=hkallweit1@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox