1 // Copyright 2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <string.h>
15 #include "sdkconfig.h"
16 #include "esp_attr.h"
17 #include "soc/gpio_periph.h"
18 #include "soc/rtc.h"
19 #include "hal/emac.h"
20 #include "hal/gpio_hal.h"
21
22 #define ETH_CRC_LENGTH (4)
23
24 #if CONFIG_ETH_RMII_CLK_OUTPUT
emac_config_apll_clock(void)25 static void emac_config_apll_clock(void)
26 {
27 /* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
28 rtc_xtal_freq_t rtc_xtal_freq = rtc_clk_xtal_freq_get();
29 switch (rtc_xtal_freq) {
30 case RTC_XTAL_FREQ_40M: // Recommended
31 /* 50 MHz = 40MHz * (4 + 6) / (2 * (2 + 2) = 50.000 */
32 /* sdm0 = 0, sdm1 = 0, sdm2 = 6, o_div = 2 */
33 rtc_clk_apll_enable(true, 0, 0, 6, 2);
34 break;
35 case RTC_XTAL_FREQ_26M:
36 /* 50 MHz = 26MHz * (4 + 15 + 118 / 256 + 39/65536) / ((3 + 2) * 2) = 49.999992 */
37 /* sdm0 = 39, sdm1 = 118, sdm2 = 15, o_div = 3 */
38 rtc_clk_apll_enable(true, 39, 118, 15, 3);
39 break;
40 case RTC_XTAL_FREQ_24M:
41 /* 50 MHz = 24MHz * (4 + 12 + 255 / 256 + 255/65536) / ((2 + 2) * 2) = 49.499977 */
42 /* sdm0 = 255, sdm1 = 255, sdm2 = 12, o_div = 2 */
43 rtc_clk_apll_enable(true, 255, 255, 12, 2);
44 break;
45 default: // Assume we have a 40M xtal
46 rtc_clk_apll_enable(true, 0, 0, 6, 2);
47 break;
48 }
49 }
50 #endif
51
emac_hal_init(emac_hal_context_t * hal,void * descriptors,uint8_t ** rx_buf,uint8_t ** tx_buf)52 void emac_hal_init(emac_hal_context_t *hal, void *descriptors,
53 uint8_t **rx_buf, uint8_t **tx_buf)
54 {
55 hal->dma_regs = &EMAC_DMA;
56 hal->mac_regs = &EMAC_MAC;
57 hal->ext_regs = &EMAC_EXT;
58 hal->descriptors = descriptors;
59 hal->rx_buf = rx_buf;
60 hal->tx_buf = tx_buf;
61 }
62
emac_hal_lowlevel_init(emac_hal_context_t * hal)63 void emac_hal_lowlevel_init(emac_hal_context_t *hal)
64 {
65 /* GPIO configuration */
66 /* TX_EN to GPIO21 */
67 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
68 PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
69 /* TXD0 to GPIO19 */
70 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
71 PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
72 /* TXD1 to GPIO22 */
73 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
74 PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
75 /* RXD0 to GPIO25 */
76 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
77 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
78 /* RXD1 to GPIO26 */
79 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
80 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
81 /* CRS_DV to GPIO27 */
82 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
83 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
84 #if CONFIG_ETH_RMII_CLK_INPUT
85 #if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
86 /* RMII clock (50MHz) input to GPIO0 */
87 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
88 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
89 #else
90 #error "ESP32 EMAC only support input RMII clock to GPIO0"
91 #endif
92 #endif
93 #if CONFIG_ETH_RMII_CLK_OUTPUT
94 #if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
95 /* APLL clock output to GPIO0 (must be configured to 50MHz!) */
96 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
97 PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
98 #elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 16
99 /* RMII CLK (50MHz) output to GPIO16 */
100 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
101 PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
102 #elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 17
103 /* RMII CLK (50MHz) output to GPIO17 */
104 gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
105 PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
106 #endif
107 #endif // CONFIG_ETH_RMII_CLK_OUTPUT
108 /* Clock configuration */
109 #if CONFIG_ETH_PHY_INTERFACE_MII
110 hal->ext_regs->ex_phyinf_conf.phy_intf_sel = 0;
111 hal->ext_regs->ex_clk_ctrl.mii_clk_rx_en = 1;
112 hal->ext_regs->ex_clk_ctrl.mii_clk_tx_en = 1;
113 #elif CONFIG_ETH_PHY_INTERFACE_RMII
114 hal->ext_regs->ex_phyinf_conf.phy_intf_sel = 4;
115 #if CONFIG_ETH_RMII_CLK_INPUT
116 hal->ext_regs->ex_clk_ctrl.ext_en = 1;
117 hal->ext_regs->ex_clk_ctrl.int_en = 0;
118 hal->ext_regs->ex_oscclk_conf.clk_sel = 1;
119 #elif CONFIG_ETH_RMII_CLK_OUTPUT
120 hal->ext_regs->ex_clk_ctrl.ext_en = 0;
121 hal->ext_regs->ex_clk_ctrl.int_en = 1;
122 hal->ext_regs->ex_oscclk_conf.clk_sel = 0;
123 emac_config_apll_clock();
124 hal->ext_regs->ex_clkout_conf.div_num = 0;
125 hal->ext_regs->ex_clkout_conf.h_div_num = 0;
126 #if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
127 /* Choose the APLL clock to output on GPIO */
128 REG_WRITE(PIN_CTRL, 6);
129 #endif // CONFIG_RMII_CLK_OUTPUT_GPIO0
130 #endif // CONFIG_ETH_RMII_CLK_INPUT
131 #endif // CONFIG_ETH_PHY_INTERFACE_MII
132 }
133
emac_hal_reset(emac_hal_context_t * hal)134 void emac_hal_reset(emac_hal_context_t *hal)
135 {
136 hal->dma_regs->dmabusmode.sw_rst = 1;
137 }
138
emac_hal_is_reset_done(emac_hal_context_t * hal)139 bool emac_hal_is_reset_done(emac_hal_context_t *hal)
140 {
141 return hal->dma_regs->dmabusmode.sw_rst ? false : true;
142 }
143
emac_hal_set_csr_clock_range(emac_hal_context_t * hal)144 void emac_hal_set_csr_clock_range(emac_hal_context_t *hal)
145 {
146 /* Tell MAC system clock Frequency, which will determin the frequency range of MDC(1MHz~2.5MHz) */
147 if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 20 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 35) {
148 hal->mac_regs->emacgmiiaddr.miicsrclk = 2;
149 } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 35 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 60) {
150 hal->mac_regs->emacgmiiaddr.miicsrclk = 3;
151 } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 60 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 100) {
152 hal->mac_regs->emacgmiiaddr.miicsrclk = 0;
153 } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 100 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 150) {
154 hal->mac_regs->emacgmiiaddr.miicsrclk = 1;
155 } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ > 150 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 250) {
156 hal->mac_regs->emacgmiiaddr.miicsrclk = 4;
157 } else {
158 hal->mac_regs->emacgmiiaddr.miicsrclk = 5;
159 }
160 }
161
emac_hal_reset_desc_chain(emac_hal_context_t * hal)162 void emac_hal_reset_desc_chain(emac_hal_context_t *hal)
163 {
164 /* reset DMA descriptors */
165 hal->rx_desc = (eth_dma_rx_descriptor_t *)(hal->descriptors);
166 hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->descriptors +
167 sizeof(eth_dma_rx_descriptor_t) * CONFIG_ETH_DMA_RX_BUFFER_NUM);
168 /* init rx chain */
169 for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
170 /* Set Own bit of the Rx descriptor Status: DMA */
171 hal->rx_desc[i].RDES0.Own = 1;
172 /* Set Buffer1 size and Second Address Chained bit */
173 hal->rx_desc[i].RDES1.SecondAddressChained = 1;
174 hal->rx_desc[i].RDES1.ReceiveBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
175 /* Enable Ethernet DMA Rx Descriptor interrupt */
176 hal->rx_desc[i].RDES1.DisableInterruptOnComplete = 0;
177 /* point to the buffer */
178 hal->rx_desc[i].Buffer1Addr = (uint32_t)(hal->rx_buf[i]);
179 /* point to next descriptor */
180 hal->rx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc + i + 1);
181 }
182 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
183 hal->rx_desc[CONFIG_ETH_DMA_RX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc);
184
185 /* init tx chain */
186 for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
187 /* Set Second Address Chained bit */
188 hal->tx_desc[i].TDES0.SecondAddressChained = 1;
189 hal->tx_desc[i].TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
190 /* Enable Ethernet DMA Tx Descriptor interrupt */
191 hal->tx_desc[1].TDES0.InterruptOnComplete = 1;
192 /* Enable Transmit Timestamp */
193 hal->tx_desc[i].TDES0.TransmitTimestampEnable = 1;
194 /* point to the buffer */
195 hal->tx_desc[i].Buffer1Addr = (uint32_t)(hal->tx_buf[i]);
196 /* point to next descriptor */
197 hal->tx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc + i + 1);
198 }
199 /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
200 hal->tx_desc[CONFIG_ETH_DMA_TX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc);
201
202 /* set base address of the first descriptor */
203 hal->dma_regs->dmarxbaseaddr = (uint32_t)hal->rx_desc;
204 hal->dma_regs->dmatxbaseaddr = (uint32_t)hal->tx_desc;
205 }
206
emac_hal_init_mac_default(emac_hal_context_t * hal)207 void emac_hal_init_mac_default(emac_hal_context_t *hal)
208 {
209 /* MACCR Configuration */
210 typeof(hal->mac_regs->gmacconfig) maccr = hal->mac_regs->gmacconfig;
211 /* Enable the watchdog on the receiver, frame longer than 2048 Bytes is not allowed */
212 maccr.watchdog = EMAC_WATCHDOG_ENABLE;
213 /* Enable the jabber timer on the transmitter, frame longer than 2048 Bytes is not allowed */
214 maccr.jabber = EMAC_JABBER_ENABLE;
215 /* minimum IFG between frames during transmission is 96 bit times */
216 maccr.interframegap = EMAC_INTERFRAME_GAP_96BIT;
217 /* Enable Carrier Sense During Transmission */
218 maccr.disablecrs = EMAC_CARRIERSENSE_ENABLE;
219 /* Select port: 10/100 Mbps */
220 maccr.mii = EMAC_PORT_10_100MBPS;
221 /* Select speed: here set default 100M, afterwards, will reset by auto-negotiation */
222 maccr.fespeed = EMAC_SPEED_100M;
223 /* Allow the reception of frames when the TX_EN signal is asserted in Half-Duplex mode */
224 maccr.rxown = EMAC_RECEIVE_OWN_ENABLE;
225 /* Disable internal loopback mode */
226 maccr.loopback = EMAC_LOOPBACK_DISABLE;
227 /* Select duplex mode: here set default full duplex, afterwards, will reset by auto-negotiation */
228 maccr.duplex = EMAC_DUPLEX_FULL;
229 /* Select the checksum mode for received frame payload's TCP/UDP/ICMP headers */
230 maccr.rxipcoffload = EMAC_CHECKSUM_HW;
231 /* Enable MAC retry transmission when a colision occurs in half duplex mode */
232 maccr.retry = EMAC_RETRY_TRANSMISSION_ENABLE;
233 /* MAC passes all incoming frames to host, without modifying them */
234 maccr.padcrcstrip = EMAC_AUTO_PAD_CRC_STRIP_DISABLE;
235 /* Set Back-Off limit time before retry a transmittion after a collision */
236 maccr.backofflimit = EMAC_BACKOFF_LIMIT_10;
237 /* Disable deferral check, MAC defers until the CRS signal goes inactive */
238 maccr.deferralcheck = EMAC_DEFERRAL_CHECK_DISABLE;
239 /* Set preamble length 7 Bytes */
240 maccr.pltf = EMAC_PREAMBLE_LENGTH_7;
241 hal->mac_regs->gmacconfig = maccr;
242
243 /* MACFFR Configuration */
244 typeof(hal->mac_regs->gmacff) macffr = hal->mac_regs->gmacff;
245 /* Receiver module passes only those frames to the Application that pass the SA or DA address filter */
246 macffr.receive_all = EMAC_RECEIVE_ALL_DISABLE;
247 /* Disable source address filter */
248 macffr.safe = EMAC_SOURCE_ADDR_FILTER_DISABLE;
249 macffr.saif = 0;
250 /* MAC blocks all control frames */
251 macffr.pcf = EMAC_CONTROL_FRAME_BLOCKALL;
252 /* AFM module passes all received broadcast frames and multicast frames */
253 macffr.dbf = EMAC_RECEPT_BROADCAST_ENABLE;
254 macffr.pam = 1;
255 /* Address Check block operates in normal filtering mode for the DA address */
256 macffr.daif = EMAC_DEST_ADDR_FILTER_NORMAL;
257 /* Disable Promiscuous Mode */
258 macffr.pmode = EMAC_PROMISCUOUS_DISABLE;
259 hal->mac_regs->gmacff = macffr;
260 }
261
emac_hal_enable_flow_ctrl(emac_hal_context_t * hal,bool enable)262 void emac_hal_enable_flow_ctrl(emac_hal_context_t *hal, bool enable)
263 {
264 /* MACFCR Configuration */
265 typeof(hal->mac_regs->gmacfc) macfcr = hal->mac_regs->gmacfc;
266 if (enable) {
267 /* Pause time */
268 macfcr.pause_time = EMAC_PAUSE_TIME;
269 /* Enable generation of Zero-Quanta Pause Control frames */
270 macfcr.dzpq = EMAC_ZERO_QUANTA_PAUSE_ENABLE;
271 /* Threshold of the PAUSE to be checked for automatic retransmission of PAUSE Frame */
272 macfcr.plt = EMAC_PAUSE_LOW_THRESHOLD_MINUS_28;
273 /* Don't allow MAC detect Pause frames with MAC address0 unicast address and unique multicast address */
274 macfcr.upfd = EMAC_UNICAST_PAUSE_DETECT_DISABLE;
275 /* Enable MAC to decode the received Pause frame and disable its transmitter for a specific time */
276 macfcr.rfce = EMAC_RECEIVE_FLOW_CONTROL_ENABLE;
277 /* Enable MAC to transmit Pause frames in full duplex mode or the MAC back-pressure operation in half duplex mode */
278 macfcr.tfce = EMAC_TRANSMIT_FLOW_CONTROL_ENABLE;
279 } else {
280 macfcr.val = 0;
281 }
282 hal->mac_regs->gmacfc = macfcr;
283 }
284
emac_hal_init_dma_default(emac_hal_context_t * hal)285 void emac_hal_init_dma_default(emac_hal_context_t *hal)
286 {
287 /* DMAOMR Configuration */
288 typeof(hal->dma_regs->dmaoperation_mode) dmaomr = hal->dma_regs->dmaoperation_mode;
289 /* Enable Dropping of TCP/IP Checksum Error Frames */
290 dmaomr.dis_drop_tcpip_err_fram = EMAC_DROP_TCPIP_CHECKSUM_ERROR_ENABLE;
291 /* Enable Receive Store Forward */
292 dmaomr.rx_store_forward = EMAC_RECEIVE_STORE_FORWARD_ENABLE;
293 /* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */
294 dmaomr.dis_flush_recv_frames = EMAC_FLUSH_RECEIVED_FRAME_ENABLE;
295 /* Enable Transmit Store Forward */
296 dmaomr.tx_str_fwd = EMAC_TRANSMIT_STORE_FORWARD_ENABLE;
297 /* Flush Transmit FIFO */
298 dmaomr.flush_tx_fifo = 1;
299 /* Transmit Threshold Control */
300 dmaomr.tx_thresh_ctrl = EMAC_TRANSMIT_THRESHOLD_CONTROL_64;
301 /* Disable Forward Error Frame */
302 dmaomr.fwd_err_frame = EMAC_FORWARD_ERROR_FRAME_DISABLE;
303 /* Disable forward undersized good frame */
304 dmaomr.fwd_under_gf = EMAC_FORWARD_UNDERSIZED_GOOD_FRAME_DISABLE;
305 /* Receive Threshold Control */
306 dmaomr.rx_thresh_ctrl = EMAC_RECEIVE_THRESHOLD_CONTROL_64;
307 /* Allow the DMA to process a second frame of Transmit data even before obtaining the status for the first frame */
308 dmaomr.opt_second_frame = EMAC_OPERATE_SECOND_FRAME_ENABLE;
309 hal->dma_regs->dmaoperation_mode = dmaomr;
310
311 /* DMABMR Configuration */
312 typeof(hal->dma_regs->dmabusmode) dmabmr = hal->dma_regs->dmabusmode;
313 /* Enable Mixed Burst */
314 dmabmr.dmamixedburst = EMAC_MIXED_BURST_ENABLE;
315 /* Enable Address Aligned Beates */
316 dmabmr.dmaaddralibea = EMAC_ADDR_ALIGN_BEATS_ENABLE;
317 /* Use Separate PBL */
318 dmabmr.use_sep_pbl = EMAC_USE_SEPARATE_PBL;
319 /* Set Rx/Tx DMA Burst Length */
320 dmabmr.rx_dma_pbl = EMAC_DMA_BURST_LENGTH_32BEAT;
321 dmabmr.prog_burst_len = EMAC_DMA_BURST_LENGTH_32BEAT;
322 /* Enable Enhanced Descriptor,8 Words(32 Bytes) */
323 dmabmr.alt_desc_size = EMAC_ENHANCED_DESCRIPTOR_ENABLE;
324 /* Specifies the number of word to skip between two unchained descriptors (Ring mode) */
325 dmabmr.desc_skip_len = 0;
326 /* DMA Arbitration Scheme */
327 dmabmr.dma_arb_sch = EMAC_DMA_ARBITRATION_SCHEME_ROUNDROBIN;
328 /* Set priority ratio in the weighted round-robin arbitration between Rx DMA and Tx DMA */
329 dmabmr.pri_ratio = EMAC_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1;
330 hal->dma_regs->dmabusmode = dmabmr;
331 }
332
emac_hal_set_speed(emac_hal_context_t * hal,uint32_t speed)333 void emac_hal_set_speed(emac_hal_context_t *hal, uint32_t speed)
334 {
335 hal->mac_regs->gmacconfig.fespeed = speed;
336 }
337
emac_hal_set_duplex(emac_hal_context_t * hal,uint32_t duplex)338 void emac_hal_set_duplex(emac_hal_context_t *hal, uint32_t duplex)
339 {
340 hal->mac_regs->gmacconfig.duplex = duplex;
341 }
342
emac_hal_set_promiscuous(emac_hal_context_t * hal,bool enable)343 void emac_hal_set_promiscuous(emac_hal_context_t *hal, bool enable)
344 {
345 if (enable) {
346 hal->mac_regs->gmacff.pmode = 1;
347 } else {
348 hal->mac_regs->gmacff.pmode = 0;
349 }
350 }
351
emac_hal_send_pause_frame(emac_hal_context_t * hal,bool enable)352 void emac_hal_send_pause_frame(emac_hal_context_t *hal, bool enable)
353 {
354 if (enable) {
355 hal->ext_regs->ex_phyinf_conf.sbd_flowctrl = 1;
356 } else {
357 hal->ext_regs->ex_phyinf_conf.sbd_flowctrl = 0;
358 }
359 }
360
emac_hal_is_mii_busy(emac_hal_context_t * hal)361 bool emac_hal_is_mii_busy(emac_hal_context_t *hal)
362 {
363 return hal->mac_regs->emacgmiiaddr.miibusy ? true : false;
364 }
365
emac_hal_set_phy_cmd(emac_hal_context_t * hal,uint32_t phy_addr,uint32_t phy_reg,bool write)366 void emac_hal_set_phy_cmd(emac_hal_context_t *hal, uint32_t phy_addr, uint32_t phy_reg, bool write)
367 {
368 typeof(hal->mac_regs->emacgmiiaddr) macmiiar = hal->mac_regs->emacgmiiaddr;
369 macmiiar.miidev = phy_addr;
370 /* Set the PHY register address */
371 macmiiar.miireg = phy_reg;
372 if (write) {
373 /* Set write mode */
374 macmiiar.miiwrite = 1;
375 } else {
376 /* Set read mode */
377 macmiiar.miiwrite = 0;
378 }
379 /* Set MII busy bit */
380 macmiiar.miibusy = 1;
381 /* Write the result value into the MII Address register */
382 hal->mac_regs->emacgmiiaddr = macmiiar;
383 }
384
emac_hal_set_phy_data(emac_hal_context_t * hal,uint32_t reg_value)385 void emac_hal_set_phy_data(emac_hal_context_t *hal, uint32_t reg_value)
386 {
387 hal->mac_regs->emacmiidata.mii_data = reg_value;
388 }
389
emac_hal_get_phy_data(emac_hal_context_t * hal)390 uint32_t emac_hal_get_phy_data(emac_hal_context_t *hal)
391 {
392 return hal->mac_regs->emacmiidata.mii_data;
393 }
394
emac_hal_set_address(emac_hal_context_t * hal,uint8_t * mac_addr)395 void emac_hal_set_address(emac_hal_context_t *hal, uint8_t *mac_addr)
396 {
397 /* Make sure mac address is unicast type */
398 if (!(mac_addr[0] & 0x01)) {
399 hal->mac_regs->emacaddr0high.address0_hi = (mac_addr[5] << 8) | mac_addr[4];
400 hal->mac_regs->emacaddr0low = (mac_addr[3] << 24) | (mac_addr[2] << 16) | (mac_addr[1] << 8) | (mac_addr[0]);
401 }
402 }
403
emac_hal_start(emac_hal_context_t * hal)404 void emac_hal_start(emac_hal_context_t *hal)
405 {
406 typeof(hal->dma_regs->dmaoperation_mode) opm = hal->dma_regs->dmaoperation_mode;
407 typeof(hal->mac_regs->gmacconfig) cfg = hal->mac_regs->gmacconfig;
408
409 /* Enable Ethernet MAC and DMA Interrupt */
410 hal->dma_regs->dmain_en.val = 0xFFFFFFFF;
411
412 /* Flush Transmit FIFO */
413 opm.flush_tx_fifo = 1;
414 /* Start DMA transmission */
415 opm.start_stop_transmission_command = 1;
416 /* Start DMA reception */
417 opm.start_stop_rx = 1;
418 /* Enable transmit state machine of the MAC for transmission on the MII */
419 cfg.tx = 1;
420 /* Enable receive state machine of the MAC for reception from the MII */
421 cfg.rx = 1;
422
423 hal->dma_regs->dmaoperation_mode = opm;
424 hal->mac_regs->gmacconfig = cfg;
425
426 /* Clear all pending interrupts */
427 hal->dma_regs->dmastatus.val = 0xFFFFFFFF;
428 }
429
emac_hal_stop(emac_hal_context_t * hal)430 void emac_hal_stop(emac_hal_context_t *hal)
431 {
432 typeof(hal->dma_regs->dmaoperation_mode) opm = hal->dma_regs->dmaoperation_mode;
433 typeof(hal->mac_regs->gmacconfig) cfg = hal->mac_regs->gmacconfig;
434
435 /* Flush Transmit FIFO */
436 opm.flush_tx_fifo = 1;
437 /* Stop DMA transmission */
438 opm.start_stop_transmission_command = 0;
439 /* Stop DMA reception */
440 opm.start_stop_rx = 0;
441 /* Disable receive state machine of the MAC for reception from the MII */
442 cfg.rx = 0;
443 /* Disable transmit state machine of the MAC for transmission on the MII */
444 cfg.tx = 0;
445
446 hal->dma_regs->dmaoperation_mode = opm;
447 hal->mac_regs->gmacconfig = cfg;
448
449 /* Disable Ethernet MAC and DMA Interrupt */
450 hal->dma_regs->dmain_en.val = 0x0;
451 }
452
emac_hal_get_tx_desc_owner(emac_hal_context_t * hal)453 uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal)
454 {
455 return hal->tx_desc->TDES0.Own;
456 }
457
emac_hal_transmit_frame(emac_hal_context_t * hal,uint8_t * buf,uint32_t length)458 uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
459 {
460 /* Get the number of Tx buffers to use for the frame */
461 uint32_t bufcount = 0;
462 uint32_t lastlen = length;
463 uint32_t sentout = 0;
464 while (lastlen > CONFIG_ETH_DMA_BUFFER_SIZE) {
465 lastlen -= CONFIG_ETH_DMA_BUFFER_SIZE;
466 bufcount++;
467 }
468 if (lastlen) {
469 bufcount++;
470 }
471 if (bufcount > CONFIG_ETH_DMA_TX_BUFFER_NUM) {
472 goto err;
473 }
474
475 eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc;
476 /* A frame is transmitted in multiple descriptor */
477 for (size_t i = 0; i < bufcount; i++) {
478 /* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
479 if (desc_iter->TDES0.Own != EMAC_DMADESC_OWNER_CPU) {
480 goto err;
481 }
482 /* Clear FIRST and LAST segment bits */
483 desc_iter->TDES0.FirstSegment = 0;
484 desc_iter->TDES0.LastSegment = 0;
485 desc_iter->TDES0.InterruptOnComplete = 0;
486 if (i == 0) {
487 /* Setting the first segment bit */
488 desc_iter->TDES0.FirstSegment = 1;
489 }
490 if (i == (bufcount - 1)) {
491 /* Setting the last segment bit */
492 desc_iter->TDES0.LastSegment = 1;
493 /* Enable transmit interrupt */
494 desc_iter->TDES0.InterruptOnComplete = 1;
495 /* Program size */
496 desc_iter->TDES1.TransmitBuffer1Size = lastlen;
497 /* copy data from uplayer stack buffer */
498 memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen);
499 sentout += lastlen;
500 } else {
501 /* Program size */
502 desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
503 /* copy data from uplayer stack buffer */
504 memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
505 sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
506 }
507 /* Point to next descriptor */
508 desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
509 }
510
511 /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
512 for (size_t i = 0; i < bufcount; i++) {
513 hal->tx_desc->TDES0.Own = EMAC_DMADESC_OWNER_DMA;
514 hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
515 }
516 hal->dma_regs->dmatxpolldemand = 0;
517 return sentout;
518 err:
519 return 0;
520 }
521
emac_hal_receive_frame(emac_hal_context_t * hal,uint8_t * buf,uint32_t size,uint32_t * frames_remain,uint32_t * free_desc)522 uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain, uint32_t *free_desc)
523 {
524 eth_dma_rx_descriptor_t *desc_iter = NULL;
525 eth_dma_rx_descriptor_t *first_desc = NULL;
526 uint32_t used_descs = 0;
527 uint32_t seg_count = 0;
528 uint32_t ret_len = 0;
529 uint32_t copy_len = 0;
530 uint32_t write_len = 0;
531 uint32_t frame_count = 0;
532
533 first_desc = hal->rx_desc;
534 desc_iter = hal->rx_desc;
535 /* Traverse descriptors owned by CPU */
536 while ((desc_iter->RDES0.Own != EMAC_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM) && !frame_count) {
537 used_descs++;
538 seg_count++;
539 /* Last segment in frame */
540 if (desc_iter->RDES0.LastDescriptor) {
541 /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
542 ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
543 /* packets larger than expected will be truncated */
544 copy_len = ret_len > size ? size : ret_len;
545 /* update unhandled frame count */
546 frame_count++;
547 }
548 /* First segment in frame */
549 if (desc_iter->RDES0.FirstDescriptor) {
550 first_desc = desc_iter;
551 }
552 /* point to next descriptor */
553 desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
554 }
555 /* there's at least one frame to process */
556 if (frame_count) {
557 /* check how many frames left to handle */
558 while ((desc_iter->RDES0.Own != EMAC_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
559 used_descs++;
560 if (desc_iter->RDES0.LastDescriptor) {
561 frame_count++;
562 }
563 /* point to next descriptor */
564 desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
565 }
566 desc_iter = first_desc;
567 for (size_t i = 0; i < seg_count - 1; i++) {
568 used_descs--;
569 write_len = copy_len < CONFIG_ETH_DMA_BUFFER_SIZE ? copy_len : CONFIG_ETH_DMA_BUFFER_SIZE;
570 /* copy data to buffer */
571 memcpy(buf, (void *)(desc_iter->Buffer1Addr), write_len);
572 buf += write_len;
573 copy_len -= write_len;
574 /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
575 desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
576 desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
577 }
578 memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
579 desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
580 /* update rxdesc */
581 hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
582 /* poll rx demand */
583 hal->dma_regs->dmarxpolldemand = 0;
584 frame_count--;
585 used_descs--;
586 }
587 *frames_remain = frame_count;
588 *free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
589 return ret_len;
590 }
591
emac_hal_isr(void * arg)592 IRAM_ATTR void emac_hal_isr(void *arg)
593 {
594 emac_hal_context_t *hal = (emac_hal_context_t *)arg;
595 typeof(hal->dma_regs->dmastatus) dma_status = hal->dma_regs->dmastatus;
596 hal->dma_regs->dmastatus.val = dma_status.val;
597 /* DMA Normal Interrupt */
598 if (dma_status.norm_int_summ) {
599 /* Transmit Interrupt */
600 if (dma_status.trans_int) {
601 emac_hal_tx_complete_cb(arg);
602 }
603 /* Transmit Buffer Unavailable */
604 if (dma_status.trans_buf_unavail) {
605 emac_hal_tx_unavail_cb(arg);
606 }
607 /* Receive Interrupt */
608 if (dma_status.recv_int) {
609 emac_hal_rx_complete_cb(arg);
610 }
611 /* Early Receive Interrupt */
612 if (dma_status.early_recv_int) {
613 emac_hal_rx_early_cb(arg);
614 }
615 }
616 /* DMA Abnormal Interrupt */
617 if (dma_status.abn_int_summ) {
618 /* Transmit Process Stopped */
619 if (dma_status.trans_proc_stop) {
620 }
621 /* Transmit Jabber Timeout */
622 if (dma_status.trans_jabber_to) {
623 }
624 /* Receive FIFO Overflow */
625 if (dma_status.recv_ovflow) {
626 }
627 /* Transmit Underflow */
628 if (dma_status.trans_undflow) {
629 }
630 /* Receive Buffer Unavailable */
631 if (dma_status.recv_buf_unavail) {
632 emac_hal_rx_unavail_cb(arg);
633 }
634 /* Receive Process Stopped */
635 if (dma_status.recv_proc_stop) {
636 }
637 /* Receive Watchdog Timeout */
638 if (dma_status.recv_wdt_to) {
639 }
640 /* Early Transmit Interrupt */
641 if (dma_status.early_trans_int) {
642 }
643 /* Fatal Bus Error */
644 if (dma_status.fatal_bus_err_int) {
645 }
646 }
647 }
648
emac_hal_tx_complete_cb(void * arg)649 IRAM_ATTR __attribute__((weak)) void emac_hal_tx_complete_cb(void *arg)
650 {
651 // This is a weak function, do nothing by default
652 // Upper code can rewrite this function
653 // Note: you're in the interrupt context
654 return;
655 }
656
emac_hal_tx_unavail_cb(void * arg)657 IRAM_ATTR __attribute__((weak)) void emac_hal_tx_unavail_cb(void *arg)
658 {
659 // This is a weak function, do nothing by default
660 // Upper code can rewrite this function
661 // Note: you're in the interrupt context
662 return;
663 }
664
emac_hal_rx_complete_cb(void * arg)665 IRAM_ATTR __attribute__((weak)) void emac_hal_rx_complete_cb(void *arg)
666 {
667 // This is a weak function, do nothing by default
668 // Upper code can rewrite this function
669 // Note: you're in the interrupt context
670 return;
671 }
672
emac_hal_rx_early_cb(void * arg)673 IRAM_ATTR __attribute__((weak)) void emac_hal_rx_early_cb(void *arg)
674 {
675 // This is a weak function, do nothing by default
676 // Upper code can rewrite this function
677 // Note: you're in the interrupt context
678 return;
679 }
680
emac_hal_rx_unavail_cb(void * arg)681 IRAM_ATTR __attribute__((weak)) void emac_hal_rx_unavail_cb(void *arg)
682 {
683 // This is a weak function, do nothing by default
684 // Upper code can rewrite this function
685 // Note: you're in the interrupt context
686 return;
687 }
688