mdio: introduce Clause 45 APIs

Add `mdio_read_c45()`/`mdio_write_c45()` APIs for Clause 45 access
and remove the `protocol` MDIO binding property so that MDIO bus
controller can support more than one protocol.

A new MDIO header is introduced with generic opcodes, MMD and
registers addresses, to be used by MDIO and PHY drivers.

Existing MDIO drivers that support both Clause 22 and Clause 45
access are migrated to the new APIs.

Signed-off-by: Manuel Argüelles <manuel.arguelles@nxp.com>
This commit is contained in:
Manuel Argüelles 2023-08-18 15:58:09 +07:00 committed by Carles Cufí
commit 280ddaef4a
12 changed files with 421 additions and 209 deletions

View file

@ -29,7 +29,6 @@
&emdio {
pinctrl-0 = <&emdio_default>;
pinctrl-names = "default";
protocol = "clause 22";
status = "okay";
phy0: ethernet-phy {

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2023 PHOENIX CONTACT Electronics GmbH
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -17,8 +18,8 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL);
#include <zephyr/sys/util.h>
#include <zephyr/net/phy.h>
#include <zephyr/net/mii.h>
#include <zephyr/net/mdio.h>
#include <zephyr/drivers/mdio.h>
#include <zephyr/drivers/mdio/mdio_adin2111.h>
/* PHYs out of reset check retry delay */
#define ADIN2111_PHY_AWAIT_DELAY_POLL_US 15U
@ -37,36 +38,10 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL);
#define ADIN2111_PHY_ID 0x0283BCA1U
#define ADIN1110_PHY_ID 0x0283BC91U
/* 10BASE-T1L PMA Status Register */
#define ADIN2111_PHY_PMA_STATUS 0x000108F7U
/* Indicates PHY support of 10BASE-T1L high voltage (2.4V) tx level op mode */
#define ADIN2111_PHY_PMA_STATUS_B10L_TX_LVL_HI_ABLE BIT(12)
/* BASE-T1 Autonegotiation Control Register */
#define ADIN2111_PHY_AN_CONTROL 0x00070200U
/* Autonegotiation Enable */
#define ADIN2111_PHY_AN_CONTROL_AN_EN BIT(12)
/* Autonegotiation Restart */
#define ADIN2111_PHY_AN_CONTROL_AN_RESTART BIT(9)
/* BASE-T1 Autonegotiation Status Register */
#define ADIN2111_PHY_AN_STATUS 0x00070201U
/* Autonegotiation Complete */
#define ADIN2111_PHY_AN_STATUS_AN_COMPLETE BIT(5)
/* Link Status */
#define ADIN2111_PHY_AN_STATUS_AN_LINK_STATUS BIT(2)
/* 10BASE-T1 Autonegotiation Advertisement Register */
#define ADIN2111_PHY_AN_ADV_ABILITY_H 0x00070204U
/* Advertise PHY capability of 2.4V tx level op mode */
#define ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_ABL BIT(13)
/* Advertise PHY request of 2.4V tx level op mode */
#define ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_REQ BIT(12)
/* System Interrupt Mask Register */
#define ADIN2111_PHY_CRSM_IRQ_MASK 0x001E0020U
#define ADIN2111_PHY_CRSM_IRQ_MASK 0x0020U
/* System Interrupt Status Register */
#define ADIN2111_PHY_CRSM_IRQ_STATUS 0x001E0010U
#define ADIN2111_PHY_CRSM_IRQ_STATUS 0x0010U
/**
* Mask of reserved interrupts that indicates a fatal error in the system.
*
@ -82,21 +57,21 @@ LOG_MODULE_REGISTER(phy_adin2111, CONFIG_PHY_LOG_LEVEL);
#define ADIN2111_PHY_CRSM_IRQ_STATUS_FATAL_ERR 0x2BFFU
/* PHY Subsystem Interrupt Mask Register */
#define ADIN2111_PHY_SUBSYS_IRQ_MASK 0x001F0021U
#define ADIN2111_PHY_SUBSYS_IRQ_MASK 0x0021U
/* PHY Subsystem Interrupt Status Register */
#define ADIN2111_PHY_SUBSYS_IRQ_STATUS 0x001F0011U
#define ADIN2111_PHY_SUBSYS_IRQ_STATUS 0x0011U
/* Link Status Change */
#define ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH BIT(1)
/* Software Power-down Control Register */
#define ADIN2111_PHY_CRSM_SFT_PD_CNTRL 0x001E8812U
#define ADIN2111_PHY_CRSM_SFT_PD_CNTRL 0x8812U
/* System Status Register */
#define ADIN2111_PHY_CRSM_STAT 0x001E8818U
#define ADIN2111_PHY_CRSM_STAT 0x8818U
/* Software Power-down Status */
#define ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY BIT(1)
/* LED Control Register */
#define ADIN2111_PHY_LED_CNTRL 0x001E8C82U
#define ADIN2111_PHY_LED_CNTRL 0x8C82U
/* LED 1 Enable */
#define ADIN2111_PHY_LED_CNTRL_LED1_EN BIT(15)
/* LED 0 Enable */
@ -131,22 +106,20 @@ static inline int phy_adin2111_c22_write(const struct device *dev, uint16_t reg,
return mdio_write(cfg->mdio, cfg->phy_addr, reg, val);
}
static inline int phy_adin2111_c45_write(const struct device *dev, uint32_t reg,
uint16_t val)
static inline int phy_adin2111_c45_write(const struct device *dev, uint16_t devad,
uint16_t reg, uint16_t val)
{
const struct phy_adin2111_config *cfg = dev->config;
return adin2111_mdio_c45_write(cfg->mdio, cfg->phy_addr, ((reg >> 16U) & 0x1FU),
(reg & UINT16_MAX), val);
return mdio_write_c45(cfg->mdio, cfg->phy_addr, devad, reg, val);
}
static inline int phy_adin2111_c45_read(const struct device *dev, uint32_t reg,
uint16_t *val)
static inline int phy_adin2111_c45_read(const struct device *dev, uint16_t devad,
uint16_t reg, uint16_t *val)
{
const struct phy_adin2111_config *cfg = dev->config;
return adin2111_mdio_c45_read(cfg->mdio, cfg->phy_addr, ((reg >> 16U) & 0x1FU),
(reg & 0xFFFFU), val);
return mdio_read_c45(cfg->mdio, cfg->phy_addr, devad, reg, val);
}
static int phy_adin2111_reg_read(const struct device *dev, uint16_t reg_addr,
@ -192,7 +165,8 @@ static int phy_adin2111_await_phy(const struct device *dev)
* it comes out from reset.
*/
for (count = 0U; count < ADIN2111_PHY_AWAIT_RETRY_COUNT; ++count) {
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_CRSM_IRQ_MASK, &val);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
ADIN2111_PHY_CRSM_IRQ_MASK, &val);
if (ret >= 0) {
if (val != 0U) {
break;
@ -233,8 +207,9 @@ int phy_adin2111_handle_phy_irq(const struct device *dev,
uint16_t subsys_status;
int ret;
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_SUBSYS_IRQ_STATUS,
&subsys_status);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2,
ADIN2111_PHY_SUBSYS_IRQ_STATUS,
&subsys_status);
if (ret < 0) {
return ret;
}
@ -262,15 +237,16 @@ static int phy_adin2111_sft_pd(const struct device *dev, bool enter)
const uint16_t expected = enter ? ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY : 0U;
uint16_t val;
ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_CRSM_SFT_PD_CNTRL,
enter ? 1U : 0U);
ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
ADIN2111_PHY_CRSM_SFT_PD_CNTRL,
enter ? 1U : 0U);
if (ret < 0) {
return ret;
}
for (count = 0U; count < ADIN2111_PHY_SFT_PD_RETRY_COUNT; ++count) {
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_CRSM_STAT,
&val);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
ADIN2111_PHY_CRSM_STAT, &val);
if (ret >= 0) {
if ((val & ADIN2111_CRSM_STAT_CRSM_SFT_PD_RDY) == expected) {
break;
@ -368,20 +344,23 @@ static int phy_adin2111_init(const struct device *dev)
}
/* disable interrupts */
ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_CRSM_IRQ_MASK, 0U);
ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
ADIN2111_PHY_CRSM_IRQ_MASK, 0U);
if (ret < 0) {
return ret;
}
/* enable link status change irq */
ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_SUBSYS_IRQ_MASK,
ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC2,
ADIN2111_PHY_SUBSYS_IRQ_MASK,
ADIN2111_PHY_SUBSYS_IRQ_STATUS_LINK_STAT_CHNG_LH);
if (ret < 0) {
return ret;
}
/* clear PHY IRQ status before enabling ADIN IRQs */
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_CRSM_IRQ_STATUS, &val);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
ADIN2111_PHY_CRSM_IRQ_STATUS, &val);
if (ret < 0) {
return ret;
}
@ -391,13 +370,15 @@ static int phy_adin2111_init(const struct device *dev)
return -ENODEV;
}
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_SUBSYS_IRQ_STATUS, &val);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC2,
ADIN2111_PHY_SUBSYS_IRQ_STATUS, &val);
if (ret < 0) {
return ret;
}
if (!cfg->led0_en || !cfg->led1_en) {
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_LED_CNTRL, &val);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_VENDOR_SPECIFIC1,
ADIN2111_PHY_LED_CNTRL, &val);
if (ret < 0) {
return ret;
}
@ -407,19 +388,20 @@ static int phy_adin2111_init(const struct device *dev)
if (!cfg->led1_en) {
val &= ~(ADIN2111_PHY_LED_CNTRL_LED1_EN);
}
ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_LED_CNTRL, val);
ret = phy_adin2111_c45_write(dev, MDIO_MMD_VENDOR_SPECIFIC1,
ADIN2111_PHY_LED_CNTRL, val);
if (ret < 0) {
return ret;
}
}
/* check 2.4V support */
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_PMA_STATUS, &val);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_PMAPMD, MDIO_PMA_B10L_STAT, &val);
if (ret < 0) {
return ret;
}
tx_24v_supported = !!(val & ADIN2111_PHY_PMA_STATUS_B10L_TX_LVL_HI_ABLE);
tx_24v_supported = !!(val & MDIO_PMA_B10L_STAT_2V4_ABLE);
LOG_INF("PHY %u 2.4V mode %s", cfg->phy_addr,
tx_24v_supported ? "supported" : "not supported");
@ -430,16 +412,15 @@ static int phy_adin2111_init(const struct device *dev)
}
/* config 2.4V auto-negotiation */
ret = phy_adin2111_c45_read(dev, ADIN2111_PHY_AN_ADV_ABILITY_H,
&val);
ret = phy_adin2111_c45_read(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, &val);
if (ret < 0) {
return ret;
}
if (tx_24v_supported) {
val |= ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_ABL;
val |= MDIO_AN_T1_ADV_H_10L_TX_HI;
} else {
val &= ~ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_ABL;
val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI;
}
if (cfg->tx_24v) {
@ -449,20 +430,19 @@ static int phy_adin2111_init(const struct device *dev)
return -EINVAL;
}
val |= ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_REQ;
val |= MDIO_AN_T1_ADV_H_10L_TX_HI_REQ;
} else {
val &= ~ADIN2111_PHY_AN_ADV_ABILITY_H_B10L_TX_LVL_HI_REQ;
val &= ~MDIO_AN_T1_ADV_H_10L_TX_HI_REQ;
}
ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_AN_ADV_ABILITY_H,
val);
ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H, val);
if (ret < 0) {
return ret;
}
/* enable auto-negotiation */
ret = phy_adin2111_c45_write(dev, ADIN2111_PHY_AN_CONTROL,
ADIN2111_PHY_AN_CONTROL_AN_EN);
ret = phy_adin2111_c45_write(dev, MDIO_MMD_AN, MDIO_AN_T1_CTRL,
MDIO_AN_T1_CTRL_EN);
if (ret < 0) {
return ret;
}

