From b636f2613df87025c4afc9b320f17321b5dc3753 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 15 Mar 2026 16:56:08 -1000 Subject: [PATCH] [ethernet] Add IDF 6.0 registry component dependencies ESP-IDF 6.0 moved individual ethernet PHY and SPI MAC/PHY drivers out of the builtin esp_eth component into the Espressif Component Registry. Changes: - Add USE_ETHERNET_W5500/DM9051 defines, replacing CONFIG_ETH_SPI_ETHERNET_* Kconfig options that were removed in IDF 6.0 - Conditionally pull registry components (lan87xx, rtl8201, dp83848, ip101, ksz80xx, w5500, dm9051) via add_idf_component() on IDF >= 6.0 - Skip CONFIG_ETH_SPI_ETHERNET_{TYPE} sdkconfig on IDF >= 6.0 - Fix emac_rmii_clock_gpio_t cast using decltype (enum removed in IDF 6.0) - Use esp_eth_phy_new_generic() for OPENETH and JL1101 on IDF >= 6.0 - Fix JL1101 to work on IDF 5.4.2+ with PlatformIO (was previously falling through to mark_failed due to overly restrictive guard) - Exclude custom JL1101 driver on IDF >= 6.0 - Add registry components to idf_component.yml for static analysis - Update defines.h for static analysis All changes maintain backward compatibility with IDF 5.x. --- esphome/components/ethernet/__init__.py | 37 ++++++++++++++++++- .../components/ethernet/esp_eth_phy_jl1101.c | 3 +- .../ethernet/ethernet_component_esp32.cpp | 34 +++++++++++------ esphome/core/defines.h | 4 +- esphome/idf_component.yml | 28 ++++++++++++++ 5 files changed, 91 insertions(+), 15 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 83bef4d91cb..ba8830948ac 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass import logging from esphome import automation, pins @@ -126,9 +127,32 @@ _PHY_TYPE_TO_DEFINE = { "JL1101": "USE_ETHERNET_JL1101", "KSZ8081": "USE_ETHERNET_KSZ8081", "KSZ8081RNA": "USE_ETHERNET_KSZ8081", + "W5500": "USE_ETHERNET_W5500", + "DM9051": "USE_ETHERNET_DM9051", "LAN8670": "USE_ETHERNET_LAN8670", } + +@dataclass(frozen=True) +class IDFRegistryComponent: + """An ESP-IDF component from the Espressif Component Registry.""" + + name: str + version: str + + +# IDF 6.0 moved per-chip PHY/MAC drivers to the Espressif Component Registry. +_IDF6_ETHERNET_COMPONENTS: dict[str, IDFRegistryComponent] = { + "LAN8720": IDFRegistryComponent("espressif/lan87xx", "1.0.0"), + "RTL8201": IDFRegistryComponent("espressif/rtl8201", "1.0.1"), + "DP83848": IDFRegistryComponent("espressif/dp83848", "1.0.0"), + "IP101": IDFRegistryComponent("espressif/ip101", "1.0.0"), + "KSZ8081": IDFRegistryComponent("espressif/ksz80xx", "1.0.0"), + "KSZ8081RNA": IDFRegistryComponent("espressif/ksz80xx", "1.0.0"), + "W5500": IDFRegistryComponent("espressif/w5500", "1.0.1"), + "DM9051": IDFRegistryComponent("espressif/dm9051", "1.0.0"), +} + SPI_ETHERNET_TYPES = ["W5500", "DM9051"] SPI_ETHERNET_DEFAULT_POLLING_INTERVAL = TimePeriodMilliseconds(milliseconds=10) @@ -439,6 +463,7 @@ async def _to_code_esp32(var, config): from esphome.components.esp32 import ( add_idf_component, add_idf_sdkconfig_option, + idf_version, include_builtin_idf_component, ) @@ -459,7 +484,11 @@ async def _to_code_esp32(var, config): cg.add_define("USE_ETHERNET_SPI") add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True) - add_idf_sdkconfig_option(f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True) + # CONFIG_ETH_SPI_ETHERNET_{TYPE} Kconfig options were removed in IDF 6.0 + if idf_version() < cv.Version(6, 0, 0): + add_idf_sdkconfig_option( + f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True + ) elif config[CONF_TYPE] == "OPENETH": cg.add_define("USE_ETHERNET_OPENETH") add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True) @@ -491,6 +520,12 @@ async def _to_code_esp32(var, config): # Add LAN867x 10BASE-T1S PHY support component add_idf_component(name="espressif/lan867x", ref="2.0.0") + # IDF 6.0 moved per-chip PHY/MAC drivers to the Espressif Component Registry + if idf_version() >= cv.Version(6, 0, 0) and ( + component := _IDF6_ETHERNET_COMPONENTS.get(config[CONF_TYPE]) + ): + add_idf_component(name=component.name, ref=component.version) + def _final_validate_rmii_pins(config: ConfigType) -> None: """Validate that RMII pins are not used by other components.""" diff --git a/esphome/components/ethernet/esp_eth_phy_jl1101.c b/esphome/components/ethernet/esp_eth_phy_jl1101.c index b81d8227d45..692f759eed8 100644 --- a/esphome/components/ethernet/esp_eth_phy_jl1101.c +++ b/esphome/components/ethernet/esp_eth_phy_jl1101.c @@ -29,7 +29,8 @@ #include "esp_rom_sys.h" #include "esp_idf_version.h" -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) +#if defined(USE_ETHERNET_JL1101) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) && \ + (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) static const char *TAG = "jl1101"; #define PHY_CHECK(a, str, goto_tag, ...) \ diff --git a/esphome/components/ethernet/ethernet_component_esp32.cpp b/esphome/components/ethernet/ethernet_component_esp32.cpp index ac8680f3e13..82ac69f4b9b 100644 --- a/esphome/components/ethernet/ethernet_component_esp32.cpp +++ b/esphome/components/ethernet/ethernet_component_esp32.cpp @@ -164,21 +164,21 @@ void EthernetComponent::setup() { .post_cb = nullptr, }; -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg); #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(host, &devcfg); #endif -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 w5500_config.int_gpio_num = this->interrupt_pin_; #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT w5500_config.poll_period_ms = this->polling_interval_; #endif #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 dm9051_config.int_gpio_num = this->interrupt_pin_; #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT dm9051_config.poll_period_ms = this->polling_interval_; @@ -204,7 +204,8 @@ void EthernetComponent::setup() { esp32_emac_config.smi_mdio_gpio_num = this->mdio_pin_; #endif esp32_emac_config.clock_config.rmii.clock_mode = this->clk_mode_; - esp32_emac_config.clock_config.rmii.clock_gpio = (emac_rmii_clock_gpio_t) this->clk_pin_; + esp32_emac_config.clock_config.rmii.clock_gpio = + static_cast(this->clk_pin_); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); #endif @@ -213,7 +214,11 @@ void EthernetComponent::setup() { #ifdef USE_ETHERNET_OPENETH case ETHERNET_TYPE_OPENETH: { phy_config.autonego_timeout_ms = 1000; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + this->phy_ = esp_eth_phy_new_generic(&phy_config); +#else this->phy_ = esp_eth_phy_new_dp83848(&phy_config); +#endif break; } #endif @@ -242,9 +247,16 @@ void EthernetComponent::setup() { break; } #endif -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) +#ifdef USE_ETHERNET_JL1101 case ETHERNET_TYPE_JL1101: { +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + // No registry component exists; generic PHY driver works for JL1101 + this->phy_ = esp_eth_phy_new_generic(&phy_config); +#else + // IDF < 5.4.2 or non-PlatformIO: uses custom ESPHome driver (esp_eth_phy_jl1101.c) + // IDF 5.4.2+ with PlatformIO: uses builtin esp_eth_phy_new_jl1101() this->phy_ = esp_eth_phy_new_jl1101(&phy_config); +#endif break; } #endif @@ -263,14 +275,14 @@ void EthernetComponent::setup() { #endif #endif #ifdef USE_ETHERNET_SPI -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 case ETHERNET_TYPE_W5500: { mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); this->phy_ = esp_eth_phy_new_w5500(&phy_config); break; } #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 case ETHERNET_TYPE_DM9051: { mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); this->phy_ = esp_eth_phy_new_dm9051(&phy_config); @@ -354,7 +366,7 @@ void EthernetComponent::dump_config() { eth_type = "IP101"; break; #endif -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) +#ifdef USE_ETHERNET_JL1101 case ETHERNET_TYPE_JL1101: eth_type = "JL1101"; break; @@ -368,12 +380,12 @@ void EthernetComponent::dump_config() { eth_type = "KSZ8081RNA"; break; #endif -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 case ETHERNET_TYPE_W5500: eth_type = "W5500"; break; #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 case ETHERNET_TYPE_DM9051: eth_type = "DM9051"; break; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 75e63b1462b..e3d443dda4b 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -281,8 +281,8 @@ #define USE_ETHERNET_SPI #define USE_ETHERNET_SPI_POLLING_SUPPORT #define USE_ETHERNET_OPENETH -#define CONFIG_ETH_SPI_ETHERNET_W5500 1 -#define CONFIG_ETH_SPI_ETHERNET_DM9051 1 +#define USE_ETHERNET_W5500 +#define USE_ETHERNET_DM9051 #define CONFIG_ETH_USE_ESP32_EMAC 1 #define USE_ETHERNET_MANUAL_IP #define USE_ETHERNET_IP_STATE_LISTENERS diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 1e2d452919c..ef33ccfc047 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -29,6 +29,34 @@ dependencies: version: "2.0.0" rules: - if: "target in [esp32, esp32p4]" + espressif/lan87xx: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/rtl8201: + version: "1.0.1" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/dp83848: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/ip101: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/ksz80xx: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/w5500: + version: "1.0.1" + rules: + - if: "idf_version >=6.0.0" + espressif/dm9051: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0" espressif/esp_tinyusb: version: "2.1.1" rules: