diff --git a/components/esp_eth/src/esp_eth_mac_esp.c b/components/esp_eth/src/esp_eth_mac_esp.c index 472e0c3fe5..7704d9ac48 100644 --- a/components/esp_eth/src/esp_eth_mac_esp.c +++ b/components/esp_eth/src/esp_eth_mac_esp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -242,7 +242,7 @@ static esp_err_t emac_esp32_transmit_multiple_bufs(esp_eth_mac_t *mac, uint32_t uint32_t len[argc]; uint32_t exp_len = 0; for (int i = 0; i < argc; i++) { - bufs[i] = va_arg(args, uint8_t*); + bufs[i] = va_arg(args, uint8_t *); len[i] = va_arg(args, uint32_t); exp_len += len[i]; } @@ -295,7 +295,7 @@ static void emac_esp32_rx_task(void *arg) ESP_LOGD(TAG, "receive len= %d", recv_len); emac->eth->stack_input(emac->eth, buffer, recv_len); } - /* if allocation failed and there is a waiting frame */ + /* if allocation failed and there is a waiting frame */ } else if (frame_len) { ESP_LOGE(TAG, "no mem for receive buffer"); /* ensure that interface to EMAC does not get stuck with unprocessed frames */ @@ -342,7 +342,7 @@ static esp_err_t emac_config_apll_clock(void) } // If the difference of real APLL frequency is not within 50 ppm, i.e. 2500 Hz, the APLL is unavailable ESP_RETURN_ON_FALSE(abs((int)real_freq - (int)expt_freq) <= 2500, - ESP_ERR_INVALID_STATE, TAG, "The APLL is working at an unusable frequency"); + ESP_ERR_INVALID_STATE, TAG, "The APLL is working at an unusable frequency"); return ESP_OK; } @@ -381,9 +381,9 @@ static esp_err_t emac_esp32_init(esp_eth_mac_t *mac) esp_pm_lock_acquire(emac->pm_lock); #endif return ESP_OK; + err: eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL); - periph_module_disable(PERIPH_EMAC_MODULE); return ret; } @@ -427,7 +427,10 @@ static esp_err_t emac_esp32_del(esp_eth_mac_t *mac) { emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); esp_emac_free_driver_obj(emac, emac_hal_get_desc_chain(&emac->hal)); - periph_module_disable(PERIPH_EMAC_MODULE); + /// disable bus clock + PERIPH_RCC_ATOMIC() { + emac_ll_enable_bus_clock(0, false); + } return ESP_OK; } @@ -601,12 +604,16 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config esp_eth_mac_t *ret = NULL; void *descriptors = NULL; emac_esp32_t *emac = NULL; - ESP_GOTO_ON_FALSE(config, NULL, err, TAG, "can't set mac config to null"); + ESP_RETURN_ON_FALSE(config, NULL, TAG, "can't set mac config to null"); ret_code = esp_emac_alloc_driver_obj(config, &emac, &descriptors); - ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "alloc driver object failed"); + ESP_RETURN_ON_FALSE(ret_code == ESP_OK, NULL, TAG, "alloc driver object failed"); - /* enable APB to access Ethernet peripheral registers */ - periph_module_enable(PERIPH_EMAC_MODULE); + // enable bus clock for the EMAC module, and reset the registers into default state + // this must be called before HAL layer initialization + PERIPH_RCC_ATOMIC() { + emac_ll_enable_bus_clock(0, true); + emac_ll_reset_register(0); + } /* initialize hal layer driver */ emac_hal_init(&emac->hal, descriptors, emac->rx_buf, emac->tx_buf); /* alloc interrupt */ @@ -619,7 +626,7 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config } ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "alloc emac interrupt failed"); ret_code = esp_emac_config_data_interface(esp32_config, emac); - ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err_interf, TAG, "config emac interface failed"); + ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "config emac interface failed"); emac->dma_burst_len = esp32_config->dma_burst_len; emac->sw_reset_timeout_ms = config->sw_reset_timeout_ms; @@ -649,8 +656,6 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config emac->parent.receive = emac_esp32_receive; return &(emac->parent); -err_interf: - periph_module_disable(PERIPH_EMAC_MODULE); err: esp_emac_free_driver_obj(emac, descriptors); return ret; diff --git a/components/hal/esp32/include/hal/emac_ll.h b/components/hal/esp32/include/hal/emac_ll.h index 7c81da8978..0125ec8058 100644 --- a/components/hal/esp32/include/hal/emac_ll.h +++ b/components/hal/esp32/include/hal/emac_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,7 @@ #include "soc/emac_dma_struct.h" #include "soc/emac_mac_struct.h" #include "soc/emac_ext_struct.h" +#include "soc/dport_reg.h" #ifdef __cplusplus extern "C" { @@ -142,6 +143,41 @@ extern "C" { /* Enable needed interrupts (recv/recv_buf_unavailabal/normal must be enabled to make eth work) */ #define EMAC_LL_CONFIG_ENABLE_INTR_MASK (EMAC_LL_INTR_RECEIVE_ENABLE | EMAC_LL_INTR_NORMAL_SUMMARY_ENABLE) +/** + * @brief Enable the bus clock for the EMAC module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void emac_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + uint32_t reg_val = DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG); + reg_val &= ~DPORT_WIFI_CLK_EMAC_EN; + reg_val |= enable << 14; + DPORT_WRITE_PERI_REG(DPORT_WIFI_CLK_EN_REG, reg_val); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define emac_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; emac_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the EMAC module + * + * @param group_id Group ID + */ +static inline void emac_ll_reset_register(int group_id) +{ + (void)group_id; + DPORT_WRITE_PERI_REG(DPORT_CORE_RST_EN_REG, DPORT_EMAC_RST); + DPORT_WRITE_PERI_REG(DPORT_CORE_RST_EN_REG, 0); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define emac_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; emac_ll_reset_register(__VA_ARGS__) + /************** Start of mac regs operation ********************/ /* emacgmiiaddr */ static inline void emac_ll_set_csr_clock_division(emac_mac_dev_t *mac_regs, uint32_t div_mode) @@ -367,8 +403,6 @@ static inline void emac_ll_set_addr(emac_mac_dev_t *mac_regs, const uint8_t *add } /*************** End of mac regs operation *********************/ - - /************** Start of dma regs operation ********************/ /* dmabusmode */ static inline void emac_ll_reset(emac_dma_dev_t *dma_regs) @@ -551,7 +585,6 @@ __attribute__((always_inline)) static inline void emac_ll_clear_all_pending_intr dma_regs->dmastatus.val = 0xFFFFFFFF; } - /* dmatxpolldemand / dmarxpolldemand */ static inline void emac_ll_transmit_poll_demand(emac_dma_dev_t *dma_regs, uint32_t val) { @@ -564,8 +597,6 @@ static inline void emac_ll_receive_poll_demand(emac_dma_dev_t *dma_regs, uint32_ /*************** End of dma regs operation *********************/ - - /************** Start of ext regs operation ********************/ static inline void emac_ll_clock_enable_mii(emac_ext_dev_t *ext_regs) { @@ -599,7 +630,6 @@ static inline void emac_ll_clock_enable_rmii_output(emac_ext_dev_t *ext_regs) ext_regs->ex_clkout_conf.h_div_num = 0; } - static inline void emac_ll_pause_frame_enable(emac_ext_dev_t *ext_regs, bool enable) { ext_regs->ex_phyinf_conf.sbd_flowctrl = enable;