View file

@ -14,7 +14,6 @@ LOG_MODULE_REGISTER(mdio_adin2111, CONFIG_MDIO_LOG_LEVEL);
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/mdio.h>
#include <zephyr/drivers/mdio/mdio_adin2111.h>
#include <zephyr/drivers/ethernet/eth_adin2111.h>
/* MDIO ready check retry delay */
@ -56,9 +55,9 @@ static int mdio_adin2111_wait_ready(const struct device *dev, uint16_t reg,
}
int adin2111_mdio_c45_read(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad,
uint16_t *data)
static int mdio_adin2111_read_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad,
uint16_t *data)
{
const struct mdio_adin2111_config *const cfg = dev->config;
uint32_t rdy;
@ -96,9 +95,9 @@ int adin2111_mdio_c45_read(const struct device *dev, uint8_t prtad,
return ret;
}
int adin2111_mdio_c45_write(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad,
uint16_t data)
static int mdio_adin2111_write_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad,
uint16_t data)
{
const struct mdio_adin2111_config *const cfg = dev->config;
@ -191,6 +190,8 @@ static void mdio_adin2111_bus_disable(const struct device *dev)
static const struct mdio_driver_api mdio_adin2111_api = {
.read = mdio_adin2111_read,
.write = mdio_adin2111_write,
.read_c45 = mdio_adin2111_read_c45,
.write_c45 = mdio_adin2111_write_c45,
.bus_enable = mdio_adin2111_bus_enable,
.bus_disable = mdio_adin2111_bus_disable
};

View file

@ -143,12 +143,7 @@ static const struct mdio_esp32_dev_config mdio_esp32_dev_config_##n = { \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
};
#define MDIO_ESP32_PROTOCOL_ASSERT(n) \
BUILD_ASSERT(DT_INST_ENUM_IDX(n, protocol) == CLAUSE_22, \
"ESP32 MDIO only supports CLAUSE_22 protocol")
#define MDIO_ESP32_DEVICE(n) \
MDIO_ESP32_PROTOCOL_ASSERT(n); \
PINCTRL_DT_INST_DEFINE(n); \
MDIO_ESP32_CONFIG(n); \
static struct mdio_esp32_dev_data mdio_esp32_dev_data##n; \

