[ethernet] Set SPI CS hold time for ENC28J60 (#17885)

This commit is contained in:
Jonathan Swoboda
2026-07-27 17:24:53 -04:00
committed by GitHub
parent fa8c7e60da
commit 6420de53f0
2 changed files with 45 additions and 32 deletions
+42 -31
View File
@@ -437,37 +437,48 @@ GENERIC_SCHEMA = cv.All(
cv.only_on([Platform.ESP32]), cv.only_on([Platform.ESP32]),
) )
SPI_SCHEMA = cv.All(
BASE_SCHEMA.extend( def _spi_schema(default_clock: str = "26.67MHz", max_clock: int = int(80e6)):
cv.Schema( return cv.All(
{ BASE_SCHEMA.extend(
cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_number, cv.Schema(
cv.Required(CONF_MISO_PIN): pins.internal_gpio_input_pin_number, {
cv.Required(CONF_MOSI_PIN): pins.internal_gpio_output_pin_number, cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_number,
cv.Required(CONF_CS_PIN): pins.internal_gpio_output_pin_number, cv.Required(CONF_MISO_PIN): pins.internal_gpio_input_pin_number,
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_number, cv.Required(CONF_MOSI_PIN): pins.internal_gpio_output_pin_number,
cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number, cv.Required(CONF_CS_PIN): pins.internal_gpio_output_pin_number,
cv.SplitDefault(CONF_CLOCK_SPEED, esp32="26.67MHz"): cv.All( cv.Optional(
cv.only_on_esp32, CONF_INTERRUPT_PIN
cv.frequency, ): pins.internal_gpio_input_pin_number,
cv.int_range(int(8e6), int(80e6)), cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
), cv.SplitDefault(CONF_CLOCK_SPEED, esp32=default_clock): cv.All(
cv.Optional(CONF_INTERFACE): cv.All( cv.only_on_esp32,
cv.only_on_esp32, cv.frequency,
cv.one_of(*SPI_INTERFACE_MAP.keys(), lower=True), cv.int_range(int(8e6), max_clock),
), ),
# Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate() cv.Optional(CONF_INTERFACE): cv.All(
cv.Optional(CONF_POLLING_INTERVAL): cv.All( cv.only_on_esp32,
cv.only_on_esp32, cv.one_of(*SPI_INTERFACE_MAP.keys(), lower=True),
cv.positive_time_period_milliseconds, ),
cv.Range(min=TimePeriodMilliseconds(milliseconds=1)), # Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate()
), cv.Optional(CONF_POLLING_INTERVAL): cv.All(
} cv.only_on_esp32,
cv.positive_time_period_milliseconds,
cv.Range(min=TimePeriodMilliseconds(milliseconds=1)),
),
}
),
), ),
), cv.only_on([Platform.ESP32, Platform.RP2]),
cv.only_on([Platform.ESP32, Platform.RP2]), _validate_spi_interface,
_validate_spi_interface, )
)
SPI_SCHEMA = _spi_schema()
# The ENC28J60's SCK maximum is 20 MHz, so the shared 26.67 MHz default is out
# of spec for it and makes the driver's CS hold time helper compute no hold
SPI_SCHEMA_ENC28J60 = _spi_schema(default_clock="20MHz", max_clock=int(20e6))
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
cv.typed_schema( cv.typed_schema(
@@ -483,7 +494,7 @@ CONFIG_SCHEMA = cv.All(
"W5500": SPI_SCHEMA, "W5500": SPI_SCHEMA,
"OPENETH": cv.All(BASE_SCHEMA, cv.only_on([Platform.ESP32])), "OPENETH": cv.All(BASE_SCHEMA, cv.only_on([Platform.ESP32])),
"DM9051": SPI_SCHEMA, "DM9051": SPI_SCHEMA,
"ENC28J60": SPI_SCHEMA, "ENC28J60": SPI_SCHEMA_ENC28J60,
"W6100": cv.All(SPI_SCHEMA, cv.only_on([Platform.RP2])), "W6100": cv.All(SPI_SCHEMA, cv.only_on([Platform.RP2])),
"W6300": cv.All(SPI_SCHEMA, cv.only_on([Platform.RP2])), "W6300": cv.All(SPI_SCHEMA, cv.only_on([Platform.RP2])),
"LAN8670": RMII_SCHEMA, "LAN8670": RMII_SCHEMA,
@@ -232,8 +232,10 @@ void EthernetComponent::ethernet_lazy_init_() {
dm9051_config.poll_period_ms = this->polling_interval_; dm9051_config.poll_period_ms = this->polling_interval_;
#endif #endif
#elif defined(USE_ETHERNET_ENC28J60) #elif defined(USE_ETHERNET_ENC28J60)
// ENC28J60 does not support poll_period_ms. CS must stay asserted for the chip's CS hold
// time (t10, 210 ns) after the last clock or MAC/MII register reads fail ("wrong chip ID")
enc28j60_config.spi_devcfg->cs_ena_posttrans = enc28j60_cal_spi_cs_hold_time((this->clock_speed_ + 999999) / 1000000);
enc28j60_config.int_gpio_num = this->interrupt_pin_; enc28j60_config.int_gpio_num = this->interrupt_pin_;
// ENC28J60 does not support poll_period_ms
#endif #endif
phy_config.phy_addr = this->phy_addr_spi_; phy_config.phy_addr = this->phy_addr_spi_;