forked from espressif/esp-idf
refactor(emac): add LL functions for bus clock control
This commit is contained in:
@@ -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
|
* 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 len[argc];
|
||||||
uint32_t exp_len = 0;
|
uint32_t exp_len = 0;
|
||||||
for (int i = 0; i < argc; i++) {
|
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);
|
len[i] = va_arg(args, uint32_t);
|
||||||
exp_len += len[i];
|
exp_len += len[i];
|
||||||
}
|
}
|
||||||
@@ -295,7 +295,7 @@ static void emac_esp32_rx_task(void *arg)
|
|||||||
ESP_LOGD(TAG, "receive len= %d", recv_len);
|
ESP_LOGD(TAG, "receive len= %d", recv_len);
|
||||||
emac->eth->stack_input(emac->eth, buffer, 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) {
|
} else if (frame_len) {
|
||||||
ESP_LOGE(TAG, "no mem for receive buffer");
|
ESP_LOGE(TAG, "no mem for receive buffer");
|
||||||
/* ensure that interface to EMAC does not get stuck with unprocessed frames */
|
/* 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
|
// 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_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;
|
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);
|
esp_pm_lock_acquire(emac->pm_lock);
|
||||||
#endif
|
#endif
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
|
eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
|
||||||
periph_module_disable(PERIPH_EMAC_MODULE);
|
|
||||||
return ret;
|
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);
|
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
|
||||||
esp_emac_free_driver_obj(emac, emac_hal_get_desc_chain(&emac->hal));
|
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;
|
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;
|
esp_eth_mac_t *ret = NULL;
|
||||||
void *descriptors = NULL;
|
void *descriptors = NULL;
|
||||||
emac_esp32_t *emac = 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);
|
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 */
|
// enable bus clock for the EMAC module, and reset the registers into default state
|
||||||
periph_module_enable(PERIPH_EMAC_MODULE);
|
// 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 */
|
/* initialize hal layer driver */
|
||||||
emac_hal_init(&emac->hal, descriptors, emac->rx_buf, emac->tx_buf);
|
emac_hal_init(&emac->hal, descriptors, emac->rx_buf, emac->tx_buf);
|
||||||
/* alloc interrupt */
|
/* 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");
|
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);
|
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->dma_burst_len = esp32_config->dma_burst_len;
|
||||||
emac->sw_reset_timeout_ms = config->sw_reset_timeout_ms;
|
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;
|
emac->parent.receive = emac_esp32_receive;
|
||||||
return &(emac->parent);
|
return &(emac->parent);
|
||||||
|
|
||||||
err_interf:
|
|
||||||
periph_module_disable(PERIPH_EMAC_MODULE);
|
|
||||||
err:
|
err:
|
||||||
esp_emac_free_driver_obj(emac, descriptors);
|
esp_emac_free_driver_obj(emac, descriptors);
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "soc/emac_dma_struct.h"
|
#include "soc/emac_dma_struct.h"
|
||||||
#include "soc/emac_mac_struct.h"
|
#include "soc/emac_mac_struct.h"
|
||||||
#include "soc/emac_ext_struct.h"
|
#include "soc/emac_ext_struct.h"
|
||||||
|
#include "soc/dport_reg.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -142,6 +143,41 @@ extern "C" {
|
|||||||
/* Enable needed interrupts (recv/recv_buf_unavailabal/normal must be enabled to make eth work) */
|
/* 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)
|
#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 ********************/
|
/************** Start of mac regs operation ********************/
|
||||||
/* emacgmiiaddr */
|
/* emacgmiiaddr */
|
||||||
static inline void emac_ll_set_csr_clock_division(emac_mac_dev_t *mac_regs, uint32_t div_mode)
|
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 *********************/
|
/*************** End of mac regs operation *********************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************** Start of dma regs operation ********************/
|
/************** Start of dma regs operation ********************/
|
||||||
/* dmabusmode */
|
/* dmabusmode */
|
||||||
static inline void emac_ll_reset(emac_dma_dev_t *dma_regs)
|
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;
|
dma_regs->dmastatus.val = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* dmatxpolldemand / dmarxpolldemand */
|
/* dmatxpolldemand / dmarxpolldemand */
|
||||||
static inline void emac_ll_transmit_poll_demand(emac_dma_dev_t *dma_regs, uint32_t val)
|
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 *********************/
|
/*************** End of dma regs operation *********************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************** Start of ext regs operation ********************/
|
/************** Start of ext regs operation ********************/
|
||||||
static inline void emac_ll_clock_enable_mii(emac_ext_dev_t *ext_regs)
|
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;
|
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)
|
static inline void emac_ll_pause_frame_enable(emac_ext_dev_t *ext_regs, bool enable)
|
||||||
{
|
{
|
||||||
ext_regs->ex_phyinf_conf.sbd_flowctrl = enable;
|
ext_regs->ex_phyinf_conf.sbd_flowctrl = enable;
|
||||||
|
Reference in New Issue
Block a user