View file

@ -180,12 +180,7 @@ static const struct mdio_driver_api mdio_gpio_driver_api = {
.mdio_gpio = GPIO_DT_SPEC_INST_GET(inst, mdio_gpios), \
};
#define MDIO_GPIO_PROTOCOL_ASSERT(inst) \
BUILD_ASSERT(DT_INST_ENUM_IDX(inst, protocol) == CLAUSE_22, \
"MDIO GPIO only supports CLAUSE_22 protocol")
#define MDIO_GPIO_DEVICE(inst) \
MDIO_GPIO_PROTOCOL_ASSERT(inst); \
MDIO_GPIO_CONFIG(inst); \
static struct mdio_gpio_data mdio_gpio_dev_data_##inst; \
DEVICE_DT_INST_DEFINE(inst, &mdio_gpio_initialize, NULL, &mdio_gpio_dev_data_##inst, \

View file

@ -1,5 +1,5 @@
/*
* Copyright 2022 NXP
* Copyright 2022-2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -16,7 +16,6 @@ LOG_MODULE_REGISTER(nxp_s32_emdio, CONFIG_MDIO_LOG_LEVEL);
#define NETC_SWT_IDX 0
struct nxp_s32_mdio_config {
int protocol;
const struct pinctrl_dev_config *pincfg;
};
@ -27,15 +26,9 @@ struct nxp_s32_mdio_data {
static int nxp_s32_mdio_read(const struct device *dev, uint8_t prtad,
uint8_t regad, uint16_t *regval)
{
const struct nxp_s32_mdio_config *const cfg = dev->config;
struct nxp_s32_mdio_data *data = dev->data;
Std_ReturnType status;
if (cfg->protocol != CLAUSE_22) {
LOG_ERR("Unsupported protocol");
return -ENOTSUP;
}
k_mutex_lock(&data->rw_mutex, K_FOREVER);
status = Netc_EthSwt_Ip_ReadTrcvRegister(NETC_SWT_IDX, prtad, regad, regval);
k_mutex_unlock(&data->rw_mutex);
@ -46,15 +39,9 @@ static int nxp_s32_mdio_read(const struct device *dev, uint8_t prtad,
static int nxp_s32_mdio_write(const struct device *dev, uint8_t prtad,
uint8_t regad, uint16_t regval)
{
const struct nxp_s32_mdio_config *const cfg = dev->config;
struct nxp_s32_mdio_data *data = dev->data;
Std_ReturnType status;
if (cfg->protocol != CLAUSE_22) {
LOG_ERR("Unsupported protocol");
return -ENOTSUP;
}
k_mutex_lock(&data->rw_mutex, K_FOREVER);
status = Netc_EthSwt_Ip_WriteTrcvRegister(NETC_SWT_IDX, prtad, regad, regval);
k_mutex_unlock(&data->rw_mutex);
@ -96,7 +83,6 @@ PINCTRL_DT_DEFINE(MDIO_NODE);
static struct nxp_s32_mdio_data nxp_s32_mdio0_data;
static const struct nxp_s32_mdio_config nxp_s32_mdio0_cfg = {
.protocol = DT_ENUM_IDX(MDIO_NODE, protocol),
.pincfg = PINCTRL_DT_DEV_CONFIG_GET(MDIO_NODE),
};

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021 IP-Logix Inc.
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,6 +14,7 @@
#include <soc.h>
#include <zephyr/drivers/mdio.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/net/mdio.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mdio_sam, CONFIG_MDIO_LOG_LEVEL);
@ -31,11 +33,11 @@ struct mdio_sam_dev_data {
struct mdio_sam_dev_config {
Gmac * const regs;
const struct pinctrl_dev_config *pcfg;
int protocol;
};
static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t regad,
uint8_t rw, uint16_t data_in, uint16_t *data_out)
enum mdio_opcode op, bool c45, uint16_t data_in,
uint16_t *data_out)
{
const struct mdio_sam_dev_config *const cfg = dev->config;
struct mdio_sam_dev_data *const data = dev->data;
@ -44,24 +46,12 @@ static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t regad,
k_sem_take(&data->sem, K_FOREVER);
/* Write mdio transaction */
if (cfg->protocol == CLAUSE_45) {
cfg->regs->GMAC_MAN = (GMAC_MAN_OP(rw ? 0x2 : 0x3))
| GMAC_MAN_WTN(0x02)
| GMAC_MAN_PHYA(prtad)
| GMAC_MAN_REGA(regad)
| GMAC_MAN_DATA(data_in);
} else if (cfg->protocol == CLAUSE_22) {
cfg->regs->GMAC_MAN = GMAC_MAN_CLTTO
| (GMAC_MAN_OP(rw ? 0x2 : 0x1))
| GMAC_MAN_WTN(0x02)
| GMAC_MAN_PHYA(prtad)
| GMAC_MAN_REGA(regad)
| GMAC_MAN_DATA(data_in);
} else {
LOG_ERR("Unsupported protocol");
}
cfg->regs->GMAC_MAN = (c45 ? 0U : GMAC_MAN_CLTTO)
| GMAC_MAN_OP(op)
| GMAC_MAN_WTN(0x02)
| GMAC_MAN_PHYA(prtad)
| GMAC_MAN_REGA(regad)
| GMAC_MAN_DATA(data_in);
/* Wait until done */
while (!(cfg->regs->GMAC_NSR & GMAC_NSR_IDLE)) {
@ -87,13 +77,45 @@ static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t regad,
static int mdio_sam_read(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t *data)
{
return mdio_transfer(dev, prtad, regad, 1, 0, data);
return mdio_transfer(dev, prtad, regad, MDIO_OP_C22_READ, false,
0, data);
}
static int mdio_sam_write(const struct device *dev, uint8_t prtad,
uint8_t regad, uint16_t data)
{
return mdio_transfer(dev, prtad, regad, 0, data, NULL);
return mdio_transfer(dev, prtad, regad, MDIO_OP_C22_WRITE, false,
data, NULL);
}
static int mdio_sam_read_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad, uint16_t *data)
{
int err;
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);
}
return err;
}
static int mdio_sam_write_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad, uint16_t data)
{
int err;
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 void mdio_sam_bus_enable(const struct device *dev)
@ -126,6 +148,8 @@ static int mdio_sam_initialize(const struct device *dev)
static const struct mdio_driver_api mdio_sam_driver_api = {
.read = mdio_sam_read,
.write = mdio_sam_write,
.read_c45 = mdio_sam_read_c45,
.write_c45 = mdio_sam_write_c45,
.bus_enable = mdio_sam_bus_enable,
.bus_disable = mdio_sam_bus_disable,
};
@ -134,7 +158,6 @@ static const struct mdio_driver_api mdio_sam_driver_api = {
static const struct mdio_sam_dev_config mdio_sam_dev_config_##n = { \
.regs = (Gmac *)DT_INST_REG_ADDR(n), \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.protocol = DT_INST_ENUM_IDX(n, protocol), \
};
#define MDIO_SAM_DEVICE(n) \

View file

@ -6,19 +6,3 @@
include: base.yaml
bus: mdio
properties:
protocol:
type: string
description: |
MDIO bus framing protocol to use for communication. Most devices
support clause 22.
- clause 22: IEEE802.3 clause 22 frame format
- clause 45: IEEE802.3 clause 45 frame format
- micrel SMI: Micrel Serial Management Interface frame format
enum:
- "clause 22"
- "clause 45"
- "micrel SMI"
default: "clause 22"

View file

@ -69,7 +69,6 @@
mdio: mdio {
compatible = "espressif,esp32-mdio";
protocol = "clause 22";
clocks = <&rtc ESP32_EMAC_MODULE>;
status = "disabled";
};

View file

@ -32,14 +32,6 @@ extern "C" {
* These are for internal use only, so skip these in
* public documentation.
*/
/** Order of items in this enum must match the `protocol` dts binding */
enum MDIO_PROTOCOL {
CLAUSE_22 = 0,
CLAUSE_45 = 1,
MICREL_SMI = 2,
};
__subsystem struct mdio_driver_api {
/** Enable the MDIO bus device */
void (*bus_enable)(const struct device *dev);
@ -54,6 +46,14 @@ __subsystem struct mdio_driver_api {
/** Write data to MDIO bus */
int (*write)(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t data);
/** Read data from MDIO bus using Clause 45 access */
int (*read_c45)(const struct device *dev, uint8_t prtad, uint8_t devad,
uint16_t regad, uint16_t *data);
/** Write data to MDIO bus using Clause 45 access */
int (*write_c45)(const struct device *dev, uint8_t prtad, uint8_t devad,
uint16_t regad, uint16_t data);
};
/**
* @endcond
@ -105,6 +105,7 @@ static inline void z_impl_mdio_bus_disable(const struct device *dev)
* @retval 0 If successful.
* @retval -EIO General input / output error.
* @retval -ETIMEDOUT If transaction timedout on the bus
* @retval -ENOSYS if read is not supported
*/
__syscall int mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t *data);
@ -115,6 +116,10 @@ static inline int z_impl_mdio_read(const struct device *dev, uint8_t prtad,
const struct mdio_driver_api *api =
(const struct mdio_driver_api *)dev->api;
if (api->read == NULL) {
return -ENOSYS;
}
return api->read(dev, prtad, regad, data);
}
@ -133,6 +138,7 @@ static inline int z_impl_mdio_read(const struct device *dev, uint8_t prtad,
* @retval 0 If successful.
* @retval -EIO General input / output error.
* @retval -ETIMEDOUT If transaction timedout on the bus
* @retval -ENOSYS if write is not supported
*/
__syscall int mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t data);
@ -143,9 +149,81 @@ static inline int z_impl_mdio_write(const struct device *dev, uint8_t prtad,
const struct mdio_driver_api *api =
(const struct mdio_driver_api *)dev->api;
if (api->write == NULL) {
return -ENOSYS;
}
return api->write(dev, prtad, regad, data);
}
/**
* @brief Read from MDIO Bus using Clause 45 access
*
* This routine provides an interface to perform a read on the MDIO bus using
* IEEE 802.3 Clause 45 access.
*
* @param[in] dev Pointer to the device structure for the controller
* @param[in] prtad Port address
* @param[in] devad Device address
* @param[in] regad Register address
* @param data Pointer to receive read data
*
* @retval 0 If successful.
* @retval -EIO General input / output error.
* @retval -ETIMEDOUT If transaction timedout on the bus
* @retval -ENOSYS if write using Clause 45 access is not supported
*/
__syscall int mdio_read_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad, uint16_t *data);
static inline int z_impl_mdio_read_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad,
uint16_t *data)
{
const struct mdio_driver_api *api =
(const struct mdio_driver_api *)dev->api;
if (api->read_c45 == NULL) {
return -ENOSYS;
}
return api->read_c45(dev, prtad, devad, regad, data);
}
/**
* @brief Write to MDIO bus using Clause 45 access
*
* This routine provides an interface to perform a write on the MDIO bus using
* IEEE 802.3 Clause 45 access.
*
* @param[in] dev Pointer to the device structure for the controller
* @param[in] prtad Port address
* @param[in] devad Device address
* @param[in] regad Register address
* @param[in] data Data to write
*
* @retval 0 If successful.
* @retval -EIO General input / output error.
* @retval -ETIMEDOUT If transaction timedout on the bus
* @retval -ENOSYS if write using Clause 45 access is not supported
*/
__syscall int mdio_write_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad, uint16_t data);
static inline int z_impl_mdio_write_c45(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad,
uint16_t data)
{
const struct mdio_driver_api *api =
(const struct mdio_driver_api *)dev->api;
if (api->write_c45 == NULL) {
return -ENOSYS;
}
return api->write_c45(dev, prtad, devad, regad, data);
}
#ifdef __cplusplus
}
#endif

