From 6a39889eb8ed35d566c2877ec6b46aba5950443f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 15:00:36 +0200 Subject: [PATCH 01/13] dts: bindings: ethernet: move adi,adin*11*.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit move adi,adin1110.yaml adi,adin2111.yaml from the phy subdir back into the ethernet dir. They are ethernet controller bindings, not phy bindings. Signed-off-by: Fin Maaß --- dts/bindings/ethernet/{phy => }/adi,adin1110.yaml | 0 dts/bindings/ethernet/{phy => }/adi,adin2111.yaml | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename dts/bindings/ethernet/{phy => }/adi,adin1110.yaml (100%) rename dts/bindings/ethernet/{phy => }/adi,adin2111.yaml (100%) diff --git a/dts/bindings/ethernet/phy/adi,adin1110.yaml b/dts/bindings/ethernet/adi,adin1110.yaml similarity index 100% rename from dts/bindings/ethernet/phy/adi,adin1110.yaml rename to dts/bindings/ethernet/adi,adin1110.yaml diff --git a/dts/bindings/ethernet/phy/adi,adin2111.yaml b/dts/bindings/ethernet/adi,adin2111.yaml similarity index 100% rename from dts/bindings/ethernet/phy/adi,adin2111.yaml rename to dts/bindings/ethernet/adi,adin2111.yaml From e4ecb1aef1bf64411939b2520112722070c8669b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 15:03:37 +0200 Subject: [PATCH 02/13] drivers: ethernet: phy: ar8031: remove fixed link mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixed link mode is a mode where we don't comunicate with the phy, therefore we don't need it in other phys as the generic phy_mii one. Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_qualcomm_ar8031.c | 38 ++++------------------ 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/drivers/ethernet/phy/phy_qualcomm_ar8031.c b/drivers/ethernet/phy/phy_qualcomm_ar8031.c index 0a744c7bcbdae..9736139c1980b 100644 --- a/drivers/ethernet/phy/phy_qualcomm_ar8031.c +++ b/drivers/ethernet/phy/phy_qualcomm_ar8031.c @@ -57,9 +57,7 @@ LOG_MODULE_REGISTER(phy_qc_ar8031, CONFIG_PHY_LOG_LEVEL); struct qc_ar8031_config { uint8_t addr; - bool fixed_link; bool enable_eee; - int fixed_speed; const struct device *mdio_dev; }; @@ -414,36 +412,14 @@ static int qc_ar8031_init(const struct device *dev) } } - /* Fixed Link */ - if (cfg->fixed_link) { - /* Disable isolate */ - ret = qc_ar8031_read(dev, MII_BMCR, ®_value); - if (ret) { - return -EIO; - } - reg_value &= ~MII_BMCR_ISOLATE; - ret = qc_ar8031_write(dev, MII_BMCR, reg_value); - if (ret) { - return -EIO; - } - - const static int speed_to_phy_link_speed[] = { - LINK_HALF_10BASE, LINK_FULL_10BASE, LINK_HALF_100BASE, - LINK_FULL_100BASE, LINK_HALF_1000BASE, LINK_FULL_1000BASE, - }; + /* Advertise all speeds */ + qc_ar8031_cfg_link(dev, LINK_HALF_10BASE | LINK_FULL_10BASE | + LINK_HALF_100BASE | LINK_FULL_100BASE | + LINK_HALF_1000BASE | LINK_FULL_1000BASE, 0); - data->state.speed = speed_to_phy_link_speed[cfg->fixed_speed]; - data->state.is_up = true; - } else { /* Auto negotiation */ - /* Advertise all speeds */ - qc_ar8031_cfg_link(dev, LINK_HALF_10BASE | LINK_FULL_10BASE | - LINK_HALF_100BASE | LINK_FULL_100BASE | - LINK_HALF_1000BASE | LINK_FULL_1000BASE, 0); + k_work_init_delayable(&data->monitor_work, monitor_work_handler); - k_work_init_delayable(&data->monitor_work, monitor_work_handler); - - monitor_work_handler(&data->monitor_work.work); - } + monitor_work_handler(&data->monitor_work.work); return 0; } @@ -459,8 +435,6 @@ static DEVICE_API(ethphy, ar8031_driver_api) = { #define AR8031_CONFIG(n) \ static const struct qc_ar8031_config qc_ar8031_config_##n = { \ .addr = DT_INST_REG_ADDR(n), \ - .fixed_link = DT_INST_NODE_HAS_PROP(n, fixed_link), \ - .fixed_speed = DT_INST_ENUM_IDX_OR(n, fixed_link, 0), \ .mdio_dev = DEVICE_DT_GET(DT_INST_BUS(n)), \ .enable_eee = DT_INST_NODE_HAS_PROP(n, eee_en), \ }; From 0fe8331f57e722eff89a2d2d0b9ff68775b184ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 15:15:49 +0200 Subject: [PATCH 03/13] drivers: ethernet: phy: dts: split ethernet-phy.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit split ethernet-phy.yaml, so that parts, that are used by other phys are separated. Signed-off-by: Fin Maaß --- .../ethernet/phy/davicom,dm8806-phy.yaml | 2 +- .../ethernet/phy/ethernet-phy-common.yaml | 21 +++++++++++++++++++ dts/bindings/ethernet/phy/ethernet-phy.yaml | 14 +------------ .../ethernet/phy/microchip,ksz8081.yaml | 2 +- .../ethernet/phy/microchip,vsc8541-phy.yaml | 2 +- dts/bindings/ethernet/phy/qca,ar8031.yaml | 2 +- .../ethernet/phy/realtek,rtl8211f.yaml | 2 +- dts/bindings/ethernet/phy/ti,dp83825.yaml | 2 +- dts/bindings/ethernet/phy/ti,dp83867.yaml | 2 +- 9 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 dts/bindings/ethernet/phy/ethernet-phy-common.yaml diff --git a/dts/bindings/ethernet/phy/davicom,dm8806-phy.yaml b/dts/bindings/ethernet/phy/davicom,dm8806-phy.yaml index c4196bfe33449..9830a04729bc8 100644 --- a/dts/bindings/ethernet/phy/davicom,dm8806-phy.yaml +++ b/dts/bindings/ethernet/phy/davicom,dm8806-phy.yaml @@ -5,7 +5,7 @@ description: Davicom DM8806 Ethernet MAC and PHY with RMII interface compatible: "davicom,dm8806-phy" -include: [ethernet-phy.yaml] +include: [ethernet-phy-common.yaml] on-bus: mdio diff --git a/dts/bindings/ethernet/phy/ethernet-phy-common.yaml b/dts/bindings/ethernet/phy/ethernet-phy-common.yaml new file mode 100644 index 0000000000000..38a57a159e872 --- /dev/null +++ b/dts/bindings/ethernet/phy/ethernet-phy-common.yaml @@ -0,0 +1,21 @@ +# Copyright The Zephyr Project Contributors +# SPDX-License-Identifier: Apache-2.0 + +# Common fields for MIIPHY devices + +include: phy.yaml + +properties: + reg: + required: true + description: PHY address + default-speeds: + type: string-array + description: The selected speeds are used to configure the PHY during initialization + enum: + - "10BASE Half-Duplex" + - "10BASE Full-Duplex" + - "100BASE Half-Duplex" + - "100BASE Full-Duplex" + - "1000BASE Half-Duplex" + - "1000BASE Full-Duplex" diff --git a/dts/bindings/ethernet/phy/ethernet-phy.yaml b/dts/bindings/ethernet/phy/ethernet-phy.yaml index 22704da0d40d6..e00483d33b9df 100644 --- a/dts/bindings/ethernet/phy/ethernet-phy.yaml +++ b/dts/bindings/ethernet/phy/ethernet-phy.yaml @@ -7,12 +7,9 @@ description: Generic MII PHY compatible: "ethernet-phy" -include: phy.yaml +include: ethernet-phy-common.yaml properties: - reg: - required: true - description: PHY address no-reset: type: boolean description: Do not reset the PHY during initialization @@ -27,14 +24,5 @@ properties: - "1000BASE-T Half-Duplex" - "1000BASE-T Full-Duplex" default-speeds: - type: string-array - description: The selected speeds are used to configure the PHY during initialization - enum: - - "10BASE Half-Duplex" - - "10BASE Full-Duplex" - - "100BASE Half-Duplex" - - "100BASE Full-Duplex" - - "1000BASE Half-Duplex" - - "1000BASE Full-Duplex" default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex", "100BASE Full-Duplex", "1000BASE Half-Duplex", "1000BASE Full-Duplex"] diff --git a/dts/bindings/ethernet/phy/microchip,ksz8081.yaml b/dts/bindings/ethernet/phy/microchip,ksz8081.yaml index 7667fca85314b..db035981fe2d5 100644 --- a/dts/bindings/ethernet/phy/microchip,ksz8081.yaml +++ b/dts/bindings/ethernet/phy/microchip,ksz8081.yaml @@ -5,7 +5,7 @@ description: Microchip KSZ8081 Ethernet PHY device compatible: "microchip,ksz8081" -include: ethernet-phy.yaml +include: ethernet-phy-common.yaml properties: reset-gpios: diff --git a/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml b/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml index d8df5f8f4d928..c16f2e9e5d411 100644 --- a/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml +++ b/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml @@ -5,7 +5,7 @@ description: Single Port Gigabit Ethernet Copper PHY with GMII/RGMII/MII/RMII In compatible: "microchip,vsc8541" -include: [ethernet-phy.yaml] +include: [ethernet-phy-common.yaml] on-bus: mdio diff --git a/dts/bindings/ethernet/phy/qca,ar8031.yaml b/dts/bindings/ethernet/phy/qca,ar8031.yaml index 479c14f40ab89..2b3007faa262c 100644 --- a/dts/bindings/ethernet/phy/qca,ar8031.yaml +++ b/dts/bindings/ethernet/phy/qca,ar8031.yaml @@ -5,7 +5,7 @@ description: Qualcomm Atheros AR8031 Ethernet PHY compatible: "qca,ar8031" -include: ethernet-phy.yaml +include: ethernet-phy-common.yaml properties: eee-en: diff --git a/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml b/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml index 1f8cc22e71db3..815545085356a 100644 --- a/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml +++ b/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml @@ -5,7 +5,7 @@ description: Realtek RTL8211F Ethernet PHY device compatible: "realtek,rtl8211f" -include: ethernet-phy.yaml +include: ethernet-phy-common.yaml properties: reset-gpios: diff --git a/dts/bindings/ethernet/phy/ti,dp83825.yaml b/dts/bindings/ethernet/phy/ti,dp83825.yaml index 4846f31f08eac..ca6b67af74d99 100644 --- a/dts/bindings/ethernet/phy/ti,dp83825.yaml +++ b/dts/bindings/ethernet/phy/ti,dp83825.yaml @@ -5,7 +5,7 @@ description: TI DP83825 Ethernet PHY device compatible: "ti,dp83825" -include: ethernet-phy.yaml +include: ethernet-phy-common.yaml properties: reset-gpios: diff --git a/dts/bindings/ethernet/phy/ti,dp83867.yaml b/dts/bindings/ethernet/phy/ti,dp83867.yaml index 6bc38cab7b52f..f60c35620f661 100644 --- a/dts/bindings/ethernet/phy/ti,dp83867.yaml +++ b/dts/bindings/ethernet/phy/ti,dp83867.yaml @@ -5,7 +5,7 @@ description: TI DP83867 Ethernet PHY device compatible: "ti,dp83867" -include: ethernet-phy.yaml +include: ethernet-phy-common.yaml properties: reset-gpios: From dfff05a3cb4f33f06b39ffa826b693e17848ba4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 15:59:24 +0200 Subject: [PATCH 04/13] drivers: ethernet: remove phy_configure_link() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit remove the use of phy_configure_link() in the ethernet drivers. The user can now select the default speeds via DT prop, doing another phy_configure_link() in the eth driver would overwrite that. Signed-off-by: Fin Maaß --- drivers/ethernet/eth_nxp_enet.c | 55 ++------------------------- drivers/ethernet/eth_xilinx_axienet.c | 7 ---- 2 files changed, 4 insertions(+), 58 deletions(-) diff --git a/drivers/ethernet/eth_nxp_enet.c b/drivers/ethernet/eth_nxp_enet.c index b9247b23059be..a19b3ec3f7ebb 100644 --- a/drivers/ethernet/eth_nxp_enet.c +++ b/drivers/ethernet/eth_nxp_enet.c @@ -459,51 +459,12 @@ static void eth_nxp_enet_rx_thread(struct k_work *work) ENET_EnableInterrupts(data->base, kENET_RxFrameInterrupt); } -static int nxp_enet_phy_configure(const struct device *phy, uint8_t phy_mode) -{ - enum phy_link_speed speeds = LINK_HALF_10BASE | LINK_FULL_10BASE | - LINK_HALF_100BASE | LINK_FULL_100BASE; - int ret; - struct phy_link_state state; - - if (COND_CODE_1(IS_ENABLED(CONFIG_ETH_NXP_ENET_1G), - (phy_mode == NXP_ENET_RGMII_MODE), (0))) { - speeds |= (LINK_HALF_1000BASE | LINK_FULL_1000BASE); - } - - /* Configure the PHY */ - ret = phy_configure_link(phy, speeds, 0); - if (ret == -EALREADY) { - return 0; - } else if (ret == -ENOTSUP || ret == -ENOSYS) { - phy_get_link_state(phy, &state); - - if (state.is_up) { - LOG_WRN("phy_configure_link returned %d, but link is up. " - "Speed: %s, %s-duplex", - ret, - PHY_LINK_IS_SPEED_1000M(state.speed) ? "1 Gbits" : - PHY_LINK_IS_SPEED_100M(state.speed) ? "100 Mbits" : "10 Mbits", - PHY_LINK_IS_FULL_DUPLEX(state.speed) ? "full" : "half"); - } else { - LOG_ERR("phy_configure_link returned %d and link is down.", ret); - return -ENETDOWN; - } - } else if (ret) { - LOG_ERR("phy_configure_link failed with error: %d", ret); - return ret; - } - - return 0; -} - static void nxp_enet_phy_cb(const struct device *phy, struct phy_link_state *state, void *eth_dev) { const struct device *dev = eth_dev; struct nxp_enet_mac_data *data = dev->data; - const struct nxp_enet_mac_config *config = dev->config; enet_mii_speed_t speed; enet_mii_duplex_t duplex; @@ -527,16 +488,13 @@ static void nxp_enet_phy_cb(const struct device *phy, } ENET_SetMII(data->base, speed, duplex); - } - - LOG_INF("Link is %s", state->is_up ? "up" : "down"); - if (!state->is_up) { - net_eth_carrier_off(data->iface); - nxp_enet_phy_configure(phy, config->phy_mode); - } else { net_eth_carrier_on(data->iface); + } else { + net_eth_carrier_off(data->iface); } + + LOG_INF("Link is %s", state->is_up ? "up" : "down"); } static void eth_nxp_enet_iface_init(struct net_if *iface) @@ -813,11 +771,6 @@ static int eth_nxp_enet_init(const struct device *dev) ENET_ActiveRead(data->base); - err = nxp_enet_phy_configure(config->phy_dev, config->phy_mode); - if (err) { - return err; - } - LOG_DBG("%s MAC %02x:%02x:%02x:%02x:%02x:%02x", dev->name, data->mac_addr[0], data->mac_addr[1], diff --git a/drivers/ethernet/eth_xilinx_axienet.c b/drivers/ethernet/eth_xilinx_axienet.c index bdc5c1f2cac9b..4e2cabe1369dc 100644 --- a/drivers/ethernet/eth_xilinx_axienet.c +++ b/drivers/ethernet/eth_xilinx_axienet.c @@ -526,13 +526,6 @@ static int xilinx_axienet_probe(const struct device *dev) XILINX_AXIENET_RECEIVER_CONFIGURATION_FLOW_CONTROL_OFFSET, XILINX_AXIENET_RECEIVER_CONFIGURATION_FLOW_CONTROL_EN_MASK); - /* at time of writing, hardware does not support half duplex */ - err = phy_configure_link(config->phy, - LINK_FULL_10BASE | LINK_FULL_100BASE | LINK_FULL_1000BASE, 0); - if (err) { - LOG_WRN("Could not configure PHY: %d", -err); - } - LOG_INF("RX Checksum offloading %s", config->have_rx_csum_offload ? "requested" : "disabled"); LOG_INF("TX Checksum offloading %s", From 1ba37899781293466b780a8a93d0d7678836b0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 12:29:32 +0200 Subject: [PATCH 05/13] drivers: ethernet: phy: put shared macro in shared header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit put the macro to get the default speeds into a shared header for the phys. Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_mii.c | 12 ++---------- drivers/ethernet/phy/phy_mii.h | 8 ++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/ethernet/phy/phy_mii.c b/drivers/ethernet/phy/phy_mii.c index 98a955173fb24..93415390bfa47 100644 --- a/drivers/ethernet/phy/phy_mii.c +++ b/drivers/ethernet/phy/phy_mii.c @@ -549,16 +549,8 @@ static DEVICE_API(ethphy, phy_mii_driver_api) = { #endif }; -#define PHY_MII_GENERATE_DEFAULT_SPEEDS(n) \ -((DT_INST_ENUM_HAS_VALUE(n, default_speeds, 10base_half_duplex) ? LINK_HALF_10BASE : 0) | \ -(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 10base_full_duplex) ? LINK_FULL_10BASE : 0) | \ -(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 100base_half_duplex) ? LINK_HALF_100BASE : 0) | \ -(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 100base_full_duplex) ? LINK_FULL_100BASE : 0) | \ -(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 1000base_half_duplex) ? LINK_HALF_1000BASE : 0) | \ -(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 1000base_full_duplex) ? LINK_FULL_1000BASE : 0)) - #define PHY_MII_CONFIG(n) \ -BUILD_ASSERT(PHY_MII_GENERATE_DEFAULT_SPEEDS(n) != 0, \ +BUILD_ASSERT(PHY_INST_GENERATE_DEFAULT_SPEEDS(n) != 0, \ "At least one valid speed must be configured for this driver"); \ \ static const struct phy_mii_dev_config phy_mii_dev_config_##n = { \ @@ -566,7 +558,7 @@ static const struct phy_mii_dev_config phy_mii_dev_config_##n = { \ .no_reset = DT_INST_PROP(n, no_reset), \ .fixed = IS_FIXED_LINK(n), \ .fixed_speed = DT_INST_ENUM_IDX_OR(n, fixed_link, 0), \ - .default_speeds = PHY_MII_GENERATE_DEFAULT_SPEEDS(n), \ + .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \ .mdio = UTIL_AND(UTIL_NOT(IS_FIXED_LINK(n)), \ DEVICE_DT_GET(DT_INST_BUS(n))) \ }; diff --git a/drivers/ethernet/phy/phy_mii.h b/drivers/ethernet/phy/phy_mii.h index 2615f219a88f9..e29d4b2be9af9 100644 --- a/drivers/ethernet/phy/phy_mii.h +++ b/drivers/ethernet/phy/phy_mii.h @@ -11,6 +11,14 @@ #include #include +#define PHY_INST_GENERATE_DEFAULT_SPEEDS(n) \ +((DT_INST_ENUM_HAS_VALUE(n, default_speeds, 10base_half_duplex) ? LINK_HALF_10BASE : 0) | \ +(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 10base_full_duplex) ? LINK_FULL_10BASE : 0) | \ +(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 100base_half_duplex) ? LINK_HALF_100BASE : 0) | \ +(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 100base_full_duplex) ? LINK_FULL_100BASE : 0) | \ +(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 1000base_half_duplex) ? LINK_HALF_1000BASE : 0) | \ +(DT_INST_ENUM_HAS_VALUE(n, default_speeds, 1000base_full_duplex) ? LINK_FULL_1000BASE : 0)) + static inline int phy_mii_set_anar_reg(const struct device *dev, enum phy_link_speed adv_speeds) { uint32_t anar_reg = 0U; From 7ab0f6124f57062c5e36cf0d2607aed68fa5532c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 12:31:05 +0200 Subject: [PATCH 06/13] drivers: ethernet: phy: ksz8081: use default speeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use default speeds from dt to configure phy on init. Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_microchip_ksz8081.c | 5 +++++ dts/bindings/ethernet/phy/microchip,ksz8081.yaml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/drivers/ethernet/phy/phy_microchip_ksz8081.c b/drivers/ethernet/phy/phy_microchip_ksz8081.c index f159a8ce6c565..3f7368137b0fe 100644 --- a/drivers/ethernet/phy/phy_microchip_ksz8081.c +++ b/drivers/ethernet/phy/phy_microchip_ksz8081.c @@ -44,6 +44,7 @@ struct mc_ksz8081_config { uint8_t addr; const struct device *mdio_dev; enum ksz8081_interface phy_iface; + enum phy_link_speed default_speeds; #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) const struct gpio_dt_spec reset_gpio; #endif @@ -489,6 +490,9 @@ static int phy_mc_ksz8081_init(const struct device *dev) k_work_init_delayable(&data->phy_monitor_work, phy_mc_ksz8081_monitor_work_handler); + /* Advertise default speeds */ + phy_mc_ksz8081_cfg_link(dev, config->default_speeds, 0); + return 0; } @@ -519,6 +523,7 @@ static DEVICE_API(ethphy, mc_ksz8081_phy_api) = { .addr = DT_INST_REG_ADDR(n), \ .mdio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .phy_iface = DT_INST_ENUM_IDX(n, microchip_interface_type), \ + .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \ RESET_GPIO(n) \ INTERRUPT_GPIO(n) \ }; \ diff --git a/dts/bindings/ethernet/phy/microchip,ksz8081.yaml b/dts/bindings/ethernet/phy/microchip,ksz8081.yaml index db035981fe2d5..702a1f45ff853 100644 --- a/dts/bindings/ethernet/phy/microchip,ksz8081.yaml +++ b/dts/bindings/ethernet/phy/microchip,ksz8081.yaml @@ -22,3 +22,6 @@ properties: - "mii" - "rmii" - "rmii-25MHz" + default-speeds: + default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex", + "100BASE Full-Duplex"] From aab1f7c7c236e8e249a62c29b0008a8c7e3c6f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 12:31:38 +0200 Subject: [PATCH 07/13] drivers: ethernet: phy: ar8031: use default speeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use default speeds from dt to configure phy on init. Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_qualcomm_ar8031.c | 8 ++++---- dts/bindings/ethernet/phy/qca,ar8031.yaml | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/ethernet/phy/phy_qualcomm_ar8031.c b/drivers/ethernet/phy/phy_qualcomm_ar8031.c index 9736139c1980b..8197857cf4323 100644 --- a/drivers/ethernet/phy/phy_qualcomm_ar8031.c +++ b/drivers/ethernet/phy/phy_qualcomm_ar8031.c @@ -58,6 +58,7 @@ LOG_MODULE_REGISTER(phy_qc_ar8031, CONFIG_PHY_LOG_LEVEL); struct qc_ar8031_config { uint8_t addr; bool enable_eee; + enum phy_link_speed default_speeds; const struct device *mdio_dev; }; @@ -412,10 +413,8 @@ static int qc_ar8031_init(const struct device *dev) } } - /* Advertise all speeds */ - qc_ar8031_cfg_link(dev, LINK_HALF_10BASE | LINK_FULL_10BASE | - LINK_HALF_100BASE | LINK_FULL_100BASE | - LINK_HALF_1000BASE | LINK_FULL_1000BASE, 0); + /* Advertise default speeds */ + qc_ar8031_cfg_link(dev, cfg->default_speeds, 0); k_work_init_delayable(&data->monitor_work, monitor_work_handler); @@ -436,6 +435,7 @@ static DEVICE_API(ethphy, ar8031_driver_api) = { static const struct qc_ar8031_config qc_ar8031_config_##n = { \ .addr = DT_INST_REG_ADDR(n), \ .mdio_dev = DEVICE_DT_GET(DT_INST_BUS(n)), \ + .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \ .enable_eee = DT_INST_NODE_HAS_PROP(n, eee_en), \ }; diff --git a/dts/bindings/ethernet/phy/qca,ar8031.yaml b/dts/bindings/ethernet/phy/qca,ar8031.yaml index 2b3007faa262c..a57abae770997 100644 --- a/dts/bindings/ethernet/phy/qca,ar8031.yaml +++ b/dts/bindings/ethernet/phy/qca,ar8031.yaml @@ -13,3 +13,6 @@ properties: description: | Enable IEEE 802.3az Energy Efficient Ethernet which provides a mechanism to greatly save the power consumption between data packets burst. + default-speeds: + default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex", + "100BASE Full-Duplex", "1000BASE Half-Duplex", "1000BASE Full-Duplex"] From 8b246fdd1346924a33c5c5afb9c8dda8246de310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 12:32:18 +0200 Subject: [PATCH 08/13] drivers: ethernet: phy: rtl8211f: use default speeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use default speeds from dt to configure phy on init. Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_realtek_rtl8211f.c | 5 +++++ dts/bindings/ethernet/phy/realtek,rtl8211f.yaml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/drivers/ethernet/phy/phy_realtek_rtl8211f.c b/drivers/ethernet/phy/phy_realtek_rtl8211f.c index d4996bdc03476..46b8a24f0731a 100644 --- a/drivers/ethernet/phy/phy_realtek_rtl8211f.c +++ b/drivers/ethernet/phy/phy_realtek_rtl8211f.c @@ -61,6 +61,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); struct rt_rtl8211f_config { uint8_t addr; const struct device *mdio_dev; + enum phy_link_speed default_speeds; #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) const struct gpio_dt_spec reset_gpio; #endif @@ -599,6 +600,9 @@ static int phy_rt_rtl8211f_init(const struct device *dev) phy_rt_rtl8211f_monitor_work_handler(&data->phy_monitor_work.work); #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + /* Advertise default speeds */ + phy_rt_rtl8211f_cfg_link(dev, config->default_speeds, 0); + return 0; } @@ -628,6 +632,7 @@ static DEVICE_API(ethphy, rt_rtl8211f_phy_api) = { static const struct rt_rtl8211f_config rt_rtl8211f_##n##_config = { \ .addr = DT_INST_REG_ADDR(n), \ .mdio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \ RESET_GPIO(n) \ INTERRUPT_GPIO(n) \ }; \ diff --git a/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml b/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml index 815545085356a..a20ea85335624 100644 --- a/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml +++ b/dts/bindings/ethernet/phy/realtek,rtl8211f.yaml @@ -14,3 +14,6 @@ properties: int-gpios: type: phandle-array description: GPIO for interrupt signal indicating PHY state change. + default-speeds: + default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex", + "100BASE Full-Duplex", "1000BASE Half-Duplex", "1000BASE Full-Duplex"] From e1b6493fa7a276993629abfde1aaea3d7ce45c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 12:32:44 +0200 Subject: [PATCH 09/13] drivers: ethernet: phy: dp83825: use default speeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use default speeds from dt to configure phy on init. Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_ti_dp83825.c | 5 +++++ dts/bindings/ethernet/phy/ti,dp83825.yaml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/drivers/ethernet/phy/phy_ti_dp83825.c b/drivers/ethernet/phy/phy_ti_dp83825.c index ba20fa2faaa4d..6e17be50debf2 100644 --- a/drivers/ethernet/phy/phy_ti_dp83825.c +++ b/drivers/ethernet/phy/phy_ti_dp83825.c @@ -45,6 +45,7 @@ struct ti_dp83825_config { uint8_t addr; const struct device *mdio_dev; enum dp83825_interface phy_iface; + enum phy_link_speed default_speeds; #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) const struct gpio_dt_spec reset_gpio; #endif @@ -537,6 +538,9 @@ static int phy_ti_dp83825_init(const struct device *dev) phy_ti_dp83825_monitor_work_handler(&data->phy_monitor_work.work); #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + /* Advertise default speeds */ + phy_ti_dp83825_cfg_link(dev, config->default_speeds, 0); + return 0; } @@ -565,6 +569,7 @@ static DEVICE_API(ethphy, ti_dp83825_phy_api) = { .addr = DT_INST_REG_ADDR(n), \ .mdio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .phy_iface = DT_INST_ENUM_IDX(n, ti_interface_type), \ + .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \ RESET_GPIO(n) INTERRUPT_GPIO(n)}; \ \ static struct ti_dp83825_data ti_dp83825_##n##_data; \ diff --git a/dts/bindings/ethernet/phy/ti,dp83825.yaml b/dts/bindings/ethernet/phy/ti,dp83825.yaml index ca6b67af74d99..a39e874420789 100644 --- a/dts/bindings/ethernet/phy/ti,dp83825.yaml +++ b/dts/bindings/ethernet/phy/ti,dp83825.yaml @@ -21,3 +21,6 @@ properties: enum: - "rmii" - "rmii-25MHz" + default-speeds: + default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex", + "100BASE Full-Duplex"] From 507d123a44bb3322cd675782d27f845b69908a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 13 Jun 2025 12:33:12 +0200 Subject: [PATCH 10/13] drivers: ethernet: phy: dp83867: use default speeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use default speeds from dt to configure phy on init. Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_ti_dp83867.c | 5 +++++ dts/bindings/ethernet/phy/ti,dp83867.yaml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/drivers/ethernet/phy/phy_ti_dp83867.c b/drivers/ethernet/phy/phy_ti_dp83867.c index ab60bbc764212..24d54520092c9 100644 --- a/drivers/ethernet/phy/phy_ti_dp83867.c +++ b/drivers/ethernet/phy/phy_ti_dp83867.c @@ -70,6 +70,7 @@ struct ti_dp83867_config { uint32_t ti_rx_internal_delay; uint32_t ti_tx_internal_delay; enum dp83826_interface phy_iface; + enum phy_link_speed default_speeds; #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) const struct gpio_dt_spec reset_gpio; #endif @@ -575,6 +576,9 @@ static int phy_ti_dp83867_init(const struct device *dev) #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ phy_ti_dp83867_monitor_work_handler(&data->phy_monitor_work.work); + /* Advertise default speeds */ + phy_ti_dp83867_cfg_link(dev, config->default_speeds, 0); + return 0; } @@ -607,6 +611,7 @@ static DEVICE_API(ethphy, ti_dp83867_phy_api) = { .ti_tx_internal_delay = DT_INST_PROP_OR(n, ti_tx_internal_delay, \ DP83867_RGMII_RX_CLK_DELAY_INV), \ .phy_iface = DT_INST_ENUM_IDX(n, ti_interface_type), \ + .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \ RESET_GPIO(n) INTERRUPT_GPIO(n)}; \ \ static struct ti_dp83867_data ti_dp83867_##n##_data; \ diff --git a/dts/bindings/ethernet/phy/ti,dp83867.yaml b/dts/bindings/ethernet/phy/ti,dp83867.yaml index f60c35620f661..58aa1efab590c 100644 --- a/dts/bindings/ethernet/phy/ti,dp83867.yaml +++ b/dts/bindings/ethernet/phy/ti,dp83867.yaml @@ -33,3 +33,6 @@ properties: - "rgmii-id" - "rgmii-rxid" - "rgmii-txid" + default-speeds: + default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex", + "100BASE Full-Duplex", "1000BASE Half-Duplex", "1000BASE Full-Duplex"] From f4e2b8d3527020eb05b55cff0beb2904402e2775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Wed, 18 Jun 2025 12:07:22 +0200 Subject: [PATCH 11/13] drivers: ethernet: phy: microchip_vsc8541: improve driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - implement configure link - support half duplex - use defines from mii.h - fix check ret vals Signed-off-by: Fin Maaß Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_microchip_vsc8541.c | 187 +++++++------------ 1 file changed, 70 insertions(+), 117 deletions(-) diff --git a/drivers/ethernet/phy/phy_microchip_vsc8541.c b/drivers/ethernet/phy/phy_microchip_vsc8541.c index d30895feb9a9e..2961e44e67d39 100644 --- a/drivers/ethernet/phy/phy_microchip_vsc8541.c +++ b/drivers/ethernet/phy/phy_microchip_vsc8541.c @@ -16,6 +16,8 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL); #include #include +#include "phy_mii.h" + /* phy page selectors */ #define PHY_PAGE_0 0x00 /* main registers space active */ #define PHY_PAGE_1 0x01 /* reg 16 - 30 will be redirected to ext. register space 1 */ @@ -26,18 +28,6 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL); #define PHY_REG(page, reg) ((page << 8) | (reg << 0)) /* Generic Register */ -#define PHY_REG_PAGE0_BMCR PHY_REG(PHY_PAGE_0, 0x00) -#define PHY_REG_PAGE0_BMSR PHY_REG(PHY_PAGE_0, 0x01) -#define PHY_REG_PAGE0_ID1 PHY_REG(PHY_PAGE_0, 0x02) -#define PHY_REG_PAGE0_ID2 PHY_REG(PHY_PAGE_0, 0x03) -#define PHY_REG_PAGE0_ADV PHY_REG(PHY_PAGE_0, 0x04) -#define PHY_REG_LPA 0x05 -#define PHY_REG_EXP 0x06 -#define PHY_REG_PAGE0_CTRL1000 PHY_REG(PHY_PAGE_0, 0x09) -#define PHY_REG_PAGE0_STAT1000 PHY_REG(0, 0x0A) -#define PHY_REG_MMD_CTRL 0x0D -#define PHY_REG_MMD_DATA 0x0E -#define PHY_REG_STAT1000_EXT1 0x0F #define PHY_REG_PAGE0_STAT100 PHY_REG(PHY_PAGE_0, 0x10) #define PHY_REG_PAGE0_STAT1000_EXT2 PHY_REG(PHY_PAGE_0, 0x11) #define PHY_REG_AUX_CTRL 0x12 @@ -45,6 +35,7 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL); #define PHY_REG_PAGE0_ERROR_COUNTER_2 PHY_REG(0, 0x14) #define PHY_REG_PAGE0_EXT_CTRL_STAT PHY_REG(PHY_PAGE_0, 0x16) #define PHY_REG_PAGE0_EXT_CONTROL_1 PHY_REG(PHY_PAGE_0, 0x17) +#define PHY_REG_PAGE0_EXT_DEV_AUX PHY_REG(PHY_PAGE_0, 0x1C) #define PHY_REG_LED_MODE 0x1d #define PHY_REG_PAGE_SELECTOR 0x1F @@ -54,19 +45,7 @@ LOG_MODULE_REGISTER(microchip_vsc8541, CONFIG_PHY_LOG_LEVEL); #define PHY_REG_PAGE2_RGMII_CONTROL PHY_REG(PHY_PAGE_2, 0x14) #define PHY_REG_PAGE2_MAC_IF_CONTROL PHY_REG(PHY_PAGE_2, 0x1b) -/* selected bits in registers */ -#define BMCR_RESET (1 << 15) -#define BMCR_LOOPBACK (1 << 14) -#define BMCR_ANENABLE (1 << 12) -#define BMCR_ANRESTART (1 << 9) -#define BMCR_FULLDPLX (1 << 8) -#define BMCR_SPEED10 ((0 << 13) | (0 << 6)) -#define BMCR_SPEED100 ((1 << 13) | (0 << 6)) -#define BMCR_SPEED1000 ((0 << 13) | (1 << 6)) - -#define BMCR_SPEEDMASK ((1 << 13) | (1 << 6)) - -#define BMSR_LSTATUS (1 << 2) +#define PHY_REG_PAGE0_EXT_DEV_AUX_DUPLEX BIT(5) enum vsc8541_interface { VSC8541_MII, @@ -123,11 +102,11 @@ static int phy_mc_vsc8541_verify_phy_id(const struct device *dev) uint16_t phy_id_1; uint16_t phy_id_2; - if (0 != phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_ID1, (uint32_t *)&phy_id_1)) { + if (phy_mc_vsc8541_read(dev, MII_PHYID1R, (uint32_t *)&phy_id_1) < 0) { return -EINVAL; } - if (0 != phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_ID2, (uint32_t *)&phy_id_2)) { + if (phy_mc_vsc8541_read(dev, MII_PHYID2R, (uint32_t *)&phy_id_2) < 0) { return -EINVAL; } @@ -153,6 +132,8 @@ static int phy_mc_vsc8541_verify_phy_id(const struct device *dev) static int phy_mc_vsc8541_reset(const struct device *dev) { const struct mc_vsc8541_config *cfg = dev->config; + int ret; + uint32_t reg = 0U; #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) @@ -162,16 +143,15 @@ static int phy_mc_vsc8541_reset(const struct device *dev) } /* configure the reset pin */ - int ret = gpio_pin_configure_dt(&cfg->reset_gpio, GPIO_OUTPUT_ACTIVE); - - if (ret) { + ret = gpio_pin_configure_dt(&cfg->reset_gpio, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { return ret; } for (uint32_t i = 0; i < 2; i++) { /* Start reset */ ret = gpio_pin_set_dt(&cfg->reset_gpio, 0); - if (ret) { + if (ret < 0) { LOG_WRN("failed to set reset gpio"); return -EINVAL; } @@ -194,7 +174,7 @@ static int phy_mc_vsc8541_reset(const struct device *dev) #if CONFIG_PHY_VERIFY_DEVICE_IDENTIFICATION /* confirm phy organizationally unique identifier, if enabled */ - if (0 != phy_mc_vsc8541_verify_phy_id(dev)) { + if (phy_mc_vsc8541_verify_phy_id(dev) < 0) { LOG_ERR("failed to verify phy id"); return -EINVAL; } @@ -204,29 +184,21 @@ static int phy_mc_vsc8541_reset(const struct device *dev) if (cfg->microchip_interface_type == VSC8541_RGMII) { ret = phy_mc_vsc8541_write(dev, PHY_REG_PAGE0_EXT_CONTROL_1, (0x0 << 13) | (0x2 << 11)); - if (ret) { + if (ret < 0) { return ret; } } /* software reset */ - ret = phy_mc_vsc8541_write(dev, PHY_REG_PAGE0_BMCR, MII_BMCR_RESET); - if (ret) { + ret = phy_mc_vsc8541_write(dev, MII_BMCR, MII_BMCR_RESET); + if (ret < 0) { return ret; } /* wait for phy finished software reset */ - uint32_t reg = 0; - do { - phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_BMCR, ®); - } while (reg & BMCR_RESET); - - /* forced MDI-X */ - ret = phy_mc_vsc8541_write(dev, PHY_REG_PAGE1_EXT_MODE_CTRL, (3 << 2)); - if (ret) { - return ret; - } + phy_mc_vsc8541_read(dev, MII_BMCR, ®); + } while (reg & MII_BMCR_RESET); /* configure the RGMII clk delay */ reg = 0x0; @@ -234,32 +206,8 @@ static int phy_mc_vsc8541_reset(const struct device *dev) reg |= (cfg->rgmii_rx_clk_delay << 4); /* TX_CLK delay */ reg |= (cfg->rgmii_tx_clk_delay << 0); - ret = phy_mc_vsc8541_write(dev, PHY_REG_PAGE2_RGMII_CONTROL, reg); - if (ret) { - return ret; - } - - /* we use limited advertising, to force gigabit speed */ - /* initial version of this driver supports only 1GB/s */ - - /* 1000MBit/s + AUTO */ - ret = phy_mc_vsc8541_write(dev, PHY_REG_PAGE0_ADV, (1 << 8) | (1 << 6) | 0x01); - if (ret) { - return ret; - } - - ret = phy_mc_vsc8541_write(dev, PHY_REG_PAGE0_CTRL1000, (1 << 12) | (1 << 11) | (1 << 9)); - if (ret) { - return ret; - } - - /* start auto negotiation */ - ret = phy_mc_vsc8541_write(dev, PHY_REG_PAGE0_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - if (ret) { - return ret; - } - return ret; + return phy_mc_vsc8541_write(dev, PHY_REG_PAGE2_RGMII_CONTROL, reg); } /** @@ -271,54 +219,64 @@ static int phy_mc_vsc8541_reset(const struct device *dev) static int phy_mc_vsc8541_get_speed(const struct device *dev, struct phy_link_state *state) { int ret; - uint32_t status; + uint32_t aux_status; uint32_t link10_status; uint32_t link100_status; uint32_t link1000_status; + bool is_duplex; - ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_BMSR, &status); - if (ret) { + ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_EXT_DEV_AUX, &aux_status); + if (ret < 0) { return ret; } - ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_EXT_CTRL_STAT, &link10_status); - if (ret) { + is_duplex = (aux_status & PHY_REG_PAGE0_EXT_DEV_AUX_DUPLEX) != 0; + + ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_STAT1000_EXT2, &link1000_status); + if (ret < 0) { return ret; } - ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_STAT100, &link100_status); - if (ret) { - return ret; + if ((link1000_status & BIT(12))) { + state->speed = is_duplex ? LINK_FULL_1000BASE : LINK_HALF_1000BASE; + return 0; /* no need to check lower speeds */ } - ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_STAT1000_EXT2, &link1000_status); - if (ret) { + ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_STAT100, &link100_status); + if (ret < 0) { return ret; } - if ((status & (1 << 2)) == 0) { - /* no link */ - state->speed = LINK_HALF_10BASE; + if (link100_status & BIT(12)) { + state->speed = is_duplex ? LINK_FULL_100BASE : LINK_HALF_100BASE; + return 0; /* no need to check lower speeds */ } - if ((status & (1 << 5)) == 0) { - /* auto negotiation not yet complete */ - state->speed = LINK_HALF_10BASE; + ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_EXT_CTRL_STAT, &link10_status); + if (ret < 0) { + return ret; } - if ((link1000_status & (1 << 12))) { - state->speed = LINK_FULL_1000BASE; - } - if (link100_status & (1 << 12)) { - state->speed = LINK_FULL_100BASE; - } - if (link10_status & (1 << 6)) { - state->speed = LINK_FULL_10BASE; + if (link10_status & BIT(6)) { + state->speed = is_duplex ? LINK_FULL_10BASE : LINK_HALF_10BASE; + } else { + state->speed = 0; /* no link */ } return 0; } +static int phy_mc_vsc8541_cfg_link(const struct device *dev, enum phy_link_speed adv_speeds, + enum phy_cfg_link_flag flags) +{ + if (flags & PHY_FLAG_AUTO_NEGOTIATION_DISABLED) { + LOG_ERR("Disabling auto-negotiation is not supported by this driver"); + return -ENOTSUP; + } + + return phy_mii_cfg_link_autoneg(dev, adv_speeds, true); +} + /** * @brief Initializes the phy and starts the link monitor * @@ -326,17 +284,14 @@ static int phy_mc_vsc8541_get_speed(const struct device *dev, struct phy_link_st static int phy_mc_vsc8541_init(const struct device *dev) { struct mc_vsc8541_data *data = dev->data; + struct mc_vsc8541_config *cfg = dev->config; + int ret; - data->cb = NULL; - data->cb_data = NULL; - data->state.is_up = false; - data->state.speed = LINK_HALF_10BASE; data->active_page = -1; /* Reset PHY */ - int ret = phy_mc_vsc8541_reset(dev); - - if (ret) { + ret = phy_mc_vsc8541_reset(dev); + if (ret < 0) { LOG_ERR("initialize failed"); return ret; } @@ -363,37 +318,35 @@ static int phy_mc_vsc8541_get_link(const struct device *dev, struct phy_link_sta int ret; uint32_t reg_sr; uint32_t reg_cr; + bool hasLink; + bool auto_negotiation_finished = true; - ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_BMSR, ®_sr); - if (ret) { + ret = phy_mc_vsc8541_read(dev, MII_BMSR, ®_sr); + if (ret < 0) { return ret; } - ret = phy_mc_vsc8541_read(dev, PHY_REG_PAGE0_BMCR, ®_cr); - if (ret) { + ret = phy_mc_vsc8541_read(dev, MII_BMCR, ®_cr); + if (ret < 0) { return ret; } - uint32_t hasLink = reg_sr & (1 << 2) ? 1 : 0; + hasLink = (reg_sr & MII_BMSR_LINK_STATUS) != 0; - uint32_t auto_negotiation_finished; - - if (reg_cr & (BMCR_ANENABLE)) { + if (reg_cr & MII_BMCR_AUTONEG_ENABLE) { /* auto negotiation active; update status */ - auto_negotiation_finished = reg_sr & (1 << 5) ? 1 : 0; - } else { - auto_negotiation_finished = 1; + auto_negotiation_finished = (reg_sr & MII_BMSR_AUTONEG_COMPLETE) != 0; } - if (hasLink & auto_negotiation_finished) { - state->is_up = 1; + if (hasLink && auto_negotiation_finished) { + state->is_up = true; ret = phy_mc_vsc8541_get_speed(dev, state); - if (ret) { + if (ret < 0) { return ret; } } else { - state->is_up = 0; - state->speed = LINK_HALF_10BASE; + state->is_up = false; + state->speed = 0; } return 0; From e819c7663ff4bbed533f02b34ea08ab016835f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Wed, 18 Jun 2025 10:35:10 +0200 Subject: [PATCH 12/13] drivers: ethernet: phy: microchip_vsc8541: use mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use mutex to protect page register phy_mc_vsc8541_get_link got removed from phy_mc_vsc8541_link_cb_set so, that phy_mc_vsc8541_link_monitor (own thread) is the only one to change data->state Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_microchip_vsc8541.c | 32 +++++++++++--------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/ethernet/phy/phy_microchip_vsc8541.c b/drivers/ethernet/phy/phy_microchip_vsc8541.c index 2961e44e67d39..28d87cc392721 100644 --- a/drivers/ethernet/phy/phy_microchip_vsc8541.c +++ b/drivers/ethernet/phy/phy_microchip_vsc8541.c @@ -289,6 +289,8 @@ static int phy_mc_vsc8541_init(const struct device *dev) data->active_page = -1; + k_mutex_init(&data->mutex); + /* Reset PHY */ ret = phy_mc_vsc8541_reset(dev); if (ret < 0) { @@ -366,8 +368,6 @@ static int phy_mc_vsc8541_link_cb_set(const struct device *dev, phy_callback_t c data->cb = cb; data->cb_data = user_data; - phy_mc_vsc8541_get_link(dev, &data->state); - data->cb(dev, &data->state, data->cb_data); return 0; @@ -427,22 +427,24 @@ static int phy_mc_vsc8541_read(const struct device *dev, uint16_t reg_addr, uint /* mask out lower byte */ reg_addr &= 0x00ff; + k_mutex_lock(&dev_data->mutex, K_FOREVER); + /* select page, given by register upper byte */ if (dev_data->active_page != page) { ret = mdio_write(cfg->mdio_dev, cfg->addr, PHY_REG_PAGE_SELECTOR, (uint16_t)page); - if (ret) { - return ret; + if (ret < 0) { + goto read_end; } dev_data->active_page = (int)page; } /* select register, given by register lower byte */ ret = mdio_read(cfg->mdio_dev, cfg->addr, reg_addr, (uint16_t *)data); - if (ret) { - return ret; - } - return 0; +read_end: + k_mutex_unlock(&dev_data->mutex); + + return ret; } /** @@ -465,22 +467,24 @@ static int phy_mc_vsc8541_write(const struct device *dev, uint16_t reg_addr, uin /* mask out lower byte */ reg_addr &= 0x00ff; + k_mutex_lock(&dev_data->mutex, K_FOREVER); + /* select page, given by register upper byte */ if (dev_data->active_page != page) { ret = mdio_write(cfg->mdio_dev, cfg->addr, PHY_REG_PAGE_SELECTOR, (uint16_t)page); - if (ret) { - return ret; + if (ret < 0) { + goto write_end; } dev_data->active_page = (int)page; } /* write register, given by lower byte */ ret = mdio_write(cfg->mdio_dev, cfg->addr, reg_addr, (uint16_t)data); - if (ret) { - return ret; - } - return 0; +write_end: + k_mutex_unlock(&dev_data->mutex); + + return ret; } static DEVICE_API(ethphy, mc_vsc8541_phy_api) = { From 5e306fb7527b7977fdc5c1162950c145680ab2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Wed, 18 Jun 2025 12:08:15 +0200 Subject: [PATCH 13/13] drivers: ethernet: phy: microchip_vsc8541: use default speeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use default speeds dt prop Signed-off-by: Fin Maaß --- drivers/ethernet/phy/phy_microchip_vsc8541.c | 4 ++++ dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/ethernet/phy/phy_microchip_vsc8541.c b/drivers/ethernet/phy/phy_microchip_vsc8541.c index 28d87cc392721..626b81fc46524 100644 --- a/drivers/ethernet/phy/phy_microchip_vsc8541.c +++ b/drivers/ethernet/phy/phy_microchip_vsc8541.c @@ -64,6 +64,7 @@ struct mc_vsc8541_config { uint8_t addr; const struct device *mdio_dev; enum vsc8541_interface microchip_interface_type; + enum phy_link_speed default_speeds; uint8_t rgmii_rx_clk_delay; uint8_t rgmii_tx_clk_delay; #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) @@ -306,6 +307,8 @@ static int phy_mc_vsc8541_init(const struct device *dev) k_thread_name_set(&data->link_monitor_thread, "phy-link-mon"); + phy_mc_vsc8541_cfg_link(dev, cfg->default_speeds, 0); + return 0; } @@ -513,6 +516,7 @@ static DEVICE_API(ethphy, mc_vsc8541_phy_api) = { .microchip_interface_type = DT_INST_ENUM_IDX(n, microchip_interface_type), \ .rgmii_rx_clk_delay = DT_INST_PROP(n, microchip_rgmii_rx_clk_delay), \ .rgmii_tx_clk_delay = DT_INST_PROP(n, microchip_rgmii_tx_clk_delay), \ + .default_speeds = PHY_INST_GENERATE_DEFAULT_SPEEDS(n), \ RESET_GPIO(n) INTERRUPT_GPIO(n)}; \ \ static struct mc_vsc8541_data mc_vsc8541_##n##_data; \ diff --git a/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml b/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml index c16f2e9e5d411..2c0347200fc41 100644 --- a/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml +++ b/dts/bindings/ethernet/phy/microchip,vsc8541-phy.yaml @@ -42,3 +42,7 @@ properties: description: | Used to configure the TX clock delay for RGMII interface. The value can be 0 to 7. Refer to the datasheet for more details on the delay settings. + + default-speeds: + default: ["10BASE Half-Duplex", "10BASE Full-Duplex", "100BASE Half-Duplex", + "100BASE Full-Duplex", "1000BASE Half-Duplex", "1000BASE Full-Duplex"]