From 62237cf28cdd5e91a4b1e244c59930512b8fc121 Mon Sep 17 00:00:00 2001 From: Meowthink Date: Mon, 15 Jun 2020 09:59:20 +0800 Subject: [PATCH 1/3] Add Microchip KSZ8041 PHY support. Merges https://github.com/espressif/esp-idf/pull/5452 --- components/esp_eth/CMakeLists.txt | 1 + components/esp_eth/include/esp_eth_phy.h | 11 + components/esp_eth/src/esp_eth_phy_ksz8041.c | 321 +++++++++++++++++++ 3 files changed, 333 insertions(+) create mode 100644 components/esp_eth/src/esp_eth_phy_ksz8041.c diff --git a/components/esp_eth/CMakeLists.txt b/components/esp_eth/CMakeLists.txt index faced5b780..dca1b07778 100644 --- a/components/esp_eth/CMakeLists.txt +++ b/components/esp_eth/CMakeLists.txt @@ -22,6 +22,7 @@ if(CONFIG_ETH_ENABLED) list(APPEND srcs "src/esp_eth_mac_esp32.c" "src/esp_eth_phy_dp83848.c" "src/esp_eth_phy_ip101.c" + "src/esp_eth_phy_ksz8041.c" "src/esp_eth_phy_lan8720.c" "src/esp_eth_phy_rtl8201.c") endif() diff --git a/components/esp_eth/include/esp_eth_phy.h b/components/esp_eth/include/esp_eth_phy.h index 4aedff1112..f74d8c72e0 100644 --- a/components/esp_eth/include/esp_eth_phy.h +++ b/components/esp_eth/include/esp_eth_phy.h @@ -251,6 +251,17 @@ esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config); * - NULL: create PHY instance failed because some error occurred */ esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config); + +/** +* @brief Create a PHY instance of KSZ8041 +* +* @param[in] config: configuration of PHY +* +* @return +* - instance: create PHY instance successfully +* - NULL: create PHY instance failed because some error occurred +*/ +esp_eth_phy_t *esp_eth_phy_new_ksz8041(const eth_phy_config_t *config); #endif #ifdef __cplusplus } diff --git a/components/esp_eth/src/esp_eth_phy_ksz8041.c b/components/esp_eth/src/esp_eth_phy_ksz8041.c new file mode 100644 index 0000000000..2442851054 --- /dev/null +++ b/components/esp_eth/src/esp_eth_phy_ksz8041.c @@ -0,0 +1,321 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include "esp_log.h" +#include "esp_eth.h" +#include "eth_phy_regs_struct.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" + +static const char *TAG = "ksz8041"; +#define PHY_CHECK(a, str, goto_tag, ...) \ + do \ + { \ + if (!(a)) \ + { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + goto goto_tag; \ + } \ + } while (0) + +/***************Vendor Specific Register***************/ +/** + * @brief PC2R(PHY Control 2 Register) + * + */ +typedef union { + struct { + uint32_t hp_mdix : 1; /* HP Auto MDI/MDI-X Mode */ + uint32_t mdi_x_select : 1; /* MDI/MDI-X Select */ + uint32_t pairswap_dis : 1; /* Disable Auto MDI/MDI-X */ + uint32_t energy_det : 1; /* Presence of Signal on RX+/- Wire Pair */ + uint32_t force_link : 1; /* Force Link Pass */ + uint32_t power_saving : 1; /* Enable Powering Saving */ + uint32_t irq_level : 1; /* Interrupt Pin Active Level */ + uint32_t jabber : 1; /* Enable Jabber Counter */ + uint32_t auto_nego_comp : 1; /* Auto Negotiation Complete */ + uint32_t flow_ctl_cap : 1; /* Flow Control Capable */ + uint32_t phy_iso : 1; /* PHY in Isolate Mode */ + uint32_t op_mode_ind : 3; /* Operation Mode Indication */ + uint32_t en_sqe_test : 1; /* Enable SQE Test */ + uint32_t dis_data_scr: 1; /* Disable Scrambler */ + }; + uint32_t val; +} pc2r_reg_t; +#define ETH_PHY_PC2R_REG_ADDR (0x1F) + +typedef struct { + esp_eth_phy_t parent; + esp_eth_mediator_t *eth; + uint32_t addr; + uint32_t reset_timeout_ms; + uint32_t autonego_timeout_ms; + eth_link_t link_status; + int reset_gpio_num; +} phy_ksz8041_t; + +static esp_err_t ksz8041_update_link_duplex_speed(phy_ksz8041_t *ksz8041) +{ + esp_eth_mediator_t *eth = ksz8041->eth; + eth_speed_t speed = ETH_SPEED_10M; + eth_duplex_t duplex = ETH_DUPLEX_HALF; + bmsr_reg_t bmsr; + pc2r_reg_t pc2r; + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, + "read BMSR failed", err); + eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN; + /* check if link status changed */ + if (ksz8041->link_status != link) { + /* when link up, read negotiation result */ + if (link == ETH_LINK_UP) { + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_PC2R_REG_ADDR, &(pc2r.val)) == ESP_OK, + "read PC2R failed", err); + switch (pc2r.op_mode_ind) { + case 1: //10Base-T half-duplex + speed = ETH_SPEED_10M; + duplex = ETH_DUPLEX_HALF; + break; + case 2: //100Base-TX half-duplex + speed = ETH_SPEED_100M; + duplex = ETH_DUPLEX_HALF; + break; + case 5: //10Base-T full-duplex + speed = ETH_SPEED_10M; + duplex = ETH_DUPLEX_FULL; + break; + case 6: //100Base-TX full-duplex + speed = ETH_SPEED_100M; + duplex = ETH_DUPLEX_FULL; + break; + default: + break; + } + PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK, + "change speed failed", err); + PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK, + "change duplex failed", err); + } + PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, + "change link failed", err); + ksz8041->link_status = link; + } + return ESP_OK; +err: + return ESP_FAIL; +} + +static esp_err_t ksz8041_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth) +{ + PHY_CHECK(eth, "can't set mediator to null", err); + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + ksz8041->eth = eth; + return ESP_OK; +err: + return ESP_ERR_INVALID_ARG; +} + +static esp_err_t ksz8041_get_link(esp_eth_phy_t *phy) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + /* Update information about link, speed, duplex */ + PHY_CHECK(ksz8041_update_link_duplex_speed(ksz8041) == ESP_OK, "update link duplex speed failed", err); + return ESP_OK; +err: + return ESP_FAIL; +} + +static esp_err_t ksz8041_reset(esp_eth_phy_t *phy) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + ksz8041->link_status = ETH_LINK_DOWN; + esp_eth_mediator_t *eth = ksz8041->eth; + bmcr_reg_t bmcr = {.reset = 1}; + PHY_CHECK(eth->phy_reg_write(eth, ksz8041->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, + "write BMCR failed", err); + /* wait for reset complete */ + uint32_t to = 0; + for (to = 0; to < ksz8041->reset_timeout_ms / 10; to++) { + vTaskDelay(pdMS_TO_TICKS(10)); + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); + if (!bmcr.reset) { + break; + } + } + PHY_CHECK(to < ksz8041->reset_timeout_ms / 10, "reset timeout", err); + return ESP_OK; +err: + return ESP_FAIL; +} + +static esp_err_t ksz8041_reset_hw(esp_eth_phy_t *phy) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + if (ksz8041->reset_gpio_num >= 0) { + gpio_pad_select_gpio(ksz8041->reset_gpio_num); + gpio_set_direction(ksz8041->reset_gpio_num, GPIO_MODE_OUTPUT); + gpio_set_level(ksz8041->reset_gpio_num, 0); + gpio_set_level(ksz8041->reset_gpio_num, 1); + } + return ESP_OK; +} + +static esp_err_t ksz8041_negotiate(esp_eth_phy_t *phy) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + esp_eth_mediator_t *eth = ksz8041->eth; + /* Restart auto negotiation */ + bmcr_reg_t bmcr = { + .speed_select = 1, /* 100Mbps */ + .duplex_mode = 1, /* Full Duplex */ + .en_auto_nego = 1, /* Auto Negotiation */ + .restart_auto_nego = 1 /* Restart Auto Negotiation */ + }; + PHY_CHECK(eth->phy_reg_write(eth, ksz8041->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err); + /* Wait for auto negotiation complete */ + bmsr_reg_t bmsr; + pc2r_reg_t pc2r; + int32_t to = 0; + for (to = 0; to < ksz8041->autonego_timeout_ms / 10; to++) { + vTaskDelay(pdMS_TO_TICKS(10)); + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, + "read BMSR failed", err); + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_PC2R_REG_ADDR, &(pc2r.val)) == ESP_OK, + "read PC2R failed", err); + if (bmsr.auto_nego_complete && pc2r.auto_nego_comp) { + break; + } + } + /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ + if (to >= ksz8041->autonego_timeout_ms / 10) { + ESP_LOGW(TAG, "auto negotiation timeout"); + } + /* Updata information about link, speed, duplex */ + PHY_CHECK(ksz8041_update_link_duplex_speed(ksz8041) == ESP_OK, "update link duplex speed failed", err); + return ESP_OK; +err: + return ESP_FAIL; +} + +static esp_err_t ksz8041_pwrctl(esp_eth_phy_t *phy, bool enable) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + esp_eth_mediator_t *eth = ksz8041->eth; + bmcr_reg_t bmcr; + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); + if (!enable) { + /* General Power Down Mode */ + bmcr.power_down = 1; + } else { + /* Normal operation Mode */ + bmcr.power_down = 0; + } + PHY_CHECK(eth->phy_reg_write(eth, ksz8041->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, + "write BMCR failed", err); + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); + if (!enable) { + PHY_CHECK(bmcr.power_down == 1, "power down failed", err); + } else { + PHY_CHECK(bmcr.power_down == 0, "power up failed", err); + } + return ESP_OK; +err: + return ESP_FAIL; +} + +static esp_err_t ksz8041_set_addr(esp_eth_phy_t *phy, uint32_t addr) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + ksz8041->addr = addr; + return ESP_OK; +} + +static esp_err_t ksz8041_get_addr(esp_eth_phy_t *phy, uint32_t *addr) +{ + PHY_CHECK(addr, "addr can't be null", err); + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + *addr = ksz8041->addr; + return ESP_OK; +err: + return ESP_ERR_INVALID_ARG; +} + +static esp_err_t ksz8041_del(esp_eth_phy_t *phy) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + free(ksz8041); + return ESP_OK; +} + +static esp_err_t ksz8041_init(esp_eth_phy_t *phy) +{ + phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); + esp_eth_mediator_t *eth = ksz8041->eth; + /* Power on Ethernet PHY */ + PHY_CHECK(ksz8041_pwrctl(phy, true) == ESP_OK, "power control failed", err); + /* Reset Ethernet PHY */ + PHY_CHECK(ksz8041_reset(phy) == ESP_OK, "reset failed", err); + /* Check PHY ID */ + phyidr1_reg_t id1; + phyidr2_reg_t id2; + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK, + "read ID1 failed", err); + PHY_CHECK(eth->phy_reg_read(eth, ksz8041->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK, + "read ID2 failed", err); + PHY_CHECK(id1.oui_msb == 0x22 && id2.oui_lsb == 0x5 && id2.vendor_model == 0x11, "wrong chip ID", err); + return ESP_OK; +err: + return ESP_FAIL; +} + +static esp_err_t ksz8041_deinit(esp_eth_phy_t *phy) +{ + /* Power off Ethernet PHY */ + PHY_CHECK(ksz8041_pwrctl(phy, false) == ESP_OK, "power control failed", err); + return ESP_OK; +err: + return ESP_FAIL; +} + +esp_eth_phy_t *esp_eth_phy_new_ksz8041(const eth_phy_config_t *config) +{ + PHY_CHECK(config, "can't set phy config to null", err); + phy_ksz8041_t *ksz8041 = calloc(1, sizeof(phy_ksz8041_t)); + PHY_CHECK(ksz8041, "calloc ksz8041 failed", err); + ksz8041->addr = config->phy_addr; + ksz8041->reset_gpio_num = config->reset_gpio_num; + ksz8041->reset_timeout_ms = config->reset_timeout_ms; + ksz8041->link_status = ETH_LINK_DOWN; + ksz8041->autonego_timeout_ms = config->autonego_timeout_ms; + ksz8041->parent.reset = ksz8041_reset; + ksz8041->parent.reset_hw = ksz8041_reset_hw; + ksz8041->parent.init = ksz8041_init; + ksz8041->parent.deinit = ksz8041_deinit; + ksz8041->parent.set_mediator = ksz8041_set_mediator; + ksz8041->parent.negotiate = ksz8041_negotiate; + ksz8041->parent.get_link = ksz8041_get_link; + ksz8041->parent.pwrctl = ksz8041_pwrctl; + ksz8041->parent.get_addr = ksz8041_get_addr; + ksz8041->parent.set_addr = ksz8041_set_addr; + ksz8041->parent.del = ksz8041_del; + + return &(ksz8041->parent); +err: + return NULL; +} From 648bcc7a87d90b7aec0dec024a3a707e3d8a46c3 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 9 Jul 2020 21:49:07 +0800 Subject: [PATCH 2/3] ethernet: add ksz8041 in basic ethernet example --- components/esp_eth/include/esp_eth_phy.h | 23 ++++++++++--------- components/esp_eth/src/esp_eth_phy_ksz8041.c | 3 ++- .../ethernet/basic/main/Kconfig.projbuild | 6 +++++ .../basic/main/ethernet_example_main.c | 2 ++ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/components/esp_eth/include/esp_eth_phy.h b/components/esp_eth/include/esp_eth_phy.h index f74d8c72e0..b3aa39b438 100644 --- a/components/esp_eth/include/esp_eth_phy.h +++ b/components/esp_eth/include/esp_eth_phy.h @@ -240,6 +240,17 @@ esp_eth_phy_t *esp_eth_phy_new_lan8720(const eth_phy_config_t *config); */ esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config); +/** +* @brief Create a PHY instance of KSZ8041 +* +* @param[in] config: configuration of PHY +* +* @return +* - instance: create PHY instance successfully +* - NULL: create PHY instance failed because some error occurred +*/ +esp_eth_phy_t *esp_eth_phy_new_ksz8041(const eth_phy_config_t *config); + #if CONFIG_ETH_SPI_ETHERNET_DM9051 /** * @brief Create a PHY instance of DM9051 @@ -251,18 +262,8 @@ esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config); * - NULL: create PHY instance failed because some error occurred */ esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config); - -/** -* @brief Create a PHY instance of KSZ8041 -* -* @param[in] config: configuration of PHY -* -* @return -* - instance: create PHY instance successfully -* - NULL: create PHY instance failed because some error occurred -*/ -esp_eth_phy_t *esp_eth_phy_new_ksz8041(const eth_phy_config_t *config); #endif + #ifdef __cplusplus } #endif diff --git a/components/esp_eth/src/esp_eth_phy_ksz8041.c b/components/esp_eth/src/esp_eth_phy_ksz8041.c index 2442851054..a421b1ae08 100644 --- a/components/esp_eth/src/esp_eth_phy_ksz8041.c +++ b/components/esp_eth/src/esp_eth_phy_ksz8041.c @@ -20,6 +20,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" +#include "esp_rom_gpio.h" static const char *TAG = "ksz8041"; #define PHY_CHECK(a, str, goto_tag, ...) \ @@ -166,7 +167,7 @@ static esp_err_t ksz8041_reset_hw(esp_eth_phy_t *phy) { phy_ksz8041_t *ksz8041 = __containerof(phy, phy_ksz8041_t, parent); if (ksz8041->reset_gpio_num >= 0) { - gpio_pad_select_gpio(ksz8041->reset_gpio_num); + esp_rom_gpio_pad_select_gpio(ksz8041->reset_gpio_num); gpio_set_direction(ksz8041->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(ksz8041->reset_gpio_num, 0); gpio_set_level(ksz8041->reset_gpio_num, 1); diff --git a/examples/ethernet/basic/main/Kconfig.projbuild b/examples/ethernet/basic/main/Kconfig.projbuild index 99e573e49e..331720b266 100644 --- a/examples/ethernet/basic/main/Kconfig.projbuild +++ b/examples/ethernet/basic/main/Kconfig.projbuild @@ -52,6 +52,12 @@ menu "Example Configuration" help DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver. Goto http://www.ti.com/product/DP83848J for more information about it. + + config EXAMPLE_ETH_PHY_KSZ8041 + bool "KSZ8041" + help + The KSZ8041 is a single supply 10Base-T/100Base-TX Physical Layer Transceiver. + Goto https://www.microchip.com/wwwproducts/en/KSZ8041 for more information about it. endchoice config EXAMPLE_ETH_MDC_GPIO diff --git a/examples/ethernet/basic/main/ethernet_example_main.c b/examples/ethernet/basic/main/ethernet_example_main.c index 59c81ef996..1455a5b577 100644 --- a/examples/ethernet/basic/main/ethernet_example_main.c +++ b/examples/ethernet/basic/main/ethernet_example_main.c @@ -93,6 +93,8 @@ void app_main(void) esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); #elif CONFIG_EXAMPLE_ETH_PHY_DP83848 esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config); +#elif CONFIG_EXAMPLE_ETH_PHY_KSZ8041 + esp_eth_phy_t *phy = esp_eth_phy_new_ksz8041(&phy_config); #endif #elif CONFIG_EXAMPLE_USE_DM9051 gpio_install_isr_service(0); From abcea5197606396668c1901088f2114719e747cd Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 9 Jul 2020 22:03:11 +0800 Subject: [PATCH 3/3] ethernet: insert min assert time for PHY HW reset Closes https://github.com/espressif/esp-idf/issues/5528 --- components/esp_eth/src/esp_eth_phy_dm9051.c | 1 + components/esp_eth/src/esp_eth_phy_dp83848.c | 1 + components/esp_eth/src/esp_eth_phy_ip101.c | 1 + components/esp_eth/src/esp_eth_phy_ksz8041.c | 1 + components/esp_eth/src/esp_eth_phy_lan8720.c | 1 + components/esp_eth/src/esp_eth_phy_rtl8201.c | 1 + 6 files changed, 6 insertions(+) diff --git a/components/esp_eth/src/esp_eth_phy_dm9051.c b/components/esp_eth/src/esp_eth_phy_dm9051.c index bfd93ce6b7..a19c1e69b3 100644 --- a/components/esp_eth/src/esp_eth_phy_dm9051.c +++ b/components/esp_eth/src/esp_eth_phy_dm9051.c @@ -193,6 +193,7 @@ static esp_err_t dm9051_reset_hw(esp_eth_phy_t *phy) esp_rom_gpio_pad_select_gpio(dm9051->reset_gpio_num); gpio_set_direction(dm9051->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(dm9051->reset_gpio_num, 0); + ets_delay_us(100); // insert min input assert time gpio_set_level(dm9051->reset_gpio_num, 1); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_dp83848.c b/components/esp_eth/src/esp_eth_phy_dp83848.c index ce2e96cdd2..c83e50306a 100644 --- a/components/esp_eth/src/esp_eth_phy_dp83848.c +++ b/components/esp_eth/src/esp_eth_phy_dp83848.c @@ -182,6 +182,7 @@ static esp_err_t dp83848_reset_hw(esp_eth_phy_t *phy) esp_rom_gpio_pad_select_gpio(dp83848->reset_gpio_num); gpio_set_direction(dp83848->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(dp83848->reset_gpio_num, 0); + ets_delay_us(100); // insert min input assert time gpio_set_level(dp83848->reset_gpio_num, 1); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_ip101.c b/components/esp_eth/src/esp_eth_phy_ip101.c index e05da282dd..0ab53b893b 100644 --- a/components/esp_eth/src/esp_eth_phy_ip101.c +++ b/components/esp_eth/src/esp_eth_phy_ip101.c @@ -222,6 +222,7 @@ static esp_err_t ip101_reset_hw(esp_eth_phy_t *phy) esp_rom_gpio_pad_select_gpio(ip101->reset_gpio_num); gpio_set_direction(ip101->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(ip101->reset_gpio_num, 0); + ets_delay_us(100); // insert min input assert time gpio_set_level(ip101->reset_gpio_num, 1); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_ksz8041.c b/components/esp_eth/src/esp_eth_phy_ksz8041.c index a421b1ae08..b9a43f09c3 100644 --- a/components/esp_eth/src/esp_eth_phy_ksz8041.c +++ b/components/esp_eth/src/esp_eth_phy_ksz8041.c @@ -170,6 +170,7 @@ static esp_err_t ksz8041_reset_hw(esp_eth_phy_t *phy) esp_rom_gpio_pad_select_gpio(ksz8041->reset_gpio_num); gpio_set_direction(ksz8041->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(ksz8041->reset_gpio_num, 0); + ets_delay_us(100); // insert min input assert time gpio_set_level(ksz8041->reset_gpio_num, 1); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_lan8720.c b/components/esp_eth/src/esp_eth_phy_lan8720.c index 52e27a9c22..3b4b9d50d5 100644 --- a/components/esp_eth/src/esp_eth_phy_lan8720.c +++ b/components/esp_eth/src/esp_eth_phy_lan8720.c @@ -267,6 +267,7 @@ static esp_err_t lan8720_reset_hw(esp_eth_phy_t *phy) esp_rom_gpio_pad_select_gpio(lan8720->reset_gpio_num); gpio_set_direction(lan8720->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(lan8720->reset_gpio_num, 0); + ets_delay_us(100); // insert min input assert time gpio_set_level(lan8720->reset_gpio_num, 1); } return ESP_OK; diff --git a/components/esp_eth/src/esp_eth_phy_rtl8201.c b/components/esp_eth/src/esp_eth_phy_rtl8201.c index ce613348a6..dd9239d67f 100644 --- a/components/esp_eth/src/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/esp_eth_phy_rtl8201.c @@ -176,6 +176,7 @@ static esp_err_t rtl8201_reset_hw(esp_eth_phy_t *phy) esp_rom_gpio_pad_select_gpio(rtl8201->reset_gpio_num); gpio_set_direction(rtl8201->reset_gpio_num, GPIO_MODE_OUTPUT); gpio_set_level(rtl8201->reset_gpio_num, 0); + ets_delay_us(100); // insert min input assert time gpio_set_level(rtl8201->reset_gpio_num, 1); } return ESP_OK;