View file

@ -1,61 +0,0 @@
/*
* Copyright (c) 2023 PHOENIX CONTACT Electronics GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_MDIO_ADIN2111_H__
#define ZEPHYR_INCLUDE_DRIVERS_MDIO_ADIN2111_H__
#include <stdint.h>
#include <zephyr/device.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Read from MDIO Bus using Clause 45 access
*
* @note The caller is responsible for device lock.
* Shall not be called from ISR.
*
* @param[in] dev MDIO device.
* @param[in] prtad Port address.
* @param[in] devad Device address.
* @param[in] regad Register address.
* @param[out] data Pointer to receive read data.
*
* @retval 0 If successful.
* @retval -EIO General input / output error.
* @retval -ETIMEDOUT If transaction timedout on the bus.
* @retval <0 Error, a negative errno code.
*/
int adin2111_mdio_c45_read(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad, uint16_t *data);
/**
* @brief Write to MDIO bus using Clause 45 access
*
* @note The caller is responsible for device lock.
* Shall not be called from ISR.
*
* @param[in] dev MDIO device.
* @param[in] prtad Port address.
* @param[in] devad Device address.
* @param[in] regad Register address.
* @param[in] data Data to write.
*
* @retval 0 If successful.
* @retval -EIO General input / output error.
* @retval -ETIMEDOUT If transaction timedout on the bus.
* @retval <0 Error, a negative errno code.
*/
int adin2111_mdio_c45_write(const struct device *dev, uint8_t prtad,
uint8_t devad, uint16_t regad, uint16_t data);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_MDIO_ADIN2111_H__ */

