1 /*
2  * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <string.h>
7 #include <stdlib.h>
8 #include <sys/cdefs.h>
9 #include "driver/periph_ctrl.h"
10 #include "driver/gpio.h"
11 #include "esp_attr.h"
12 #include "esp_log.h"
13 #include "esp_check.h"
14 #include "esp_eth.h"
15 #include "esp_pm.h"
16 #include "esp_system.h"
17 #include "esp_heap_caps.h"
18 #include "esp_intr_alloc.h"
19 #include "esp_private/esp_clk.h"
20 #include "freertos/FreeRTOS.h"
21 #include "freertos/task.h"
22 #include "freertos/semphr.h"
23 #include "hal/cpu_hal.h"
24 #include "hal/emac_hal.h"
25 #include "hal/gpio_hal.h"
26 #include "soc/soc.h"
27 #include "soc/rtc.h"
28 #include "sdkconfig.h"
29 #include "esp_rom_gpio.h"
30 #include "esp_rom_sys.h"
31 #include "hal/emac_ll.h"
32 
33 static const char *TAG = "esp.emac";
34 
35 #define PHY_OPERATION_TIMEOUT_US (1000)
36 #define MAC_STOP_TIMEOUT_US (250)
37 #define FLOW_CONTROL_LOW_WATER_MARK (CONFIG_ETH_DMA_RX_BUFFER_NUM / 3)
38 #define FLOW_CONTROL_HIGH_WATER_MARK (FLOW_CONTROL_LOW_WATER_MARK * 2)
39 
40 typedef struct {
41     esp_eth_mac_t parent;
42     esp_eth_mediator_t *eth;
43     emac_hal_context_t hal;
44     intr_handle_t intr_hdl;
45     TaskHandle_t rx_task_hdl;
46     uint32_t sw_reset_timeout_ms;
47     uint32_t frames_remain;
48     uint32_t free_rx_descriptor;
49     uint32_t flow_control_high_water_mark;
50     uint32_t flow_control_low_water_mark;
51     int smi_mdc_gpio_num;
52     int smi_mdio_gpio_num;
53     eth_mac_clock_config_t clock_config;
54     uint8_t addr[6];
55     uint8_t *rx_buf[CONFIG_ETH_DMA_RX_BUFFER_NUM];
56     uint8_t *tx_buf[CONFIG_ETH_DMA_TX_BUFFER_NUM];
57     bool isr_need_yield;
58     bool flow_ctrl_enabled; // indicates whether the user want to do flow control
59     bool do_flow_ctrl;  // indicates whether we need to do software flow control
60 #ifdef CONFIG_PM_ENABLE
61     esp_pm_lock_handle_t pm_lock;
62 #endif
63 } emac_esp32_t;
64 
65 static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl, void **out_descriptors);
66 static void esp_emac_free_driver_obj(emac_esp32_t *emac, void *descriptors);
67 static esp_err_t emac_esp32_start(esp_eth_mac_t *mac);
68 static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac);
69 
emac_esp32_set_mediator(esp_eth_mac_t * mac,esp_eth_mediator_t * eth)70 static esp_err_t emac_esp32_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)
71 {
72     esp_err_t ret = ESP_OK;
73     ESP_GOTO_ON_FALSE(eth, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac's mediator to null");
74     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
75     emac->eth = eth;
76     return ESP_OK;
77 err:
78     return ret;
79 }
80 
emac_esp32_write_phy_reg(esp_eth_mac_t * mac,uint32_t phy_addr,uint32_t phy_reg,uint32_t reg_value)81 static esp_err_t emac_esp32_write_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)
82 {
83     esp_err_t ret = ESP_OK;
84     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
85     ESP_GOTO_ON_FALSE(!emac_ll_is_mii_busy(emac->hal.mac_regs), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
86     emac_ll_set_phy_data(emac->hal.mac_regs, reg_value);
87     emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, true);
88     /* polling the busy flag */
89     uint32_t to = 0;
90     bool busy = true;
91     do {
92         esp_rom_delay_us(100);
93         busy = emac_ll_is_mii_busy(emac->hal.mac_regs);
94         to += 100;
95     } while (busy && to < PHY_OPERATION_TIMEOUT_US);
96     ESP_GOTO_ON_FALSE(!busy, ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
97     return ESP_OK;
98 err:
99     return ret;
100 }
101 
emac_esp32_read_phy_reg(esp_eth_mac_t * mac,uint32_t phy_addr,uint32_t phy_reg,uint32_t * reg_value)102 static esp_err_t emac_esp32_read_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)
103 {
104     esp_err_t ret = ESP_OK;
105     ESP_GOTO_ON_FALSE(reg_value, ESP_ERR_INVALID_ARG, err, TAG, "can't set reg_value to null");
106     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
107     ESP_GOTO_ON_FALSE(!emac_ll_is_mii_busy(emac->hal.mac_regs), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
108     emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, false);
109     /* polling the busy flag */
110     uint32_t to = 0;
111     bool busy = true;
112     do {
113         esp_rom_delay_us(100);
114         busy = emac_ll_is_mii_busy(emac->hal.mac_regs);
115         to += 100;
116     } while (busy && to < PHY_OPERATION_TIMEOUT_US);
117     ESP_GOTO_ON_FALSE(!busy, ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
118     /* Store value */
119     *reg_value = emac_ll_get_phy_data(emac->hal.mac_regs);
120     return ESP_OK;
121 err:
122     return ret;
123 }
124 
emac_esp32_set_addr(esp_eth_mac_t * mac,uint8_t * addr)125 static esp_err_t emac_esp32_set_addr(esp_eth_mac_t *mac, uint8_t *addr)
126 {
127     esp_err_t ret = ESP_OK;
128     ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
129     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
130     memcpy(emac->addr, addr, 6);
131     emac_hal_set_address(&emac->hal, emac->addr);
132     return ESP_OK;
133 err:
134     return ret;
135 }
136 
emac_esp32_get_addr(esp_eth_mac_t * mac,uint8_t * addr)137 static esp_err_t emac_esp32_get_addr(esp_eth_mac_t *mac, uint8_t *addr)
138 {
139     esp_err_t ret = ESP_OK;
140     ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
141     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
142     memcpy(addr, emac->addr, 6);
143     return ESP_OK;
144 err:
145     return ret;
146 }
147 
emac_esp32_set_link(esp_eth_mac_t * mac,eth_link_t link)148 static esp_err_t emac_esp32_set_link(esp_eth_mac_t *mac, eth_link_t link)
149 {
150     esp_err_t ret = ESP_OK;
151     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
152     switch (link) {
153     case ETH_LINK_UP:
154         ESP_GOTO_ON_ERROR(esp_intr_enable(emac->intr_hdl), err, TAG, "enable interrupt failed");
155         emac_esp32_start(mac);
156         break;
157     case ETH_LINK_DOWN:
158         ESP_GOTO_ON_ERROR(esp_intr_disable(emac->intr_hdl), err, TAG, "disable interrupt failed");
159         emac_esp32_stop(mac);
160         break;
161     default:
162         ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown link status");
163         break;
164     }
165     return ESP_OK;
166 err:
167     return ret;
168 }
169 
emac_esp32_set_speed(esp_eth_mac_t * mac,eth_speed_t speed)170 static esp_err_t emac_esp32_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
171 {
172     esp_err_t ret = ESP_ERR_INVALID_ARG;
173     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
174     if (speed >= ETH_SPEED_10M && speed < ETH_SPEED_MAX) {
175         emac_ll_set_port_speed(emac->hal.mac_regs, speed);
176         ESP_LOGD(TAG, "working in %dMbps", speed == ETH_SPEED_10M ? 10 : 100);
177         return ESP_OK;
178     }
179     return ret;
180 }
181 
emac_esp32_set_duplex(esp_eth_mac_t * mac,eth_duplex_t duplex)182 static esp_err_t emac_esp32_set_duplex(esp_eth_mac_t *mac, eth_duplex_t duplex)
183 {
184     esp_err_t ret = ESP_ERR_INVALID_ARG;
185     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
186     if (duplex == ETH_DUPLEX_HALF || duplex == ETH_DUPLEX_FULL) {
187         emac_ll_set_duplex(emac->hal.mac_regs, duplex);
188         ESP_LOGD(TAG, "working in %s duplex", duplex == ETH_DUPLEX_HALF ? "half" : "full");
189         return ESP_OK;
190     }
191     return ret;
192 }
193 
emac_esp32_set_promiscuous(esp_eth_mac_t * mac,bool enable)194 static esp_err_t emac_esp32_set_promiscuous(esp_eth_mac_t *mac, bool enable)
195 {
196     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
197     emac_ll_promiscuous_mode_enable(emac->hal.mac_regs, enable);
198     return ESP_OK;
199 }
200 
emac_esp32_enable_flow_ctrl(esp_eth_mac_t * mac,bool enable)201 static esp_err_t emac_esp32_enable_flow_ctrl(esp_eth_mac_t *mac, bool enable)
202 {
203     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
204     emac->flow_ctrl_enabled = enable;
205     return ESP_OK;
206 }
207 
emac_esp32_set_peer_pause_ability(esp_eth_mac_t * mac,uint32_t ability)208 static esp_err_t emac_esp32_set_peer_pause_ability(esp_eth_mac_t *mac, uint32_t ability)
209 {
210     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
211     // we want to enable flow control, and peer does support pause function
212     // then configure the MAC layer to enable flow control feature
213     if (emac->flow_ctrl_enabled && ability) {
214         emac_hal_enable_flow_ctrl(&emac->hal, true);
215         emac->do_flow_ctrl = true;
216     } else {
217         emac_hal_enable_flow_ctrl(&emac->hal, false);
218         emac->do_flow_ctrl = false;
219         ESP_LOGD(TAG, "Flow control not enabled for the link");
220     }
221     return ESP_OK;
222 }
223 
emac_esp32_transmit(esp_eth_mac_t * mac,uint8_t * buf,uint32_t length)224 static esp_err_t emac_esp32_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length)
225 {
226     esp_err_t ret = ESP_OK;
227     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
228     uint32_t sent_len = emac_hal_transmit_frame(&emac->hal, buf, length);
229     ESP_GOTO_ON_FALSE(sent_len == length, ESP_ERR_NO_MEM, err, TAG, "insufficient TX buffer size");
230     return ESP_OK;
231 err:
232     return ret;
233 }
234 
emac_esp32_receive(esp_eth_mac_t * mac,uint8_t * buf,uint32_t * length)235 static esp_err_t emac_esp32_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length)
236 {
237     esp_err_t ret = ESP_OK;
238     uint32_t expected_len = *length;
239     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
240     ESP_GOTO_ON_FALSE(buf && length, ESP_ERR_INVALID_ARG, err, TAG, "can't set buf and length to null");
241     uint32_t receive_len = emac_hal_receive_frame(&emac->hal, buf, expected_len, &emac->frames_remain, &emac->free_rx_descriptor);
242     /* we need to check the return value in case the buffer size is not enough */
243     ESP_LOGD(TAG, "receive len= %d", receive_len);
244     ESP_GOTO_ON_FALSE(expected_len >= receive_len, ESP_ERR_INVALID_SIZE, err, TAG, "received buffer longer than expected");
245     *length = receive_len;
246     return ESP_OK;
247 err:
248     *length = expected_len;
249     return ret;
250 }
251 
emac_esp32_rx_task(void * arg)252 static void emac_esp32_rx_task(void *arg)
253 {
254     emac_esp32_t *emac = (emac_esp32_t *)arg;
255     uint8_t *buffer = NULL;
256     uint32_t length = 0;
257     while (1) {
258         // block indefinitely until got notification from underlay event
259         ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
260         do {
261             length = ETH_MAX_PACKET_SIZE;
262             buffer = malloc(length);
263             if (!buffer) {
264                 ESP_LOGE(TAG, "no mem for receive buffer");
265             } else if (emac_esp32_receive(&emac->parent, buffer, &length) == ESP_OK) {
266                 /* pass the buffer to stack (e.g. TCP/IP layer) */
267                 if (length) {
268                     emac->eth->stack_input(emac->eth, buffer, length);
269                 } else {
270                     free(buffer);
271                 }
272             } else {
273                 free(buffer);
274             }
275 #if CONFIG_ETH_SOFT_FLOW_CONTROL
276             // we need to do extra checking of remained frames in case there are no unhandled frames left, but pause frame is still undergoing
277             if ((emac->free_rx_descriptor < emac->flow_control_low_water_mark) && emac->do_flow_ctrl && emac->frames_remain) {
278                 emac_ll_pause_frame_enable(emac->hal.ext_regs, true);
279             } else if ((emac->free_rx_descriptor > emac->flow_control_high_water_mark) || !emac->frames_remain) {
280                 emac_ll_pause_frame_enable(emac->hal.ext_regs, false);
281             }
282 #endif
283         } while (emac->frames_remain);
284     }
285     vTaskDelete(NULL);
286 }
287 
emac_esp32_init_smi_gpio(emac_esp32_t * emac)288 static void emac_esp32_init_smi_gpio(emac_esp32_t *emac)
289 {
290     if (emac->smi_mdc_gpio_num >= 0) {
291         /* Setup SMI MDC GPIO */
292         gpio_set_direction(emac->smi_mdc_gpio_num, GPIO_MODE_OUTPUT);
293         esp_rom_gpio_connect_out_signal(emac->smi_mdc_gpio_num, EMAC_MDC_O_IDX, false, false);
294         gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[emac->smi_mdc_gpio_num], PIN_FUNC_GPIO);
295     }
296     if (emac->smi_mdio_gpio_num >= 0) {
297         /* Setup SMI MDIO GPIO */
298         gpio_set_direction(emac->smi_mdio_gpio_num, GPIO_MODE_INPUT_OUTPUT);
299         esp_rom_gpio_connect_out_signal(emac->smi_mdio_gpio_num, EMAC_MDO_O_IDX, false, false);
300         esp_rom_gpio_connect_in_signal(emac->smi_mdio_gpio_num, EMAC_MDI_I_IDX, false);
301         gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[emac->smi_mdio_gpio_num], PIN_FUNC_GPIO);
302     }
303 }
304 
emac_config_apll_clock(void)305 static void emac_config_apll_clock(void)
306 {
307     /* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
308     rtc_xtal_freq_t rtc_xtal_freq = rtc_clk_xtal_freq_get();
309     switch (rtc_xtal_freq) {
310     case RTC_XTAL_FREQ_40M: // Recommended
311         /* 50 MHz = 40MHz * (4 + 6) / (2 * (2 + 2) = 50.000 */
312         /* sdm0 = 0, sdm1 = 0, sdm2 = 6, o_div = 2 */
313         rtc_clk_apll_enable(true, 0, 0, 6, 2);
314         break;
315     case RTC_XTAL_FREQ_26M:
316         /* 50 MHz = 26MHz * (4 + 15 + 118 / 256 + 39/65536) / ((3 + 2) * 2) = 49.999992 */
317         /* sdm0 = 39, sdm1 = 118, sdm2 = 15, o_div = 3 */
318         rtc_clk_apll_enable(true, 39, 118, 15, 3);
319         break;
320     case RTC_XTAL_FREQ_24M:
321         /* 50 MHz = 24MHz * (4 + 12 + 255 / 256 + 255/65536) / ((2 + 2) * 2) = 49.499977 */
322         /* sdm0 = 255, sdm1 = 255, sdm2 = 12, o_div = 2 */
323         rtc_clk_apll_enable(true, 255, 255, 12, 2);
324         break;
325     default: // Assume we have a 40M xtal
326         rtc_clk_apll_enable(true, 0, 0, 6, 2);
327         break;
328     }
329 }
330 
emac_esp32_init(esp_eth_mac_t * mac)331 static esp_err_t emac_esp32_init(esp_eth_mac_t *mac)
332 {
333     esp_err_t ret = ESP_OK;
334     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
335     esp_eth_mediator_t *eth = emac->eth;
336 
337     /* init gpio used by smi interface */
338     emac_esp32_init_smi_gpio(emac);
339     ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL), err, TAG, "lowlevel init failed");
340     /* software reset */
341     emac_ll_reset(emac->hal.dma_regs);
342     uint32_t to = 0;
343     for (to = 0; to < emac->sw_reset_timeout_ms / 10; to++) {
344         if (emac_ll_is_reset_done(emac->hal.dma_regs)) {
345             break;
346         }
347         vTaskDelay(pdMS_TO_TICKS(10));
348     }
349     ESP_GOTO_ON_FALSE(to < emac->sw_reset_timeout_ms / 10, ESP_ERR_TIMEOUT, err, TAG, "reset timeout");
350     /* set smi clock */
351     emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq());
352     /* reset descriptor chain */
353     emac_hal_reset_desc_chain(&emac->hal);
354     /* init mac registers by default */
355     emac_hal_init_mac_default(&emac->hal);
356     /* init dma registers by default */
357     emac_hal_init_dma_default(&emac->hal);
358     /* get emac address from efuse */
359     ESP_GOTO_ON_ERROR(esp_read_mac(emac->addr, ESP_MAC_ETH), err, TAG, "fetch ethernet mac address failed");
360     /* set MAC address to emac register */
361     emac_hal_set_address(&emac->hal, emac->addr);
362 #ifdef CONFIG_PM_ENABLE
363     esp_pm_lock_acquire(emac->pm_lock);
364 #endif
365     return ESP_OK;
366 err:
367     eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
368     periph_module_disable(PERIPH_EMAC_MODULE);
369     return ret;
370 }
371 
emac_esp32_deinit(esp_eth_mac_t * mac)372 static esp_err_t emac_esp32_deinit(esp_eth_mac_t *mac)
373 {
374     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
375     esp_eth_mediator_t *eth = emac->eth;
376 #ifdef CONFIG_PM_ENABLE
377     esp_pm_lock_release(emac->pm_lock);
378 #endif
379     emac_hal_stop(&emac->hal);
380     eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
381     return ESP_OK;
382 }
383 
emac_esp32_start(esp_eth_mac_t * mac)384 static esp_err_t emac_esp32_start(esp_eth_mac_t *mac)
385 {
386     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
387     emac_hal_reset_desc_chain(&emac->hal);
388     emac_hal_start(&emac->hal);
389     return ESP_OK;
390 }
391 
emac_esp32_stop(esp_eth_mac_t * mac)392 static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac)
393 {
394     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
395     esp_err_t ret = ESP_OK;
396     int32_t to = 0;
397     do {
398         if ((ret = emac_hal_stop(&emac->hal)) == ESP_OK) {
399             break;
400         }
401         to += 25;
402         esp_rom_delay_us(25);
403     } while (to < MAC_STOP_TIMEOUT_US);
404     return ret;
405 }
406 
emac_esp32_del(esp_eth_mac_t * mac)407 static esp_err_t emac_esp32_del(esp_eth_mac_t *mac)
408 {
409     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
410     esp_emac_free_driver_obj(emac, emac->hal.descriptors);
411     periph_module_disable(PERIPH_EMAC_MODULE);
412     return ESP_OK;
413 }
414 
415 // To achieve a better performance, we put the ISR always in IRAM
emac_isr_default_handler(void * args)416 IRAM_ATTR void emac_isr_default_handler(void *args)
417 {
418     emac_hal_context_t *hal = (emac_hal_context_t *)args;
419     emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal);
420     BaseType_t high_task_wakeup = pdFALSE;
421     uint32_t intr_stat = emac_ll_get_intr_status(hal->dma_regs);
422     emac_ll_clear_corresponding_intr(hal->dma_regs, intr_stat);
423 
424 #if EMAC_LL_CONFIG_ENABLE_INTR_MASK & EMAC_LL_INTR_RECEIVE_ENABLE
425     if (intr_stat & EMAC_LL_DMA_RECEIVE_FINISH_INTR) {
426         /* notify receive task */
427         vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
428         if (high_task_wakeup == pdTRUE) {
429             portYIELD_FROM_ISR();
430         }
431     }
432 #endif
433 }
434 
esp_emac_free_driver_obj(emac_esp32_t * emac,void * descriptors)435 static void esp_emac_free_driver_obj(emac_esp32_t *emac, void *descriptors)
436 {
437     if (emac) {
438         if (emac->rx_task_hdl) {
439             vTaskDelete(emac->rx_task_hdl);
440         }
441         if (emac->intr_hdl) {
442             esp_intr_free(emac->intr_hdl);
443         }
444         for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
445             free(emac->tx_buf[i]);
446         }
447         for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
448             free(emac->rx_buf[i]);
449         }
450 #ifdef CONFIG_PM_ENABLE
451         if (emac->pm_lock) {
452             esp_pm_lock_delete(emac->pm_lock);
453         }
454 #endif
455         free(emac);
456     }
457     if (descriptors) {
458         free(descriptors);
459     }
460 }
461 
esp_emac_alloc_driver_obj(const eth_mac_config_t * config,emac_esp32_t ** emac_out_hdl,void ** out_descriptors)462 static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl, void **out_descriptors)
463 {
464     esp_err_t ret = ESP_OK;
465     emac_esp32_t *emac = NULL;
466     void *descriptors = NULL;
467     if (config->flags & ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE) {
468         emac = heap_caps_calloc(1, sizeof(emac_esp32_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
469     } else {
470         emac = calloc(1, sizeof(emac_esp32_t));
471     }
472     ESP_GOTO_ON_FALSE(emac, ESP_ERR_NO_MEM, err, TAG, "no mem for esp emac object");
473     /* alloc memory for ethernet dma descriptor */
474     uint32_t desc_size = CONFIG_ETH_DMA_RX_BUFFER_NUM * sizeof(eth_dma_rx_descriptor_t) +
475                          CONFIG_ETH_DMA_TX_BUFFER_NUM * sizeof(eth_dma_tx_descriptor_t);
476     descriptors = heap_caps_calloc(1, desc_size, MALLOC_CAP_DMA);
477     ESP_GOTO_ON_FALSE(descriptors, ESP_ERR_NO_MEM, err, TAG, "no mem for descriptors");
478     /* alloc memory for ethernet dma buffer */
479     for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
480         emac->rx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA);
481         ESP_GOTO_ON_FALSE(emac->rx_buf[i], ESP_ERR_NO_MEM, err, TAG, "no mem for RX DMA buffers");
482     }
483     for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
484         emac->tx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA);
485         ESP_GOTO_ON_FALSE(emac->tx_buf[i], ESP_ERR_NO_MEM, err, TAG, "no mem for TX DMA buffers");
486     }
487     /* alloc PM lock */
488 #ifdef CONFIG_PM_ENABLE
489     ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "emac_esp32", &emac->pm_lock), err, TAG, "create pm lock failed");
490 #endif
491     /* create rx task */
492     BaseType_t core_num = tskNO_AFFINITY;
493     if (config->flags & ETH_MAC_FLAG_PIN_TO_CORE) {
494         core_num = cpu_hal_get_core_id();
495     }
496     BaseType_t xReturned = xTaskCreatePinnedToCore(emac_esp32_rx_task, "emac_rx", config->rx_task_stack_size, emac,
497                            config->rx_task_prio, &emac->rx_task_hdl, core_num);
498     ESP_GOTO_ON_FALSE(xReturned == pdPASS, ESP_FAIL, err, TAG, "create emac_rx task failed");
499 
500     *out_descriptors = descriptors;
501     *emac_out_hdl = emac;
502     return ESP_OK;
503 err:
504     esp_emac_free_driver_obj(emac, descriptors);
505     return ret;
506 }
507 
esp_emac_config_data_interface(const eth_mac_config_t * config,emac_esp32_t * emac)508 static esp_err_t esp_emac_config_data_interface(const eth_mac_config_t *config, emac_esp32_t *emac)
509 {
510     esp_err_t ret = ESP_OK;
511     switch (config->interface) {
512     case EMAC_DATA_INTERFACE_MII:
513         emac->clock_config = config->clock_config;
514         /* MII interface GPIO initialization */
515         emac_hal_iomux_init_mii();
516         /* Enable MII clock */
517         emac_ll_clock_enable_mii(emac->hal.ext_regs);
518         break;
519     case EMAC_DATA_INTERFACE_RMII:
520         // by default, the clock mode is selected at compile time (by Kconfig)
521         if (config->clock_config.rmii.clock_mode == EMAC_CLK_DEFAULT) {
522 #if CONFIG_ETH_RMII_CLK_INPUT
523 #if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
524             emac->clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
525             emac->clock_config.rmii.clock_gpio = CONFIG_ETH_RMII_CLK_IN_GPIO;
526 #else
527 #error "ESP32 EMAC only support input RMII clock to GPIO0"
528 #endif // CONFIG_ETH_RMII_CLK_IN_GPIO == 0
529 #elif CONFIG_ETH_RMII_CLK_OUTPUT
530             emac->clock_config.rmii.clock_mode = EMAC_CLK_OUT;
531 #if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
532             emac->clock_config.rmii.clock_gpio = 0;
533 #elif CONFIG_ETH_RMII_CLK_OUT_GPIO
534             emac->clock_config.rmii.clock_gpio = CONFIG_ETH_RMII_CLK_OUT_GPIO;
535 #endif // CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
536 #else
537 #error "Unsupported RMII clock mode"
538 #endif
539         } else {
540             emac->clock_config = config->clock_config;
541         }
542         /* RMII interface GPIO initialization */
543         emac_hal_iomux_init_rmii();
544         /* If ref_clk is configured as input */
545         if (emac->clock_config.rmii.clock_mode == EMAC_CLK_EXT_IN) {
546             ESP_GOTO_ON_FALSE(emac->clock_config.rmii.clock_gpio == EMAC_CLK_IN_GPIO,
547                               ESP_ERR_INVALID_ARG, err, TAG, "ESP32 EMAC only support input RMII clock to GPIO0");
548             emac_hal_iomux_rmii_clk_input();
549             emac_ll_clock_enable_rmii_input(emac->hal.ext_regs);
550         } else if (emac->clock_config.rmii.clock_mode == EMAC_CLK_OUT) {
551             ESP_GOTO_ON_FALSE(emac->clock_config.rmii.clock_gpio == EMAC_APPL_CLK_OUT_GPIO ||
552                               emac->clock_config.rmii.clock_gpio == EMAC_CLK_OUT_GPIO ||
553                               emac->clock_config.rmii.clock_gpio == EMAC_CLK_OUT_180_GPIO,
554                               ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC clock output GPIO");
555             emac_hal_iomux_rmii_clk_ouput(emac->clock_config.rmii.clock_gpio);
556             if (emac->clock_config.rmii.clock_gpio == EMAC_APPL_CLK_OUT_GPIO) {
557                 REG_SET_FIELD(PIN_CTRL, CLK_OUT1, 6);
558             }
559             /* Enable RMII clock */
560             emac_ll_clock_enable_rmii_output(emac->hal.ext_regs);
561             emac_config_apll_clock();
562         } else {
563             ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC clock mode");
564         }
565         break;
566     default:
567         ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC Data Interface:%d", config->interface);
568     }
569 err:
570     return ret;
571 }
572 
esp_eth_mac_new_esp32(const eth_mac_config_t * config)573 esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config)
574 {
575     esp_err_t ret_code = ESP_OK;
576     esp_eth_mac_t *ret = NULL;
577     void *descriptors = NULL;
578     emac_esp32_t *emac = NULL;
579     ESP_GOTO_ON_FALSE(config, NULL, err, TAG, "can't set mac config to null");
580     ret_code = esp_emac_alloc_driver_obj(config, &emac, &descriptors);
581     ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "alloc driver object failed");
582 
583     /* enable APB to access Ethernet peripheral registers */
584     periph_module_enable(PERIPH_EMAC_MODULE);
585     /* initialize hal layer driver */
586     emac_hal_init(&emac->hal, descriptors, emac->rx_buf, emac->tx_buf);
587     /* alloc interrupt */
588     if (config->flags & ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE) {
589         ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, ESP_INTR_FLAG_IRAM,
590                                   emac_isr_default_handler, &emac->hal, &(emac->intr_hdl));
591     } else {
592         ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0,
593                                   emac_isr_default_handler, &emac->hal, &(emac->intr_hdl));
594     }
595     ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "alloc emac interrupt failed");
596     ret_code = esp_emac_config_data_interface(config, emac);
597     ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err_interf, TAG, "config emac interface failed");
598 
599     emac->sw_reset_timeout_ms = config->sw_reset_timeout_ms;
600     emac->smi_mdc_gpio_num = config->smi_mdc_gpio_num;
601     emac->smi_mdio_gpio_num = config->smi_mdio_gpio_num;
602     emac->flow_control_high_water_mark = FLOW_CONTROL_HIGH_WATER_MARK;
603     emac->flow_control_low_water_mark = FLOW_CONTROL_LOW_WATER_MARK;
604     emac->parent.set_mediator = emac_esp32_set_mediator;
605     emac->parent.init = emac_esp32_init;
606     emac->parent.deinit = emac_esp32_deinit;
607     emac->parent.start = emac_esp32_start;
608     emac->parent.stop = emac_esp32_stop;
609     emac->parent.del = emac_esp32_del;
610     emac->parent.write_phy_reg = emac_esp32_write_phy_reg;
611     emac->parent.read_phy_reg = emac_esp32_read_phy_reg;
612     emac->parent.set_addr = emac_esp32_set_addr;
613     emac->parent.get_addr = emac_esp32_get_addr;
614     emac->parent.set_speed = emac_esp32_set_speed;
615     emac->parent.set_duplex = emac_esp32_set_duplex;
616     emac->parent.set_link = emac_esp32_set_link;
617     emac->parent.set_promiscuous = emac_esp32_set_promiscuous;
618     emac->parent.set_peer_pause_ability = emac_esp32_set_peer_pause_ability;
619     emac->parent.enable_flow_ctrl = emac_esp32_enable_flow_ctrl;
620     emac->parent.transmit = emac_esp32_transmit;
621     emac->parent.receive = emac_esp32_receive;
622     return &(emac->parent);
623 
624 err_interf:
625     periph_module_disable(PERIPH_EMAC_MODULE);
626 err:
627     esp_emac_free_driver_obj(emac, descriptors);
628     return ret;
629 }
630