[PATCH v4 1/3] net/axgbe: add external PHY read/write functions

Ashok Kumar Natarajan
2026-02-27T08:44:00Z

Introduce helper functions to perform external PHY register read and
write operations. These helpers currently support only IEEE Clause 22
PHY access, providing a simple and consistent API for accessing
standard 16‑bit MII registers on external PHY devices.

Signed-off-by: Ashok Kumar Natarajan <ashokkumar.natarajan@amd.com>
---
.mailmap | 1 +
drivers/net/axgbe/axgbe_dev.c | 56 ++++++++++++++++--------------
drivers/net/axgbe/axgbe_ethdev.h | 16 ++++++---
drivers/net/axgbe/axgbe_phy_impl.c | 45 +++++++++++++++++++++++-
4 files changed, 85 insertions(+), 33 deletions(-)

diff --git a/.mailmap b/.mailmap
index 6c4c977dde..5c8b47f1a9 100644
--- a/.mailmap
+++ b/.mailmap
@@ -165,6 +165,7 @@ Ashish Paul <apaul@juniper.net>
Ashish Sadanandan <ashish.sadanandan@gmail.com>
Ashish Shah <ashish.n.shah@intel.com>
Ashok Kaladi <ashok.k.kaladi@intel.com>
+Ashok Kumar Natarajan <ashokkumar.natarajan@amd.com>
Ashwin Sekhar T K <asekhar@marvell.com> <ashwin.sekhar@caviumnetworks.com>
Asim Jamshed <asim.jamshed@gmail.com>
Atul Patel <atul.patel@intel.com>
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 634d4ee4a5..10a99aeac2 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -63,9 +63,9 @@ static int mdio_complete(struct axgbe_port *pdata)
return 0;
}

-static unsigned int axgbe_create_mdio_sca_c22(int port, int reg)
+static unsigned int axgbe_create_mdio_sca_c22(u8 port, u16 reg)
{
- unsigned int mdio_sca;
+ u32 mdio_sca;

mdio_sca = 0;
AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
@@ -74,20 +74,20 @@ static unsigned int axgbe_create_mdio_sca_c22(int port, int reg)
return mdio_sca;
}

-static unsigned int axgbe_create_mdio_sca_c45(int port, unsigned int da, int reg)
+static unsigned int axgbe_create_mdio_sca_c45(u8 port, u8 dev_addr, u16 reg)
{
- unsigned int mdio_sca;
+ u32 mdio_sca;

mdio_sca = 0;
AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port);
- AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, da);
+ AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, dev_addr);

return mdio_sca;
}

static int axgbe_write_ext_mii_regs(struct axgbe_port *pdata,
- unsigned int mdio_sca, u16 val)
+ u32 mdio_sca, u16 value)
{
unsigned int mdio_sccd;
uint64_t timeout;
@@ -95,7 +95,7 @@ static int axgbe_write_ext_mii_regs(struct axgbe_port *pdata,
AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);

mdio_sccd = 0;
- AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val);
+ AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, value);
AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1);
AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
@@ -113,28 +113,28 @@ static int axgbe_write_ext_mii_regs(struct axgbe_port *pdata,

static int axgbe_write_ext_mii_regs_c22(struct axgbe_port *pdata,
- int addr, int reg, u16 val)
+ u8 phy_addr, u16 reg, u16 value)
{
- unsigned int mdio_sca;
+ u32 mdio_sca;

- mdio_sca = axgbe_create_mdio_sca_c22(addr, reg);
+ mdio_sca = axgbe_create_mdio_sca_c22(phy_addr, reg);

- return axgbe_write_ext_mii_regs(pdata, mdio_sca, val);
+ return axgbe_write_ext_mii_regs(pdata, mdio_sca, value);
}

static int axgbe_write_ext_mii_regs_c45(struct axgbe_port *pdata,
- int addr, int devad, int reg, u16 val)
+ u8 phy_addr, u8 dev_addr, u16 reg, u16 value)
{
- unsigned int mdio_sca;
+ u32 mdio_sca;

- mdio_sca = axgbe_create_mdio_sca_c45(addr, devad, reg);
+ mdio_sca = axgbe_create_mdio_sca_c45(phy_addr, dev_addr, reg);

- return axgbe_write_ext_mii_regs(pdata, mdio_sca, val);
+ return axgbe_write_ext_mii_regs(pdata, mdio_sca, value);
}