233
include/zephyr/net/mdio.h Normal file
View file

@ -0,0 +1,233 @@
/*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Definitions for IEEE 802.3 management interface
*/
#ifndef ZEPHYR_INCLUDE_NET_MDIO_H_
#define ZEPHYR_INCLUDE_NET_MDIO_H_
/**
* @brief Definitions for IEEE 802.3 management interface
* @defgroup ethernet_mdio IEEE 802.3 management interface
* @ingroup ethernet
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** MDIO transaction operation code */
enum mdio_opcode {
/** IEEE 802.3 22.2.4.5.4 write operation */
MDIO_OP_C22_WRITE = 1,
/** IEEE 802.3 22.2.4.5.4 read operation */
MDIO_OP_C22_READ = 2,
/** IEEE 802.3 45.3.4 address operation */
MDIO_OP_C45_ADDRESS = 0,
/** IEEE 802.3 45.3.4 write operation */
MDIO_OP_C45_WRITE = 1,
/** IEEE 802.3 45.3.4 post-read-increment-address operation */
MDIO_OP_C45_READ_INC = 2,
/** IEEE 802.3 45.3.4 read operation */
MDIO_OP_C45_READ = 3
};
/* MDIO Manageable Device addresses */
/** Physical Medium Attachment / Physical Medium Dependent */
#define MDIO_MMD_PMAPMD 0x01U
/** WAN Interface Sublayer */
#define MDIO_MMD_WIS 0x02U
/** Physical Coding Sublayer */
#define MDIO_MMD_PCS 0x03U
/** PHY Extender Sublayer */
#define MDIO_MMD_PHYXS 0x04U
/** DTE Extender Sublayer */
#define MDIO_MMD_DTEXS 0x05U
/** Transmission Convergence */
#define MDIO_MMD_TC 0x06U
/** Auto-negotiation */
#define MDIO_MMD_AN 0x07U
/** Separated PMA (1) */
#define MDIO_MMD_SEPARATED_PMA1 0x08U
/** Separated PMA (2) */
#define MDIO_MMD_SEPARATED_PMA2 0x09U
/** Separated PMA (3) */
#define MDIO_MMD_SEPARATED_PMA3 0x0AU
/** Separated PMA (4) */
#define MDIO_MMD_SEPARATED_PMA4 0x0BU
/** Clause 22 extension */
#define MDIO_MMD_C22EXT 0x1DU
/** Vendor Specific 1 */
#define MDIO_MMD_VENDOR_SPECIFIC1 0x1EU
/** Vendor Specific 2 */
#define MDIO_MMD_VENDOR_SPECIFIC2 0x1FU
/* MDIO generic registers */
/** Control 1 */
#define MDIO_CTRL1 0x0000U
/** Status 1 */
#define MDIO_STAT1 0x0001U
/** Device identifier (1) */
#define MDIO_DEVID1 0x0002U
/** Device identifier (2) */
#define MDIO_DEVID2 0x0003U
/** Speed ability */
#define MDIO_SPEED 0x0004U
/** Devices in package (1) */
#define MDIO_DEVS1 0x0005U
/** Devices in package (2) */
#define MDIO_DEVS2 0x0006U
/** Control 2 */
#define MDIO_CTRL2 0x0007U
/** Status 2 */
#define MDIO_STAT2 0x0008U
/** Package identifier (1) */
#define MDIO_PKGID1 0x000EU
/** Package identifier (2) */
#define MDIO_PKGID2 0x000FU
/* BASE-T1 registers */
/** BASE-T1 Auto-negotiation control */
#define MDIO_AN_T1_CTRL 0x0200U
/** BASE-T1 Auto-negotiation status */
#define MDIO_AN_T1_STAT 0x0201U
/** BASE-T1 Auto-negotiation advertisement register [15:0] */
#define MDIO_AN_T1_ADV_L 0x0202U
/** BASE-T1 Auto-negotiation advertisement register [31:16] */
#define MDIO_AN_T1_ADV_M 0x0203U
/** BASE-T1 Auto-negotiation advertisement register [47:32] */
#define MDIO_AN_T1_ADV_H 0x0204U
/* BASE-T1 Auto-negotiation Control register */
/** Auto-negotiation Restart */
#define MDIO_AN_T1_CTRL_RESTART BIT(9)
/** Auto-negotiation Enable */
#define MDIO_AN_T1_CTRL_EN BIT(12)
/* BASE-T1 Auto-negotiation Status register */
/** Link Status */
#define MDIO_AN_T1_STAT_LINK_STATUS BIT(2)
/** Auto-negotiation Ability */
#define MDIO_AN_T1_STAT_ABLE BIT(3)
/** Auto-negotiation Remote Fault */
#define MDIO_AN_T1_STAT_REMOTE_FAULT BIT(4)
/** Auto-negotiation Complete */
#define MDIO_AN_T1_STAT_COMPLETE BIT(5)
/** Page Received */
#define MDIO_AN_T1_STAT_PAGE_RX BIT(6)
/* BASE-T1 Auto-negotiation Advertisement register [15:0] */
/** Pause Ability */
#define MDIO_AN_T1_ADV_L_PAUSE_CAP BIT(10)
/** Pause Ability */
#define MDIO_AN_T1_ADV_L_PAUSE_ASYM BIT(11)
/** Force Master/Slave Configuration */
#define MDIO_AN_T1_ADV_L_FORCE_MS BIT(12)
/** Remote Fault */
#define MDIO_AN_T1_ADV_L_REMOTE_FAULT BIT(13)
/** Acknowledge (ACK) */
#define MDIO_AN_T1_ADV_L_ACK BIT(14)
/** Next Page Request */
#define MDIO_AN_T1_ADV_L_NEXT_PAGE_REQ BIT(15)
/* BASE-T1 Auto-negotiation Advertisement register [31:16] */
/** 10BASE-T1L Ability */
#define MDIO_AN_T1_ADV_M_B10L BIT(14)
/** Master/slave Configuration */
#define MDIO_AN_T1_ADV_M_MST BIT(4)
/* BASE-T1 Auto-negotiation Advertisement register [47:32] */
/* 10BASE-T1L High Level Transmit Operating Mode Request */
#define MDIO_AN_T1_ADV_H_10L_TX_HI_REQ BIT(12)
/* 10BASE-T1L High Level Transmit Operating Mode Ability */
#define MDIO_AN_T1_ADV_H_10L_TX_HI BIT(13)
/* 10BASE-T1L registers */
/** 10BASE-T1L PMA control */
#define MDIO_PMA_B10L_CTRL 0x08F6U
/** 10BASE-T1L PMA status */
#define MDIO_PMA_B10L_STAT 0x08F7U
/** 10BASE-T1L PMA link status*/
#define MDIO_PMA_B10L_LINK_STAT 0x8302U
/** 10BASE-T1L PCS control */
#define MDIO_PCS_B10L_CTRL 0x08E6U
/** 10BASE-T1L PCS status */
#define MDIO_PCS_B10L_STAT 0x08E7U
/* 10BASE-T1L PMA control register */
/** 10BASE-T1L Transmit Disable Mode */
#define MDIO_PMA_B10L_CTRL_TX_DIS_MODE_EN BIT(14)
/** 10BASE-T1L Transmit Voltage Amplitude Control */
#define MDIO_PMA_B10L_CTRL_TX_LVL_HI BIT(12)
/** 10BASE-T1L EEE Enable */
#define MDIO_PMA_B10L_CTRL_EEE BIT(10)
/** 10BASE-T1L PMA Loopback */
#define MDIO_PMA_B10L_CTRL_LB_PMA_LOC_EN BIT(0)
/* 10BASE-T1L PMA status register */
/** 10BASE-T1L PMA receive link up */
#define MDIO_PMA_B10L_STAT_LINK BIT(0)
/** 10BASE-T1L Fault condition detected */
#define MDIO_PMA_B10L_STAT_FAULT BIT(1)
/** 10BASE-T1L Receive polarity is reversed */
#define MDIO_PMA_B10L_STAT_POLARITY BIT(2)
/** 10BASE-T1L Able to detect fault on receive path */
#define MDIO_PMA_B10L_STAT_RECV_FAULT BIT(9)
/** 10BASE-T1L PHY has EEE ability */
#define MDIO_PMA_B10L_STAT_EEE BIT(10)
/** 10BASE-T1L PMA has low-power ability */
#define MDIO_PMA_B10L_STAT_LOW_POWER BIT(11)
/** 10BASE-T1L PHY has 2.4 Vpp operating mode ability */
#define MDIO_PMA_B10L_STAT_2V4_ABLE BIT(12)
/** 10BASE-T1L PHY has loopback ability */
#define MDIO_PMA_B10L_STAT_LB_ABLE BIT(13)
/* 10BASE-T1L PMA link status*/
/** 10BASE-T1L Remote Receiver Status OK Latch Low */
#define MDIO_PMA_B10L_LINK_STAT_REM_RCVR_STAT_OK_LL BIT(9)
/** 10BASE-T1L Remote Receiver Status OK */
#define MDIO_PMA_B10L_LINK_STAT_REM_RCVR_STAT_OK BIT(8)
/** 10BASE-T1L Local Receiver Status OK */
#define MDIO_PMA_B10L_LINK_STAT_LOC_RCVR_STAT_OK_LL BIT(7)
/** 10BASE-T1L Local Receiver Status OK */
#define MDIO_PMA_B10L_LINK_STAT_LOC_RCVR_STAT_OK BIT(6)
/** 10BASE-T1L Descrambler Status OK Latch Low */
#define MDIO_PMA_B10L_LINK_STAT_DSCR_STAT_OK_LL BIT(5)
/** 10BASE-T1L Descrambler Status OK */
#define MDIO_PMA_B10L_LINK_STAT_DSCR_STAT_OK BIT(4)
/** 10BASE-T1L Link Status OK Latch Low */
#define MDIO_PMA_B10L_LINK_STAT_LINK_STAT_OK_LL BIT(1)
/** 10BASE-T1L Link Status OK */
#define MDIO_PMA_B10L_LINK_STAT_LINK_STAT_OK BIT(0)
/* 10BASE-T1L PCS control */
/** 10BASE-T1L PCS Loopback Enable */
#define MDIO_PCS_B10L_CTRL_LB_PCS_EN BIT(14)
/* 10BASE-T1L PCS status */
/** 10BASE-T1L PCS Descrambler Status */
#define MDIO_PCS_B10L_STAT_DSCR_STAT_OK_LL BIT(2)
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_NET_MDIO_H_ */