1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 /*******   Includes      *******/
22 #include <string.h>
23 #include "emac.h"
24 #include "emac_reva.h"
25 
26 /*******   Variables     *******/
27 mxc_emac_reva_device_t mxc_emac_context;
28 static mxc_emac_reva_device_t *emac = &mxc_emac_context;
29 
30 /*******   Functions     *******/
31 /* ************************************************************************* */
32 /* Private Functions                                                         */
33 /* ************************************************************************* */
emac_mdio_write(unsigned char reg,uint16_t value)34 static void emac_mdio_write(unsigned char reg, uint16_t value)
35 {
36     unsigned int netctl;
37     unsigned int netstat;
38     unsigned int frame;
39 
40     netctl = EMAC_READL(emac, cn);
41     netctl |= EMAC_BIT(CN, MPEN);
42     EMAC_WRITEL(emac, cn, netctl);
43 
44     frame = (EMAC_BF(PHY_MT, SOP, 1) | EMAC_BF(PHY_MT, OP, 1) |
45              EMAC_BF(PHY_MT, PHYADDR, emac->phy_addr) | EMAC_BF(PHY_MT, REGADDR, reg) |
46              EMAC_BF(PHY_MT, CODE, 2) | EMAC_BF(PHY_MT, DATA, value));
47     EMAC_WRITEL(emac, phy_mt, frame);
48 
49     do {
50         netstat = EMAC_READL(emac, status);
51     } while (!(netstat & EMAC_BIT(STATUS, IDLE)));
52 
53     netctl = EMAC_READL(emac, cn);
54     netctl &= ~EMAC_BIT(CN, MPEN);
55     EMAC_WRITEL(emac, cn, netctl);
56 }
57 
emac_mdio_read(unsigned char reg)58 static uint16_t emac_mdio_read(unsigned char reg)
59 {
60     unsigned int netctl;
61     unsigned int netstat;
62     unsigned int frame;
63 
64     netctl = EMAC_READL(emac, cn);
65     netctl |= EMAC_BIT(CN, MPEN);
66     EMAC_WRITEL(emac, cn, netctl);
67 
68     frame = (EMAC_BF(PHY_MT, SOP, 1) | EMAC_BF(PHY_MT, OP, 2) |
69              EMAC_BF(PHY_MT, PHYADDR, emac->phy_addr) | EMAC_BF(PHY_MT, REGADDR, reg) |
70              EMAC_BF(PHY_MT, CODE, 2));
71     EMAC_WRITEL(emac, phy_mt, frame);
72 
73     do {
74         netstat = EMAC_READL(emac, status);
75     } while (!(netstat & EMAC_BIT(STATUS, IDLE)));
76 
77     frame = EMAC_READL(emac, phy_mt);
78 
79     netctl = EMAC_READL(emac, cn);
80     netctl &= ~EMAC_BIT(CN, MPEN);
81     EMAC_WRITEL(emac, cn, netctl);
82 
83     return EMAC_BFEXT(PHY_MT, DATA, frame);
84 }
85 
emac_reclaim_rx_buffers(unsigned int new_tail)86 static void emac_reclaim_rx_buffers(unsigned int new_tail)
87 {
88     unsigned int i;
89 
90     i = emac->rx_tail;
91 
92     while (i > new_tail) {
93         emac->rx_ring[i].addr &= ~RXADDR_USED;
94         i++;
95 
96         if (emac->rx_ring_size < i) {
97             i = 0;
98         }
99     }
100 
101     while (i < new_tail) {
102         emac->rx_ring[i].addr &= ~RXADDR_USED;
103         i++;
104     }
105 
106     barrier();
107     emac->rx_tail = new_tail;
108 }
109 
emac_phy_reset(void)110 static void emac_phy_reset(void)
111 {
112     uint16_t status;
113     int i;
114 
115     emac_mdio_write(MII_ADVERTISE, (ADVERTISE_CSMA | ADVERTISE_ALL));
116     emac_mdio_write(MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART));
117 
118     for (i = 0; i < (CONFIG_SYS_EMAC_AUTONEG_TIMEOUT / 100); i++) {
119         status = emac_mdio_read(MII_BMSR);
120 
121         if (status & BMSR_ANEGCOMPLETE) {
122             break;
123         }
124 
125         emac->delay_us(100);
126     }
127 }
128 
129 #ifdef CONFIG_EMAC_SEARCH_PHY
emac_phy_find(void)130 static int emac_phy_find(void)
131 {
132     int i;
133     uint16_t phy_id;
134 
135     for (i = 0; i < 32; i++) {
136         emac->phy_addr = i;
137 
138         phy_id = emac_mdio_read(MII_PHYSID1);
139 
140         if (0xffff != phy_id) {
141             return E_NO_ERROR;
142         }
143     }
144 
145     return E_NO_DEVICE;
146 }
147 #endif //CONFIG_EMAC_SEARCH_PHY
148 
emac_mii_nway_result(unsigned int negotiated)149 static unsigned int emac_mii_nway_result(unsigned int negotiated)
150 {
151     unsigned int ret;
152 
153     if (negotiated & LPA_100FULL) {
154         ret = LPA_100FULL;
155     } else if (negotiated & LPA_100BASE4) {
156         ret = LPA_100BASE4;
157     } else if (negotiated & LPA_100HALF) {
158         ret = LPA_100HALF;
159     } else if (negotiated & LPA_10FULL) {
160         ret = LPA_10FULL;
161     } else {
162         ret = LPA_10HALF;
163     }
164 
165     return ret;
166 }
167 
emac_phy_init(void)168 static int emac_phy_init(void)
169 {
170     int result = E_NO_ERROR;
171     uint16_t phy_id;
172     uint16_t status;
173     uint16_t adv;
174     uint16_t lpa;
175     int media;
176     int speed;
177     int duplex;
178     int i;
179     unsigned int ncfgr;
180 
181 #ifdef CONFIG_EMAC_SEARCH_PHY
182     result = emac_phy_find();
183 
184     if (result) {
185         return result;
186     }
187 
188 #endif //CONFIG_EMAC_SEARCH_PHY
189 
190     phy_id = emac_mdio_read(MII_PHYSID1);
191 
192     if (0xffff == phy_id) {
193         return E_NO_DEVICE;
194     }
195 
196     status = emac_mdio_read(MII_BMSR);
197 
198     if (!(status & BMSR_LSTATUS)) {
199         emac_phy_reset();
200 
201         for (i = 0; i < (CONFIG_SYS_EMAC_AUTONEG_TIMEOUT / 100); i++) {
202             status = emac_mdio_read(MII_BMSR);
203 
204             if (status & BMSR_LSTATUS) {
205                 break;
206             }
207 
208             emac->delay_us(100);
209         }
210     }
211 
212     if (!(status & BMSR_LSTATUS)) {
213         return E_NO_RESPONSE; //PHY Link Down
214     } else {
215         adv = emac_mdio_read(MII_ADVERTISE);
216         lpa = emac_mdio_read(MII_LPA);
217 
218         media = emac_mii_nway_result(lpa & adv);
219         speed = ((media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) ? 1 : 0);
220         duplex = (media & ADVERTISE_FULL) ? 1 : 0;
221 
222         ncfgr = EMAC_READL(emac, cfg);
223         ncfgr &= ~(EMAC_BIT(CFG, SPD) | EMAC_BIT(CFG, FULLDPLX));
224 
225         if (speed) {
226             ncfgr |= EMAC_BIT(CFG, SPD);
227         }
228 
229         if (duplex) {
230             ncfgr |= EMAC_BIT(CFG, FULLDPLX);
231         }
232 
233         /* Discard FCS Field */
234         ncfgr |= EMAC_BIT(CFG, DCRXFCS);
235 
236         EMAC_WRITEL(emac, cfg, ncfgr);
237     }
238 
239     return result;
240 }
241 
242 /* ************************************************************************* */
243 /* Control/Configuration Functions                                           */
244 /* ************************************************************************* */
MXC_EMAC_RevA_Init(mxc_emac_reva_config_t * config)245 int MXC_EMAC_RevA_Init(mxc_emac_reva_config_t *config)
246 {
247     int result = E_UNKNOWN;
248     unsigned int ncfgr, emac_pclk_rate, clk_div;
249 
250     if (!config) {
251         return E_NULL_PTR;
252     }
253 
254     if (!emac->first_init) {
255         /* Assign interface base address */
256         emac->regs = (mxc_emac_reva_regs_t *)MXC_EMAC;
257 
258         /* Clock configuration */
259         emac_pclk_rate = PeripheralClock;
260 
261         if (emac_pclk_rate < 20000000) {
262             clk_div = EMAC_CLK_DIV8;
263         } else if (emac_pclk_rate < 40000000) {
264             clk_div = EMAC_CLK_DIV16;
265         } else if (emac_pclk_rate < 80000000) {
266             clk_div = EMAC_CLK_DIV32;
267         } else {
268             clk_div = EMAC_CLK_DIV64;
269         }
270 
271         ncfgr = EMAC_BF(CFG, MDCCLK, clk_div);
272         EMAC_WRITEL(emac, cfg, ncfgr);
273 
274         /* Initialization to be finished */
275         emac->first_init = 1;
276     }
277 
278     /* Set configuration */
279     result = MXC_EMAC_RevA_SetConfiguration(config);
280 
281     return result;
282 }
283 
MXC_EMAC_RevA_SetConfiguration(mxc_emac_reva_config_t * config)284 int MXC_EMAC_RevA_SetConfiguration(mxc_emac_reva_config_t *config)
285 {
286     if (!emac->first_init) {
287         return E_UNINITIALIZED;
288     }
289 
290     if (!(config->rx_buff) || !(config->rx_ring_buff) || !(config->tx_ring_buff)) {
291         return E_NULL_PTR;
292     }
293 
294     if ((config->rx_ring_buff_size % sizeof(mxc_emac_dma_desc_t)) ||
295         (config->tx_ring_buff_size % sizeof(mxc_emac_dma_desc_t)) ||
296         (config->rx_buff_size % EMAC_RX_BUFFER_SIZE)) {
297         return E_INVALID;
298     }
299 
300     if (((config->rx_ring_buff_size / sizeof(mxc_emac_dma_desc_t)) > MAX_SYS_EMAC_RX_RING_SIZE) ||
301         ((config->tx_ring_buff_size / sizeof(mxc_emac_dma_desc_t)) > MAX_SYS_EMAC_TX_RING_SIZE) ||
302         (config->rx_buff_size > MAX_SYS_EMAC_RX_BUFFER_SIZE)) {
303         return E_INVALID;
304     }
305 
306     if (!config->delay_us) {
307         return E_INVALID;
308     }
309 
310     emac->rx_buffer = (void *)(config->rx_buff);
311     emac->rx_buffer_dma = (unsigned int)(config->rx_buff);
312     emac->rx_buffer_size = config->rx_buff_size;
313 
314     emac->rx_ring = (mxc_emac_reva_dma_desc_t *)(config->rx_ring_buff);
315     emac->rx_ring_dma = (unsigned int)(config->rx_ring_buff);
316     emac->rx_ring_size = (config->rx_ring_buff_size / sizeof(mxc_emac_dma_desc_t));
317 
318     emac->tx_ring = (mxc_emac_reva_dma_desc_t *)(config->tx_ring_buff);
319     emac->tx_ring_dma = (unsigned int)(config->tx_ring_buff);
320     emac->tx_ring_size = (config->tx_ring_buff_size / sizeof(mxc_emac_dma_desc_t));
321 
322     emac->phy_addr = config->phy_addr;
323     emac->delay_us = config->delay_us;
324 
325     if (config->interrupt_mode) {
326         memcpy((void *)&emac->cb_funcs, (const void *)&config->conf_cb_funcs,
327                sizeof(mxc_emac_cb_funcs_tbl_t));
328         MXC_EMAC_RevA_EnableInterruptEvents(config->interrupt_events);
329     } else {
330         memset((void *)&emac->cb_funcs, 0, sizeof(mxc_emac_cb_funcs_tbl_t));
331         MXC_EMAC_RevA_DisableInterruptEvents(0xFFFFFFFF);
332     }
333 
334     return E_NO_ERROR;
335 }
336 
MXC_EMAC_RevA_SetHwAddr(unsigned char * enetaddr)337 int MXC_EMAC_RevA_SetHwAddr(unsigned char *enetaddr)
338 {
339     uint16_t hwaddr_top;
340     unsigned int hwaddr_bottom;
341 
342     if (!enetaddr) {
343         return E_NULL_PTR;
344     }
345 
346     /* Set Hardware Address */
347     hwaddr_bottom =
348         ((enetaddr[0]) | (enetaddr[1] << 8) | (enetaddr[2] << 16) | (enetaddr[3] << 24));
349     EMAC_WRITEL(emac, sa1l, hwaddr_bottom);
350 
351     hwaddr_top = (enetaddr[4] | (enetaddr[5] << 8));
352     EMAC_WRITEL(emac, sa1h, hwaddr_top);
353 
354     return E_NO_ERROR;
355 }
356 
MXC_EMAC_RevA_EnableInterruptEvents(unsigned int events)357 int MXC_EMAC_RevA_EnableInterruptEvents(unsigned int events)
358 {
359     unsigned int ier, imr;
360 
361     if (!emac->first_init) {
362         return E_UNINITIALIZED;
363     }
364 
365     /* First Read from Interrupt Mask Register */
366     imr = EMAC_READL(emac, int_mask);
367 
368     /* IER is Write-Only */
369     ier = ~imr | events;
370     EMAC_WRITEL(emac, int_en, ier);
371 
372     return E_NO_ERROR;
373 }
374 
MXC_EMAC_RevA_DisableInterruptEvents(unsigned int events)375 int MXC_EMAC_RevA_DisableInterruptEvents(unsigned int events)
376 {
377     unsigned int idr, imr;
378 
379     if (!emac->first_init) {
380         return E_UNINITIALIZED;
381     }
382 
383     /* First Read from Interrupt Mask Register */
384     imr = EMAC_READL(emac, int_mask);
385 
386     /* IDR is Write-Only */
387     idr = imr | events;
388     EMAC_WRITEL(emac, int_dis, idr);
389 
390     return E_NO_ERROR;
391 }
392 
393 /* ************************************************************************* */
394 /* Low-Level Functions                                                       */
395 /* ************************************************************************* */
MXC_EMAC_RevA_Start(void)396 int MXC_EMAC_RevA_Start(void)
397 {
398     int result = E_UNKNOWN;
399     unsigned int i;
400     unsigned int paddr;
401     unsigned int ncr;
402 
403     if (!emac->first_init) {
404         return E_UNINITIALIZED;
405     }
406 
407     /* DMA Descriptors */
408     paddr = emac->rx_buffer_dma;
409 
410     for (i = 0; i < emac->rx_ring_size; i++) {
411         if ((emac->rx_ring_size - 1) == i) {
412             paddr |= RXADDR_WRAP;
413         }
414 
415         emac->rx_ring[i].addr = paddr;
416         emac->rx_ring[i].ctrl = 0;
417 
418         paddr += EMAC_RX_BUFFER_SIZE;
419     }
420 
421     for (i = 0; i < emac->tx_ring_size; i++) {
422         emac->tx_ring[i].addr = 0;
423 
424         if ((emac->tx_ring_size - 1) == i) {
425             emac->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP;
426         } else {
427             emac->tx_ring[i].ctrl = TXBUF_USED;
428         }
429     }
430 
431     emac->tx_tail = 0;
432     emac->tx_head = 0;
433     emac->rx_tail = 0;
434 
435     EMAC_WRITEL(emac, rxbuf_ptr, emac->rx_ring_dma);
436     EMAC_WRITEL(emac, txbuf_ptr, emac->tx_ring_dma);
437 
438 #ifdef CONFIG_EMAC_MII_MODE
439     EMAC_WRITEL(emac, usrio, EMAC_BIT(USRIO, MII));
440 #endif
441 
442     result = emac_phy_init();
443 
444     if (E_NO_ERROR == result) {
445         /* For Diagnostic */
446 #ifdef CONFIG_EMAC_LOCAL_LOOPBACK_MODE
447         ncr = EMAC_READL(emac, cn);
448 
449         ncr &= ~EMAC_BIT(CN, LB);
450         ncr |= EMAC_BIT(CN, LBL);
451 
452         EMAC_WRITEL(emac, cn, ncr);
453 #endif
454         /* Enable TX and RX */
455         ncr = EMAC_READL(emac, cn);
456         ncr |= EMAC_BIT(CN, TXEN);
457         ncr |= EMAC_BIT(CN, TXSTART);
458         EMAC_WRITEL(emac, cn, ncr);
459 
460         ncr = EMAC_READL(emac, cn);
461         ncr |= EMAC_BIT(CN, RXEN);
462         EMAC_WRITEL(emac, cn, ncr);
463     }
464 
465     return result;
466 }
467 
MXC_EMAC_RevA_Stop(void)468 int MXC_EMAC_RevA_Stop(void)
469 {
470     unsigned int ncr;
471     unsigned int tsr;
472 
473     /* Halt the Controller and Wait for Any Ongoing Transmission to End */
474     ncr = EMAC_READL(emac, cn);
475     ncr |= EMAC_BIT(CN, TXHALT);
476     EMAC_WRITEL(emac, cn, ncr);
477 
478     do {
479         tsr = EMAC_READL(emac, tx_st);
480     } while (tsr & EMAC_BIT(TX_ST, TXGO));
481 
482     /* Clear Statistics */
483     EMAC_WRITEL(emac, cn, EMAC_BIT(CN, CLST));
484 
485     return E_NO_ERROR;
486 }
487 
MXC_EMAC_RevA_ReadLinkStatus(void)488 int MXC_EMAC_RevA_ReadLinkStatus(void)
489 {
490     int result = E_UNKNOWN;
491     uint16_t status;
492 
493     status = emac_mdio_read(MII_BMSR);
494 
495     if (status & BMSR_LSTATUS) {
496         result = E_NO_ERROR;
497     } else {
498         result = E_NO_DEVICE; //PHY Link Down
499     }
500 
501     return result;
502 }
503 
504 /* ************************************************************************* */
505 /* Transaction-Level Functions                                               */
506 /* ************************************************************************* */
MXC_EMAC_RevA_SendSync(const void * packet,unsigned int length)507 int MXC_EMAC_RevA_SendSync(const void *packet, unsigned int length)
508 {
509     int i;
510     unsigned int paddr;
511     unsigned int ctrl;
512     unsigned int tx_head;
513     unsigned int ncr;
514 
515     if (!packet) {
516         return E_NULL_PTR;
517     }
518 
519     if (!emac->delay_us) {
520         return E_UNINITIALIZED;
521     }
522 
523     tx_head = emac->tx_head;
524     paddr = (unsigned int)packet;
525 
526     ctrl = length & TXBUF_FRMLEN_MASK;
527     ctrl |= TXBUF_FRAME_END;
528 
529     if (tx_head == (emac->tx_ring_size - 1)) {
530         ctrl |= TXBUF_WRAP;
531         emac->tx_head = 0;
532     } else {
533         emac->tx_head++;
534     }
535 
536     emac->tx_ring[tx_head].ctrl = ctrl;
537     emac->tx_ring[tx_head].addr = paddr;
538     barrier();
539 
540     ncr = EMAC_READL(emac, cn);
541     ncr |= EMAC_BIT(CN, TXEN);
542     ncr |= EMAC_BIT(CN, TXSTART);
543     ncr |= EMAC_BIT(CN, RXEN);
544     EMAC_WRITEL(emac, cn, ncr);
545 
546     for (i = 0; i <= CONFIG_SYS_EMAC_TX_TIMEOUT; i++) {
547         barrier();
548 
549         ctrl = emac->tx_ring[tx_head].ctrl;
550 
551         if (ctrl & TXBUF_USED) {
552             break;
553         }
554 
555         emac->delay_us(1);
556     }
557 
558     if (i <= CONFIG_SYS_EMAC_TX_TIMEOUT) {
559         if (ctrl & TXBUF_UNDERRUN) {
560             return E_UNDERFLOW;
561         }
562 
563         if (ctrl & TXBUF_EXHAUSTED) {
564             return E_OVERFLOW;
565         }
566     } else {
567         return E_TIME_OUT;
568     }
569 
570     return E_NO_ERROR;
571 }
572 
MXC_EMAC_RevA_SendAsync(const void * packet,unsigned int length)573 int MXC_EMAC_RevA_SendAsync(const void *packet, unsigned int length)
574 {
575     unsigned int paddr;
576     unsigned int ctrl;
577     unsigned int tx_head;
578     unsigned int ncr;
579 
580     if (!packet) {
581         return E_NULL_PTR;
582     }
583 
584     tx_head = emac->tx_head;
585     paddr = (unsigned int)packet;
586 
587     ctrl = length & TXBUF_FRMLEN_MASK;
588     ctrl |= TXBUF_FRAME_END;
589 
590     if (tx_head == (emac->tx_ring_size - 1)) {
591         ctrl |= TXBUF_WRAP;
592         emac->tx_head = 0;
593     } else {
594         emac->tx_head++;
595     }
596 
597     emac->tx_ring[tx_head].ctrl = ctrl;
598     emac->tx_ring[tx_head].addr = paddr;
599     barrier();
600 
601     ncr = EMAC_READL(emac, cn);
602     ncr |= EMAC_BIT(CN, TXEN);
603     ncr |= EMAC_BIT(CN, TXSTART);
604     ncr |= EMAC_BIT(CN, RXEN);
605     EMAC_WRITEL(emac, cn, ncr);
606 
607     barrier();
608 
609     return E_NO_ERROR;
610 }
611 
MXC_EMAC_RevA_Recv(void * rx_buff,unsigned int max_len)612 int MXC_EMAC_RevA_Recv(void *rx_buff, unsigned int max_len)
613 {
614     int result = E_UNKNOWN;
615     int wrapped = 0;
616     unsigned int length;
617     unsigned int status;
618     unsigned int rx_tail;
619     unsigned int headlen;
620     unsigned int taillen;
621     unsigned char packet_received = 0;
622     unsigned char *tail_buff_ptr;
623     void *buffer;
624 
625     if (!emac->first_init) {
626         return E_UNINITIALIZED;
627     }
628 
629     if (!rx_buff) {
630         return E_NULL_PTR;
631     }
632 
633     rx_tail = emac->rx_tail;
634 
635     while (1) {
636         if (!(emac->rx_ring[rx_tail].addr & RXADDR_USED)) {
637             /* No RX Frame */
638             return 0;
639         }
640 
641         status = emac->rx_ring[rx_tail].ctrl;
642 
643         if (status & RXBUF_FRAME_START) {
644             if (rx_tail != emac->rx_tail) {
645                 emac_reclaim_rx_buffers(rx_tail);
646             }
647 
648             wrapped = 0;
649         }
650 
651         if (status & RXBUF_FRAME_END) {
652             packet_received = 1;
653 
654             buffer = emac->rx_buffer + (EMAC_RX_BUFFER_SIZE * emac->rx_tail);
655             length = status & RXBUF_FRMLEN_MASK;
656 
657             if (wrapped) {
658                 headlen = EMAC_RX_BUFFER_SIZE * (emac->rx_ring_size - emac->rx_tail);
659                 taillen = length - headlen;
660                 tail_buff_ptr = (unsigned char *)rx_buff + headlen;
661 
662                 if ((headlen + taillen) <= max_len) {
663                     memcpy(rx_buff, (const void *)buffer, headlen);
664                     memcpy((void *)tail_buff_ptr, (const void *)emac->rx_buffer, taillen);
665                     result = headlen + taillen;
666                 } else {
667                     result = E_NONE_AVAIL; //RX User Buffer Full
668                 }
669             } else if (length <= max_len) {
670                 memcpy(rx_buff, (const void *)buffer, length);
671                 result = length;
672             } else {
673                 result = E_NONE_AVAIL; //RX User Buffer Full
674             }
675 
676             if (++rx_tail >= emac->rx_ring_size) {
677                 rx_tail = 0;
678             }
679 
680             emac_reclaim_rx_buffers(rx_tail);
681         } else {
682             if (++rx_tail >= emac->rx_ring_size) {
683                 wrapped = 1;
684                 rx_tail = 0;
685             }
686         }
687 
688         barrier();
689 
690         if (packet_received) {
691             return result;
692         }
693     }
694 
695     return result;
696 }
697 
MXC_EMAC_RevA_IrqHandler(void)698 void MXC_EMAC_RevA_IrqHandler(void)
699 {
700     unsigned int isr = 0;
701 
702     isr = EMAC_READL(emac, int_st);
703 
704     if ((isr & MXC_EMAC_REVA_EVENT_MPS) && emac->cb_funcs.mps_handler) {
705         emac->cb_funcs.mps_handler();
706     }
707 
708     if ((isr & MXC_EMAC_REVA_EVENT_RXCMPL) && emac->cb_funcs.rxcmpl_handler) {
709         emac->cb_funcs.rxcmpl_handler();
710     }
711 
712     if ((isr & MXC_EMAC_REVA_EVENT_RXUBR) && emac->cb_funcs.rxubr_handler) {
713         emac->cb_funcs.rxubr_handler();
714     }
715 
716     if ((isr & MXC_EMAC_REVA_EVENT_TXUBR) && emac->cb_funcs.txubr_handler) {
717         emac->cb_funcs.txubr_handler();
718     }
719 
720     if ((isr & MXC_EMAC_REVA_EVENT_TXUR) && emac->cb_funcs.txur_handler) {
721         emac->cb_funcs.txur_handler();
722     }
723 
724     if ((isr & MXC_EMAC_REVA_EVENT_RLE) && emac->cb_funcs.rle_handler) {
725         emac->cb_funcs.rle_handler();
726     }
727 
728     if ((isr & MXC_EMAC_REVA_EVENT_TXERR) && emac->cb_funcs.txerr_handler) {
729         emac->cb_funcs.txerr_handler();
730     }
731 
732     if ((isr & MXC_EMAC_REVA_EVENT_TXCMPL) && emac->cb_funcs.txcmpl_handler) {
733         emac->cb_funcs.txcmpl_handler();
734     }
735 
736     if ((isr & MXC_EMAC_REVA_EVENT_LC) && emac->cb_funcs.lc_handler) {
737         emac->cb_funcs.lc_handler();
738     }
739 
740     if ((isr & MXC_EMAC_REVA_EVENT_RXOR) && emac->cb_funcs.rxor_handler) {
741         emac->cb_funcs.rxor_handler();
742     }
743 
744     if ((isr & MXC_EMAC_REVA_EVENT_HRESPNO) && emac->cb_funcs.hrespno_handler) {
745         emac->cb_funcs.hrespno_handler();
746     }
747 
748     if ((isr & MXC_EMAC_REVA_EVENT_PPR) && emac->cb_funcs.ppr_handler) {
749         emac->cb_funcs.ppr_handler();
750     }
751 
752     if ((isr & MXC_EMAC_REVA_EVENT_PTZ) && emac->cb_funcs.ptz_handler) {
753         emac->cb_funcs.ptz_handler();
754     }
755 }
756