-static int axgbe_read_ext_mii_regs(struct axgbe_port *pdata,
- unsigned int mdio_sca)
+static int axgbe_read_ext_mii_regs(struct axgbe_port *pdata, u32 mdio_sca,
+ u16 *value)
{
unsigned int mdio_sccd;
uint64_t timeout;
@@ -158,26 +158,28 @@ static int axgbe_read_ext_mii_regs(struct axgbe_port *pdata,
return -ETIMEDOUT;

success:
- return AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
+ *value = AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
+ return 0;
}

-static int axgbe_read_ext_mii_regs_c22(struct axgbe_port *pdata, int addr, int reg)
+static int axgbe_read_ext_mii_regs_c22(struct axgbe_port *pdata, u8 phy_addr,
+ u16 reg, u16 *value)
{
- unsigned int mdio_sca;
+ u32 mdio_sca;

- mdio_sca = axgbe_create_mdio_sca_c22(addr, reg);
+ mdio_sca = axgbe_create_mdio_sca_c22(phy_addr, reg);

- return axgbe_read_ext_mii_regs(pdata, mdio_sca);
+ return axgbe_read_ext_mii_regs(pdata, mdio_sca, value);
}

-static int axgbe_read_ext_mii_regs_c45(struct axgbe_port *pdata, int addr,
- int devad, int reg)
+static int axgbe_read_ext_mii_regs_c45(struct axgbe_port *pdata, u8 phy_addr,
+ u8 dev_addr, u16 reg, u16 *value)
{
- unsigned int mdio_sca;
+ u32 mdio_sca;

- mdio_sca = axgbe_create_mdio_sca_c45(addr, devad, reg);
+ mdio_sca = axgbe_create_mdio_sca_c45(phy_addr, dev_addr, reg);

- return axgbe_read_ext_mii_regs(pdata, mdio_sca);
+ return axgbe_read_ext_mii_regs(pdata, mdio_sca, value);
}

static int axgbe_set_ext_mii_mode(struct axgbe_port *pdata, unsigned int port,
diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h
index b94a7f3562..24336f31f6 100644
--- a/drivers/net/axgbe/axgbe_ethdev.h
+++ b/drivers/net/axgbe/axgbe_ethdev.h
@@ -327,11 +327,14 @@ struct axgbe_hw_if {

int (*set_ext_mii_mode)(struct axgbe_port *, unsigned int,
enum axgbe_mdio_mode);
- int (*read_ext_mii_regs_c22)(struct axgbe_port *pdata, int addr, int reg);
- int (*write_ext_mii_regs_c22)(struct axgbe_port *pdata, int addr, int reg, uint16_t val);
- int (*read_ext_mii_regs_c45)(struct axgbe_port *pdata, int addr, int devad, int reg);
- int (*write_ext_mii_regs_c45)(struct axgbe_port *pdata, int addr, int devad,
- int reg, uint16_t val);
+ int (*read_ext_mii_regs_c22)(struct axgbe_port *pdata, u8 phy_addr,
+ u16 reg, u16 *value);
+ int (*write_ext_mii_regs_c22)(struct axgbe_port *pdata, u8 phy_addr,
+ u16 reg, u16 value);
+ int (*read_ext_mii_regs_c45)(struct axgbe_port *pdata, u8 phy_addr,
+ u8 dev_addr, u16 reg, u16 *value);
+ int (*write_ext_mii_regs_c45)(struct axgbe_port *pdata, u8 phy_addr,
+ u8 dev_addr, u16 reg, u16 value);

/* For FLOW ctrl */
int (*config_tx_flow_control)(struct axgbe_port *);
@@ -398,6 +401,9 @@ struct axgbe_phy_impl_if {
/* Pre/Post KR training enablement support */
void (*kr_training_pre)(struct axgbe_port *);
void (*kr_training_post)(struct axgbe_port *);
+
+ int (*read)(struct axgbe_port *pdata, u16 reg, u16 *value);
+ int (*write)(struct axgbe_port *pdata, u16 reg, u16 value);
};

struct axgbe_phy_if {
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index 9249e11335..cbab2908b4 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -203,7 +203,7 @@ struct axgbe_phy_data {

unsigned int rrc_count;

- unsigned int mdio_addr;
+ uint8_t mdio_addr;

/* SFP Support */
enum axgbe_sfp_comm sfp_comm;
@@ -251,6 +251,8 @@ static void axgbe_phy_perform_ratechange(struct axgbe_port *pdata,
enum axgbe_mb_cmd cmd, enum axgbe_mb_subcmd sub_cmd);
static void axgbe_phy_rrc(struct axgbe_port *pdata);

+static int axgbe_phy_get_comm_ownership(struct axgbe_port *pdata);
+static void axgbe_phy_put_comm_ownership(struct axgbe_port *pdata);

static int axgbe_phy_i2c_xfer(struct axgbe_port *pdata,
struct axgbe_i2c_op *i2c_op)
@@ -258,6 +260,44 @@ static int axgbe_phy_i2c_xfer(struct axgbe_port *pdata,
return pdata->i2c_if.i2c_xfer(pdata, i2c_op);
}

+static int axgbe_phy_read(struct axgbe_port *pdata, u16 reg, u16 *value)
+{
+ struct axgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+
+ ret = axgbe_phy_get_comm_ownership(pdata);
+ if (ret)
+ return ret;
+
+ ret = pdata->hw_if.read_ext_mii_regs_c22(pdata,
+ phy_data->mdio_addr, reg, value);
+ if (ret)
+ PMD_DRV_LOG_LINE(ERR, "mdio read failed %s",
+ strerror(-ret));
+
+ axgbe_phy_put_comm_ownership(pdata);
+ return ret;
+}
+
+static int axgbe_phy_write(struct axgbe_port *pdata, u16 reg, u16 value)
+{
+ struct axgbe_phy_data *phy_data = pdata->phy_data;
+ int ret;
+ ret = axgbe_phy_get_comm_ownership(pdata);
+ if (ret)
+ return ret;
+
+ ret = pdata->hw_if.write_ext_mii_regs_c22(pdata,
+ phy_data->mdio_addr, reg, value);
+ if (ret)
+ PMD_DRV_LOG_LINE(ERR, "mdio write failed %s",
+ strerror(-ret));
+
+ axgbe_phy_put_comm_ownership(pdata);
+ return ret;
+}
+
+
static int axgbe_phy_redrv_write(struct axgbe_port *pdata, unsigned int reg,
unsigned int val)
{
@@ -2542,4 +2582,7 @@ void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if)

phy_impl->kr_training_pre = axgbe_phy_kr_training_pre;
phy_impl->kr_training_post = axgbe_phy_kr_training_post;
+
+ phy_impl->read = axgbe_phy_read;
+ phy_impl->write = axgbe_phy_write;
}
--
2.34.1