Skip to content

drivers: mdio_nxp_enet_qos: Add Clause 45 support. #93442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 24, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 75 additions & 14 deletions drivers/mdio/mdio_nxp_enet_qos.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct mdio_transaction {
};
uint8_t portaddr;
uint8_t regaddr;
uint16_t regaddr_c45;
enet_qos_t *base;
struct k_mutex *mdio_bus_mutex;
};
Expand All @@ -44,32 +45,53 @@ static bool check_busy(enet_qos_t *base)
return ENET_QOS_REG_GET(MAC_MDIO_ADDRESS, GB, val);
}

static int do_transaction(struct mdio_transaction *mdio)
static int do_transaction(struct mdio_transaction *mdio, bool clause45)
{
enet_qos_t *base = mdio->base;
uint8_t goc_1_code;
int ret;

k_mutex_lock(mdio->mdio_bus_mutex, K_FOREVER);

if (mdio->op == MDIO_OP_C22_WRITE) {
base->MAC_MDIO_DATA =
/* Prepare the data to be written */
ENET_QOS_REG_PREP(MAC_MDIO_DATA, GD, mdio->write_data);
goc_1_code = 0b0;
} else if (mdio->op == MDIO_OP_C22_READ) {
goc_1_code = 0b1;
if (clause45) {
if (mdio->op == MDIO_OP_C45_WRITE) {
goc_1_code = 0b0;
base->MAC_MDIO_DATA =
/* Prepare the data and regaddr to be written */
ENET_QOS_REG_PREP(MAC_MDIO_DATA, GD, mdio->write_data) |
ENET_QOS_REG_PREP(MAC_MDIO_DATA, RA, mdio->regaddr_c45);
} else if (mdio->op == MDIO_OP_C45_READ) {
goc_1_code = 0b1;
base->MAC_MDIO_DATA =
/* Prepare the regaddr to be written */
ENET_QOS_REG_PREP(MAC_MDIO_DATA, RA, mdio->regaddr_c45);
} else {
ret = -EINVAL;
goto done;
}
} else {
ret = -EINVAL;
goto done;
if (mdio->op == MDIO_OP_C22_WRITE) {
base->MAC_MDIO_DATA =
/* Prepare the data to be written */
ENET_QOS_REG_PREP(MAC_MDIO_DATA, GD, mdio->write_data);
goc_1_code = 0b0;
} else if (mdio->op == MDIO_OP_C22_READ) {
goc_1_code = 0b1;
} else {
ret = -EINVAL;
goto done;
}
}
base->MAC_MDIO_ADDRESS &= ~(
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, C45E, 0b1) |
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, GOC_1, 0b1) |
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, GOC_0, 0b1) |
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, PA, 0b11111) |
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, RDA, 0b11111));

base->MAC_MDIO_ADDRESS |=
/* C45E */
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, C45E, clause45) |
/* OP command */
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, GOC_1, goc_1_code) |
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, GOC_0, 0b1) |
Expand All @@ -82,7 +104,6 @@ static int do_transaction(struct mdio_transaction *mdio)
/* Start the transaction */
ENET_QOS_REG_PREP(MAC_MDIO_ADDRESS, GB, 0b1);


ret = -ETIMEDOUT;
for (int i = CONFIG_MDIO_NXP_ENET_QOS_RECHECK_COUNT; i > 0; i--) {
if (!check_busy(base)) {
Expand All @@ -97,7 +118,7 @@ static int do_transaction(struct mdio_transaction *mdio)
goto done;
}

if (mdio->op == MDIO_OP_C22_READ) {
if (mdio->op == MDIO_OP_C22_READ || mdio->op == MDIO_OP_C45_READ) {
uint32_t val = mdio->base->MAC_MDIO_DATA;

*mdio->read_data =
Expand Down Expand Up @@ -127,7 +148,7 @@ static int nxp_enet_qos_mdio_read(const struct device *dev,
.mdio_bus_mutex = &data->mdio_mutex,
};

return do_transaction(&mdio_read);
return do_transaction(&mdio_read, false);
}

static int nxp_enet_qos_mdio_write(const struct device *dev,
Expand All @@ -146,12 +167,52 @@ static int nxp_enet_qos_mdio_write(const struct device *dev,
.mdio_bus_mutex = &data->mdio_mutex,
};

return do_transaction(&mdio_write);
return do_transaction(&mdio_write, false);
}

static int nxp_enet_qos_mdio_read_c45(const struct device *dev, uint8_t portaddr, uint8_t devaddr,
uint16_t regaddr, uint16_t *read_data)
{
const struct nxp_enet_qos_mdio_config *config = dev->config;
struct nxp_enet_qos_mdio_data *data = dev->data;
enet_qos_t *base = ENET_QOS_MODULE_CFG(config->enet_dev)->base;
struct mdio_transaction mdio_read = {
.op = MDIO_OP_C45_READ,
.read_data = read_data,
.portaddr = portaddr,
.regaddr = devaddr,
.regaddr_c45 = regaddr,
.base = base,
.mdio_bus_mutex = &data->mdio_mutex,
};

return do_transaction(&mdio_read, true);
}

int nxp_enet_qos_mdio_write_c45(const struct device *dev, uint8_t portaddr, uint8_t devaddr,
uint16_t regaddr, uint16_t write_data)
{
const struct nxp_enet_qos_mdio_config *config = dev->config;
struct nxp_enet_qos_mdio_data *data = dev->data;
enet_qos_t *base = ENET_QOS_MODULE_CFG(config->enet_dev)->base;
struct mdio_transaction mdio_write = {
.op = MDIO_OP_C45_WRITE,
.write_data = write_data,
.portaddr = portaddr,
.regaddr = devaddr,
.regaddr_c45 = regaddr,
.base = base,
.mdio_bus_mutex = &data->mdio_mutex,
};

return do_transaction(&mdio_write, true);
}

static DEVICE_API(mdio, nxp_enet_qos_mdio_api) = {
.read = nxp_enet_qos_mdio_read,
.write = nxp_enet_qos_mdio_write,
.read_c45 = nxp_enet_qos_mdio_read_c45,
.write_c45 = nxp_enet_qos_mdio_write_c45,
};

static int nxp_enet_qos_mdio_init(const struct device *dev)
Expand Down