Skip to content

driver: mdio: mdio_nxp_enet: Implement c45 read/write #88247

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
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
97 changes: 46 additions & 51 deletions drivers/mdio/mdio_nxp_enet.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@ static int nxp_enet_mdio_wait_xfer(const struct device *dev)
return 0;
}

/* MDIO Read API implementation */
static int nxp_enet_mdio_read(const struct device *dev,
uint8_t prtad, uint8_t regad, uint16_t *read_data)
static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t regad,
enum mdio_opcode op, bool c45, uint16_t data_in, uint16_t *data_out)
{
struct nxp_enet_mdio_data *data = dev->data;
int ret;
Expand All @@ -71,25 +70,27 @@ static int nxp_enet_mdio_read(const struct device *dev,

/*
* Clear the bit (W1C) that indicates MDIO transfer is ready to
* prepare to wait for it to be set once this read is done
* prepare to wait for it to be set once this transfer is done
*/
data->base->EIR = ENET_EIR_MII_MASK;

/*
* Write MDIO frame to MII management register which will
* send the read command and data out to the MDIO bus as this frame:
* ST = start, 1 means start
* OP = operation, 2 means read
* send the command and data out to the MDIO bus as this frame:
* ST = start, C22: 1 means start
* C45: 0 means start
* OP = operation, see mdio_opcode for specifics on what the values are
* PA = PHY/Port address
* RA = Register/Device Address
* TA = Turnaround, must be 2 to be valid
* data = data to be written to the PHY register
*/
data->base->MMFR = ENET_MMFR_ST(0x1U) |
ENET_MMFR_OP(MDIO_OP_C22_READ) |
ENET_MMFR_PA(prtad) |
ENET_MMFR_RA(regad) |
ENET_MMFR_TA(0x2U);
data->base->MMFR = ENET_MMFR_ST(c45 ? 0x0U : 0x1U)
| ENET_MMFR_OP(op)
| ENET_MMFR_PA(prtad)
| ENET_MMFR_RA(regad)
| ENET_MMFR_TA(0x2U)
| data_in;

ret = nxp_enet_mdio_wait_xfer(dev);
if (ret) {
Expand All @@ -98,7 +99,9 @@ static int nxp_enet_mdio_read(const struct device *dev,
}

/* The data is received in the same register that we wrote the command to */
*read_data = (data->base->MMFR & ENET_MMFR_DATA_MASK) >> ENET_MMFR_DATA_SHIFT;
if (data_out != NULL) {
*data_out = (data->base->MMFR & ENET_MMFR_DATA_MASK) >> ENET_MMFR_DATA_SHIFT;
}

/* Clear the same bit as before because the event has been handled */
data->base->EIR = ENET_EIR_MII_MASK;
Expand All @@ -109,57 +112,49 @@ static int nxp_enet_mdio_read(const struct device *dev,
return ret;
}

/* MDIO Write API implementation */
static int nxp_enet_mdio_write(const struct device *dev,
uint8_t prtad, uint8_t regad, uint16_t write_data)
static int nxp_enet_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t *read_data)
{
struct nxp_enet_mdio_data *data = dev->data;
int ret;

/* Only one MDIO bus operation attempt at a time */
(void)k_mutex_lock(&data->mdio_mutex, K_FOREVER);
return mdio_transfer(dev, prtad, regad, MDIO_OP_C22_READ, false, 0, read_data);
}

/*
* Clear the bit (W1C) that indicates MDIO transfer is ready to
* prepare to wait for it to be set once this write is done
*/
data->base->EIR = ENET_EIR_MII_MASK;
static int nxp_enet_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t write_data)
{
return mdio_transfer(dev, prtad, regad, MDIO_OP_C22_WRITE, false, write_data, NULL);
}

/*
* Write MDIO frame to MII management register which will
* send the write command and data out to the MDIO bus as this frame:
* ST = start, 1 means start
* OP = operation, 1 means write
* PA = PHY/Port address
* RA = Register/Device Address
* TA = Turnaround, must be 2 to be valid
* data = data to be written to the PHY register
*/
data->base->MMFR = ENET_MMFR_ST(0x1U) |
ENET_MMFR_OP(MDIO_OP_C22_WRITE) |
ENET_MMFR_PA(prtad) |
ENET_MMFR_RA(regad) |
ENET_MMFR_TA(0x2U) |
write_data;
static int nxp_enet_mdio_read_c45(const struct device *dev, uint8_t prtad, uint8_t devad,
uint16_t regad, uint16_t *data)
{
int err;

ret = nxp_enet_mdio_wait_xfer(dev);
if (ret) {
(void)k_mutex_unlock(&data->mdio_mutex);
return ret;
err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_ADDRESS, true, regad, NULL);
if (!err) {
err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_READ, true, 0, data);
}

/* Clear the same bit as before because the event has been handled */
data->base->EIR = ENET_EIR_MII_MASK;
return err;
}

/* This MDIO interaction is finished */
(void)k_mutex_unlock(&data->mdio_mutex);
int nxp_enet_mdio_write_c45(const struct device *dev, uint8_t prtad, uint8_t devad, uint16_t regad,
uint16_t data)
{
int err;

return ret;
err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_ADDRESS, true, regad, NULL);
if (!err) {
err = mdio_transfer(dev, prtad, devad, MDIO_OP_C45_WRITE, true, data, NULL);
}

return err;
}

static DEVICE_API(mdio, nxp_enet_mdio_api) = {
.read = nxp_enet_mdio_read,
.write = nxp_enet_mdio_write,
.read_c45 = nxp_enet_mdio_read_c45,
.write_c45 = nxp_enet_mdio_write_c45
};

static void nxp_enet_mdio_isr_cb(const struct device *dev)
Expand Down